diff --git a/AUTHORS b/AUTHORS
new file mode 100755
index 0000000000000000000000000000000000000000..f9299b4171e0132ee58fe2a00dc56daaaa25fe0a
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,23 @@
+
+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 
+
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000000000000000000000000000000000000..c12c4022aabce6e9e769e3c721ee35ac44c91f33
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,5 @@
+ifneq ($(TARGET_SIMULATOR),true)
+#ifeq ($(TARGET_ARCH),x86)
+include $(call all-subdir-makefiles)
+#endif
+endif
diff --git a/COPYING b/COPYING
new file mode 100755
index 0000000000000000000000000000000000000000..623b6258a134210f0b0ada106fdaab7f0370d9c5
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+		    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.
diff --git a/COPYING.LIB b/COPYING.LIB
new file mode 100755
index 0000000000000000000000000000000000000000..161a3d1d47b94f5d092b4c5fa316007c6f22fe81
--- /dev/null
+++ b/COPYING.LIB
@@ -0,0 +1,482 @@
+		  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!
diff --git a/CREDITS b/CREDITS
new file mode 100755
index 0000000000000000000000000000000000000000..82cc12461a59fd802efab86a77108aaeee21a609
--- /dev/null
+++ b/CREDITS
@@ -0,0 +1,61 @@
+The following people have contributed directly or indirectly 
+to the ntfs-3g project.
+
+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
+Don Bright
+Mario Emmenlauer 
+Yuval Fledel 
+Kano from Kanotix
+Roland Kletzing
+Maarten Lankhorst
+Gergely Madarasz
+Patrick McLean
+Florent Mertens
+Yura Pakhuchiy 
+Miklos Szeredi
+Bartosz Taudul
+Zhanglinbao
+Wade Fitzpatrick
+Carsten Einig
+Adam Cecile
+Bruno Damour
+Ales Fruman
+Curt McDowell
+Thomas Franken
+Jonatan Lambert
+Klaus Knopper
+Zhanglinbao
+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
+
diff --git a/ChangeLog b/ChangeLog
new file mode 100755
index 0000000000000000000000000000000000000000..a49d76a1dffea8faf08004c5e3459370cedfe51f
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,6 @@
+
+Detailed ChangeLog can be found at
+	http://www.tuxera.com/community/release-history/
+
+The changes and history may also be found on the source repository :
+	http://sourceforge.net/p/ntfs-3g/ntfs-3g/ci/edge/tree/
diff --git a/INSTALL b/INSTALL
new file mode 100755
index 0000000000000000000000000000000000000000..2099840756e6302d837dcd51b5dcd6262f7adb16
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,370 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation,
+Inc.
+
+   Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.  This file is offered as-is,
+without warranty of any kind.
+
+Basic Installation
+==================
+
+   Briefly, the shell command `./configure && make && make install'
+should configure, build, and install this package.  The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package.  Some packages provide this
+`INSTALL' file but do not implement all of the features documented
+below.  The lack of an optional feature in a given package is not
+necessarily a bug.  More recommendations for GNU packages can be found
+in *note Makefile Conventions: (standards)Makefile Conventions.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+   It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring.  Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+   The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'.  You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
+
+   The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.
+
+     Running `configure' might take a while.  While running, it prints
+     some messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package, generally using the just-built uninstalled binaries.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.  When installing into a prefix owned by root, it is
+     recommended that the package be configured and built as a regular
+     user, and only the `make install' phase executed with root
+     privileges.
+
+  5. Optionally, type `make installcheck' to repeat any self-tests, but
+     this time using the binaries in their final installed location.
+     This target does not install anything.  Running this target as a
+     regular user, particularly if the prior `make install' required
+     root privileges, verifies that the installation completed
+     correctly.
+
+  6. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+  7. Often, you can also type `make uninstall' to remove the installed
+     files again.  In practice, not all packages have tested that
+     uninstallation works correctly, even though it is required by the
+     GNU Coding Standards.
+
+  8. Some packages, particularly those that use Automake, provide `make
+     distcheck', which can by used by developers to test that all other
+     targets like `make install' and `make uninstall' work correctly.
+     This target is generally not run by end users.
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+   You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment.  Here
+is an example:
+
+     ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+   *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you can use GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.  This
+is known as a "VPATH" build.
+
+   With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory.  After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+   On MacOS X 10.5 and later systems, you can create libraries and
+executables that work on multiple system types--known as "fat" or
+"universal" binaries--by specifying multiple `-arch' options to the
+compiler but only a single `-arch' option to the preprocessor.  Like
+this:
+
+     ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+                 CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+                 CPP="gcc -E" CXXCPP="g++ -E"
+
+   This is not guaranteed to produce working output in all cases, you
+may have to build one architecture at a time and combine the results
+using the `lipo' tool if you have problems.
+
+Installation Names
+==================
+
+   By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc.  You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX', where PREFIX must be an
+absolute file name.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.  In general, the
+default for these options is expressed in terms of `${prefix}', so that
+specifying just `--prefix' will affect all of the other directory
+specifications that were not explicitly provided.
+
+   The most portable way to affect installation locations is to pass the
+correct locations to `configure'; however, many packages provide one or
+both of the following shortcuts of passing variable assignments to the
+`make install' command line to change installation locations without
+having to reconfigure or recompile.
+
+   The first method involves providing an override variable for each
+affected directory.  For example, `make install
+prefix=/alternate/directory' will choose an alternate location for all
+directory configuration variables that were expressed in terms of
+`${prefix}'.  Any directories that were specified during `configure',
+but not in terms of `${prefix}', must each be overridden at install
+time for the entire installation to be relocated.  The approach of
+makefile variable overrides for each directory variable is required by
+the GNU Coding Standards, and ideally causes no recompilation.
+However, some platforms have known limitations with the semantics of
+shared libraries that end up requiring recompilation when using this
+method, particularly noticeable in packages that use GNU Libtool.
+
+   The second method involves providing the `DESTDIR' variable.  For
+example, `make install DESTDIR=/alternate/directory' will prepend
+`/alternate/directory' before all installation names.  The approach of
+`DESTDIR' overrides is not required by the GNU Coding Standards, and
+does not work on platforms that have drive letters.  On the other hand,
+it does better at avoiding recompilation issues, and works well even
+when some directory options were not specified in terms of `${prefix}'
+at `configure' time.
+
+Optional Features
+=================
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+   Some packages offer the ability to configure how verbose the
+execution of `make' will be.  For these packages, running `./configure
+--enable-silent-rules' sets the default to minimal output, which can be
+overridden with `make V=1'; while running `./configure
+--disable-silent-rules' sets the default to verbose, which can be
+overridden with `make V=0'.
+
+Particular systems
+==================
+
+   On HP-UX, the default C compiler is not ANSI C compatible.  If GNU
+CC is not installed, it is recommended to use the following options in
+order to use an ANSI C compiler:
+
+     ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
+
+and if that doesn't work, install pre-built binaries of GCC for HP-UX.
+
+   HP-UX `make' updates targets which have the same time stamps as
+their prerequisites, which makes it generally unusable when shipped
+generated files such as `configure' are involved.  Use GNU `make'
+instead.
+
+   On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
+parse its `<wchar.h>' header file.  The option `-nodtk' can be used as
+a workaround.  If GNU CC is not installed, it is therefore recommended
+to try
+
+     ./configure CC="cc"
+
+and if that doesn't work, try
+
+     ./configure CC="cc -nodtk"
+
+   On Solaris, don't put `/usr/ucb' early in your `PATH'.  This
+directory contains several dysfunctional programs; working variants of
+these programs are available in `/usr/bin'.  So, if you need `/usr/ucb'
+in your `PATH', put it _after_ `/usr/bin'.
+
+   On Haiku, software installed for all users goes in `/boot/common',
+not `/usr/local'.  It is recommended to use the following options:
+
+     ./configure --prefix=/boot/common
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on.  Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+     CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+     OS
+     KERNEL-OS
+
+   See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+   Variables not defined in a site shell script can be set in the
+environment passed to `configure'.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf limitation.  Until the limitation is lifted, you can use
+this workaround:
+
+     CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+     Print a summary of all of the options to `configure', and exit.
+
+`--help=short'
+`--help=recursive'
+     Print a summary of the options unique to this package's
+     `configure', and exit.  The `short' variant lists options used
+     only in the top level, while the `recursive' variant lists options
+     also present in any nested packages.
+
+`--version'
+`-V'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally `config.cache'.  FILE defaults to `/dev/null' to
+     disable caching.
+
+`--config-cache'
+`-C'
+     Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`--prefix=DIR'
+     Use DIR as the installation prefix.  *note Installation Names::
+     for more details, including other options available for fine-tuning
+     the installation locations.
+
+`--no-create'
+`-n'
+     Run the configure checks, but stop before creating any output
+     files.
+
+`configure' also accepts some other, not widely useful, options.  Run
+`configure --help' for more details.
diff --git a/Makefile.am b/Makefile.am
new file mode 100755
index 0000000000000000000000000000000000000000..0123e1f98081fb281acd7e8fa175609dda4fe065
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,60 @@
+
+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"
+
+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;
+
+extra:	extras
+
+extras: libs
+	(cd ntfsprogs && $(MAKE) extras) || exit 1;
+endif
diff --git a/Makefile.in b/Makefile.in
new file mode 100755
index 0000000000000000000000000000000000000000..8c03a2c5629319fec8111fa9bec19a7eea63aaf7
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,941 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = .
+DIST_COMMON = INSTALL NEWS README AUTHORS ChangeLog \
+	$(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+	$(top_srcdir)/configure $(am__configure_deps) \
+	$(srcdir)/config.h.in COPYING COPYING.LIB compile config.guess \
+	config.sub install-sh missing ltmain.sh
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+	ctags-recursive dvi-recursive html-recursive info-recursive \
+	install-data-recursive install-dvi-recursive \
+	install-exec-recursive install-html-recursive \
+	install-info-recursive install-pdf-recursive \
+	install-ps-recursive install-recursive installcheck-recursive \
+	installdirs-recursive pdf-recursive ps-recursive \
+	tags-recursive uninstall-recursive
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+am__installdirs = "$(DESTDIR)$(docdir)"
+DATA = $(doc_DATA)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
+  distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+  $(RECURSIVE_TARGETS) \
+  $(RECURSIVE_CLEAN_TARGETS) \
+  $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+	cscope distdir dist dist-all distcheck
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
+	$(LISP)config.h.in
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+CSCOPE = cscope
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+  if test -d "$(distdir)"; then \
+    find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
+      && rm -rf "$(distdir)" \
+      || { sleep 5 && rm -rf "$(distdir)"; }; \
+  else :; fi
+am__post_remove_distdir = $(am__remove_distdir)
+am__relativize = \
+  dir0=`pwd`; \
+  sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+  sed_rest='s,^[^/]*/*,,'; \
+  sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+  sed_butlast='s,/*[^/]*$$,,'; \
+  while test -n "$$dir1"; do \
+    first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+    if test "$$first" != "."; then \
+      if test "$$first" = ".."; then \
+        dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+        dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+      else \
+        first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+        if test "$$first2" = "$$first"; then \
+          dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+        else \
+          dir2="../$$dir2"; \
+        fi; \
+        dir0="$$dir0"/"$$first"; \
+      fi; \
+    fi; \
+    dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+  done; \
+  reldir="$$dir2"
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+DIST_TARGETS = dist-gzip
+distuninstallcheck_listfiles = find . -type f -print
+am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
+  | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FUSE_MODULE_CFLAGS = @FUSE_MODULE_CFLAGS@
+FUSE_MODULE_LIBS = @FUSE_MODULE_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDCONFIG = @LDCONFIG@
+LDFLAGS = @LDFLAGS@
+LIBFUSE_LITE_CFLAGS = @LIBFUSE_LITE_CFLAGS@
+LIBFUSE_LITE_LIBS = @LIBFUSE_LITE_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBNTFS_3G_VERSION = @LIBNTFS_3G_VERSION@
+LIBNTFS_CPPFLAGS = @LIBNTFS_CPPFLAGS@
+LIBNTFS_LIBS = @LIBNTFS_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MKNTFS_CPPFLAGS = @MKNTFS_CPPFLAGS@
+MKNTFS_LIBS = @MKNTFS_LIBS@
+MV = @MV@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NTFSPROGS_STATIC_LIBS = @NTFSPROGS_STATIC_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+OUTPUT_FORMAT = @OUTPUT_FORMAT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+RM = @RM@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+all_includes = @all_includes@
+all_libraries = @all_libraries@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+ntfs3gincludedir = @ntfs3gincludedir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgconfigdir = @pkgconfigdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+rootbindir = @rootbindir@
+rootlibdir = @rootlibdir@
+rootsbindir = @rootsbindir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+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
+all: config.h
+	$(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+am--refresh: Makefile
+	@:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \
+	      $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    echo ' $(SHELL) ./config.status'; \
+	    $(SHELL) ./config.status;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	$(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	$(am__cd) $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+$(am__aclocal_m4_deps):
+
+config.h: stamp-h1
+	@test -f $@ || rm -f stamp-h1
+	@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+	@rm -f stamp-h1
+	cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) 
+	($(am__cd) $(top_srcdir) && $(AUTOHEADER))
+	rm -f stamp-h1
+	touch $@
+
+distclean-hdr:
+	-rm -f config.h stamp-h1
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool config.lt
+install-docDATA: $(doc_DATA)
+	@$(NORMAL_INSTALL)
+	@list='$(doc_DATA)'; test -n "$(docdir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \
+	fi; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \
+	done
+
+uninstall-docDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(doc_DATA)'; test -n "$(docdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir)
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+#     (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+	@fail=; \
+	if $(am__make_keepgoing); then \
+	  failcom='fail=yes'; \
+	else \
+	  failcom='exit 1'; \
+	fi; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-recursive
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-recursive
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscope: cscope.files
+	test ! -s cscope.files \
+	  || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
+clean-cscope:
+	-rm -f cscope.files
+cscope.files: clean-cscope cscopelist
+cscopelist: cscopelist-recursive
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+	-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
+
+distdir: $(DISTFILES)
+	$(am__remove_distdir)
+	test -d "$(distdir)" || mkdir "$(distdir)"
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+	@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    $(am__make_dryrun) \
+	      || test -d "$(distdir)/$$subdir" \
+	      || $(MKDIR_P) "$(distdir)/$$subdir" \
+	      || exit 1; \
+	    dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+	    $(am__relativize); \
+	    new_distdir=$$reldir; \
+	    dir1=$$subdir; dir2="$(top_distdir)"; \
+	    $(am__relativize); \
+	    new_top_distdir=$$reldir; \
+	    echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+	    echo "     am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+	    ($(am__cd) $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$new_top_distdir" \
+	        distdir="$$new_distdir" \
+		am__remove_distdir=: \
+		am__skip_length_check=: \
+		am__skip_mode_fix=: \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+	$(MAKE) $(AM_MAKEFLAGS) \
+	  top_distdir="$(top_distdir)" distdir="$(distdir)" \
+	  dist-hook
+	-test -n "$(am__skip_mode_fix)" \
+	|| find "$(distdir)" -type d ! -perm -755 \
+		-exec chmod u+rwx,go+rx {} \; -o \
+	  ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+	  ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+	  ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+	|| chmod -R a+r "$(distdir)"
+dist-gzip: distdir
+	tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+	$(am__post_remove_distdir)
+
+dist-bzip2: distdir
+	tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
+	$(am__post_remove_distdir)
+
+dist-lzip: distdir
+	tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
+	$(am__post_remove_distdir)
+
+dist-xz: distdir
+	tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
+	$(am__post_remove_distdir)
+
+dist-tarZ: distdir
+	@echo WARNING: "Support for shar distribution archives is" \
+	               "deprecated." >&2
+	@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
+	tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+	$(am__post_remove_distdir)
+
+dist-shar: distdir
+	@echo WARNING: "Support for distribution archives compressed with" \
+		       "legacy program 'compress' is deprecated." >&2
+	@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
+	shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+	$(am__post_remove_distdir)
+
+dist-zip: distdir
+	-rm -f $(distdir).zip
+	zip -rq $(distdir).zip $(distdir)
+	$(am__post_remove_distdir)
+
+dist dist-all:
+	$(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:'
+	$(am__post_remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+	case '$(DIST_ARCHIVES)' in \
+	*.tar.gz*) \
+	  GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
+	*.tar.bz2*) \
+	  bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
+	*.tar.lz*) \
+	  lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
+	*.tar.xz*) \
+	  xz -dc $(distdir).tar.xz | $(am__untar) ;;\
+	*.tar.Z*) \
+	  uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+	*.shar.gz*) \
+	  GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
+	*.zip*) \
+	  unzip $(distdir).zip ;;\
+	esac
+	chmod -R a-w $(distdir)
+	chmod u+w $(distdir)
+	mkdir $(distdir)/_build $(distdir)/_inst
+	chmod a-w $(distdir)
+	test -d $(distdir)/_build || exit 0; \
+	dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+	  && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+	  && am__cwd=`pwd` \
+	  && $(am__cd) $(distdir)/_build \
+	  && ../configure \
+	    $(AM_DISTCHECK_CONFIGURE_FLAGS) \
+	    $(DISTCHECK_CONFIGURE_FLAGS) \
+	    --srcdir=.. --prefix="$$dc_install_base" \
+	  && $(MAKE) $(AM_MAKEFLAGS) \
+	  && $(MAKE) $(AM_MAKEFLAGS) dvi \
+	  && $(MAKE) $(AM_MAKEFLAGS) check \
+	  && $(MAKE) $(AM_MAKEFLAGS) install \
+	  && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+	  && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+	  && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+	        distuninstallcheck \
+	  && chmod -R a-w "$$dc_install_base" \
+	  && ({ \
+	       (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+	            distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+	      } || { rm -rf "$$dc_destdir"; exit 1; }) \
+	  && rm -rf "$$dc_destdir" \
+	  && $(MAKE) $(AM_MAKEFLAGS) dist \
+	  && rm -rf $(DIST_ARCHIVES) \
+	  && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
+	  && cd "$$am__cwd" \
+	  || exit 1
+	$(am__post_remove_distdir)
+	@(echo "$(distdir) archives ready for distribution: "; \
+	  list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+	  sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+	@test -n '$(distuninstallcheck_dir)' || { \
+	  echo 'ERROR: trying to run $@ with an empty' \
+	       '$$(distuninstallcheck_dir)' >&2; \
+	  exit 1; \
+	}; \
+	$(am__cd) '$(distuninstallcheck_dir)' || { \
+	  echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \
+	  exit 1; \
+	}; \
+	test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \
+	   || { echo "ERROR: files left after uninstall:" ; \
+	        if test -n "$(DESTDIR)"; then \
+	          echo "  (check DESTDIR support)"; \
+	        fi ; \
+	        $(distuninstallcheck_listfiles) ; \
+	        exit 1; } >&2
+distcleancheck: distclean
+	@if test '$(srcdir)' = . ; then \
+	  echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+	  exit 1 ; \
+	fi
+	@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+	  || { echo "ERROR: files left in build directory after distclean:" ; \
+	       $(distcleancheck_listfiles) ; \
+	       exit 1; } >&2
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(DATA) config.h
+installdirs: installdirs-recursive
+installdirs-am:
+	for dir in "$(DESTDIR)$(docdir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-hdr \
+	distclean-libtool distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-docDATA
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -rf $(top_srcdir)/autom4te.cache
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-docDATA
+
+.MAKE: $(am__recursive_targets) all install-am install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
+	am--refresh check check-am clean clean-cscope clean-generic \
+	clean-libtool cscope cscopelist-am ctags ctags-am dist \
+	dist-all dist-bzip2 dist-gzip dist-hook dist-lzip dist-shar \
+	dist-tarZ dist-xz dist-zip distcheck distclean \
+	distclean-generic distclean-hdr distclean-libtool \
+	distclean-tags distcleancheck distdir distuninstallcheck dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-data install-data-am install-docDATA install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am install-man \
+	install-pdf install-pdf-am install-ps install-ps-am \
+	install-strip installcheck installcheck-am installdirs \
+	installdirs-am maintainer-clean maintainer-clean-generic \
+	mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
+	ps ps-am tags tags-am uninstall uninstall-am uninstall-docDATA
+
+
+dist-hook:
+	$(MKDIR_P) "$(distdir)/m4"
+
+libtool: $(LIBTOOL_DEPS)
+	$(SHELL) ./config.status --recheck
+
+libs:
+@FUSE_INTERNAL_TRUE@	(cd libfuse-lite && $(MAKE) libs) || exit 1;
+	(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;
+
+@ENABLE_NTFSPROGS_TRUE@strip:
+@ENABLE_NTFSPROGS_TRUE@	(cd ntfsprogs && $(MAKE) strip) || exit 1;
+
+@ENABLE_NTFSPROGS_TRUE@extra:	extras
+
+@ENABLE_NTFSPROGS_TRUE@extras: libs
+@ENABLE_NTFSPROGS_TRUE@	(cd ntfsprogs && $(MAKE) extras) || exit 1;
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/NEWS b/NEWS
new file mode 100755
index 0000000000000000000000000000000000000000..3a7effdeb62795189b1789e8635b71b95f0de695
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,5 @@
+
+Project news are at http://tuxera.com/community/ntfs-3g-download/
+
+Release notes are maintained at http://tuxera.com/community/release-history/
+
diff --git a/README b/README
new file mode 100755
index 0000000000000000000000000000000000000000..0f6a7db2d0e06817ff224c26f7cca68f28010e72
--- /dev/null
+++ b/README
@@ -0,0 +1,153 @@
+
+INTRODUCTION
+============
+
+The NTFS-3G driver is an open source, freely available read/write NTFS driver 
+for Linux, FreeBSD, Mac OS X, NetBSD, OpenSolaris, QNX and Haiku. It provides 
+safe and fast handling of the Windows XP, Windows Server 2003, Windows 2000, 
+Windows Vista, Windows Server 2008 and Windows 7 file systems. 
+
+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.
+
+Besides the common file system features, NTFS-3G has support for file 
+ownership and permissions, POSIX ACLs, junction points, extended attributes 
+and creating compressed files. Parameter files in the directory .NTFS-3G may 
+be required to enable them, please get the instructions from
+
+	http://www.tuxera.com/community/ntfs-3g-advanced/
+
+News, support answers, problem submission instructions, support and discussion 
+forums, performance numbers and other information are available on the project 
+web site at
+
+	http://www.tuxera.com/community/
+
+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.
+
+QUICK INSTALLATION
+==================
+
+Linux: Make sure you have the basic development tools and the kernel includes 
+the FUSE kernel module. Then unpack the source tarball and 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-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
+
+Non-Linux: Please see 
+
+	http://www.tuxera.com/community/ntfs-3g-download/
+
+for known OS specific installation and source packages, but generally
+the same procedures apply.
+
+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):
+
+	mount -t ntfs-3g /dev/sda1 /mnt/windows
+or
+	ntfs-3g /dev/sda1 /mnt/windows
+
+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:
+
+	/dev/sda1 /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 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.
+
+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.
diff --git a/TODO.ntfsprogs b/TODO.ntfsprogs
new file mode 100755
index 0000000000000000000000000000000000000000..3a60421f459263a9929297f9c83015777bb84645
--- /dev/null
+++ b/TODO.ntfsprogs
@@ -0,0 +1,126 @@
+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
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100755
index 0000000000000000000000000000000000000000..3ae1bb4489dfee939af3e7d52d067228f480fcb0
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,1528 @@
+# generated automatically by aclocal 1.14.1 -*- Autoconf -*-
+
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
+
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
+[m4_warning([this file was generated for autoconf 2.69.
+You have another version of autoconf.  It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically 'autoreconf'.])])
+
+dnl Autoconf macros for libgcrypt
+dnl       Copyright (C) 2002, 2004, 2011 Free Software Foundation, Inc.
+dnl
+dnl This file is free software; as a special exception the author gives
+dnl unlimited permission to copy and/or distribute it, with or without
+dnl modifications, as long as this notice is preserved.
+dnl
+dnl This file is distributed in the hope that it will be useful, but
+dnl WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+
+dnl AM_PATH_LIBGCRYPT([MINIMUM-VERSION,
+dnl                   [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]])
+dnl Test for libgcrypt and define LIBGCRYPT_CFLAGS and LIBGCRYPT_LIBS.
+dnl MINIMUN-VERSION is a string with the version number optionalliy prefixed
+dnl with the API version to also check the API compatibility. Example:
+dnl a MINIMUN-VERSION of 1:1.2.5 won't pass the test unless the installed
+dnl version of libgcrypt is at least 1.2.5 *and* the API number is 1.  Using
+dnl this features allows to prevent build against newer versions of libgcrypt
+dnl with a changed API.
+dnl
+AC_DEFUN([AM_PATH_LIBGCRYPT],
+[ AC_REQUIRE([AC_CANONICAL_HOST])
+  AC_ARG_WITH(libgcrypt-prefix,
+            AC_HELP_STRING([--with-libgcrypt-prefix=PFX],
+                           [prefix where LIBGCRYPT is installed (optional)]),
+     libgcrypt_config_prefix="$withval", libgcrypt_config_prefix="")
+  if test x$libgcrypt_config_prefix != x ; then
+     if test x${LIBGCRYPT_CONFIG+set} != xset ; then
+        LIBGCRYPT_CONFIG=$libgcrypt_config_prefix/bin/libgcrypt-config
+     fi
+  fi
+
+  AC_PATH_TOOL(LIBGCRYPT_CONFIG, libgcrypt-config, no)
+  tmp=ifelse([$1], ,1:1.2.0,$1)
+  if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then
+     req_libgcrypt_api=`echo "$tmp"     | sed 's/\(.*\):\(.*\)/\1/'`
+     min_libgcrypt_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'`
+  else
+     req_libgcrypt_api=0
+     min_libgcrypt_version="$tmp"
+  fi
+
+  AC_MSG_CHECKING(for LIBGCRYPT - version >= $min_libgcrypt_version)
+  ok=no
+  if test "$LIBGCRYPT_CONFIG" != "no" ; then
+    req_major=`echo $min_libgcrypt_version | \
+               sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'`
+    req_minor=`echo $min_libgcrypt_version | \
+               sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'`
+    req_micro=`echo $min_libgcrypt_version | \
+               sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'`
+    libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version`
+    major=`echo $libgcrypt_config_version | \
+               sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
+    minor=`echo $libgcrypt_config_version | \
+               sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'`
+    micro=`echo $libgcrypt_config_version | \
+               sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'`
+    if test "$major" -gt "$req_major"; then
+        ok=yes
+    else
+        if test "$major" -eq "$req_major"; then
+            if test "$minor" -gt "$req_minor"; then
+               ok=yes
+            else
+               if test "$minor" -eq "$req_minor"; then
+                   if test "$micro" -ge "$req_micro"; then
+                     ok=yes
+                   fi
+               fi
+            fi
+        fi
+    fi
+  fi
+  if test $ok = yes; then
+    AC_MSG_RESULT([yes ($libgcrypt_config_version)])
+  else
+    AC_MSG_RESULT(no)
+  fi
+  if test $ok = yes; then
+     # If we have a recent libgcrypt, we should also check that the
+     # API is compatible
+     if test "$req_libgcrypt_api" -gt 0 ; then
+        tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0`
+        if test "$tmp" -gt 0 ; then
+           AC_MSG_CHECKING([LIBGCRYPT API version])
+           if test "$req_libgcrypt_api" -eq "$tmp" ; then
+             AC_MSG_RESULT([okay])
+           else
+             ok=no
+             AC_MSG_RESULT([does not match. want=$req_libgcrypt_api got=$tmp])
+           fi
+        fi
+     fi
+  fi
+  if test $ok = yes; then
+    LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags`
+    LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs`
+    ifelse([$2], , :, [$2])
+    libgcrypt_config_host=`$LIBGCRYPT_CONFIG --host 2>/dev/null || echo none`
+    if test x"$libgcrypt_config_host" != xnone ; then
+      if test x"$libgcrypt_config_host" != x"$host" ; then
+  AC_MSG_WARN([[
+***
+*** The config script $LIBGCRYPT_CONFIG was
+*** built for $libgcrypt_config_host and thus may not match the
+*** used host $host.
+*** You may want to use the configure option --with-libgcrypt-prefix
+*** to specify a matching config script.
+***]])
+      fi
+    fi
+  else
+    LIBGCRYPT_CFLAGS=""
+    LIBGCRYPT_LIBS=""
+    ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(LIBGCRYPT_CFLAGS)
+  AC_SUBST(LIBGCRYPT_LIBS)
+])
+
+# pkg.m4 - Macros to locate and utilise pkg-config.            -*- Autoconf -*-
+# serial 1 (pkg-config-0.24)
+# 
+# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# PKG_PROG_PKG_CONFIG([MIN-VERSION])
+# ----------------------------------
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
+m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
+AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
+AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+	AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+	_pkg_min_version=m4_default([$1], [0.9.0])
+	AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+	if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+		AC_MSG_RESULT([yes])
+	else
+		AC_MSG_RESULT([no])
+		PKG_CONFIG=""
+	fi
+fi[]dnl
+])# PKG_PROG_PKG_CONFIG
+
+# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# Check to see whether a particular set of modules exists.  Similar
+# to PKG_CHECK_MODULES(), but does not set variables or print errors.
+#
+# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+# only at the first occurence in configure.ac, so if the first place
+# it's called might be skipped (such as if it is within an "if", you
+# have to call PKG_CHECK_EXISTS manually
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+    AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+  m4_default([$2], [:])
+m4_ifvaln([$3], [else
+  $3])dnl
+fi])
+
+# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+# ---------------------------------------------
+m4_define([_PKG_CONFIG],
+[if test -n "$$1"; then
+    pkg_cv_[]$1="$$1"
+ elif test -n "$PKG_CONFIG"; then
+    PKG_CHECK_EXISTS([$3],
+                     [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes ],
+		     [pkg_failed=yes])
+ else
+    pkg_failed=untried
+fi[]dnl
+])# _PKG_CONFIG
+
+# _PKG_SHORT_ERRORS_SUPPORTED
+# -----------------------------
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi[]dnl
+])# _PKG_SHORT_ERRORS_SUPPORTED
+
+
+# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+#
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES might not happen, you should be sure to include an
+# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+#
+#
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+   	AC_MSG_RESULT([no])
+        _PKG_SHORT_ERRORS_SUPPORTED
+        if test $_pkg_short_errors_supported = yes; then
+	        $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
+        else 
+	        $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+	m4_default([$4], [AC_MSG_ERROR(
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT])[]dnl
+        ])
+elif test $pkg_failed = untried; then
+     	AC_MSG_RESULT([no])
+	m4_default([$4], [AC_MSG_FAILURE(
+[The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
+        ])
+else
+	$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+	$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+        AC_MSG_RESULT([yes])
+	$3
+fi[]dnl
+])# PKG_CHECK_MODULES
+
+
+# PKG_INSTALLDIR(DIRECTORY)
+# -------------------------
+# Substitutes the variable pkgconfigdir as the location where a module
+# should install pkg-config .pc files. By default the directory is
+# $libdir/pkgconfig, but the default can be changed by passing
+# DIRECTORY. The user can override through the --with-pkgconfigdir
+# parameter.
+AC_DEFUN([PKG_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+    [pkg-config installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([pkgconfigdir],
+    [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
+    [with_pkgconfigdir=]pkg_default)
+AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+]) dnl PKG_INSTALLDIR
+
+
+# PKG_NOARCH_INSTALLDIR(DIRECTORY)
+# -------------------------
+# Substitutes the variable noarch_pkgconfigdir as the location where a
+# module should install arch-independent pkg-config .pc files. By
+# default the directory is $datadir/pkgconfig, but the default can be
+# changed by passing DIRECTORY. The user can override through the
+# --with-noarch-pkgconfigdir parameter.
+AC_DEFUN([PKG_NOARCH_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+    [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([noarch-pkgconfigdir],
+    [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
+    [with_noarch_pkgconfigdir=]pkg_default)
+AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+]) dnl PKG_NOARCH_INSTALLDIR
+
+
+# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
+# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# -------------------------------------------
+# Retrieves the value of the pkg-config variable for the given module.
+AC_DEFUN([PKG_CHECK_VAR],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
+
+_PKG_CONFIG([$1], [variable="][$3]["], [$2])
+AS_VAR_COPY([$1], [pkg_cv_][$1])
+
+AS_VAR_IF([$1], [""], [$5], [$4])dnl
+])# PKG_CHECK_VAR
+
+# Copyright (C) 2002-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.14'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version.  Point them to the right macro.
+m4_if([$1], [1.14.1], [],
+      [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too.  Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.14.1])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to '$srcdir/foo'.  In other projects, it is set to
+# '$srcdir', '$srcdir/..', or '$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory.  The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run.  This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+#    fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+#    fails if $ac_aux_dir is absolute,
+#    fails when called from a subdirectory in a VPATH build with
+#          a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir.  In an in-source build this is usually
+# harmless because $srcdir is '.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
+#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+#   MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH.  The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL                                            -*- Autoconf -*-
+
+# Copyright (C) 1997-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ([2.52])dnl
+ m4_if([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])],
+       [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+  AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+
+# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery.  Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+m4_if([$1], [CC],   [depcc="$CC"   am_compiler_list=],
+      [$1], [CXX],  [depcc="$CXX"  am_compiler_list=],
+      [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+      [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'],
+      [$1], [UPC],  [depcc="$UPC"  am_compiler_list=],
+      [$1], [GCJ],  [depcc="$GCJ"  am_compiler_list='gcc3 gcc'],
+                    [depcc="$$1"   am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+               [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named 'D' -- because '-MD' means "put the output
+  # in D".
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_$1_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+  fi
+  am__universal=false
+  m4_case([$1], [CC],
+    [case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac],
+    [CXX],
+    [case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac])
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+      # Solaris 10 /bin/sh.
+      echo '/* dummy */' > sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with '-c' and '-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle '-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs.
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # After this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested.
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+      # This compiler won't grok '-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_$1_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES.
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE([dependency-tracking], [dnl
+AS_HELP_STRING(
+  [--enable-dependency-tracking],
+  [do not reject slow dependency extractors])
+AS_HELP_STRING(
+  [--disable-dependency-tracking],
+  [speeds up one-time build])])
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+  am__nodep='_no'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+AC_SUBST([am__nodep])dnl
+_AM_SUBST_NOTMAKE([am__nodep])dnl
+])
+
+# Generate code to set up dependency tracking.              -*- Autoconf -*-
+
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[{
+  # Older Autoconf quotes --file arguments for eval, but not when files
+  # are listed without --file.  Let's play safe and only enable the eval
+  # if we detect the quoting.
+  case $CONFIG_FILES in
+  *\'*) eval set x "$CONFIG_FILES" ;;
+  *)   set x $CONFIG_FILES ;;
+  esac
+  shift
+  for mf
+  do
+    # Strip MF so we end up with the name of the file.
+    mf=`echo "$mf" | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile or not.
+    # We used to match only the files named 'Makefile.in', but
+    # some people rename them; so instead we look at the file content.
+    # Grep'ing the first line is not enough: some people post-process
+    # each Makefile.in and add a new line on top of each file to say so.
+    # Grep'ing the whole file is not good either: AIX grep has a line
+    # limit of 2048, but all sed's we know have understand at least 4000.
+    if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+      dirpart=`AS_DIRNAME("$mf")`
+    else
+      continue
+    fi
+    # Extract the definition of DEPDIR, am__include, and am__quote
+    # from the Makefile without running 'make'.
+    DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+    test -z "$DEPDIR" && continue
+    am__include=`sed -n 's/^am__include = //p' < "$mf"`
+    test -z "$am__include" && continue
+    am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+    # Find all dependency output files, they are included files with
+    # $(DEPDIR) in their names.  We invoke sed twice because it is the
+    # simplest approach to changing $(DEPDIR) to its actual value in the
+    # expansion.
+    for file in `sed -n "
+      s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+	 sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
+      # Make sure the directory exists.
+      test -f "$dirpart/$file" && continue
+      fdir=`AS_DIRNAME(["$file"])`
+      AS_MKDIR_P([$dirpart/$fdir])
+      # echo "creating $dirpart/$file"
+      echo '# dummy' > "$dirpart/$file"
+    done
+  done
+}
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled.  FIXME.  This creates each '.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+     [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+     [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Do all the work for Automake.                             -*- Autoconf -*-
+
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This macro actually does too much.  Some checks are only needed if
+# your package does certain things.  But this isn't really a big deal.
+
+dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
+m4_define([AC_PROG_CC],
+m4_defn([AC_PROG_CC])
+[_AM_PROG_CC_C_O
+])
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out.  PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition.  After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.65])dnl
+dnl Autoconf wants to disallow AM_ names.  We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[AC_DIAGNOSE([obsolete],
+             [$0: two- and three-arguments forms are deprecated.])
+m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(
+  m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]),
+  [ok:ok],,
+  [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package])
+ AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}])
+AM_MISSING_PROG([AUTOCONF], [autoconf])
+AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}])
+AM_MISSING_PROG([AUTOHEADER], [autoheader])
+AM_MISSING_PROG([MAKEINFO], [makeinfo])
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+# For better backward compatibility.  To be removed once Automake 1.9.x
+# dies out for good.  For more background, see:
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
+AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+	      [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+			     [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+		  [_AM_DEPENDENCIES([CC])],
+		  [m4_define([AC_PROG_CC],
+			     m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+		  [_AM_DEPENDENCIES([CXX])],
+		  [m4_define([AC_PROG_CXX],
+			     m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+		  [_AM_DEPENDENCIES([OBJC])],
+		  [m4_define([AC_PROG_OBJC],
+			     m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
+		  [_AM_DEPENDENCIES([OBJCXX])],
+		  [m4_define([AC_PROG_OBJCXX],
+			     m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
+])
+AC_REQUIRE([AM_SILENT_RULES])dnl
+dnl The testsuite driver may need to know about EXEEXT, so add the
+dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen.  This
+dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+  [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes.  So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+  cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present.  This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
+
+Please tell bug-automake@gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message.  This
+can help us improve future automake versions.
+
+END
+  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+    echo 'Configuration will proceed anyway, since you have set the' >&2
+    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+    echo >&2
+  else
+    cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: <http://www.gnu.org/software/coreutils/>.
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+    AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
+  fi
+fi])
+
+dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion.  Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated.  The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+if test x"${install_sh}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+AC_SUBST([install_sh])])
+
+# Copyright (C) 2003-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot.  For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Add --enable-maintainer-mode option to configure.         -*- Autoconf -*-
+# From Jim Meyering
+
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MAINTAINER_MODE([DEFAULT-MODE])
+# ----------------------------------
+# Control maintainer-specific portions of Makefiles.
+# Default is to disable them, unless 'enable' is passed literally.
+# For symmetry, 'disable' may be passed as well.  Anyway, the user
+# can override the default with the --enable/--disable switch.
+AC_DEFUN([AM_MAINTAINER_MODE],
+[m4_case(m4_default([$1], [disable]),
+       [enable], [m4_define([am_maintainer_other], [disable])],
+       [disable], [m4_define([am_maintainer_other], [enable])],
+       [m4_define([am_maintainer_other], [enable])
+        m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
+AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+  dnl maintainer-mode's default is 'disable' unless 'enable' is passed
+  AC_ARG_ENABLE([maintainer-mode],
+    [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode],
+      am_maintainer_other[ make rules and dependencies not useful
+      (and sometimes confusing) to the casual installer])],
+    [USE_MAINTAINER_MODE=$enableval],
+    [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
+  AC_MSG_RESULT([$USE_MAINTAINER_MODE])
+  AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
+  MAINT=$MAINTAINER_MODE_TRUE
+  AC_SUBST([MAINT])dnl
+]
+)
+
+# Check to see how 'make' treats includes.	            -*- Autoconf -*-
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+	@echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from 'make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+  am__include=include
+  am__quote=
+  _am_result=GNU
+  ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   case `$am_make -s -f confmf 2> /dev/null` in #(
+   *the\ am__doit\ target*)
+     am__include=.include
+     am__quote="\""
+     _am_result=BSD
+     ;;
+   esac
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
+
+# Copyright (C) 1997-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it is modern enough.
+# If it is, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+if test x"${MISSING+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+  *)
+    MISSING="\${SHELL} $am_aux_dir/missing" ;;
+  esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --is-lightweight"; then
+  am_missing_run="$MISSING "
+else
+  am_missing_run=
+  AC_MSG_WARN(['missing' script is too old or missing])
+fi
+])
+
+# Helper functions for option handling.                     -*- Autoconf -*-
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# --------------------
+# Set option NAME.  Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), [1])])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_CC_C_O
+# ---------------
+# Like AC_PROG_CC_C_O, but changed for automake.  We rewrite AC_PROG_CC
+# to automatically call this.
+AC_DEFUN([_AM_PROG_CC_C_O],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([compile])dnl
+AC_LANG_PUSH([C])dnl
+AC_CACHE_CHECK(
+  [whether $CC understands -c and -o together],
+  [am_cv_prog_cc_c_o],
+  [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
+  # Make sure it works both with $CC and with simple cc.
+  # Following AC_PROG_CC_C_O, we do the test twice because some
+  # compilers refuse to overwrite an existing .o file with -o,
+  # though they will create one.
+  am_cv_prog_cc_c_o=yes
+  for am_i in 1 2; do
+    if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \
+         && test -f conftest2.$ac_objext; then
+      : OK
+    else
+      am_cv_prog_cc_c_o=no
+      break
+    fi
+  done
+  rm -f core conftest*
+  unset am_i])
+if test "$am_cv_prog_cc_c_o" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+AC_LANG_POP([C])])
+
+# For backward compatibility.
+AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_RUN_LOG(COMMAND)
+# -------------------
+# Run COMMAND, save the exit status in ac_status, and log it.
+# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
+AC_DEFUN([AM_RUN_LOG],
+[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
+   ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   (exit $ac_status); }])
+
+# Check to make sure that the build environment is sane.    -*- Autoconf -*-
+
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[[\\\"\#\$\&\'\`$am_lf]]*)
+    AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+  *[[\\\"\#\$\&\'\`$am_lf\ \	]]*)
+    AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);;
+esac
+
+# Do 'set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   am_has_slept=no
+   for am_try in 1 2; do
+     echo "timestamp, slept: $am_has_slept" > conftest.file
+     set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+     if test "$[*]" = "X"; then
+	# -L didn't work.
+	set X `ls -t "$srcdir/configure" conftest.file`
+     fi
+     if test "$[*]" != "X $srcdir/configure conftest.file" \
+	&& test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+	# If neither matched, then we have a broken ls.  This can happen
+	# if, for instance, CONFIG_SHELL is bash and it inherits a
+	# broken ls alias from the environment.  This has actually
+	# happened.  Such a system could not be considered "sane".
+	AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+  alias in your environment])
+     fi
+     if test "$[2]" = conftest.file || test $am_try -eq 2; then
+       break
+     fi
+     # Just in case.
+     sleep 1
+     am_has_slept=yes
+   done
+   test "$[2]" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT([yes])
+# If we didn't sleep, we still need to ensure time stamps of config.status and
+# generated files are strictly newer.
+am_sleep_pid=
+if grep 'slept: no' conftest.file >/dev/null 2>&1; then
+  ( sleep 1 ) &
+  am_sleep_pid=$!
+fi
+AC_CONFIG_COMMANDS_PRE(
+  [AC_MSG_CHECKING([that generated files are newer than configure])
+   if test -n "$am_sleep_pid"; then
+     # Hide warnings about reused PIDs.
+     wait $am_sleep_pid 2>/dev/null
+   fi
+   AC_MSG_RESULT([done])])
+rm -f conftest.file
+])
+
+# Copyright (C) 2009-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_SILENT_RULES([DEFAULT])
+# --------------------------
+# Enable less verbose build rules; with the default set to DEFAULT
+# ("yes" being less verbose, "no" or empty being verbose).
+AC_DEFUN([AM_SILENT_RULES],
+[AC_ARG_ENABLE([silent-rules], [dnl
+AS_HELP_STRING(
+  [--enable-silent-rules],
+  [less verbose build output (undo: "make V=1")])
+AS_HELP_STRING(
+  [--disable-silent-rules],
+  [verbose build output (undo: "make V=0")])dnl
+])
+case $enable_silent_rules in @%:@ (((
+  yes) AM_DEFAULT_VERBOSITY=0;;
+   no) AM_DEFAULT_VERBOSITY=1;;
+    *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
+esac
+dnl
+dnl A few 'make' implementations (e.g., NonStop OS and NextStep)
+dnl do not support nested variable expansions.
+dnl See automake bug#9928 and bug#10237.
+am_make=${MAKE-make}
+AC_CACHE_CHECK([whether $am_make supports nested variables],
+   [am_cv_make_support_nested_variables],
+   [if AS_ECHO([['TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+	@$(TRUE)
+.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then
+  am_cv_make_support_nested_variables=yes
+else
+  am_cv_make_support_nested_variables=no
+fi])
+if test $am_cv_make_support_nested_variables = yes; then
+  dnl Using '$V' instead of '$(V)' breaks IRIX make.
+  AM_V='$(V)'
+  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+  AM_V=$AM_DEFAULT_VERBOSITY
+  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AC_SUBST([AM_V])dnl
+AM_SUBST_NOTMAKE([AM_V])dnl
+AC_SUBST([AM_DEFAULT_V])dnl
+AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl
+AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
+AM_BACKSLASH='\'
+AC_SUBST([AM_BACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
+])
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor 'install' (even GNU) is that you can't
+# specify the program used to strip binaries.  This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in "make install-strip", and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using 'strip' when the user
+# run "make install-strip".  However 'strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the 'STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be 'maybe'.
+if test "$cross_compiling" != no; then
+  AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# AM_SUBST_NOTMAKE(VARIABLE)
+# --------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+# Check how to create a tarball.                            -*- Autoconf -*-
+
+# Copyright (C) 2004-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of 'v7', 'ustar', or 'pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+#     tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+#     $(am__untar) < result.tar
+#
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.  Yes, it's still used
+# in the wild :-(  We should find a proper way to deprecate it ...
+AC_SUBST([AMTAR], ['$${TAR-tar}'])
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+
+m4_if([$1], [v7],
+  [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
+
+  [m4_case([$1],
+    [ustar],
+     [# The POSIX 1988 'ustar' format is defined with fixed-size fields.
+      # There is notably a 21 bits limit for the UID and the GID.  In fact,
+      # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
+      # and bug#13588).
+      am_max_uid=2097151 # 2^21 - 1
+      am_max_gid=$am_max_uid
+      # The $UID and $GID variables are not portable, so we need to resort
+      # to the POSIX-mandated id(1) utility.  Errors in the 'id' calls
+      # below are definitely unexpected, so allow the users to see them
+      # (that is, avoid stderr redirection).
+      am_uid=`id -u || echo unknown`
+      am_gid=`id -g || echo unknown`
+      AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])
+      if test $am_uid -le $am_max_uid; then
+         AC_MSG_RESULT([yes])
+      else
+         AC_MSG_RESULT([no])
+         _am_tools=none
+      fi
+      AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])
+      if test $am_gid -le $am_max_gid; then
+         AC_MSG_RESULT([yes])
+      else
+        AC_MSG_RESULT([no])
+        _am_tools=none
+      fi],
+
+  [pax],
+    [],
+
+  [m4_fatal([Unknown tar format])])
+
+  AC_MSG_CHECKING([how to create a $1 tar archive])
+
+  # Go ahead even if we have the value already cached.  We do so because we
+  # need to set the values for the 'am__tar' and 'am__untar' variables.
+  _am_tools=${am_cv_prog_tar_$1-$_am_tools}
+
+  for _am_tool in $_am_tools; do
+    case $_am_tool in
+    gnutar)
+      for _am_tar in tar gnutar gtar; do
+        AM_RUN_LOG([$_am_tar --version]) && break
+      done
+      am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+      am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+      am__untar="$_am_tar -xf -"
+      ;;
+    plaintar)
+      # Must skip GNU tar: if it does not support --format= it doesn't create
+      # ustar tarball either.
+      (tar --version) >/dev/null 2>&1 && continue
+      am__tar='tar chf - "$$tardir"'
+      am__tar_='tar chf - "$tardir"'
+      am__untar='tar xf -'
+      ;;
+    pax)
+      am__tar='pax -L -x $1 -w "$$tardir"'
+      am__tar_='pax -L -x $1 -w "$tardir"'
+      am__untar='pax -r'
+      ;;
+    cpio)
+      am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+      am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+      am__untar='cpio -i -H $1 -d'
+      ;;
+    none)
+      am__tar=false
+      am__tar_=false
+      am__untar=false
+      ;;
+    esac
+
+    # If the value was cached, stop now.  We just wanted to have am__tar
+    # and am__untar set.
+    test -n "${am_cv_prog_tar_$1}" && break
+
+    # tar/untar a dummy directory, and stop if the command works.
+    rm -rf conftest.dir
+    mkdir conftest.dir
+    echo GrepMe > conftest.dir/file
+    AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+    rm -rf conftest.dir
+    if test -s conftest.tar; then
+      AM_RUN_LOG([$am__untar <conftest.tar])
+      AM_RUN_LOG([cat conftest.dir/file])
+      grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+    fi
+  done
+  rm -rf conftest.dir
+
+  AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+  AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([m4/libtool.m4])
+m4_include([m4/ltoptions.m4])
+m4_include([m4/ltsugar.m4])
+m4_include([m4/ltversion.m4])
+m4_include([m4/lt~obsolete.m4])
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000000000000000000000000000000000000..62e5439b6540ae0d9a6891cdd23ad86ed32bbd56
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+# Run this to generate configure, Makefile.in's, etc
+
+(autoreconf --version) < /dev/null > /dev/null 2>&1 || {
+  (autoconf --version) < /dev/null > /dev/null 2>&1 || {
+    echo
+    echo "**Error**: You must have the GNU Build System (autoconf, automake, "
+    echo "libtool, etc) to update the ntfs-3g build system.  Download the "
+    echo "appropriate packages for your distribution, or get the source "
+    echo "tar balls from ftp://ftp.gnu.org/pub/gnu/."
+    exit 1
+  }
+  echo
+  echo "**Error**: Your version of autoconf is too old (you need at least 2.57)"
+  echo "to update the ntfs-3g build system.  Download the appropriate "
+  echo "updated package for your distribution, or get the source tar ball "
+  echo "from ftp://ftp.gnu.org/pub/gnu/."
+  exit 1
+}
+
+echo Running autoreconf --verbose --install --force
+autoreconf --verbose --install --force
diff --git a/compile b/compile
new file mode 100755
index 0000000000000000000000000000000000000000..531136b068ef00e23d38429e6ee9a57d581a0870
--- /dev/null
+++ b/compile
@@ -0,0 +1,347 @@
+#! /bin/sh
+# Wrapper for compilers which do not understand '-c -o'.
+
+scriptversion=2012-10-14.11; # UTC
+
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
+# Written by Tom Tromey <tromey@cygnus.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+nl='
+'
+
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent tools from complaining about whitespace usage.
+IFS=" ""	$nl"
+
+file_conv=
+
+# func_file_conv build_file lazy
+# Convert a $build file to $host form and store it in $file
+# Currently only supports Windows hosts. If the determined conversion
+# type is listed in (the comma separated) LAZY, no conversion will
+# take place.
+func_file_conv ()
+{
+  file=$1
+  case $file in
+    / | /[!/]*) # absolute file, and not a UNC file
+      if test -z "$file_conv"; then
+	# lazily determine how to convert abs files
+	case `uname -s` in
+	  MINGW*)
+	    file_conv=mingw
+	    ;;
+	  CYGWIN*)
+	    file_conv=cygwin
+	    ;;
+	  *)
+	    file_conv=wine
+	    ;;
+	esac
+      fi
+      case $file_conv/,$2, in
+	*,$file_conv,*)
+	  ;;
+	mingw/*)
+	  file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
+	  ;;
+	cygwin/*)
+	  file=`cygpath -m "$file" || echo "$file"`
+	  ;;
+	wine/*)
+	  file=`winepath -w "$file" || echo "$file"`
+	  ;;
+      esac
+      ;;
+  esac
+}
+
+# func_cl_dashL linkdir
+# Make cl look for libraries in LINKDIR
+func_cl_dashL ()
+{
+  func_file_conv "$1"
+  if test -z "$lib_path"; then
+    lib_path=$file
+  else
+    lib_path="$lib_path;$file"
+  fi
+  linker_opts="$linker_opts -LIBPATH:$file"
+}
+
+# func_cl_dashl library
+# Do a library search-path lookup for cl
+func_cl_dashl ()
+{
+  lib=$1
+  found=no
+  save_IFS=$IFS
+  IFS=';'
+  for dir in $lib_path $LIB
+  do
+    IFS=$save_IFS
+    if $shared && test -f "$dir/$lib.dll.lib"; then
+      found=yes
+      lib=$dir/$lib.dll.lib
+      break
+    fi
+    if test -f "$dir/$lib.lib"; then
+      found=yes
+      lib=$dir/$lib.lib
+      break
+    fi
+    if test -f "$dir/lib$lib.a"; then
+      found=yes
+      lib=$dir/lib$lib.a
+      break
+    fi
+  done
+  IFS=$save_IFS
+
+  if test "$found" != yes; then
+    lib=$lib.lib
+  fi
+}
+
+# func_cl_wrapper cl arg...
+# Adjust compile command to suit cl
+func_cl_wrapper ()
+{
+  # Assume a capable shell
+  lib_path=
+  shared=:
+  linker_opts=
+  for arg
+  do
+    if test -n "$eat"; then
+      eat=
+    else
+      case $1 in
+	-o)
+	  # configure might choose to run compile as 'compile cc -o foo foo.c'.
+	  eat=1
+	  case $2 in
+	    *.o | *.[oO][bB][jJ])
+	      func_file_conv "$2"
+	      set x "$@" -Fo"$file"
+	      shift
+	      ;;
+	    *)
+	      func_file_conv "$2"
+	      set x "$@" -Fe"$file"
+	      shift
+	      ;;
+	  esac
+	  ;;
+	-I)
+	  eat=1
+	  func_file_conv "$2" mingw
+	  set x "$@" -I"$file"
+	  shift
+	  ;;
+	-I*)
+	  func_file_conv "${1#-I}" mingw
+	  set x "$@" -I"$file"
+	  shift
+	  ;;
+	-l)
+	  eat=1
+	  func_cl_dashl "$2"
+	  set x "$@" "$lib"
+	  shift
+	  ;;
+	-l*)
+	  func_cl_dashl "${1#-l}"
+	  set x "$@" "$lib"
+	  shift
+	  ;;
+	-L)
+	  eat=1
+	  func_cl_dashL "$2"
+	  ;;
+	-L*)
+	  func_cl_dashL "${1#-L}"
+	  ;;
+	-static)
+	  shared=false
+	  ;;
+	-Wl,*)
+	  arg=${1#-Wl,}
+	  save_ifs="$IFS"; IFS=','
+	  for flag in $arg; do
+	    IFS="$save_ifs"
+	    linker_opts="$linker_opts $flag"
+	  done
+	  IFS="$save_ifs"
+	  ;;
+	-Xlinker)
+	  eat=1
+	  linker_opts="$linker_opts $2"
+	  ;;
+	-*)
+	  set x "$@" "$1"
+	  shift
+	  ;;
+	*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
+	  func_file_conv "$1"
+	  set x "$@" -Tp"$file"
+	  shift
+	  ;;
+	*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
+	  func_file_conv "$1" mingw
+	  set x "$@" "$file"
+	  shift
+	  ;;
+	*)
+	  set x "$@" "$1"
+	  shift
+	  ;;
+      esac
+    fi
+    shift
+  done
+  if test -n "$linker_opts"; then
+    linker_opts="-link$linker_opts"
+  fi
+  exec "$@" $linker_opts
+  exit 1
+}
+
+eat=
+
+case $1 in
+  '')
+     echo "$0: No command.  Try '$0 --help' for more information." 1>&2
+     exit 1;
+     ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: compile [--help] [--version] PROGRAM [ARGS]
+
+Wrapper for compilers which do not understand '-c -o'.
+Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
+arguments, and rename the output as expected.
+
+If you are trying to build a whole package this is not the
+right script to run: please start by reading the file 'INSTALL'.
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "compile $scriptversion"
+    exit $?
+    ;;
+  cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
+    func_cl_wrapper "$@"      # Doesn't return...
+    ;;
+esac
+
+ofile=
+cfile=
+
+for arg
+do
+  if test -n "$eat"; then
+    eat=
+  else
+    case $1 in
+      -o)
+	# configure might choose to run compile as 'compile cc -o foo foo.c'.
+	# So we strip '-o arg' only if arg is an object.
+	eat=1
+	case $2 in
+	  *.o | *.obj)
+	    ofile=$2
+	    ;;
+	  *)
+	    set x "$@" -o "$2"
+	    shift
+	    ;;
+	esac
+	;;
+      *.c)
+	cfile=$1
+	set x "$@" "$1"
+	shift
+	;;
+      *)
+	set x "$@" "$1"
+	shift
+	;;
+    esac
+  fi
+  shift
+done
+
+if test -z "$ofile" || test -z "$cfile"; then
+  # If no '-o' option was seen then we might have been invoked from a
+  # pattern rule where we don't need one.  That is ok -- this is a
+  # normal compilation that the losing compiler can handle.  If no
+  # '.c' file was seen then we are probably linking.  That is also
+  # ok.
+  exec "$@"
+fi
+
+# Name of file we expect compiler to create.
+cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
+
+# Create the lock directory.
+# Note: use '[/\\:.-]' here to ensure that we don't use the same name
+# that we are using for the .o file.  Also, base the name on the expected
+# object file name, since that is what matters with a parallel build.
+lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
+while true; do
+  if mkdir "$lockdir" >/dev/null 2>&1; then
+    break
+  fi
+  sleep 1
+done
+# FIXME: race condition here if user kills between mkdir and trap.
+trap "rmdir '$lockdir'; exit 1" 1 2 15
+
+# Run the compile.
+"$@"
+ret=$?
+
+if test -f "$cofile"; then
+  test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
+elif test -f "${cofile}bj"; then
+  test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
+fi
+
+rmdir "$lockdir"
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/config.guess b/config.guess
new file mode 100755
index 0000000000000000000000000000000000000000..1f5c50c0d1529d50b94dc3533ca72a47f0fa5849
--- /dev/null
+++ b/config.guess
@@ -0,0 +1,1420 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright 1992-2014 Free Software Foundation, Inc.
+
+timestamp='2014-03-23'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+#
+# Originally written by Per Bothner.
+#
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+#
+# Please send patches with a ChangeLog entry to config-patches@gnu.org.
+
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright 1992-2014 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+	for c in cc gcc c89 c99 ; do
+	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found ;
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+case "${UNAME_SYSTEM}" in
+Linux|GNU|GNU/*)
+	# If the system lacks a compiler, then just pick glibc.
+	# We could probably try harder.
+	LIBC=gnu
+
+	eval $set_cc_for_build
+	cat <<-EOF > $dummy.c
+	#include <features.h>
+	#if defined(__UCLIBC__)
+	LIBC=uclibc
+	#elif defined(__dietlibc__)
+	LIBC=dietlibc
+	#else
+	LIBC=gnu
+	#endif
+	EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+	;;
+esac
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+	# NetBSD (nbsd) targets should (where applicable) match one or
+	# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	#
+	# Note: NetBSD doesn't particularly care about the vendor
+	# portion of the name.  We always set it to "unknown".
+	sysctl="sysctl -n hw.machine_arch"
+	UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+	    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+	case "${UNAME_MACHINE_ARCH}" in
+	    armeb) machine=armeb-unknown ;;
+	    arm*) machine=arm-unknown ;;
+	    sh3el) machine=shl-unknown ;;
+	    sh3eb) machine=sh-unknown ;;
+	    sh5el) machine=sh5le-unknown ;;
+	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently, or will in the future.
+	case "${UNAME_MACHINE_ARCH}" in
+	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+		eval $set_cc_for_build
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep -q __ELF__
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+		os=netbsd
+		;;
+	esac
+	# The OS release
+	# Debian GNU/NetBSD machines have a different userland, and
+	# thus, need a distinct triplet. However, they do not need
+	# kernel version information, so it can be replaced with a
+	# suitable tag, in the style of linux-gnu.
+	case "${UNAME_VERSION}" in
+	    Debian*)
+		release='-gnu'
+		;;
+	    *)
+		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+		;;
+	esac
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "${machine}-${os}${release}"
+	exit ;;
+    *:Bitrig:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
+	exit ;;
+    *:OpenBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+	exit ;;
+    *:ekkoBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+	exit ;;
+    *:SolidBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+	exit ;;
+    macppc:MirBSD:*:*)
+	echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    *:MirBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    alpha:OSF1:*:*)
+	case $UNAME_RELEASE in
+	*4.0)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+		;;
+	*5.*)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		;;
+	esac
+	# According to Compaq, /usr/sbin/psrinfo has been available on
+	# OSF/1 and Tru64 systems produced since 1995.  I hope that
+	# covers most systems running today.  This code pipes the CPU
+	# types through head -n 1, so we only detect the type of CPU 0.
+	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+	case "$ALPHA_CPU_TYPE" in
+	    "EV4 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV4.5 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "LCA4 (21066/21068)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV5 (21164)")
+		UNAME_MACHINE="alphaev5" ;;
+	    "EV5.6 (21164A)")
+		UNAME_MACHINE="alphaev56" ;;
+	    "EV5.6 (21164PC)")
+		UNAME_MACHINE="alphapca56" ;;
+	    "EV5.7 (21164PC)")
+		UNAME_MACHINE="alphapca57" ;;
+	    "EV6 (21264)")
+		UNAME_MACHINE="alphaev6" ;;
+	    "EV6.7 (21264A)")
+		UNAME_MACHINE="alphaev67" ;;
+	    "EV6.8CB (21264C)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8AL (21264B)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8CX (21264D)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.9A (21264/EV69A)")
+		UNAME_MACHINE="alphaev69" ;;
+	    "EV7 (21364)")
+		UNAME_MACHINE="alphaev7" ;;
+	    "EV7.9 (21364A)")
+		UNAME_MACHINE="alphaev79" ;;
+	esac
+	# A Pn.n version is a patched version.
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+	exitcode=$?
+	trap '' 0
+	exit $exitcode ;;
+    Alpha\ *:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# Should we change UNAME_MACHINE based on the output of uname instead
+	# of the specific Alpha model?
+	echo alpha-pc-interix
+	exit ;;
+    21064:Windows_NT:50:3)
+	echo alpha-dec-winnt3.5
+	exit ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-morphos
+	exit ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit ;;
+    *:z/VM:*:*)
+	echo s390-ibm-zvmoe
+	exit ;;
+    *:OS400:*:*)
+	echo powerpc-ibm-os400
+	exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit ;;
+    arm*:riscos:*:*|arm*:RISCOS:*:*)
+	echo arm-unknown-riscos
+	exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit ;;
+    DRS?6000:unix:4.0:6*)
+	echo sparc-icl-nx6
+	exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+	case `/usr/bin/uname -p` in
+	    sparc) echo sparc-icl-nx7; exit ;;
+	esac ;;
+    s390x:SunOS:*:*)
+	echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+	echo i386-pc-auroraux${UNAME_RELEASE}
+	exit ;;
+    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+	eval $set_cc_for_build
+	SUN_ARCH="i386"
+	# If there is a compiler, see if it is configured for 64-bit objects.
+	# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+	# This test works for both compilers.
+	if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+	    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+		(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+		grep IS_64BIT_ARCH >/dev/null
+	    then
+		SUN_ARCH="x86_64"
+	    fi
+	fi
+	echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+	echo m68k-milan-mint${UNAME_RELEASE}
+	exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+	echo m68k-hades-mint${UNAME_RELEASE}
+	exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+	echo m68k-unknown-mint${UNAME_RELEASE}
+	exit ;;
+    m68k:machten:*:*)
+	echo m68k-apple-machten${UNAME_RELEASE}
+	exit ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c &&
+	  dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+	  SYSTEM_NAME=`$dummy $dummyarg` &&
+	    { echo "$SYSTEM_NAME"; exit; }
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit ;;
+    Motorola:*:4.3:PL8-*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit ;;
+    AViiON:dgux:*:*)
+	# DG/UX returns AViiON for all architectures
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+	then
+	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+	    then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	    else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	    fi
+	else
+	    echo i586-dg-dgux${UNAME_RELEASE}
+	fi
+	exit ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+	exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		eval $set_cc_for_build
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+		then
+			echo "$SYSTEM_NAME"
+		else
+			echo rs6000-ibm-aix3.2.5
+		fi
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit ;;
+    *:AIX:*:[4567])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+	echo romp-ibm-bsd4.4
+	exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+		if [ -x /usr/bin/getconf ]; then
+		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+		    case "${sc_cpu_version}" in
+		      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+		      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+		      532)                      # CPU_PA_RISC2_0
+			case "${sc_kernel_bits}" in
+			  32) HP_ARCH="hppa2.0n" ;;
+			  64) HP_ARCH="hppa2.0w" ;;
+			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+			esac ;;
+		    esac
+		fi
+		if [ "${HP_ARCH}" = "" ]; then
+		    eval $set_cc_for_build
+		    sed 's/^		//' << EOF >$dummy.c
+
+		#define _HPUX_SOURCE
+		#include <stdlib.h>
+		#include <unistd.h>
+
+		int main ()
+		{
+		#if defined(_SC_KERNEL_BITS)
+		    long bits = sysconf(_SC_KERNEL_BITS);
+		#endif
+		    long cpu  = sysconf (_SC_CPU_VERSION);
+
+		    switch (cpu)
+			{
+			case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+			case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+			case CPU_PA_RISC2_0:
+		#if defined(_SC_KERNEL_BITS)
+			    switch (bits)
+				{
+				case 64: puts ("hppa2.0w"); break;
+				case 32: puts ("hppa2.0n"); break;
+				default: puts ("hppa2.0"); break;
+				} break;
+		#else  /* !defined(_SC_KERNEL_BITS) */
+			    puts ("hppa2.0"); break;
+		#endif
+			default: puts ("hppa1.0"); break;
+			}
+		    exit (0);
+		}
+EOF
+		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+		    test -z "$HP_ARCH" && HP_ARCH=hppa
+		fi ;;
+	esac
+	if [ ${HP_ARCH} = "hppa2.0w" ]
+	then
+	    eval $set_cc_for_build
+
+	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+	    # generating 64-bit code.  GNU and HP use different nomenclature:
+	    #
+	    # $ CC_FOR_BUILD=cc ./config.guess
+	    # => hppa2.0w-hp-hpux11.23
+	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+	    # => hppa64-hp-hpux11.23
+
+	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+		grep -q __LP64__
+	    then
+		HP_ARCH="hppa2.0w"
+	    else
+		HP_ARCH="hppa64"
+	    fi
+	fi
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit ;;
+    3050*:HI-UX:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+		{ echo "$SYSTEM_NAME"; exit; }
+	echo unknown-hitachi-hiuxwe2
+	exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+	exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+	exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+	exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+	exit ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    *:UNICOS/mp:*:*)
+	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    5000:UNIX_System_V:4.*:*)
+	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:FreeBSD:*:*)
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	case ${UNAME_PROCESSOR} in
+	    amd64)
+		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    *)
+		echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	esac
+	exit ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit ;;
+    *:MINGW64*:*)
+	echo ${UNAME_MACHINE}-pc-mingw64
+	exit ;;
+    *:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit ;;
+    *:MSYS*:*)
+	echo ${UNAME_MACHINE}-pc-msys
+	exit ;;
+    i*:windows32*:*)
+	# uname -m includes "-pc" on this system.
+	echo ${UNAME_MACHINE}-mingw32
+	exit ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit ;;
+    *:Interix*:*)
+	case ${UNAME_MACHINE} in
+	    x86)
+		echo i586-pc-interix${UNAME_RELEASE}
+		exit ;;
+	    authenticamd | genuineintel | EM64T)
+		echo x86_64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	    IA64)
+		echo ia64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	esac ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+	echo i${UNAME_MACHINE}-pc-mks
+	exit ;;
+    8664:Windows_NT:*)
+	echo x86_64-pc-mks
+	exit ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+	# UNAME_MACHINE based on the output of uname instead of i386?
+	echo i586-pc-interix
+	exit ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+	echo x86_64-unknown-cygwin
+	exit ;;
+    p*:CYGWIN*:*)
+	echo powerpcle-unknown-cygwin
+	exit ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    *:GNU:*:*)
+	# the GNU system
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit ;;
+    *:GNU/*:*:*)
+	# other systems with GNU libc and userland
+	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
+	exit ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit ;;
+    aarch64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    aarch64_be:Linux:*:*)
+	UNAME_MACHINE=aarch64_be
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev68 ;;
+	esac
+	objdump --private-headers /bin/sh | grep -q ld.so.1
+	if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    arc:Linux:*:* | arceb:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    arm*:Linux:*:*)
+	eval $set_cc_for_build
+	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+	    | grep -q __ARM_EABI__
+	then
+	    echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	else
+	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+		| grep -q __ARM_PCS_VFP
+	    then
+		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
+	    else
+		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
+	    fi
+	fi
+	exit ;;
+    avr32*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    cris:Linux:*:*)
+	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+	exit ;;
+    crisv32:Linux:*:*)
+	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+	exit ;;
+    frv:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    hexagon:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    i*86:Linux:*:*)
+	echo ${UNAME_MACHINE}-pc-linux-${LIBC}
+	exit ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    m32r*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    mips:Linux:*:* | mips64:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef ${UNAME_MACHINE}
+	#undef ${UNAME_MACHINE}el
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=${UNAME_MACHINE}el
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=${UNAME_MACHINE}
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
+	;;
+    openrisc*:Linux:*:*)
+	echo or1k-unknown-linux-${LIBC}
+	exit ;;
+    or32:Linux:*:* | or1k*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    padre:Linux:*:*)
+	echo sparc-unknown-linux-${LIBC}
+	exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-${LIBC}
+	exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
+	  PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
+	  *)    echo hppa-unknown-linux-${LIBC} ;;
+	esac
+	exit ;;
+    ppc64:Linux:*:*)
+	echo powerpc64-unknown-linux-${LIBC}
+	exit ;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-${LIBC}
+	exit ;;
+    ppc64le:Linux:*:*)
+	echo powerpc64le-unknown-linux-${LIBC}
+	exit ;;
+    ppcle:Linux:*:*)
+	echo powerpcle-unknown-linux-${LIBC}
+	exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
+	exit ;;
+    sh64*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    tile*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    vax:Linux:*:*)
+	echo ${UNAME_MACHINE}-dec-linux-${LIBC}
+	exit ;;
+    x86_64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    xtensa*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	echo i386-sequent-sysv4
+	exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+	# Unixware is an offshoot of SVR4, but it has its own version
+	# number series starting with 2...
+	# I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+	# Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit ;;
+    i*86:XTS-300:*:STOP)
+	echo ${UNAME_MACHINE}-unknown-stop
+	exit ;;
+    i*86:atheos:*:*)
+	echo ${UNAME_MACHINE}-unknown-atheos
+	exit ;;
+    i*86:syllable:*:*)
+	echo ${UNAME_MACHINE}-pc-syllable
+	exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+	else
+		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+	fi
+	exit ;;
+    i*86:*:5:[678]*)
+	# UnixWare 7.x, OpenUNIX and OpenServer 6.
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	exit ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+	# uname -m prints for DJGPP always 'pc', but it prints nothing about
+	# the processor, so we play safe by assuming i586.
+	# Note: whatever this is, it MUST be the same as what config.sub
+	# prints for the "djgpp" host, or else GDB configury will decide that
+	# this is a cross-build.
+	echo i586-pc-msdosdjgpp
+	exit ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+	echo m68k-convergent-sysv
+	exit ;;
+    M680?0:D-NIX:5.3:*)
+	echo m68k-diab-dnix
+	exit ;;
+    M68*:*:R3V[5678]*:*)
+	test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4; exit; } ;;
+    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+	OS_REL='.3'
+	test -r /etc/.relid \
+	    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	    && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit ;;
+    PENTIUM:*:4.0*:*)	# Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+			# says <Richard.M.Bartel@ccMail.Census.GOV>
+	echo i586-unisys-sysv4
+	exit ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes@openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit ;;
+    *:*:*:FTX*)
+	# From seanf@swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit ;;
+    i*86:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo ${UNAME_MACHINE}-stratus-vos
+	exit ;;
+    *:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo hppa1.1-stratus-vos
+	exit ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+		echo mips-nec-sysv${UNAME_RELEASE}
+	else
+		echo mips-unknown-sysv${UNAME_RELEASE}
+	fi
+	exit ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit ;;
+    BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
+	echo i586-pc-haiku
+	exit ;;
+    x86_64:Haiku:*:*)
+	echo x86_64-unknown-haiku
+	exit ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-6:SUPER-UX:*:*)
+	echo sx6-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-7:SUPER-UX:*:*)
+	echo sx7-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8:SUPER-UX:*:*)
+	echo sx8-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8R:SUPER-UX:*:*)
+	echo sx8r-nec-superux${UNAME_RELEASE}
+	exit ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Darwin:*:*)
+	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+	eval $set_cc_for_build
+	if test "$UNAME_PROCESSOR" = unknown ; then
+	    UNAME_PROCESSOR=powerpc
+	fi
+	if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
+	    if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+		if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+		    (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+		    grep IS_64BIT_ARCH >/dev/null
+		then
+		    case $UNAME_PROCESSOR in
+			i386) UNAME_PROCESSOR=x86_64 ;;
+			powerpc) UNAME_PROCESSOR=powerpc64 ;;
+		    esac
+		fi
+	    fi
+	elif test "$UNAME_PROCESSOR" = i386 ; then
+	    # Avoid executing cc on OS X 10.9, as it ships with a stub
+	    # that puts up a graphical alert prompting to install
+	    # developer tools.  Any system running Mac OS X 10.7 or
+	    # later (Darwin 11 and later) is required to have a 64-bit
+	    # processor. This is not true of the ARM version of Darwin
+	    # that Apple uses in portable devices.
+	    UNAME_PROCESSOR=x86_64
+	fi
+	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+	exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	UNAME_PROCESSOR=`uname -p`
+	if test "$UNAME_PROCESSOR" = "x86"; then
+		UNAME_PROCESSOR=i386
+		UNAME_MACHINE=pc
+	fi
+	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+	exit ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit ;;
+    NEO-?:NONSTOP_KERNEL:*:*)
+	echo neo-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSE-*:NONSTOP_KERNEL:*:*)
+	echo nse-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = "386"; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo ${UNAME_MACHINE}-unknown-plan9
+	exit ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit ;;
+    SEI:*:*:SEIUX)
+	echo mips-sei-seiux${UNAME_RELEASE}
+	exit ;;
+    *:DragonFly:*:*)
+	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit ;;
+    *:*VMS:*:*)
+	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	case "${UNAME_MACHINE}" in
+	    A*) echo alpha-dec-vms ; exit ;;
+	    I*) echo ia64-dec-vms ; exit ;;
+	    V*) echo vax-dec-vms ; exit ;;
+	esac ;;
+    *:XENIX:*:SysV)
+	echo i386-pc-xenix
+	exit ;;
+    i*86:skyos:*:*)
+	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+	exit ;;
+    i*86:rdos:*:*)
+	echo ${UNAME_MACHINE}-pc-rdos
+	exit ;;
+    i*86:AROS:*:*)
+	echo ${UNAME_MACHINE}-pc-aros
+	exit ;;
+    x86_64:VMkernel:*:*)
+	echo ${UNAME_MACHINE}-unknown-esx
+	exit ;;
+esac
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config.h b/config.h
new file mode 100755
index 0000000000000000000000000000000000000000..c232cf84a0bb73043903749c1308aa3d9dad2140
--- /dev/null
+++ b/config.h
@@ -0,0 +1,447 @@
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define if building universal (internal helper macro) */
+/* #undef AC_APPLE_UNIVERSAL_BUILD */
+
+/* Define this to 1 if you want to enable support of encrypted files in
+   libntfs and utilities. */
+/* #undef ENABLE_CRYPTO */
+
+/* Define to 1 if debug should be enabled */
+/* #undef ENABLE_DEBUG */
+
+/* Define this to 1 if you want to enable use of Windows compliant disk
+   geometry. */
+/* #undef ENABLE_HD */
+
+/* Define to 1 if the nfconv patch should be enabled */
+/* #undef ENABLE_NFCONV */
+
+/* Define this to 1 if you want to enable generation of DCE compliant UUIDs.
+   */
+/* #undef ENABLE_UUID */
+
+/* Define to 1 if using internal fuse */
+#define FUSE_INTERNAL 1
+
+/* Define to 1 if you have the `atexit' function. */
+#define HAVE_ATEXIT 1
+
+/* Define to 1 if you have the `basename' function. */
+#define HAVE_BASENAME 1
+
+/* Define to 1 if you have the <byteswap.h> header file. */
+#define HAVE_BYTESWAP_H 1
+
+/* Define to 1 if you have the `clock_gettime' function. */
+#define HAVE_CLOCK_GETTIME 1
+
+/* Define to 1 if you have the <ctype.h> header file. */
+#define HAVE_CTYPE_H 1
+
+/* Define to 1 if you have the `daemon' function. */
+#define HAVE_DAEMON 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+/* #undef HAVE_DOPRNT */
+
+/* Define to 1 if you have the `dup2' function. */
+#define HAVE_DUP2 1
+
+/* Define to 1 if you have the <endian.h> header file. */
+// #define HAVE_ENDIAN_H 1
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the `fdatasync' function. */
+#define HAVE_FDATASYNC 1
+
+/* Define to 1 if you have the <features.h> header file. */
+#define HAVE_FEATURES_H 1
+
+/* Define to 1 if you have the `ffs' function. */
+#define HAVE_FFS 1
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have the `getmntent' function. */
+#define HAVE_GETMNTENT 1
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#define HAVE_GETOPT_H 1
+
+/* Define to 1 if you have the `getopt_long' function. */
+#define HAVE_GETOPT_LONG 1
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the `hasmntopt' function. */
+// #define HAVE_HASMNTOPT 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <libgen.h> header file. */
+#define HAVE_LIBGEN_H 1
+
+/* Define to 1 if you have the <libintl.h> header file. */
+// #define HAVE_LIBINTL_H 1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <linux/fd.h> header file. */
+#define HAVE_LINUX_FD_H 1
+
+/* Define to 1 if you have the <linux/fs.h> header file. */
+#define HAVE_LINUX_FS_H 1
+
+/* Define to 1 if you have the <linux/hdreg.h> header file. */
+#define HAVE_LINUX_HDREG_H 1
+
+/* Define to 1 if you have the <linux/major.h> header file. */
+#define HAVE_LINUX_MAJOR_H 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you have the <machine/endian.h> header file. */
+/* #undef HAVE_MACHINE_ENDIAN_H */
+
+/* Define to 1 if you have the <malloc.h> header file. */
+// #define HAVE_MALLOC_H 1
+
+/* Define to 1 if mbrtowc and mbstate_t are properly declared. */
+#define HAVE_MBRTOWC 1
+
+/* Define to 1 if you have the `mbsinit' function. */
+#define HAVE_MBSINIT 1
+
+/* Define to 1 if you have the `memcpy' function. */
+#define HAVE_MEMCPY 1
+
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the <mntent.h> header file. */
+#define HAVE_MNTENT_H 1
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define to 1 if you have the `random' function. */
+#define HAVE_RANDOM 1
+
+/* Define to 1 if you have the `realpath' function. */
+#define HAVE_REALPATH 1
+
+/* Define to 1 if you have the `regcomp' function. */
+#define HAVE_REGCOMP 1
+
+/* Define to 1 if you have the <regex.h> header file. */
+#define HAVE_REGEX_H 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the `setxattr' function. */
+#define HAVE_SETXATTR 1
+
+/* Define to 1 if you have the `snprintf' function. */
+#define HAVE_SNPRINTF 1
+
+/* Define to 1 if `stat' has the bug that it succeeds when given the
+   zero-length file name argument. */
+/* #undef HAVE_STAT_EMPTY_STRING_BUG */
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#define HAVE_STDIO_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strchr' function. */
+#define HAVE_STRCHR 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the `strftime' function. */
+#define HAVE_STRFTIME 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strnlen' function. */
+#define HAVE_STRNLEN 1
+
+/* Define to 1 if you have the `strsep' function. */
+#define HAVE_STRSEP 1
+
+/* Define to 1 if you have the `strtol' function. */
+#define HAVE_STRTOL 1
+
+/* Define to 1 if you have the `strtoul' function. */
+#define HAVE_STRTOUL 1
+
+/* Define to 1 if `st_atim' is a member of `struct stat'. */
+// #define HAVE_STRUCT_STAT_ST_ATIM 1
+
+/* Define to 1 if `st_atimensec' is a member of `struct stat'. */
+/* #undef HAVE_STRUCT_STAT_ST_ATIMENSEC */
+
+/* Define to 1 if `st_atimespec' is a member of `struct stat'. */
+/* #undef HAVE_STRUCT_STAT_ST_ATIMESPEC */
+
+/* Define to 1 if `st_blocks' is a member of `struct stat'. */
+#define HAVE_STRUCT_STAT_ST_BLOCKS 1
+
+/* Define to 1 if `st_rdev' is a member of `struct stat'. */
+#define HAVE_STRUCT_STAT_ST_RDEV 1
+
+/* Define to 1 if your `struct stat' has `st_blocks'. Deprecated, use
+   `HAVE_STRUCT_STAT_ST_BLOCKS' instead. */
+#define HAVE_ST_BLOCKS 1
+
+/* Define to 1 if you have the `sysconf' function. */
+#define HAVE_SYSCONF 1
+
+/* Define to 1 if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define to 1 if you have the <sys/byteorder.h> header file. */
+/* #undef HAVE_SYS_BYTEORDER_H */
+
+/* Define to 1 if you have the <sys/disk.h> header file. */
+/* #undef HAVE_SYS_DISK_H */
+
+/* Define to 1 if you have the <sys/endian.h> header file. */
+/* #undef HAVE_SYS_ENDIAN_H */
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/mkdev.h> header file. */
+/* #undef HAVE_SYS_MKDEV_H */
+
+/* Define to 1 if you have the <sys/mount.h> header file. */
+#define HAVE_SYS_MOUNT_H 1
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/statvfs.h> header file. */
+#define HAVE_SYS_STATVFS_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/sysmacros.h> header file. */
+#define HAVE_SYS_SYSMACROS_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/vfs.h> header file. */
+#define HAVE_SYS_VFS_H 1
+
+/* Define to 1 if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `utime' function. */
+#define HAVE_UTIME 1
+
+/* Define to 1 if you have the `utimensat' function. */
+// #define HAVE_UTIMENSAT 1
+
+/* Define to 1 if you have the <utime.h> header file. */
+#define HAVE_UTIME_H 1
+
+/* Define to 1 if `utime(file, NULL)' sets file's timestamp to the present. */
+#define HAVE_UTIME_NULL 1
+
+/* Define to 1 if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+
+/* Define to 1 if you have the <wchar.h> header file. */
+#define HAVE_WCHAR_H 1
+
+/* Define to 1 if you have the <windows.h> header file. */
+/* #undef HAVE_WINDOWS_H */
+
+/* Define to 1 if the system has the type `_Bool'. */
+#define HAVE__BOOL 1
+
+/* Don't update /etc/mtab */
+/* #undef IGNORE_MTAB */
+
+/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
+   slash. */
+#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#define LT_OBJDIR ".libs/"
+
+/* Don't use default IO ops */
+/* #undef NO_NTFS_DEVICE_DEFAULT_IO_OPS */
+
+/* Name of package */
+#define PACKAGE "ntfs-3g"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "ntfs-3g"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "ntfs-3g 2015.3.14"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "ntfs-3g"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "2015.3.14"
+
+/* POSIX ACL support */
+/* #undef POSIXACLS */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Enable extensions on AIX 3, Interix.  */
+#ifndef _ALL_SOURCE
+# define _ALL_SOURCE 1
+#endif
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+/* Enable threading extensions on Solaris.  */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# define _POSIX_PTHREAD_SEMANTICS 1
+#endif
+/* Enable extensions on HP NonStop.  */
+#ifndef _TANDEM_SOURCE
+# define _TANDEM_SOURCE 1
+#endif
+/* Enable general extensions on Solaris.  */
+#ifndef __EXTENSIONS__
+# define __EXTENSIONS__ 1
+#endif
+
+
+/* Version number of package */
+#define VERSION "2015.3.14"
+
+/* Define to 1 if this is a Windows OS */
+/* #undef WINDOWS */
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+   significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+#  define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+/* #  undef WORDS_BIGENDIAN */
+# endif
+#endif
+
+/* Define to 1 if your processor stores words with the least significant byte
+   first (like Intel and VAX, unlike Motorola and SPARC). */
+#define WORDS_LITTLEENDIAN 1
+
+/* system extended attributes mappings */
+/* #undef XATTR_MAPPINGS */
+
+/* Enable large inode numbers on Mac OS X 10.5.  */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Required define if using POSIX threads */
+#define _REENTRANT 1
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to `long int' if <sys/types.h> does not define. */
+/* #undef off_t */
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+#define S_IREAD        S_IRUSR
+#define S_IWRITE       S_IWUSR
+#define S_IEXEC        S_IXUSR
+
+#include <sys/types.h>
+#define off_t long long
diff --git a/config.h.in b/config.h.in
new file mode 100755
index 0000000000000000000000000000000000000000..80027db44659fb0c3bb8c4229960eef3b703cd41
--- /dev/null
+++ b/config.h.in
@@ -0,0 +1,439 @@
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define if building universal (internal helper macro) */
+#undef AC_APPLE_UNIVERSAL_BUILD
+
+/* Define this to 1 if you want to enable support of encrypted files in
+   libntfs and utilities. */
+#undef ENABLE_CRYPTO
+
+/* Define to 1 if debug should be enabled */
+#undef ENABLE_DEBUG
+
+/* Define this to 1 if you want to enable use of Windows compliant disk
+   geometry. */
+#undef ENABLE_HD
+
+/* Define to 1 if the nfconv patch should be enabled */
+#undef ENABLE_NFCONV
+
+/* Define this to 1 if you want to enable generation of DCE compliant UUIDs.
+   */
+#undef ENABLE_UUID
+
+/* Define to 1 if using internal fuse */
+#undef FUSE_INTERNAL
+
+/* Define to 1 if you have the `atexit' function. */
+#undef HAVE_ATEXIT
+
+/* Define to 1 if you have the `basename' function. */
+#undef HAVE_BASENAME
+
+/* Define to 1 if you have the <byteswap.h> header file. */
+#undef HAVE_BYTESWAP_H
+
+/* Define to 1 if you have the `clock_gettime' function. */
+#undef HAVE_CLOCK_GETTIME
+
+/* Define to 1 if you have the <ctype.h> header file. */
+#undef HAVE_CTYPE_H
+
+/* Define to 1 if you have the `daemon' function. */
+#undef HAVE_DAEMON
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+#undef HAVE_DOPRNT
+
+/* Define to 1 if you have the `dup2' function. */
+#undef HAVE_DUP2
+
+/* Define to 1 if you have the <endian.h> header file. */
+#undef HAVE_ENDIAN_H
+
+/* Define to 1 if you have the <errno.h> header file. */
+#undef HAVE_ERRNO_H
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the `fdatasync' function. */
+#undef HAVE_FDATASYNC
+
+/* Define to 1 if you have the <features.h> header file. */
+#undef HAVE_FEATURES_H
+
+/* Define to 1 if you have the `ffs' function. */
+#undef HAVE_FFS
+
+/* Define to 1 if you have the `fork' function. */
+#undef HAVE_FORK
+
+/* Define to 1 if you have the `getmntent' function. */
+#undef HAVE_GETMNTENT
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#undef HAVE_GETOPT_H
+
+/* Define to 1 if you have the `getopt_long' function. */
+#undef HAVE_GETOPT_LONG
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define to 1 if you have the `hasmntopt' function. */
+#undef HAVE_HASMNTOPT
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <libgen.h> header file. */
+#undef HAVE_LIBGEN_H
+
+/* Define to 1 if you have the <libintl.h> header file. */
+#undef HAVE_LIBINTL_H
+
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define to 1 if you have the <linux/fd.h> header file. */
+#undef HAVE_LINUX_FD_H
+
+/* Define to 1 if you have the <linux/fs.h> header file. */
+#undef HAVE_LINUX_FS_H
+
+/* Define to 1 if you have the <linux/hdreg.h> header file. */
+#undef HAVE_LINUX_HDREG_H
+
+/* Define to 1 if you have the <linux/major.h> header file. */
+#undef HAVE_LINUX_MAJOR_H
+
+/* Define to 1 if you have the <locale.h> header file. */
+#undef HAVE_LOCALE_H
+
+/* Define to 1 if you have the <machine/endian.h> header file. */
+#undef HAVE_MACHINE_ENDIAN_H
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
+/* Define to 1 if mbrtowc and mbstate_t are properly declared. */
+#undef HAVE_MBRTOWC
+
+/* Define to 1 if you have the `mbsinit' function. */
+#undef HAVE_MBSINIT
+
+/* Define to 1 if you have the `memcpy' function. */
+#undef HAVE_MEMCPY
+
+/* Define to 1 if you have the `memmove' function. */
+#undef HAVE_MEMMOVE
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `memset' function. */
+#undef HAVE_MEMSET
+
+/* Define to 1 if you have the <mntent.h> header file. */
+#undef HAVE_MNTENT_H
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#undef HAVE_PWD_H
+
+/* Define to 1 if you have the `random' function. */
+#undef HAVE_RANDOM
+
+/* Define to 1 if you have the `realpath' function. */
+#undef HAVE_REALPATH
+
+/* Define to 1 if you have the `regcomp' function. */
+#undef HAVE_REGCOMP
+
+/* Define to 1 if you have the <regex.h> header file. */
+#undef HAVE_REGEX_H
+
+/* Define to 1 if you have the `setlocale' function. */
+#undef HAVE_SETLOCALE
+
+/* Define to 1 if you have the `setxattr' function. */
+#undef HAVE_SETXATTR
+
+/* Define to 1 if you have the `snprintf' function. */
+#undef HAVE_SNPRINTF
+
+/* Define to 1 if `stat' has the bug that it succeeds when given the
+   zero-length file name argument. */
+#undef HAVE_STAT_EMPTY_STRING_BUG
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#undef HAVE_STDARG_H
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#undef HAVE_STDBOOL_H
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#undef HAVE_STDDEF_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#undef HAVE_STRCASECMP
+
+/* Define to 1 if you have the `strchr' function. */
+#undef HAVE_STRCHR
+
+/* Define to 1 if you have the `strdup' function. */
+#undef HAVE_STRDUP
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the `strftime' function. */
+#undef HAVE_STRFTIME
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strnlen' function. */
+#undef HAVE_STRNLEN
+
+/* Define to 1 if you have the `strsep' function. */
+#undef HAVE_STRSEP
+
+/* Define to 1 if you have the `strtol' function. */
+#undef HAVE_STRTOL
+
+/* Define to 1 if you have the `strtoul' function. */
+#undef HAVE_STRTOUL
+
+/* Define to 1 if `st_atim' is a member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_ATIM
+
+/* Define to 1 if `st_atimensec' is a member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_ATIMENSEC
+
+/* Define to 1 if `st_atimespec' is a member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_ATIMESPEC
+
+/* Define to 1 if `st_blocks' is a member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_BLOCKS
+
+/* Define to 1 if `st_rdev' is a member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_RDEV
+
+/* Define to 1 if your `struct stat' has `st_blocks'. Deprecated, use
+   `HAVE_STRUCT_STAT_ST_BLOCKS' instead. */
+#undef HAVE_ST_BLOCKS
+
+/* Define to 1 if you have the `sysconf' function. */
+#undef HAVE_SYSCONF
+
+/* Define to 1 if you have the <syslog.h> header file. */
+#undef HAVE_SYSLOG_H
+
+/* Define to 1 if you have the <sys/byteorder.h> header file. */
+#undef HAVE_SYS_BYTEORDER_H
+
+/* Define to 1 if you have the <sys/disk.h> header file. */
+#undef HAVE_SYS_DISK_H
+
+/* Define to 1 if you have the <sys/endian.h> header file. */
+#undef HAVE_SYS_ENDIAN_H
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H
+
+/* Define to 1 if you have the <sys/mkdev.h> header file. */
+#undef HAVE_SYS_MKDEV_H
+
+/* Define to 1 if you have the <sys/mount.h> header file. */
+#undef HAVE_SYS_MOUNT_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/statvfs.h> header file. */
+#undef HAVE_SYS_STATVFS_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/sysmacros.h> header file. */
+#undef HAVE_SYS_SYSMACROS_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <sys/vfs.h> header file. */
+#undef HAVE_SYS_VFS_H
+
+/* Define to 1 if you have the <time.h> header file. */
+#undef HAVE_TIME_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `utime' function. */
+#undef HAVE_UTIME
+
+/* Define to 1 if you have the `utimensat' function. */
+#undef HAVE_UTIMENSAT
+
+/* Define to 1 if you have the <utime.h> header file. */
+#undef HAVE_UTIME_H
+
+/* Define to 1 if `utime(file, NULL)' sets file's timestamp to the present. */
+#undef HAVE_UTIME_NULL
+
+/* Define to 1 if you have the `vprintf' function. */
+#undef HAVE_VPRINTF
+
+/* Define to 1 if you have the <wchar.h> header file. */
+#undef HAVE_WCHAR_H
+
+/* Define to 1 if you have the <windows.h> header file. */
+#undef HAVE_WINDOWS_H
+
+/* Define to 1 if the system has the type `_Bool'. */
+#undef HAVE__BOOL
+
+/* Don't update /etc/mtab */
+#undef IGNORE_MTAB
+
+/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
+   slash. */
+#undef LSTAT_FOLLOWS_SLASHED_SYMLINK
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#undef LT_OBJDIR
+
+/* Don't use default IO ops */
+#undef NO_NTFS_DEVICE_DEFAULT_IO_OPS
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* POSIX ACL support */
+#undef POSIXACLS
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Enable extensions on AIX 3, Interix.  */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+/* Enable threading extensions on Solaris.  */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif
+/* Enable extensions on HP NonStop.  */
+#ifndef _TANDEM_SOURCE
+# undef _TANDEM_SOURCE
+#endif
+/* Enable general extensions on Solaris.  */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
+
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to 1 if this is a Windows OS */
+#undef WINDOWS
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+   significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+#  define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+#  undef WORDS_BIGENDIAN
+# endif
+#endif
+
+/* Define to 1 if your processor stores words with the least significant byte
+   first (like Intel and VAX, unlike Motorola and SPARC). */
+#undef WORDS_LITTLEENDIAN
+
+/* system extended attributes mappings */
+#undef XATTR_MAPPINGS
+
+/* Enable large inode numbers on Mac OS X 10.5.  */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define to 1 if on MINIX. */
+#undef _MINIX
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+#undef _POSIX_1_SOURCE
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+#undef _POSIX_SOURCE
+
+/* Required define if using POSIX threads */
+#undef _REENTRANT
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to `long int' if <sys/types.h> does not define. */
+#undef off_t
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
diff --git a/config.log b/config.log
new file mode 100755
index 0000000000000000000000000000000000000000..56e061c4652c68f2a09a6a861cf548c9a3d53e6f
--- /dev/null
+++ b/config.log
@@ -0,0 +1,4275 @@
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by ntfs-3g configure 2015.3.14, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  $ ./configure 
+
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = cmc-HP-Compaq-Pro-6380-MT
+uname -m = x86_64
+uname -r = 3.13.11.11
+uname -s = Linux
+uname -v = #1 SMP Fri Dec 19 15:56:19 CST 2014
+
+/usr/bin/uname -p = unknown
+/bin/uname -X     = unknown
+
+/bin/arch              = unknown
+/usr/bin/arch -k       = unknown
+/usr/convex/getsysinfo = unknown
+/usr/bin/hostinfo      = unknown
+/bin/machine           = unknown
+/usr/bin/oslevel       = unknown
+/bin/universe          = unknown
+
+PATH: /opt/qemu/bin
+PATH: /home/cmc/share/chromium/depot_tools
+PATH: /home/cmc/opt/linux-upgrade-tool
+PATH: /home/cmc/opt/android-sdk-linux/platform-tools
+PATH: /home/cmc/opt/android-sdk-linux/tools
+PATH: /home/cmc/bin
+PATH: /usr/local/sbin
+PATH: /usr/local/bin
+PATH: /usr/sbin
+PATH: /usr/bin
+PATH: /sbin
+PATH: /bin
+PATH: /usr/games
+PATH: /usr/local/games
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+configure:2502: checking build system type
+configure:2516: result: x86_64-unknown-linux-gnu
+configure:2536: checking host system type
+configure:2549: result: x86_64-unknown-linux-gnu
+configure:2569: checking target system type
+configure:2582: result: x86_64-unknown-linux-gnu
+configure:2626: checking for a BSD-compatible install
+configure:2694: result: /usr/bin/install -c
+configure:2705: checking whether build environment is sane
+configure:2760: result: yes
+configure:2911: checking for a thread-safe mkdir -p
+configure:2950: result: /bin/mkdir -p
+configure:2957: checking for gawk
+configure:2973: found /usr/bin/gawk
+configure:2984: result: gawk
+configure:2995: checking whether make sets $(MAKE)
+configure:3017: result: yes
+configure:3046: checking whether make supports nested variables
+configure:3063: result: yes
+configure:3193: checking whether to enable maintainer-specific portions of Makefiles
+configure:3202: result: no
+configure:3402: checking for style of include used by make
+configure:3430: result: GNU
+configure:3501: checking for gcc
+configure:3517: found /usr/bin/gcc
+configure:3528: result: gcc
+configure:3757: checking for C compiler version
+configure:3766: gcc --version >&5
+gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
+Copyright (C) 2013 Free Software Foundation, Inc.
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+configure:3777: $? = 0
+configure:3766: gcc -v >&5
+Using built-in specs.
+COLLECT_GCC=gcc
+COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.2-19ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
+Thread model: posix
+gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) 
+configure:3777: $? = 0
+configure:3766: gcc -V >&5
+gcc: error: unrecognized command line option '-V'
+gcc: fatal error: no input files
+compilation terminated.
+configure:3777: $? = 4
+configure:3766: gcc -qversion >&5
+gcc: error: unrecognized command line option '-qversion'
+gcc: fatal error: no input files
+compilation terminated.
+configure:3777: $? = 4
+configure:3797: checking whether the C compiler works
+configure:3819: gcc    conftest.c  >&5
+configure:3823: $? = 0
+configure:3871: result: yes
+configure:3874: checking for C compiler default output file name
+configure:3876: result: a.out
+configure:3882: checking for suffix of executables
+configure:3889: gcc -o conftest    conftest.c  >&5
+configure:3893: $? = 0
+configure:3915: result: 
+configure:3937: checking whether we are cross compiling
+configure:3945: gcc -o conftest    conftest.c  >&5
+configure:3949: $? = 0
+configure:3956: ./conftest
+configure:3960: $? = 0
+configure:3975: result: no
+configure:3980: checking for suffix of object files
+configure:4002: gcc -c   conftest.c >&5
+configure:4006: $? = 0
+configure:4027: result: o
+configure:4031: checking whether we are using the GNU C compiler
+configure:4050: gcc -c   conftest.c >&5
+configure:4050: $? = 0
+configure:4059: result: yes
+configure:4068: checking whether gcc accepts -g
+configure:4088: gcc -c -g  conftest.c >&5
+configure:4088: $? = 0
+configure:4129: result: yes
+configure:4146: checking for gcc option to accept ISO C89
+configure:4209: gcc  -c -g -O2  conftest.c >&5
+configure:4209: $? = 0
+configure:4222: result: none needed
+configure:4247: checking whether gcc understands -c and -o together
+configure:4269: gcc -c conftest.c -o conftest2.o
+configure:4272: $? = 0
+configure:4269: gcc -c conftest.c -o conftest2.o
+configure:4272: $? = 0
+configure:4284: result: yes
+configure:4303: checking dependency style of gcc
+configure:4414: result: gcc3
+configure:4435: checking how to run the C preprocessor
+configure:4466: gcc -E  conftest.c
+configure:4466: $? = 0
+configure:4480: gcc -E  conftest.c
+conftest.c:11:28: fatal error: ac_nonexistent.h: No such file or directory
+ #include <ac_nonexistent.h>
+                            ^
+compilation terminated.
+configure:4480: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| /* end confdefs.h.  */
+| #include <ac_nonexistent.h>
+configure:4505: result: gcc -E
+configure:4525: gcc -E  conftest.c
+configure:4525: $? = 0
+configure:4539: gcc -E  conftest.c
+conftest.c:11:28: fatal error: ac_nonexistent.h: No such file or directory
+ #include <ac_nonexistent.h>
+                            ^
+compilation terminated.
+configure:4539: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| /* end confdefs.h.  */
+| #include <ac_nonexistent.h>
+configure:4568: checking for grep that handles long lines and -e
+configure:4626: result: /bin/grep
+configure:4631: checking for egrep
+configure:4693: result: /bin/grep -E
+configure:4698: checking for ANSI C header files
+configure:4718: gcc -c -g -O2  conftest.c >&5
+configure:4718: $? = 0
+configure:4791: gcc -o conftest -g -O2   conftest.c  >&5
+configure:4791: $? = 0
+configure:4791: ./conftest
+configure:4791: $? = 0
+configure:4802: result: yes
+configure:4815: checking for sys/types.h
+configure:4815: gcc -c -g -O2  conftest.c >&5
+configure:4815: $? = 0
+configure:4815: result: yes
+configure:4815: checking for sys/stat.h
+configure:4815: gcc -c -g -O2  conftest.c >&5
+configure:4815: $? = 0
+configure:4815: result: yes
+configure:4815: checking for stdlib.h
+configure:4815: gcc -c -g -O2  conftest.c >&5
+configure:4815: $? = 0
+configure:4815: result: yes
+configure:4815: checking for string.h
+configure:4815: gcc -c -g -O2  conftest.c >&5
+configure:4815: $? = 0
+configure:4815: result: yes
+configure:4815: checking for memory.h
+configure:4815: gcc -c -g -O2  conftest.c >&5
+configure:4815: $? = 0
+configure:4815: result: yes
+configure:4815: checking for strings.h
+configure:4815: gcc -c -g -O2  conftest.c >&5
+configure:4815: $? = 0
+configure:4815: result: yes
+configure:4815: checking for inttypes.h
+configure:4815: gcc -c -g -O2  conftest.c >&5
+configure:4815: $? = 0
+configure:4815: result: yes
+configure:4815: checking for stdint.h
+configure:4815: gcc -c -g -O2  conftest.c >&5
+configure:4815: $? = 0
+configure:4815: result: yes
+configure:4815: checking for unistd.h
+configure:4815: gcc -c -g -O2  conftest.c >&5
+configure:4815: $? = 0
+configure:4815: result: yes
+configure:4828: checking minix/config.h usability
+configure:4828: gcc -c -g -O2  conftest.c >&5
+conftest.c:54:26: fatal error: minix/config.h: No such file or directory
+ #include <minix/config.h>
+                          ^
+compilation terminated.
+configure:4828: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <minix/config.h>
+configure:4828: result: no
+configure:4828: checking minix/config.h presence
+configure:4828: gcc -E  conftest.c
+conftest.c:21:26: fatal error: minix/config.h: No such file or directory
+ #include <minix/config.h>
+                          ^
+compilation terminated.
+configure:4828: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| /* end confdefs.h.  */
+| #include <minix/config.h>
+configure:4828: result: no
+configure:4828: checking for minix/config.h
+configure:4828: result: no
+configure:4849: checking whether it is safe to define __EXTENSIONS__
+configure:4867: gcc -c -g -O2  conftest.c >&5
+configure:4867: $? = 0
+configure:4874: result: yes
+configure:5003: checking for C compiler version
+configure:5012: gcc --version >&5
+gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
+Copyright (C) 2013 Free Software Foundation, Inc.
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+configure:5023: $? = 0
+configure:5012: gcc -v >&5
+Using built-in specs.
+COLLECT_GCC=gcc
+COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.2-19ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
+Thread model: posix
+gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) 
+configure:5023: $? = 0
+configure:5012: gcc -V >&5
+gcc: error: unrecognized command line option '-V'
+gcc: fatal error: no input files
+compilation terminated.
+configure:5023: $? = 4
+configure:5012: gcc -qversion >&5
+gcc: error: unrecognized command line option '-qversion'
+gcc: fatal error: no input files
+compilation terminated.
+configure:5023: $? = 4
+configure:5027: checking whether we are using the GNU C compiler
+configure:5055: result: yes
+configure:5064: checking whether gcc accepts -g
+configure:5125: result: yes
+configure:5142: checking for gcc option to accept ISO C89
+configure:5218: result: none needed
+configure:5243: checking whether gcc understands -c and -o together
+configure:5280: result: yes
+configure:5299: checking dependency style of gcc
+configure:5410: result: gcc3
+configure:5425: checking whether ln -s works
+configure:5429: result: yes
+configure:5484: checking how to print strings
+configure:5511: result: printf
+configure:5532: checking for a sed that does not truncate output
+configure:5596: result: /bin/sed
+configure:5614: checking for fgrep
+configure:5676: result: /bin/grep -F
+configure:5711: checking for ld used by gcc
+configure:5778: result: /usr/bin/ld
+configure:5785: checking if the linker (/usr/bin/ld) is GNU ld
+configure:5800: result: yes
+configure:5812: checking for BSD- or MS-compatible name lister (nm)
+configure:5861: result: /usr/bin/nm -B
+configure:5991: checking the name lister (/usr/bin/nm -B) interface
+configure:5998: gcc -c -g -O2  conftest.c >&5
+configure:6001: /usr/bin/nm -B "conftest.o"
+configure:6004: output
+0000000000000000 B some_variable
+configure:6011: result: BSD nm
+configure:6015: checking the maximum length of command line arguments
+configure:6145: result: 1572864
+configure:6162: checking whether the shell understands some XSI constructs
+configure:6172: result: yes
+configure:6176: checking whether the shell understands "+="
+configure:6182: result: yes
+configure:6217: checking how to convert x86_64-unknown-linux-gnu file names to x86_64-unknown-linux-gnu format
+configure:6257: result: func_convert_file_noop
+configure:6264: checking how to convert x86_64-unknown-linux-gnu file names to toolchain format
+configure:6284: result: func_convert_file_noop
+configure:6291: checking for /usr/bin/ld option to reload object files
+configure:6298: result: -r
+configure:6372: checking for objdump
+configure:6388: found /usr/bin/objdump
+configure:6399: result: objdump
+configure:6431: checking how to recognize dependent libraries
+configure:6633: result: pass_all
+configure:6718: checking for dlltool
+configure:6748: result: no
+configure:6778: checking how to associate runtime and link libraries
+configure:6805: result: printf %s\n
+configure:6865: checking for ar
+configure:6881: found /usr/bin/ar
+configure:6892: result: ar
+configure:6929: checking for archiver @FILE support
+configure:6946: gcc -c -g -O2  conftest.c >&5
+configure:6946: $? = 0
+configure:6949: ar cru libconftest.a @conftest.lst >&5
+configure:6952: $? = 0
+configure:6957: ar cru libconftest.a @conftest.lst >&5
+ar: conftest.o: No such file or directory
+configure:6960: $? = 1
+configure:6972: result: @
+configure:7030: checking for strip
+configure:7046: found /usr/bin/strip
+configure:7057: result: strip
+configure:7129: checking for ranlib
+configure:7145: found /usr/bin/ranlib
+configure:7156: result: ranlib
+configure:7258: checking command to parse /usr/bin/nm -B output from gcc object
+configure:7378: gcc -c -g -O2  conftest.c >&5
+configure:7381: $? = 0
+configure:7385: /usr/bin/nm -B conftest.o \| sed -n -e 's/^.*[ ]\([ABCDGIRSTW][ABCDGIRSTW]*\)[ ][ ]*\([_A-Za-z][_A-Za-z0-9]*\)$/\1 \2 \2/p' | sed '/ __gnu_lto/d' \> conftest.nm
+configure:7388: $? = 0
+configure:7454: gcc -o conftest -g -O2   conftest.c conftstm.o >&5
+configure:7457: $? = 0
+configure:7495: result: ok
+configure:7532: checking for sysroot
+configure:7562: result: no
+configure:7639: gcc -c -g -O2  conftest.c >&5
+configure:7642: $? = 0
+configure:7824: checking for mt
+configure:7840: found /bin/mt
+configure:7851: result: mt
+configure:7874: checking if mt is a manifest tool
+configure:7880: mt '-?'
+configure:7888: result: no
+configure:8527: checking for dlfcn.h
+configure:8527: gcc -c -g -O2  conftest.c >&5
+configure:8527: $? = 0
+configure:8527: result: yes
+configure:8733: checking for objdir
+configure:8748: result: .libs
+configure:9019: checking if gcc supports -fno-rtti -fno-exceptions
+configure:9037: gcc -c -g -O2  -fno-rtti -fno-exceptions conftest.c >&5
+cc1: warning: command line option '-fno-rtti' is valid for C++/ObjC++ but not for C [enabled by default]
+configure:9041: $? = 0
+configure:9054: result: no
+configure:9381: checking for gcc option to produce PIC
+configure:9388: result: -fPIC -DPIC
+configure:9396: checking if gcc PIC flag -fPIC -DPIC works
+configure:9414: gcc -c -g -O2  -fPIC -DPIC -DPIC conftest.c >&5
+configure:9418: $? = 0
+configure:9431: result: yes
+configure:9460: checking if gcc static flag -static works
+configure:9488: result: yes
+configure:9503: checking if gcc supports -c -o file.o
+configure:9524: gcc -c -g -O2  -o out/conftest2.o conftest.c >&5
+configure:9528: $? = 0
+configure:9550: result: yes
+configure:9558: checking if gcc supports -c -o file.o
+configure:9605: result: yes
+configure:9638: checking whether the gcc linker (/usr/bin/ld -m elf_x86_64) supports shared libraries
+configure:10791: result: yes
+configure:10828: checking whether -lc should be explicitly linked in
+configure:10836: gcc -c -g -O2  conftest.c >&5
+configure:10839: $? = 0
+configure:10854: gcc -shared  -fPIC -DPIC conftest.o  -v -Wl,-soname -Wl,conftest -o conftest 2\>\&1 \| /bin/grep  -lc  \>/dev/null 2\>\&1
+configure:10857: $? = 0
+configure:10871: result: no
+configure:11031: checking dynamic linker characteristics
+configure:11542: gcc -o conftest -g -O2   -Wl,-rpath -Wl,/foo conftest.c  >&5
+configure:11542: $? = 0
+configure:11768: result: GNU/Linux ld.so
+configure:11875: checking how to hardcode library paths into programs
+configure:11900: result: immediate
+configure:12440: checking whether stripping libraries is possible
+configure:12445: result: yes
+configure:12480: checking if libtool supports shared libraries
+configure:12482: result: yes
+configure:12485: checking whether to build shared libraries
+configure:12506: result: yes
+configure:12509: checking whether to build static libraries
+configure:12513: result: yes
+configure:12606: checking for pkg-config
+configure:12624: found /usr/bin/pkg-config
+configure:12636: result: /usr/bin/pkg-config
+configure:12661: checking pkg-config is at least version 0.9.0
+configure:12664: result: yes
+configure:12675: checking for mv
+configure:12693: found /bin/mv
+configure:12705: result: /bin/mv
+configure:12715: checking for rm
+configure:12733: found /bin/rm
+configure:12745: result: /bin/rm
+configure:12755: checking for sed
+configure:12785: result: /bin/sed
+configure:12796: checking for ldconfig
+configure:12814: found /sbin/ldconfig
+configure:12827: result: /sbin/ldconfig
+configure:12837: checking Windows OS
+configure:12849: result: no
+configure:12856: checking fuse compatibility
+configure:12880: result: internal
+configure:12910: checking for pthread_create in -lpthread
+configure:12935: gcc -o conftest -g -O2   conftest.c -lpthread   >&5
+configure:12935: $? = 0
+configure:12944: result: yes
+configure:12961: checking Solaris OS
+configure:12978: gcc -c -g -O2  conftest.c >&5
+conftest.c:32:6: error: #error "Not a Solaris system."
+     #error "Not a Solaris system."
+      ^
+configure:12978: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| /* end confdefs.h.  */
+| 
+| 			#if !((defined(sun) || defined(__sun)) && (defined(__SVR4) || defined(__svr4__)))
+| 				#error "Not a Solaris system."
+| 				#endif
+| 
+| 
+configure:12987: result: no
+configure:13488: checking uuid/uuid.h usability
+configure:13488: gcc -c -g -O2  conftest.c >&5
+conftest.c:63:23: fatal error: uuid/uuid.h: No such file or directory
+ #include <uuid/uuid.h>
+                       ^
+compilation terminated.
+configure:13488: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <uuid/uuid.h>
+configure:13488: result: no
+configure:13488: checking uuid/uuid.h presence
+configure:13488: gcc -E  conftest.c
+conftest.c:30:23: fatal error: uuid/uuid.h: No such file or directory
+ #include <uuid/uuid.h>
+                       ^
+compilation terminated.
+configure:13488: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| /* end confdefs.h.  */
+| #include <uuid/uuid.h>
+configure:13488: result: no
+configure:13488: checking for uuid/uuid.h
+configure:13488: result: no
+configure:13493: WARNING: ntfsprogs DCE compliant UUID generation code requires the uuid library.
+configure:13598: checking hd.h usability
+configure:13598: gcc -c -g -O2  conftest.c >&5
+conftest.c:63:16: fatal error: hd.h: No such file or directory
+ #include <hd.h>
+                ^
+compilation terminated.
+configure:13598: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <hd.h>
+configure:13598: result: no
+configure:13598: checking hd.h presence
+configure:13598: gcc -E  conftest.c
+conftest.c:30:16: fatal error: hd.h: No such file or directory
+ #include <hd.h>
+                ^
+compilation terminated.
+configure:13598: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| /* end confdefs.h.  */
+| #include <hd.h>
+configure:13598: result: no
+configure:13598: checking for hd.h
+configure:13598: result: no
+configure:13648: WARNING: ntfsprogs Windows compliant geometry code requires the hd library.
+configure:13656: checking for ANSI C header files
+configure:13760: result: yes
+configure:13778: checking ctype.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking ctype.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for ctype.h
+configure:13778: result: yes
+configure:13778: checking fcntl.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking fcntl.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for fcntl.h
+configure:13778: result: yes
+configure:13778: checking libgen.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking libgen.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for libgen.h
+configure:13778: result: yes
+configure:13778: checking libintl.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking libintl.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for libintl.h
+configure:13778: result: yes
+configure:13778: checking limits.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking limits.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for limits.h
+configure:13778: result: yes
+configure:13778: checking locale.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking locale.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for locale.h
+configure:13778: result: yes
+configure:13778: checking mntent.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking mntent.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for mntent.h
+configure:13778: result: yes
+configure:13778: checking stddef.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking stddef.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for stddef.h
+configure:13778: result: yes
+configure:13778: checking for stdint.h
+configure:13778: result: yes
+configure:13778: checking for stdlib.h
+configure:13778: result: yes
+configure:13778: checking stdio.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking stdio.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for stdio.h
+configure:13778: result: yes
+configure:13778: checking stdarg.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking stdarg.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for stdarg.h
+configure:13778: result: yes
+configure:13778: checking for string.h
+configure:13778: result: yes
+configure:13778: checking for strings.h
+configure:13778: result: yes
+configure:13778: checking errno.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking errno.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for errno.h
+configure:13778: result: yes
+configure:13778: checking time.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking time.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for time.h
+configure:13778: result: yes
+configure:13778: checking for unistd.h
+configure:13778: result: yes
+configure:13778: checking utime.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking utime.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for utime.h
+configure:13778: result: yes
+configure:13778: checking wchar.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking wchar.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for wchar.h
+configure:13778: result: yes
+configure:13778: checking getopt.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking getopt.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for getopt.h
+configure:13778: result: yes
+configure:13778: checking features.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking features.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for features.h
+configure:13778: result: yes
+configure:13778: checking regex.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking regex.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for regex.h
+configure:13778: result: yes
+configure:13778: checking endian.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking endian.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for endian.h
+configure:13778: result: yes
+configure:13778: checking byteswap.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking byteswap.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for byteswap.h
+configure:13778: result: yes
+configure:13778: checking sys/byteorder.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+conftest.c:88:27: fatal error: sys/byteorder.h: No such file or directory
+ #include <sys/byteorder.h>
+                           ^
+compilation terminated.
+configure:13778: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| #define STDC_HEADERS 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_LIBGEN_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_LOCALE_H 1
+| #define HAVE_MNTENT_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_STDARG_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_TIME_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_UTIME_H 1
+| #define HAVE_WCHAR_H 1
+| #define HAVE_GETOPT_H 1
+| #define HAVE_FEATURES_H 1
+| #define HAVE_REGEX_H 1
+| #define HAVE_ENDIAN_H 1
+| #define HAVE_BYTESWAP_H 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <sys/byteorder.h>
+configure:13778: result: no
+configure:13778: checking sys/byteorder.h presence
+configure:13778: gcc -E  conftest.c
+conftest.c:55:27: fatal error: sys/byteorder.h: No such file or directory
+ #include <sys/byteorder.h>
+                           ^
+compilation terminated.
+configure:13778: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| #define STDC_HEADERS 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_LIBGEN_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_LOCALE_H 1
+| #define HAVE_MNTENT_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_STDARG_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_TIME_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_UTIME_H 1
+| #define HAVE_WCHAR_H 1
+| #define HAVE_GETOPT_H 1
+| #define HAVE_FEATURES_H 1
+| #define HAVE_REGEX_H 1
+| #define HAVE_ENDIAN_H 1
+| #define HAVE_BYTESWAP_H 1
+| /* end confdefs.h.  */
+| #include <sys/byteorder.h>
+configure:13778: result: no
+configure:13778: checking for sys/byteorder.h
+configure:13778: result: no
+configure:13778: checking sys/disk.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+conftest.c:88:22: fatal error: sys/disk.h: No such file or directory
+ #include <sys/disk.h>
+                      ^
+compilation terminated.
+configure:13778: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| #define STDC_HEADERS 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_LIBGEN_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_LOCALE_H 1
+| #define HAVE_MNTENT_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_STDARG_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_TIME_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_UTIME_H 1
+| #define HAVE_WCHAR_H 1
+| #define HAVE_GETOPT_H 1
+| #define HAVE_FEATURES_H 1
+| #define HAVE_REGEX_H 1
+| #define HAVE_ENDIAN_H 1
+| #define HAVE_BYTESWAP_H 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <sys/disk.h>
+configure:13778: result: no
+configure:13778: checking sys/disk.h presence
+configure:13778: gcc -E  conftest.c
+conftest.c:55:22: fatal error: sys/disk.h: No such file or directory
+ #include <sys/disk.h>
+                      ^
+compilation terminated.
+configure:13778: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| #define STDC_HEADERS 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_LIBGEN_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_LOCALE_H 1
+| #define HAVE_MNTENT_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_STDARG_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_TIME_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_UTIME_H 1
+| #define HAVE_WCHAR_H 1
+| #define HAVE_GETOPT_H 1
+| #define HAVE_FEATURES_H 1
+| #define HAVE_REGEX_H 1
+| #define HAVE_ENDIAN_H 1
+| #define HAVE_BYTESWAP_H 1
+| /* end confdefs.h.  */
+| #include <sys/disk.h>
+configure:13778: result: no
+configure:13778: checking for sys/disk.h
+configure:13778: result: no
+configure:13778: checking sys/endian.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+conftest.c:88:24: fatal error: sys/endian.h: No such file or directory
+ #include <sys/endian.h>
+                        ^
+compilation terminated.
+configure:13778: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| #define STDC_HEADERS 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_LIBGEN_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_LOCALE_H 1
+| #define HAVE_MNTENT_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_STDARG_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_TIME_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_UTIME_H 1
+| #define HAVE_WCHAR_H 1
+| #define HAVE_GETOPT_H 1
+| #define HAVE_FEATURES_H 1
+| #define HAVE_REGEX_H 1
+| #define HAVE_ENDIAN_H 1
+| #define HAVE_BYTESWAP_H 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <sys/endian.h>
+configure:13778: result: no
+configure:13778: checking sys/endian.h presence
+configure:13778: gcc -E  conftest.c
+conftest.c:55:24: fatal error: sys/endian.h: No such file or directory
+ #include <sys/endian.h>
+                        ^
+compilation terminated.
+configure:13778: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| #define STDC_HEADERS 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_LIBGEN_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_LOCALE_H 1
+| #define HAVE_MNTENT_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_STDARG_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_TIME_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_UTIME_H 1
+| #define HAVE_WCHAR_H 1
+| #define HAVE_GETOPT_H 1
+| #define HAVE_FEATURES_H 1
+| #define HAVE_REGEX_H 1
+| #define HAVE_ENDIAN_H 1
+| #define HAVE_BYTESWAP_H 1
+| /* end confdefs.h.  */
+| #include <sys/endian.h>
+configure:13778: result: no
+configure:13778: checking for sys/endian.h
+configure:13778: result: no
+configure:13778: checking sys/param.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking sys/param.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for sys/param.h
+configure:13778: result: yes
+configure:13778: checking sys/ioctl.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking sys/ioctl.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for sys/ioctl.h
+configure:13778: result: yes
+configure:13778: checking sys/mkdev.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+conftest.c:90:23: fatal error: sys/mkdev.h: No such file or directory
+ #include <sys/mkdev.h>
+                       ^
+compilation terminated.
+configure:13778: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| #define STDC_HEADERS 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_LIBGEN_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_LOCALE_H 1
+| #define HAVE_MNTENT_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_STDARG_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_TIME_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_UTIME_H 1
+| #define HAVE_WCHAR_H 1
+| #define HAVE_GETOPT_H 1
+| #define HAVE_FEATURES_H 1
+| #define HAVE_REGEX_H 1
+| #define HAVE_ENDIAN_H 1
+| #define HAVE_BYTESWAP_H 1
+| #define HAVE_SYS_PARAM_H 1
+| #define HAVE_SYS_IOCTL_H 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <sys/mkdev.h>
+configure:13778: result: no
+configure:13778: checking sys/mkdev.h presence
+configure:13778: gcc -E  conftest.c
+conftest.c:57:23: fatal error: sys/mkdev.h: No such file or directory
+ #include <sys/mkdev.h>
+                       ^
+compilation terminated.
+configure:13778: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| #define STDC_HEADERS 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_LIBGEN_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_LOCALE_H 1
+| #define HAVE_MNTENT_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_STDARG_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_TIME_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_UTIME_H 1
+| #define HAVE_WCHAR_H 1
+| #define HAVE_GETOPT_H 1
+| #define HAVE_FEATURES_H 1
+| #define HAVE_REGEX_H 1
+| #define HAVE_ENDIAN_H 1
+| #define HAVE_BYTESWAP_H 1
+| #define HAVE_SYS_PARAM_H 1
+| #define HAVE_SYS_IOCTL_H 1
+| /* end confdefs.h.  */
+| #include <sys/mkdev.h>
+configure:13778: result: no
+configure:13778: checking for sys/mkdev.h
+configure:13778: result: no
+configure:13778: checking sys/mount.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking sys/mount.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for sys/mount.h
+configure:13778: result: yes
+configure:13778: checking for sys/stat.h
+configure:13778: result: yes
+configure:13778: checking for sys/types.h
+configure:13778: result: yes
+configure:13778: checking sys/vfs.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking sys/vfs.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for sys/vfs.h
+configure:13778: result: yes
+configure:13778: checking sys/statvfs.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking sys/statvfs.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for sys/statvfs.h
+configure:13778: result: yes
+configure:13778: checking sys/sysmacros.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking sys/sysmacros.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for sys/sysmacros.h
+configure:13778: result: yes
+configure:13778: checking linux/major.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking linux/major.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for linux/major.h
+configure:13778: result: yes
+configure:13778: checking linux/fd.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking linux/fd.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for linux/fd.h
+configure:13778: result: yes
+configure:13778: checking linux/fs.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking linux/fs.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for linux/fs.h
+configure:13778: result: yes
+configure:13778: checking for inttypes.h
+configure:13778: result: yes
+configure:13778: checking linux/hdreg.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking linux/hdreg.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for linux/hdreg.h
+configure:13778: result: yes
+configure:13778: checking machine/endian.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+conftest.c:101:28: fatal error: machine/endian.h: No such file or directory
+ #include <machine/endian.h>
+                            ^
+compilation terminated.
+configure:13778: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| #define STDC_HEADERS 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_LIBGEN_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_LOCALE_H 1
+| #define HAVE_MNTENT_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_STDARG_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_TIME_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_UTIME_H 1
+| #define HAVE_WCHAR_H 1
+| #define HAVE_GETOPT_H 1
+| #define HAVE_FEATURES_H 1
+| #define HAVE_REGEX_H 1
+| #define HAVE_ENDIAN_H 1
+| #define HAVE_BYTESWAP_H 1
+| #define HAVE_SYS_PARAM_H 1
+| #define HAVE_SYS_IOCTL_H 1
+| #define HAVE_SYS_MOUNT_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_VFS_H 1
+| #define HAVE_SYS_STATVFS_H 1
+| #define HAVE_SYS_SYSMACROS_H 1
+| #define HAVE_LINUX_MAJOR_H 1
+| #define HAVE_LINUX_FD_H 1
+| #define HAVE_LINUX_FS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LINUX_HDREG_H 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <machine/endian.h>
+configure:13778: result: no
+configure:13778: checking machine/endian.h presence
+configure:13778: gcc -E  conftest.c
+conftest.c:68:28: fatal error: machine/endian.h: No such file or directory
+ #include <machine/endian.h>
+                            ^
+compilation terminated.
+configure:13778: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| #define STDC_HEADERS 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_LIBGEN_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_LOCALE_H 1
+| #define HAVE_MNTENT_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_STDARG_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_TIME_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_UTIME_H 1
+| #define HAVE_WCHAR_H 1
+| #define HAVE_GETOPT_H 1
+| #define HAVE_FEATURES_H 1
+| #define HAVE_REGEX_H 1
+| #define HAVE_ENDIAN_H 1
+| #define HAVE_BYTESWAP_H 1
+| #define HAVE_SYS_PARAM_H 1
+| #define HAVE_SYS_IOCTL_H 1
+| #define HAVE_SYS_MOUNT_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_VFS_H 1
+| #define HAVE_SYS_STATVFS_H 1
+| #define HAVE_SYS_SYSMACROS_H 1
+| #define HAVE_LINUX_MAJOR_H 1
+| #define HAVE_LINUX_FD_H 1
+| #define HAVE_LINUX_FS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LINUX_HDREG_H 1
+| /* end confdefs.h.  */
+| #include <machine/endian.h>
+configure:13778: result: no
+configure:13778: checking for machine/endian.h
+configure:13778: result: no
+configure:13778: checking windows.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+conftest.c:101:21: fatal error: windows.h: No such file or directory
+ #include <windows.h>
+                     ^
+compilation terminated.
+configure:13778: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| #define STDC_HEADERS 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_LIBGEN_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_LOCALE_H 1
+| #define HAVE_MNTENT_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_STDARG_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_TIME_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_UTIME_H 1
+| #define HAVE_WCHAR_H 1
+| #define HAVE_GETOPT_H 1
+| #define HAVE_FEATURES_H 1
+| #define HAVE_REGEX_H 1
+| #define HAVE_ENDIAN_H 1
+| #define HAVE_BYTESWAP_H 1
+| #define HAVE_SYS_PARAM_H 1
+| #define HAVE_SYS_IOCTL_H 1
+| #define HAVE_SYS_MOUNT_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_VFS_H 1
+| #define HAVE_SYS_STATVFS_H 1
+| #define HAVE_SYS_SYSMACROS_H 1
+| #define HAVE_LINUX_MAJOR_H 1
+| #define HAVE_LINUX_FD_H 1
+| #define HAVE_LINUX_FS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LINUX_HDREG_H 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <windows.h>
+configure:13778: result: no
+configure:13778: checking windows.h presence
+configure:13778: gcc -E  conftest.c
+conftest.c:68:21: fatal error: windows.h: No such file or directory
+ #include <windows.h>
+                     ^
+compilation terminated.
+configure:13778: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| #define STDC_HEADERS 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_LIBGEN_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_LOCALE_H 1
+| #define HAVE_MNTENT_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_STDARG_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_TIME_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_UTIME_H 1
+| #define HAVE_WCHAR_H 1
+| #define HAVE_GETOPT_H 1
+| #define HAVE_FEATURES_H 1
+| #define HAVE_REGEX_H 1
+| #define HAVE_ENDIAN_H 1
+| #define HAVE_BYTESWAP_H 1
+| #define HAVE_SYS_PARAM_H 1
+| #define HAVE_SYS_IOCTL_H 1
+| #define HAVE_SYS_MOUNT_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_VFS_H 1
+| #define HAVE_SYS_STATVFS_H 1
+| #define HAVE_SYS_SYSMACROS_H 1
+| #define HAVE_LINUX_MAJOR_H 1
+| #define HAVE_LINUX_FD_H 1
+| #define HAVE_LINUX_FS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LINUX_HDREG_H 1
+| /* end confdefs.h.  */
+| #include <windows.h>
+configure:13778: result: no
+configure:13778: checking for windows.h
+configure:13778: result: no
+configure:13778: checking syslog.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking syslog.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for syslog.h
+configure:13778: result: yes
+configure:13778: checking pwd.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking pwd.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for pwd.h
+configure:13778: result: yes
+configure:13778: checking malloc.h usability
+configure:13778: gcc -c -g -O2  conftest.c >&5
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking malloc.h presence
+configure:13778: gcc -E  conftest.c
+configure:13778: $? = 0
+configure:13778: result: yes
+configure:13778: checking for malloc.h
+configure:13778: result: yes
+configure:13790: checking for stdbool.h that conforms to C99
+configure:13857: gcc -c -g -O2  conftest.c >&5
+configure:13857: $? = 0
+configure:13864: result: yes
+configure:13866: checking for _Bool
+configure:13866: gcc -c -g -O2  conftest.c >&5
+configure:13866: $? = 0
+configure:13866: gcc -c -g -O2  conftest.c >&5
+conftest.c: In function 'main':
+conftest.c:107:20: error: expected expression before ')' token
+ if (sizeof ((_Bool)))
+                    ^
+configure:13866: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| #define STDC_HEADERS 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_LIBGEN_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_LOCALE_H 1
+| #define HAVE_MNTENT_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_STDARG_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_TIME_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_UTIME_H 1
+| #define HAVE_WCHAR_H 1
+| #define HAVE_GETOPT_H 1
+| #define HAVE_FEATURES_H 1
+| #define HAVE_REGEX_H 1
+| #define HAVE_ENDIAN_H 1
+| #define HAVE_BYTESWAP_H 1
+| #define HAVE_SYS_PARAM_H 1
+| #define HAVE_SYS_IOCTL_H 1
+| #define HAVE_SYS_MOUNT_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_VFS_H 1
+| #define HAVE_SYS_STATVFS_H 1
+| #define HAVE_SYS_SYSMACROS_H 1
+| #define HAVE_LINUX_MAJOR_H 1
+| #define HAVE_LINUX_FD_H 1
+| #define HAVE_LINUX_FS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LINUX_HDREG_H 1
+| #define HAVE_SYSLOG_H 1
+| #define HAVE_PWD_H 1
+| #define HAVE_MALLOC_H 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| int
+| main ()
+| {
+| if (sizeof ((_Bool)))
+| 	    return 0;
+|   ;
+|   return 0;
+| }
+configure:13866: result: yes
+configure:13883: checking whether byte ordering is bigendian
+configure:13898: gcc -c -g -O2  conftest.c >&5
+conftest.c:74:9: error: unknown type name 'not'
+         not a universal capable compiler
+         ^
+conftest.c:74:15: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'universal'
+         not a universal capable compiler
+               ^
+conftest.c:74:15: error: unknown type name 'universal'
+configure:13898: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| #define STDC_HEADERS 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_LIBGEN_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_LOCALE_H 1
+| #define HAVE_MNTENT_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_STDARG_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_TIME_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_UTIME_H 1
+| #define HAVE_WCHAR_H 1
+| #define HAVE_GETOPT_H 1
+| #define HAVE_FEATURES_H 1
+| #define HAVE_REGEX_H 1
+| #define HAVE_ENDIAN_H 1
+| #define HAVE_BYTESWAP_H 1
+| #define HAVE_SYS_PARAM_H 1
+| #define HAVE_SYS_IOCTL_H 1
+| #define HAVE_SYS_MOUNT_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_VFS_H 1
+| #define HAVE_SYS_STATVFS_H 1
+| #define HAVE_SYS_SYSMACROS_H 1
+| #define HAVE_LINUX_MAJOR_H 1
+| #define HAVE_LINUX_FD_H 1
+| #define HAVE_LINUX_FS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LINUX_HDREG_H 1
+| #define HAVE_SYSLOG_H 1
+| #define HAVE_PWD_H 1
+| #define HAVE_MALLOC_H 1
+| #define HAVE__BOOL 1
+| #define HAVE_STDBOOL_H 1
+| /* end confdefs.h.  */
+| #ifndef __APPLE_CC__
+| 	       not a universal capable compiler
+| 	     #endif
+| 	     typedef int dummy;
+| 
+configure:13943: gcc -c -g -O2  conftest.c >&5
+configure:13943: $? = 0
+configure:13961: gcc -c -g -O2  conftest.c >&5
+conftest.c: In function 'main':
+conftest.c:80:4: error: unknown type name 'not'
+    not big endian
+    ^
+conftest.c:80:12: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'endian'
+    not big endian
+            ^
+configure:13961: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| #define STDC_HEADERS 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_LIBGEN_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_LOCALE_H 1
+| #define HAVE_MNTENT_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_STDARG_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_TIME_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_UTIME_H 1
+| #define HAVE_WCHAR_H 1
+| #define HAVE_GETOPT_H 1
+| #define HAVE_FEATURES_H 1
+| #define HAVE_REGEX_H 1
+| #define HAVE_ENDIAN_H 1
+| #define HAVE_BYTESWAP_H 1
+| #define HAVE_SYS_PARAM_H 1
+| #define HAVE_SYS_IOCTL_H 1
+| #define HAVE_SYS_MOUNT_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_VFS_H 1
+| #define HAVE_SYS_STATVFS_H 1
+| #define HAVE_SYS_SYSMACROS_H 1
+| #define HAVE_LINUX_MAJOR_H 1
+| #define HAVE_LINUX_FD_H 1
+| #define HAVE_LINUX_FS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LINUX_HDREG_H 1
+| #define HAVE_SYSLOG_H 1
+| #define HAVE_PWD_H 1
+| #define HAVE_MALLOC_H 1
+| #define HAVE__BOOL 1
+| #define HAVE_STDBOOL_H 1
+| /* end confdefs.h.  */
+| #include <sys/types.h>
+| 		#include <sys/param.h>
+| 
+| int
+| main ()
+| {
+| #if BYTE_ORDER != BIG_ENDIAN
+| 		 not big endian
+| 		#endif
+| 
+|   ;
+|   return 0;
+| }
+configure:14089: result: no
+configure:14112: checking for an ANSI C-conforming const
+configure:14178: gcc -c -g -O2  conftest.c >&5
+configure:14178: $? = 0
+configure:14185: result: yes
+configure:14193: checking for inline
+configure:14209: gcc -c -g -O2  conftest.c >&5
+configure:14209: $? = 0
+configure:14217: result: inline
+configure:14235: checking for off_t
+configure:14235: gcc -c -g -O2  conftest.c >&5
+configure:14235: $? = 0
+configure:14235: gcc -c -g -O2  conftest.c >&5
+conftest.c: In function 'main':
+conftest.c:110:20: error: expected expression before ')' token
+ if (sizeof ((off_t)))
+                    ^
+configure:14235: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| #define STDC_HEADERS 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_LIBGEN_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_LOCALE_H 1
+| #define HAVE_MNTENT_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_STDARG_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_TIME_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_UTIME_H 1
+| #define HAVE_WCHAR_H 1
+| #define HAVE_GETOPT_H 1
+| #define HAVE_FEATURES_H 1
+| #define HAVE_REGEX_H 1
+| #define HAVE_ENDIAN_H 1
+| #define HAVE_BYTESWAP_H 1
+| #define HAVE_SYS_PARAM_H 1
+| #define HAVE_SYS_IOCTL_H 1
+| #define HAVE_SYS_MOUNT_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_VFS_H 1
+| #define HAVE_SYS_STATVFS_H 1
+| #define HAVE_SYS_SYSMACROS_H 1
+| #define HAVE_LINUX_MAJOR_H 1
+| #define HAVE_LINUX_FD_H 1
+| #define HAVE_LINUX_FS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LINUX_HDREG_H 1
+| #define HAVE_SYSLOG_H 1
+| #define HAVE_PWD_H 1
+| #define HAVE_MALLOC_H 1
+| #define HAVE__BOOL 1
+| #define HAVE_STDBOOL_H 1
+| #define WORDS_LITTLEENDIAN 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| int
+| main ()
+| {
+| if (sizeof ((off_t)))
+| 	    return 0;
+|   ;
+|   return 0;
+| }
+configure:14235: result: yes
+configure:14246: checking for size_t
+configure:14246: gcc -c -g -O2  conftest.c >&5
+configure:14246: $? = 0
+configure:14246: gcc -c -g -O2  conftest.c >&5
+conftest.c: In function 'main':
+conftest.c:110:21: error: expected expression before ')' token
+ if (sizeof ((size_t)))
+                     ^
+configure:14246: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| #define STDC_HEADERS 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_LIBGEN_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_LOCALE_H 1
+| #define HAVE_MNTENT_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_STDARG_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_TIME_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_UTIME_H 1
+| #define HAVE_WCHAR_H 1
+| #define HAVE_GETOPT_H 1
+| #define HAVE_FEATURES_H 1
+| #define HAVE_REGEX_H 1
+| #define HAVE_ENDIAN_H 1
+| #define HAVE_BYTESWAP_H 1
+| #define HAVE_SYS_PARAM_H 1
+| #define HAVE_SYS_IOCTL_H 1
+| #define HAVE_SYS_MOUNT_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_VFS_H 1
+| #define HAVE_SYS_STATVFS_H 1
+| #define HAVE_SYS_SYSMACROS_H 1
+| #define HAVE_LINUX_MAJOR_H 1
+| #define HAVE_LINUX_FD_H 1
+| #define HAVE_LINUX_FS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LINUX_HDREG_H 1
+| #define HAVE_SYSLOG_H 1
+| #define HAVE_PWD_H 1
+| #define HAVE_MALLOC_H 1
+| #define HAVE__BOOL 1
+| #define HAVE_STDBOOL_H 1
+| #define WORDS_LITTLEENDIAN 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| int
+| main ()
+| {
+| if (sizeof ((size_t)))
+| 	    return 0;
+|   ;
+|   return 0;
+| }
+configure:14246: result: yes
+configure:14257: checking for struct stat.st_blocks
+configure:14257: gcc -c -g -O2  conftest.c >&5
+configure:14257: $? = 0
+configure:14257: result: yes
+configure:14277: checking for struct stat.st_rdev
+configure:14277: gcc -c -g -O2  conftest.c >&5
+configure:14277: $? = 0
+configure:14277: result: yes
+configure:14287: checking for struct stat.st_atim
+configure:14287: gcc -c -g -O2  conftest.c >&5
+conftest.c: In function 'main':
+conftest.c:114:5: error: used struct type value where scalar is required
+ if (ac_aggr.st_atim)
+     ^
+configure:14287: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| #define STDC_HEADERS 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_LIBGEN_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_LOCALE_H 1
+| #define HAVE_MNTENT_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_STDARG_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_TIME_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_UTIME_H 1
+| #define HAVE_WCHAR_H 1
+| #define HAVE_GETOPT_H 1
+| #define HAVE_FEATURES_H 1
+| #define HAVE_REGEX_H 1
+| #define HAVE_ENDIAN_H 1
+| #define HAVE_BYTESWAP_H 1
+| #define HAVE_SYS_PARAM_H 1
+| #define HAVE_SYS_IOCTL_H 1
+| #define HAVE_SYS_MOUNT_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_VFS_H 1
+| #define HAVE_SYS_STATVFS_H 1
+| #define HAVE_SYS_SYSMACROS_H 1
+| #define HAVE_LINUX_MAJOR_H 1
+| #define HAVE_LINUX_FD_H 1
+| #define HAVE_LINUX_FS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LINUX_HDREG_H 1
+| #define HAVE_SYSLOG_H 1
+| #define HAVE_PWD_H 1
+| #define HAVE_MALLOC_H 1
+| #define HAVE__BOOL 1
+| #define HAVE_STDBOOL_H 1
+| #define WORDS_LITTLEENDIAN 1
+| #define HAVE_STRUCT_STAT_ST_BLOCKS 1
+| #define HAVE_ST_BLOCKS 1
+| #define HAVE_STRUCT_STAT_ST_RDEV 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| int
+| main ()
+| {
+| static struct stat ac_aggr;
+| if (ac_aggr.st_atim)
+| return 0;
+|   ;
+|   return 0;
+| }
+configure:14287: gcc -c -g -O2  conftest.c >&5
+configure:14287: $? = 0
+configure:14287: result: yes
+configure:14297: checking for struct stat.st_atimespec
+configure:14297: gcc -c -g -O2  conftest.c >&5
+conftest.c: In function 'main':
+conftest.c:115:12: error: 'struct stat' has no member named 'st_atimespec'
+ if (ac_aggr.st_atimespec)
+            ^
+configure:14297: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| #define STDC_HEADERS 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_LIBGEN_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_LOCALE_H 1
+| #define HAVE_MNTENT_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_STDARG_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_TIME_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_UTIME_H 1
+| #define HAVE_WCHAR_H 1
+| #define HAVE_GETOPT_H 1
+| #define HAVE_FEATURES_H 1
+| #define HAVE_REGEX_H 1
+| #define HAVE_ENDIAN_H 1
+| #define HAVE_BYTESWAP_H 1
+| #define HAVE_SYS_PARAM_H 1
+| #define HAVE_SYS_IOCTL_H 1
+| #define HAVE_SYS_MOUNT_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_VFS_H 1
+| #define HAVE_SYS_STATVFS_H 1
+| #define HAVE_SYS_SYSMACROS_H 1
+| #define HAVE_LINUX_MAJOR_H 1
+| #define HAVE_LINUX_FD_H 1
+| #define HAVE_LINUX_FS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LINUX_HDREG_H 1
+| #define HAVE_SYSLOG_H 1
+| #define HAVE_PWD_H 1
+| #define HAVE_MALLOC_H 1
+| #define HAVE__BOOL 1
+| #define HAVE_STDBOOL_H 1
+| #define WORDS_LITTLEENDIAN 1
+| #define HAVE_STRUCT_STAT_ST_BLOCKS 1
+| #define HAVE_ST_BLOCKS 1
+| #define HAVE_STRUCT_STAT_ST_RDEV 1
+| #define HAVE_STRUCT_STAT_ST_ATIM 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| int
+| main ()
+| {
+| static struct stat ac_aggr;
+| if (ac_aggr.st_atimespec)
+| return 0;
+|   ;
+|   return 0;
+| }
+configure:14297: gcc -c -g -O2  conftest.c >&5
+conftest.c: In function 'main':
+conftest.c:115:19: error: 'struct stat' has no member named 'st_atimespec'
+ if (sizeof ac_aggr.st_atimespec)
+                   ^
+configure:14297: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| #define STDC_HEADERS 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_LIBGEN_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_LOCALE_H 1
+| #define HAVE_MNTENT_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_STDARG_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_TIME_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_UTIME_H 1
+| #define HAVE_WCHAR_H 1
+| #define HAVE_GETOPT_H 1
+| #define HAVE_FEATURES_H 1
+| #define HAVE_REGEX_H 1
+| #define HAVE_ENDIAN_H 1
+| #define HAVE_BYTESWAP_H 1
+| #define HAVE_SYS_PARAM_H 1
+| #define HAVE_SYS_IOCTL_H 1
+| #define HAVE_SYS_MOUNT_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_VFS_H 1
+| #define HAVE_SYS_STATVFS_H 1
+| #define HAVE_SYS_SYSMACROS_H 1
+| #define HAVE_LINUX_MAJOR_H 1
+| #define HAVE_LINUX_FD_H 1
+| #define HAVE_LINUX_FS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LINUX_HDREG_H 1
+| #define HAVE_SYSLOG_H 1
+| #define HAVE_PWD_H 1
+| #define HAVE_MALLOC_H 1
+| #define HAVE__BOOL 1
+| #define HAVE_STDBOOL_H 1
+| #define WORDS_LITTLEENDIAN 1
+| #define HAVE_STRUCT_STAT_ST_BLOCKS 1
+| #define HAVE_ST_BLOCKS 1
+| #define HAVE_STRUCT_STAT_ST_RDEV 1
+| #define HAVE_STRUCT_STAT_ST_ATIM 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| int
+| main ()
+| {
+| static struct stat ac_aggr;
+| if (sizeof ac_aggr.st_atimespec)
+| return 0;
+|   ;
+|   return 0;
+| }
+configure:14297: result: no
+configure:14307: checking for struct stat.st_atimensec
+configure:14307: gcc -c -g -O2  conftest.c >&5
+conftest.c: In function 'main':
+conftest.c:115:12: error: 'struct stat' has no member named 'st_atimensec'
+ if (ac_aggr.st_atimensec)
+            ^
+configure:14307: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| #define STDC_HEADERS 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_LIBGEN_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_LOCALE_H 1
+| #define HAVE_MNTENT_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_STDARG_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_TIME_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_UTIME_H 1
+| #define HAVE_WCHAR_H 1
+| #define HAVE_GETOPT_H 1
+| #define HAVE_FEATURES_H 1
+| #define HAVE_REGEX_H 1
+| #define HAVE_ENDIAN_H 1
+| #define HAVE_BYTESWAP_H 1
+| #define HAVE_SYS_PARAM_H 1
+| #define HAVE_SYS_IOCTL_H 1
+| #define HAVE_SYS_MOUNT_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_VFS_H 1
+| #define HAVE_SYS_STATVFS_H 1
+| #define HAVE_SYS_SYSMACROS_H 1
+| #define HAVE_LINUX_MAJOR_H 1
+| #define HAVE_LINUX_FD_H 1
+| #define HAVE_LINUX_FS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LINUX_HDREG_H 1
+| #define HAVE_SYSLOG_H 1
+| #define HAVE_PWD_H 1
+| #define HAVE_MALLOC_H 1
+| #define HAVE__BOOL 1
+| #define HAVE_STDBOOL_H 1
+| #define WORDS_LITTLEENDIAN 1
+| #define HAVE_STRUCT_STAT_ST_BLOCKS 1
+| #define HAVE_ST_BLOCKS 1
+| #define HAVE_STRUCT_STAT_ST_RDEV 1
+| #define HAVE_STRUCT_STAT_ST_ATIM 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| int
+| main ()
+| {
+| static struct stat ac_aggr;
+| if (ac_aggr.st_atimensec)
+| return 0;
+|   ;
+|   return 0;
+| }
+configure:14307: gcc -c -g -O2  conftest.c >&5
+conftest.c: In function 'main':
+conftest.c:115:19: error: 'struct stat' has no member named 'st_atimensec'
+ if (sizeof ac_aggr.st_atimensec)
+                   ^
+configure:14307: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| #define STDC_HEADERS 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_LIBGEN_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_LOCALE_H 1
+| #define HAVE_MNTENT_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_STDARG_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_TIME_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_UTIME_H 1
+| #define HAVE_WCHAR_H 1
+| #define HAVE_GETOPT_H 1
+| #define HAVE_FEATURES_H 1
+| #define HAVE_REGEX_H 1
+| #define HAVE_ENDIAN_H 1
+| #define HAVE_BYTESWAP_H 1
+| #define HAVE_SYS_PARAM_H 1
+| #define HAVE_SYS_IOCTL_H 1
+| #define HAVE_SYS_MOUNT_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_VFS_H 1
+| #define HAVE_SYS_STATVFS_H 1
+| #define HAVE_SYS_SYSMACROS_H 1
+| #define HAVE_LINUX_MAJOR_H 1
+| #define HAVE_LINUX_FD_H 1
+| #define HAVE_LINUX_FS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LINUX_HDREG_H 1
+| #define HAVE_SYSLOG_H 1
+| #define HAVE_PWD_H 1
+| #define HAVE_MALLOC_H 1
+| #define HAVE__BOOL 1
+| #define HAVE_STDBOOL_H 1
+| #define WORDS_LITTLEENDIAN 1
+| #define HAVE_STRUCT_STAT_ST_BLOCKS 1
+| #define HAVE_ST_BLOCKS 1
+| #define HAVE_STRUCT_STAT_ST_RDEV 1
+| #define HAVE_STRUCT_STAT_ST_ATIM 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| int
+| main ()
+| {
+| static struct stat ac_aggr;
+| if (sizeof ac_aggr.st_atimensec)
+| return 0;
+|   ;
+|   return 0;
+| }
+configure:14307: result: no
+configure:14343: checking for library containing getmntent
+configure:14374: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14374: $? = 0
+configure:14391: result: none required
+configure:14406: checking whether mbrtowc and mbstate_t are properly declared
+configure:14426: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14426: $? = 0
+configure:14434: result: yes
+configure:14442: checking for working memcmp
+configure:14485: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14485: $? = 0
+configure:14485: ./conftest
+configure:14485: $? = 0
+configure:14495: result: yes
+configure:14504: checking whether lstat correctly handles trailing slash
+configure:14530: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14530: $? = 0
+configure:14530: ./conftest
+configure:14530: $? = 0
+configure:14547: result: yes
+configure:14566: checking whether stat accepts an empty string
+configure:14586: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14586: $? = 0
+configure:14586: ./conftest
+configure:14586: $? = 0
+configure:14596: result: no
+configure:14614: checking for strftime
+configure:14614: gcc -o conftest -g -O2   conftest.c  >&5
+conftest.c:104:6: warning: conflicting types for built-in function 'strftime' [enabled by default]
+ char strftime ();
+      ^
+configure:14614: $? = 0
+configure:14614: result: yes
+configure:14673: checking for utime.h
+configure:14673: result: yes
+configure:14687: checking whether utime accepts a null argument
+configure:14716: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14716: $? = 0
+configure:14716: ./conftest
+configure:14716: $? = 0
+configure:14726: result: yes
+configure:14738: checking for vprintf
+configure:14738: gcc -o conftest -g -O2   conftest.c  >&5
+conftest.c:107:6: warning: conflicting types for built-in function 'vprintf' [enabled by default]
+ char vprintf ();
+      ^
+configure:14738: $? = 0
+configure:14738: result: yes
+configure:14744: checking for _doprnt
+configure:14744: gcc -o conftest -g -O2   conftest.c  >&5
+/tmp/ccezr7Vq.o: In function `main':
+/home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/conftest.c:119: undefined reference to `_doprnt'
+collect2: error: ld returned 1 exit status
+configure:14744: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ntfs-3g"
+| #define PACKAGE_TARNAME "ntfs-3g"
+| #define PACKAGE_VERSION "2015.3.14"
+| #define PACKAGE_STRING "ntfs-3g 2015.3.14"
+| #define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+| #define PACKAGE_URL ""
+| #define PACKAGE "ntfs-3g"
+| #define VERSION "2015.3.14"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define __EXTENSIONS__ 1
+| #define _ALL_SOURCE 1
+| #define _GNU_SOURCE 1
+| #define _POSIX_PTHREAD_SEMANTICS 1
+| #define _TANDEM_SOURCE 1
+| #define HAVE_DLFCN_H 1
+| #define LT_OBJDIR ".libs/"
+| #define _REENTRANT 1
+| #define FUSE_INTERNAL 1
+| #define STDC_HEADERS 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_LIBGEN_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_LOCALE_H 1
+| #define HAVE_MNTENT_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_STDARG_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_TIME_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_UTIME_H 1
+| #define HAVE_WCHAR_H 1
+| #define HAVE_GETOPT_H 1
+| #define HAVE_FEATURES_H 1
+| #define HAVE_REGEX_H 1
+| #define HAVE_ENDIAN_H 1
+| #define HAVE_BYTESWAP_H 1
+| #define HAVE_SYS_PARAM_H 1
+| #define HAVE_SYS_IOCTL_H 1
+| #define HAVE_SYS_MOUNT_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_VFS_H 1
+| #define HAVE_SYS_STATVFS_H 1
+| #define HAVE_SYS_SYSMACROS_H 1
+| #define HAVE_LINUX_MAJOR_H 1
+| #define HAVE_LINUX_FD_H 1
+| #define HAVE_LINUX_FS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LINUX_HDREG_H 1
+| #define HAVE_SYSLOG_H 1
+| #define HAVE_PWD_H 1
+| #define HAVE_MALLOC_H 1
+| #define HAVE__BOOL 1
+| #define HAVE_STDBOOL_H 1
+| #define WORDS_LITTLEENDIAN 1
+| #define HAVE_STRUCT_STAT_ST_BLOCKS 1
+| #define HAVE_ST_BLOCKS 1
+| #define HAVE_STRUCT_STAT_ST_RDEV 1
+| #define HAVE_STRUCT_STAT_ST_ATIM 1
+| #define HAVE_GETMNTENT 1
+| #define HAVE_MBRTOWC 1
+| #define LSTAT_FOLLOWS_SLASHED_SYMLINK 1
+| #define HAVE_STRFTIME 1
+| #define HAVE_UTIME_H 1
+| #define HAVE_UTIME_NULL 1
+| #define HAVE_VPRINTF 1
+| /* end confdefs.h.  */
+| /* Define _doprnt to an innocuous variant, in case <limits.h> declares _doprnt.
+|    For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+| #define _doprnt innocuous__doprnt
+| 
+| /* System header to define __stub macros and hopefully few prototypes,
+|     which can conflict with char _doprnt (); below.
+|     Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+|     <limits.h> exists even on freestanding compilers.  */
+| 
+| #ifdef __STDC__
+| # include <limits.h>
+| #else
+| # include <assert.h>
+| #endif
+| 
+| #undef _doprnt
+| 
+| /* Override any GCC internal prototype to avoid an error.
+|    Use char because int might match the return type of a GCC
+|    builtin and then its argument prototype would still apply.  */
+| #ifdef __cplusplus
+| extern "C"
+| #endif
+| char _doprnt ();
+| /* The GNU C library defines this for functions which it implements
+|     to always fail with ENOSYS.  Some functions are actually named
+|     something starting with __ and the normal name is an alias.  */
+| #if defined __stub__doprnt || defined __stub____doprnt
+| choke me
+| #endif
+| 
+| int
+| main ()
+| {
+| return _doprnt ();
+|   ;
+|   return 0;
+| }
+configure:14744: result: no
+configure:14763: checking for atexit
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for basename
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for daemon
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for dup2
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for fdatasync
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for ffs
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+conftest.c:113:6: warning: conflicting types for built-in function 'ffs' [enabled by default]
+ char ffs ();
+      ^
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for getopt_long
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for hasmntopt
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for mbsinit
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for memmove
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+conftest.c:117:6: warning: conflicting types for built-in function 'memmove' [enabled by default]
+ char memmove ();
+      ^
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for memset
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+conftest.c:118:6: warning: conflicting types for built-in function 'memset' [enabled by default]
+ char memset ();
+      ^
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for realpath
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for regcomp
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for setlocale
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for setxattr
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for strcasecmp
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+conftest.c:123:6: warning: conflicting types for built-in function 'strcasecmp' [enabled by default]
+ char strcasecmp ();
+      ^
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for strchr
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+conftest.c:124:6: warning: conflicting types for built-in function 'strchr' [enabled by default]
+ char strchr ();
+      ^
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for strdup
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+conftest.c:125:6: warning: conflicting types for built-in function 'strdup' [enabled by default]
+ char strdup ();
+      ^
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for strerror
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for strnlen
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for strsep
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for strtol
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for strtoul
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for sysconf
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for utime
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for utimensat
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for gettimeofday
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for clock_gettime
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for fork
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+conftest.c:136:6: warning: conflicting types for built-in function 'fork' [enabled by default]
+ char fork ();
+      ^
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for memcpy
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+conftest.c:137:6: warning: conflicting types for built-in function 'memcpy' [enabled by default]
+ char memcpy ();
+      ^
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for random
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14763: checking for snprintf
+configure:14763: gcc -o conftest -g -O2   conftest.c  >&5
+conftest.c:139:6: warning: conflicting types for built-in function 'snprintf' [enabled by default]
+ char snprintf ();
+      ^
+configure:14763: $? = 0
+configure:14763: result: yes
+configure:14779: checking for special C compiler options needed for large files
+configure:14824: result: no
+configure:14830: checking for _FILE_OFFSET_BITS value needed for large files
+configure:14855: gcc -c -g -O2  conftest.c >&5
+configure:14855: $? = 0
+configure:14887: result: no
+configure:15266: checking that generated files are newer than configure
+configure:15272: result: done
+configure:15356: creating ./config.status
+
+## ---------------------- ##
+## Running config.status. ##
+## ---------------------- ##
+
+This file was extended by ntfs-3g config.status 2015.3.14, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  CONFIG_FILES    = 
+  CONFIG_HEADERS  = 
+  CONFIG_LINKS    = 
+  CONFIG_COMMANDS = 
+  $ ./config.status 
+
+on cmc-HP-Compaq-Pro-6380-MT
+
+config.status:1266: creating Makefile
+config.status:1266: creating include/Makefile
+config.status:1266: creating include/fuse-lite/Makefile
+config.status:1266: creating include/ntfs-3g/Makefile
+config.status:1266: creating libfuse-lite/Makefile
+config.status:1266: creating libntfs-3g/Makefile
+config.status:1266: creating libntfs-3g/libntfs-3g.pc
+config.status:1266: creating libntfs-3g/libntfs-3g.script.so
+config.status:1266: creating ntfsprogs/Makefile
+config.status:1266: creating ntfsprogs/mkntfs.8
+config.status:1266: creating ntfsprogs/ntfscat.8
+config.status:1266: creating ntfsprogs/ntfsclone.8
+config.status:1266: creating ntfsprogs/ntfscluster.8
+config.status:1266: creating ntfsprogs/ntfscmp.8
+config.status:1266: creating ntfsprogs/ntfscp.8
+config.status:1266: creating ntfsprogs/ntfsfix.8
+config.status:1266: creating ntfsprogs/ntfsinfo.8
+config.status:1266: creating ntfsprogs/ntfslabel.8
+config.status:1266: creating ntfsprogs/ntfsls.8
+config.status:1266: creating ntfsprogs/ntfsprogs.8
+config.status:1266: creating ntfsprogs/ntfsresize.8
+config.status:1266: creating ntfsprogs/ntfsundelete.8
+config.status:1266: creating ntfsprogs/ntfsdecrypt.8
+config.status:1266: creating ntfsprogs/ntfswipe.8
+config.status:1266: creating ntfsprogs/ntfstruncate.8
+config.status:1266: creating ntfsprogs/ntfsfallocate.8
+config.status:1266: creating src/Makefile
+config.status:1266: creating src/ntfs-3g.8
+config.status:1266: creating src/ntfs-3g.probe.8
+config.status:1266: creating src/ntfs-3g.usermap.8
+config.status:1266: creating src/ntfs-3g.secaudit.8
+config.status:1266: creating config.h
+config.status:1495: executing depfiles commands
+config.status:1495: executing libtool commands
+
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+
+ac_cv_build=x86_64-unknown-linux-gnu
+ac_cv_c_bigendian=no
+ac_cv_c_compiler_gnu=yes
+ac_cv_c_const=yes
+ac_cv_c_inline=inline
+ac_cv_env_CC_set=
+ac_cv_env_CC_value=
+ac_cv_env_CFLAGS_set=
+ac_cv_env_CFLAGS_value=
+ac_cv_env_CPPFLAGS_set=
+ac_cv_env_CPPFLAGS_value=
+ac_cv_env_CPP_set=
+ac_cv_env_CPP_value=
+ac_cv_env_FUSE_MODULE_CFLAGS_set=
+ac_cv_env_FUSE_MODULE_CFLAGS_value=
+ac_cv_env_FUSE_MODULE_LIBS_set=
+ac_cv_env_FUSE_MODULE_LIBS_value=
+ac_cv_env_GNUTLS_CFLAGS_set=
+ac_cv_env_GNUTLS_CFLAGS_value=
+ac_cv_env_GNUTLS_LIBS_set=
+ac_cv_env_GNUTLS_LIBS_value=
+ac_cv_env_LDCONFIG_set=
+ac_cv_env_LDCONFIG_value=
+ac_cv_env_LDFLAGS_set=
+ac_cv_env_LDFLAGS_value=
+ac_cv_env_LIBS_set=
+ac_cv_env_LIBS_value=
+ac_cv_env_PKG_CONFIG_LIBDIR_set=
+ac_cv_env_PKG_CONFIG_LIBDIR_value=
+ac_cv_env_PKG_CONFIG_PATH_set=
+ac_cv_env_PKG_CONFIG_PATH_value=
+ac_cv_env_PKG_CONFIG_set=
+ac_cv_env_PKG_CONFIG_value=
+ac_cv_env_build_alias_set=
+ac_cv_env_build_alias_value=
+ac_cv_env_host_alias_set=
+ac_cv_env_host_alias_value=
+ac_cv_env_target_alias_set=
+ac_cv_env_target_alias_value=
+ac_cv_func__doprnt=no
+ac_cv_func_atexit=yes
+ac_cv_func_basename=yes
+ac_cv_func_clock_gettime=yes
+ac_cv_func_daemon=yes
+ac_cv_func_dup2=yes
+ac_cv_func_fdatasync=yes
+ac_cv_func_ffs=yes
+ac_cv_func_fork=yes
+ac_cv_func_getmntent=yes
+ac_cv_func_getopt_long=yes
+ac_cv_func_gettimeofday=yes
+ac_cv_func_hasmntopt=yes
+ac_cv_func_lstat_dereferences_slashed_symlink=yes
+ac_cv_func_mbrtowc=yes
+ac_cv_func_mbsinit=yes
+ac_cv_func_memcmp_working=yes
+ac_cv_func_memcpy=yes
+ac_cv_func_memmove=yes
+ac_cv_func_memset=yes
+ac_cv_func_random=yes
+ac_cv_func_realpath=yes
+ac_cv_func_regcomp=yes
+ac_cv_func_setlocale=yes
+ac_cv_func_setxattr=yes
+ac_cv_func_snprintf=yes
+ac_cv_func_stat_empty_string_bug=no
+ac_cv_func_strcasecmp=yes
+ac_cv_func_strchr=yes
+ac_cv_func_strdup=yes
+ac_cv_func_strerror=yes
+ac_cv_func_strftime=yes
+ac_cv_func_strnlen=yes
+ac_cv_func_strsep=yes
+ac_cv_func_strtol=yes
+ac_cv_func_strtoul=yes
+ac_cv_func_sysconf=yes
+ac_cv_func_utime=yes
+ac_cv_func_utime_null=yes
+ac_cv_func_utimensat=yes
+ac_cv_func_vprintf=yes
+ac_cv_header_byteswap_h=yes
+ac_cv_header_ctype_h=yes
+ac_cv_header_dlfcn_h=yes
+ac_cv_header_endian_h=yes
+ac_cv_header_errno_h=yes
+ac_cv_header_fcntl_h=yes
+ac_cv_header_features_h=yes
+ac_cv_header_getopt_h=yes
+ac_cv_header_hd_h=no
+ac_cv_header_inttypes_h=yes
+ac_cv_header_libgen_h=yes
+ac_cv_header_libintl_h=yes
+ac_cv_header_limits_h=yes
+ac_cv_header_linux_fd_h=yes
+ac_cv_header_linux_fs_h=yes
+ac_cv_header_linux_hdreg_h=yes
+ac_cv_header_linux_major_h=yes
+ac_cv_header_locale_h=yes
+ac_cv_header_machine_endian_h=no
+ac_cv_header_malloc_h=yes
+ac_cv_header_memory_h=yes
+ac_cv_header_minix_config_h=no
+ac_cv_header_mntent_h=yes
+ac_cv_header_pwd_h=yes
+ac_cv_header_regex_h=yes
+ac_cv_header_stdarg_h=yes
+ac_cv_header_stdbool_h=yes
+ac_cv_header_stdc=yes
+ac_cv_header_stddef_h=yes
+ac_cv_header_stdint_h=yes
+ac_cv_header_stdio_h=yes
+ac_cv_header_stdlib_h=yes
+ac_cv_header_string_h=yes
+ac_cv_header_strings_h=yes
+ac_cv_header_sys_byteorder_h=no
+ac_cv_header_sys_disk_h=no
+ac_cv_header_sys_endian_h=no
+ac_cv_header_sys_ioctl_h=yes
+ac_cv_header_sys_mkdev_h=no
+ac_cv_header_sys_mount_h=yes
+ac_cv_header_sys_param_h=yes
+ac_cv_header_sys_stat_h=yes
+ac_cv_header_sys_statvfs_h=yes
+ac_cv_header_sys_sysmacros_h=yes
+ac_cv_header_sys_types_h=yes
+ac_cv_header_sys_vfs_h=yes
+ac_cv_header_syslog_h=yes
+ac_cv_header_time_h=yes
+ac_cv_header_unistd_h=yes
+ac_cv_header_utime_h=yes
+ac_cv_header_uuid_uuid_h=no
+ac_cv_header_wchar_h=yes
+ac_cv_header_windows_h=no
+ac_cv_host=x86_64-unknown-linux-gnu
+ac_cv_lib_pthread_pthread_create=yes
+ac_cv_member_struct_stat_st_atim=yes
+ac_cv_member_struct_stat_st_atimensec=no
+ac_cv_member_struct_stat_st_atimespec=no
+ac_cv_member_struct_stat_st_blocks=yes
+ac_cv_member_struct_stat_st_rdev=yes
+ac_cv_objext=o
+ac_cv_path_EGREP='/bin/grep -E'
+ac_cv_path_FGREP='/bin/grep -F'
+ac_cv_path_GREP=/bin/grep
+ac_cv_path_LDCONFIG=/sbin/ldconfig
+ac_cv_path_MV=/bin/mv
+ac_cv_path_RM=/bin/rm
+ac_cv_path_SED=/bin/sed
+ac_cv_path_ac_pt_PKG_CONFIG=/usr/bin/pkg-config
+ac_cv_path_install='/usr/bin/install -c'
+ac_cv_path_mkdir=/bin/mkdir
+ac_cv_prog_AWK=gawk
+ac_cv_prog_CPP='gcc -E'
+ac_cv_prog_ac_ct_AR=ar
+ac_cv_prog_ac_ct_CC=gcc
+ac_cv_prog_ac_ct_MANIFEST_TOOL=mt
+ac_cv_prog_ac_ct_OBJDUMP=objdump
+ac_cv_prog_ac_ct_RANLIB=ranlib
+ac_cv_prog_ac_ct_STRIP=strip
+ac_cv_prog_cc_c89=
+ac_cv_prog_cc_g=yes
+ac_cv_prog_make_make_set=yes
+ac_cv_safe_to_define___extensions__=yes
+ac_cv_search_getmntent='none required'
+ac_cv_sys_file_offset_bits=no
+ac_cv_sys_largefile_CC=no
+ac_cv_target=x86_64-unknown-linux-gnu
+ac_cv_type__Bool=yes
+ac_cv_type_off_t=yes
+ac_cv_type_size_t=yes
+am_cv_CC_dependencies_compiler_type=gcc3
+am_cv_make_support_nested_variables=yes
+am_cv_prog_cc_c_o=yes
+lt_cv_ar_at_file=@
+lt_cv_archive_cmds_need_lc=no
+lt_cv_deplibs_check_method=pass_all
+lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_ld_reload_flag=-r
+lt_cv_nm_interface='BSD nm'
+lt_cv_objdir=.libs
+lt_cv_path_LD=/usr/bin/ld
+lt_cv_path_NM='/usr/bin/nm -B'
+lt_cv_path_mainfest_tool=no
+lt_cv_prog_compiler_c_o=yes
+lt_cv_prog_compiler_pic='-fPIC -DPIC'
+lt_cv_prog_compiler_pic_works=yes
+lt_cv_prog_compiler_rtti_exceptions=no
+lt_cv_prog_compiler_static_works=yes
+lt_cv_prog_gnu_ld=yes
+lt_cv_sharedlib_from_linklib_cmd='printf %s\n'
+lt_cv_shlibpath_overrides_runpath=no
+lt_cv_sys_global_symbol_pipe='sed -n -e '\''s/^.*[	 ]\([ABCDGIRSTW][ABCDGIRSTW]*\)[	 ][	 ]*\([_A-Za-z][_A-Za-z0-9]*\)$/\1 \2 \2/p'\'' | sed '\''/ __gnu_lto/d'\'''
+lt_cv_sys_global_symbol_to_c_name_address='sed -n -e '\''s/^: \([^ ]*\)[ ]*$/  {\"\1\", (void *) 0},/p'\'' -e '\''s/^[ABCDGIRSTW]* \([^ ]*\) \([^ ]*\)$/  {"\2", (void *) \&\2},/p'\'''
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='sed -n -e '\''s/^: \([^ ]*\)[ ]*$/  {\"\1\", (void *) 0},/p'\'' -e '\''s/^[ABCDGIRSTW]* \([^ ]*\) \(lib[^ ]*\)$/  {"\2", (void *) \&\2},/p'\'' -e '\''s/^[ABCDGIRSTW]* \([^ ]*\) \([^ ]*\)$/  {"lib\2", (void *) \&\2},/p'\'''
+lt_cv_sys_global_symbol_to_cdecl='sed -n -e '\''s/^T .* \(.*\)$/extern int \1();/p'\'' -e '\''s/^[ABCDGIRSTW]* .* \(.*\)$/extern char \1;/p'\'''
+lt_cv_sys_max_cmd_len=1572864
+lt_cv_to_host_file_cmd=func_convert_file_noop
+lt_cv_to_tool_file_cmd=func_convert_file_noop
+
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+
+ACLOCAL='${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing aclocal-1.14'
+AMDEPBACKSLASH='\'
+AMDEP_FALSE='#'
+AMDEP_TRUE=''
+AMTAR='$${TAR-tar}'
+AM_BACKSLASH='\'
+AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+AM_DEFAULT_VERBOSITY='1'
+AM_V='$(V)'
+AR='ar'
+AUTOCONF='${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing autoconf'
+AUTOHEADER='${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing autoheader'
+AUTOMAKE='${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing automake-1.14'
+AWK='gawk'
+CC='gcc'
+CCDEPMODE='depmode=gcc3'
+CFLAGS='-g -O2 -Wall'
+CPP='gcc -E'
+CPPFLAGS=''
+CYGPATH_W='echo'
+DEFS='-DHAVE_CONFIG_H'
+DEPDIR='.deps'
+DLLTOOL='false'
+DSYMUTIL=''
+DUMPBIN=''
+ECHO_C=''
+ECHO_N='-n'
+ECHO_T=''
+EGREP='/bin/grep -E'
+ENABLE_CRYPTO_FALSE=''
+ENABLE_CRYPTO_TRUE='#'
+ENABLE_EXTRAS_FALSE=''
+ENABLE_EXTRAS_TRUE='#'
+ENABLE_MOUNT_HELPER_FALSE='#'
+ENABLE_MOUNT_HELPER_TRUE=''
+ENABLE_NTFSPROGS_FALSE='#'
+ENABLE_NTFSPROGS_TRUE=''
+ENABLE_NTFS_3G_FALSE='#'
+ENABLE_NTFS_3G_TRUE=''
+ENABLE_QUARANTINED_FALSE=''
+ENABLE_QUARANTINED_TRUE='#'
+EXEEXT=''
+FGREP='/bin/grep -F'
+FUSE_INTERNAL_FALSE='#'
+FUSE_INTERNAL_TRUE=''
+FUSE_MODULE_CFLAGS=''
+FUSE_MODULE_LIBS=''
+GENERATE_LDSCRIPT_FALSE=''
+GENERATE_LDSCRIPT_TRUE='#'
+GNUTLS_CFLAGS=''
+GNUTLS_LIBS=''
+GREP='/bin/grep'
+INSTALL_DATA='${INSTALL} -m 644'
+INSTALL_LIBRARY_FALSE='#'
+INSTALL_LIBRARY_TRUE=''
+INSTALL_PROGRAM='${INSTALL}'
+INSTALL_SCRIPT='${INSTALL}'
+INSTALL_STRIP_PROGRAM='$(install_sh) -c -s'
+LD='/usr/bin/ld -m elf_x86_64'
+LDCONFIG='/sbin/ldconfig'
+LDFLAGS=''
+LIBFUSE_LITE_CFLAGS=''
+LIBFUSE_LITE_LIBS=' -lpthread'
+LIBGCRYPT_CFLAGS=''
+LIBGCRYPT_CONFIG=''
+LIBGCRYPT_LIBS=''
+LIBNTFS_3G_VERSION='86'
+LIBNTFS_CPPFLAGS=''
+LIBNTFS_LIBS=''
+LIBOBJS=''
+LIBS=''
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+LIPO=''
+LN_S='ln -s'
+LTLIBOBJS=''
+MAINT='#'
+MAINTAINER_MODE_FALSE=''
+MAINTAINER_MODE_TRUE='#'
+MAKEINFO='${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing makeinfo'
+MANIFEST_TOOL=':'
+MKDIR_P='/bin/mkdir -p'
+MKNTFS_CPPFLAGS=''
+MKNTFS_LIBS=''
+MV='/bin/mv'
+NM='/usr/bin/nm -B'
+NMEDIT=''
+NTFSPROGS_STATIC_LIBS=''
+NTFS_DEVICE_DEFAULT_IO_OPS_FALSE='#'
+NTFS_DEVICE_DEFAULT_IO_OPS_TRUE=''
+OBJDUMP='objdump'
+OBJEXT='o'
+OTOOL64=''
+OTOOL=''
+OUTPUT_FORMAT=''
+PACKAGE='ntfs-3g'
+PACKAGE_BUGREPORT='ntfs-3g-devel@lists.sf.net'
+PACKAGE_NAME='ntfs-3g'
+PACKAGE_STRING='ntfs-3g 2015.3.14'
+PACKAGE_TARNAME='ntfs-3g'
+PACKAGE_URL=''
+PACKAGE_VERSION='2015.3.14'
+PATH_SEPARATOR=':'
+PKG_CONFIG='/usr/bin/pkg-config'
+PKG_CONFIG_LIBDIR=''
+PKG_CONFIG_PATH=''
+RANLIB='ranlib'
+REALLYSTATIC_FALSE=''
+REALLYSTATIC_TRUE='#'
+RM='/bin/rm'
+RUN_LDCONFIG_FALSE='#'
+RUN_LDCONFIG_TRUE=''
+SED='/bin/sed'
+SET_MAKE=''
+SHELL='/bin/bash'
+STRIP='strip'
+VERSION='2015.3.14'
+WINDOWS_FALSE=''
+WINDOWS_TRUE='#'
+ac_ct_AR='ar'
+ac_ct_CC='gcc'
+ac_ct_DUMPBIN=''
+all_includes=' '
+all_libraries=' '
+am__EXEEXT_FALSE=''
+am__EXEEXT_TRUE='#'
+am__fastdepCC_FALSE='#'
+am__fastdepCC_TRUE=''
+am__include='include'
+am__isrc=''
+am__leading_dot='.'
+am__nodep='_no'
+am__quote=''
+am__tar='$${TAR-tar} chof - "$$tardir"'
+am__untar='$${TAR-tar} xf -'
+bindir='${exec_prefix}/bin'
+build='x86_64-unknown-linux-gnu'
+build_alias=''
+build_cpu='x86_64'
+build_os='linux-gnu'
+build_vendor='unknown'
+datadir='${datarootdir}'
+datarootdir='${prefix}/share'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+dvidir='${docdir}'
+exec_prefix='${prefix}'
+host='x86_64-unknown-linux-gnu'
+host_alias=''
+host_cpu='x86_64'
+host_os='linux-gnu'
+host_vendor='unknown'
+htmldir='${docdir}'
+includedir='${prefix}/include'
+infodir='${datarootdir}/info'
+install_sh='${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/install-sh'
+libdir='${exec_prefix}/lib'
+libexecdir='${exec_prefix}/libexec'
+localedir='${datarootdir}/locale'
+localstatedir='${prefix}/var'
+mandir='${datarootdir}/man'
+mkdir_p='$(MKDIR_P)'
+ntfs3gincludedir='$(includedir)/ntfs-3g'
+oldincludedir='/usr/include'
+pdfdir='${docdir}'
+pkgconfigdir='$(libdir)/pkgconfig'
+prefix='/usr/local'
+program_transform_name='s,x,x,'
+psdir='${docdir}'
+rootbindir='/bin'
+rootlibdir='/lib'
+rootsbindir='/sbin'
+sbindir='${exec_prefix}/sbin'
+sharedstatedir='${prefix}/com'
+sysconfdir='${prefix}/etc'
+target='x86_64-unknown-linux-gnu'
+target_alias=''
+target_cpu='x86_64'
+target_os='linux-gnu'
+target_vendor='unknown'
+
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+
+/* confdefs.h */
+#define PACKAGE_NAME "ntfs-3g"
+#define PACKAGE_TARNAME "ntfs-3g"
+#define PACKAGE_VERSION "2015.3.14"
+#define PACKAGE_STRING "ntfs-3g 2015.3.14"
+#define PACKAGE_BUGREPORT "ntfs-3g-devel@lists.sf.net"
+#define PACKAGE_URL ""
+#define PACKAGE "ntfs-3g"
+#define VERSION "2015.3.14"
+#define STDC_HEADERS 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_SYS_STAT_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STRING_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_STRINGS_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_UNISTD_H 1
+#define __EXTENSIONS__ 1
+#define _ALL_SOURCE 1
+#define _GNU_SOURCE 1
+#define _POSIX_PTHREAD_SEMANTICS 1
+#define _TANDEM_SOURCE 1
+#define HAVE_DLFCN_H 1
+#define LT_OBJDIR ".libs/"
+#define _REENTRANT 1
+#define FUSE_INTERNAL 1
+#define STDC_HEADERS 1
+#define HAVE_CTYPE_H 1
+#define HAVE_FCNTL_H 1
+#define HAVE_LIBGEN_H 1
+#define HAVE_LIBINTL_H 1
+#define HAVE_LIMITS_H 1
+#define HAVE_LOCALE_H 1
+#define HAVE_MNTENT_H 1
+#define HAVE_STDDEF_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STDIO_H 1
+#define HAVE_STDARG_H 1
+#define HAVE_STRING_H 1
+#define HAVE_STRINGS_H 1
+#define HAVE_ERRNO_H 1
+#define HAVE_TIME_H 1
+#define HAVE_UNISTD_H 1
+#define HAVE_UTIME_H 1
+#define HAVE_WCHAR_H 1
+#define HAVE_GETOPT_H 1
+#define HAVE_FEATURES_H 1
+#define HAVE_REGEX_H 1
+#define HAVE_ENDIAN_H 1
+#define HAVE_BYTESWAP_H 1
+#define HAVE_SYS_PARAM_H 1
+#define HAVE_SYS_IOCTL_H 1
+#define HAVE_SYS_MOUNT_H 1
+#define HAVE_SYS_STAT_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_SYS_VFS_H 1
+#define HAVE_SYS_STATVFS_H 1
+#define HAVE_SYS_SYSMACROS_H 1
+#define HAVE_LINUX_MAJOR_H 1
+#define HAVE_LINUX_FD_H 1
+#define HAVE_LINUX_FS_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_LINUX_HDREG_H 1
+#define HAVE_SYSLOG_H 1
+#define HAVE_PWD_H 1
+#define HAVE_MALLOC_H 1
+#define HAVE__BOOL 1
+#define HAVE_STDBOOL_H 1
+#define WORDS_LITTLEENDIAN 1
+#define HAVE_STRUCT_STAT_ST_BLOCKS 1
+#define HAVE_ST_BLOCKS 1
+#define HAVE_STRUCT_STAT_ST_RDEV 1
+#define HAVE_STRUCT_STAT_ST_ATIM 1
+#define HAVE_GETMNTENT 1
+#define HAVE_MBRTOWC 1
+#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1
+#define HAVE_STRFTIME 1
+#define HAVE_UTIME_H 1
+#define HAVE_UTIME_NULL 1
+#define HAVE_VPRINTF 1
+#define HAVE_ATEXIT 1
+#define HAVE_BASENAME 1
+#define HAVE_DAEMON 1
+#define HAVE_DUP2 1
+#define HAVE_FDATASYNC 1
+#define HAVE_FFS 1
+#define HAVE_GETOPT_LONG 1
+#define HAVE_HASMNTOPT 1
+#define HAVE_MBSINIT 1
+#define HAVE_MEMMOVE 1
+#define HAVE_MEMSET 1
+#define HAVE_REALPATH 1
+#define HAVE_REGCOMP 1
+#define HAVE_SETLOCALE 1
+#define HAVE_SETXATTR 1
+#define HAVE_STRCASECMP 1
+#define HAVE_STRCHR 1
+#define HAVE_STRDUP 1
+#define HAVE_STRERROR 1
+#define HAVE_STRNLEN 1
+#define HAVE_STRSEP 1
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+#define HAVE_SYSCONF 1
+#define HAVE_UTIME 1
+#define HAVE_UTIMENSAT 1
+#define HAVE_GETTIMEOFDAY 1
+#define HAVE_CLOCK_GETTIME 1
+#define HAVE_FORK 1
+#define HAVE_MEMCPY 1
+#define HAVE_RANDOM 1
+#define HAVE_SNPRINTF 1
+
+configure: exit 0
diff --git a/config.status b/config.status
new file mode 100755
index 0000000000000000000000000000000000000000..1cf4f7350f74afe5ea6452646d361dbc85eef18b
--- /dev/null
+++ b/config.status
@@ -0,0 +1,2230 @@
+#! /bin/bash
+# Generated by configure.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=${CONFIG_SHELL-/bin/bash}
+export SHELL
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by ntfs-3g $as_me 2015.3.14, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+# Files that config.status was made for.
+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 src/Makefile src/ntfs-3g.8 src/ntfs-3g.probe.8 src/ntfs-3g.usermap.8 src/ntfs-3g.secaudit.8"
+config_headers=" config.h"
+config_commands=" depfiles libtool"
+
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+      --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <ntfs-3g-devel@lists.sf.net>."
+
+ac_cs_config=""
+ac_cs_version="\
+ntfs-3g config.status 2015.3.14
+configured by ./configure, generated by GNU Autoconf 2.69,
+  with options \"$ac_cs_config\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='/home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14'
+srcdir='.'
+INSTALL='/usr/bin/install -c'
+MKDIR_P='/bin/mkdir -p'
+AWK='gawk'
+test -n "$AWK" || AWK=awk
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=?*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  --*=)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    $as_echo "$ac_cs_config"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    '') as_fn_error $? "missing file argument" ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+if $ac_cs_recheck; then
+  set X /bin/bash './configure'  $ac_configure_extra_args --no-create --no-recursion
+  shift
+  $as_echo "running CONFIG_SHELL=/bin/bash $*" >&6
+  CONFIG_SHELL='/bin/bash'
+  export CONFIG_SHELL
+  exec "$@"
+fi
+
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="" ac_aux_dir="."
+
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+macro_version='2.4.2'
+macro_revision='1.3337'
+enable_shared='yes'
+enable_static='yes'
+pic_mode='default'
+enable_fast_install='yes'
+SHELL='/bin/bash'
+ECHO='printf %s\n'
+PATH_SEPARATOR=':'
+host_alias=''
+host='x86_64-unknown-linux-gnu'
+host_os='linux-gnu'
+build_alias=''
+build='x86_64-unknown-linux-gnu'
+build_os='linux-gnu'
+SED='/bin/sed'
+Xsed='/bin/sed -e 1s/^X//'
+GREP='/bin/grep'
+EGREP='/bin/grep -E'
+FGREP='/bin/grep -F'
+LD='/usr/bin/ld -m elf_x86_64'
+NM='/usr/bin/nm -B'
+LN_S='ln -s'
+max_cmd_len='1572864'
+ac_objext='o'
+exeext=''
+lt_unset='unset'
+lt_SP2NL='tr \040 \012'
+lt_NL2SP='tr \015\012 \040\040'
+lt_cv_to_host_file_cmd='func_convert_file_noop'
+lt_cv_to_tool_file_cmd='func_convert_file_noop'
+reload_flag=' -r'
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+OBJDUMP='objdump'
+deplibs_check_method='pass_all'
+file_magic_cmd='$MAGIC_CMD'
+file_magic_glob=''
+want_nocaseglob='no'
+DLLTOOL='false'
+sharedlib_from_linklib_cmd='printf %s\n'
+AR='ar'
+AR_FLAGS='cru'
+archiver_list_spec='@'
+STRIP='strip'
+RANLIB='ranlib'
+old_postinstall_cmds='chmod 644 $oldlib~$RANLIB $tool_oldlib'
+old_postuninstall_cmds=''
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs~$RANLIB $tool_oldlib'
+lock_old_archive_extraction='no'
+CC='gcc'
+CFLAGS='-g -O2 -Wall'
+compiler='gcc'
+GCC='yes'
+lt_cv_sys_global_symbol_pipe='sed -n -e '\''s/^.*[	 ]\([ABCDGIRSTW][ABCDGIRSTW]*\)[	 ][	 ]*\([_A-Za-z][_A-Za-z0-9]*\)$/\1 \2 \2/p'\'' | sed '\''/ __gnu_lto/d'\'''
+lt_cv_sys_global_symbol_to_cdecl='sed -n -e '\''s/^T .* \(.*\)$/extern int \1();/p'\'' -e '\''s/^[ABCDGIRSTW]* .* \(.*\)$/extern char \1;/p'\'''
+lt_cv_sys_global_symbol_to_c_name_address='sed -n -e '\''s/^: \([^ ]*\)[ ]*$/  {\"\1\", (void *) 0},/p'\'' -e '\''s/^[ABCDGIRSTW]* \([^ ]*\) \([^ ]*\)$/  {"\2", (void *) \&\2},/p'\'''
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='sed -n -e '\''s/^: \([^ ]*\)[ ]*$/  {\"\1\", (void *) 0},/p'\'' -e '\''s/^[ABCDGIRSTW]* \([^ ]*\) \(lib[^ ]*\)$/  {"\2", (void *) \&\2},/p'\'' -e '\''s/^[ABCDGIRSTW]* \([^ ]*\) \([^ ]*\)$/  {"lib\2", (void *) \&\2},/p'\'''
+nm_file_list_spec='@'
+lt_sysroot=''
+objdir='.libs'
+MAGIC_CMD='file'
+lt_prog_compiler_no_builtin_flag=' -fno-builtin'
+lt_prog_compiler_pic=' -fPIC -DPIC'
+lt_prog_compiler_wl='-Wl,'
+lt_prog_compiler_static='-static'
+lt_cv_prog_compiler_c_o='yes'
+need_locks='no'
+MANIFEST_TOOL=':'
+DSYMUTIL=''
+NMEDIT=''
+LIPO=''
+OTOOL=''
+OTOOL64=''
+libext='a'
+shrext_cmds='.so'
+extract_expsyms_cmds=''
+archive_cmds_need_lc='no'
+enable_shared_with_static_runtimes='no'
+export_dynamic_flag_spec='${wl}--export-dynamic'
+whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+compiler_needs_object='no'
+old_archive_from_new_cmds=''
+old_archive_from_expsyms_cmds=''
+archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+	    cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+	    echo "local: *; };" >> $output_objdir/$libname.ver~
+	    $CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+module_cmds=''
+module_expsym_cmds=''
+with_gnu_ld='yes'
+allow_undefined_flag=''
+no_undefined_flag=''
+hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+hardcode_libdir_separator=''
+hardcode_direct='no'
+hardcode_direct_absolute='no'
+hardcode_minus_L='no'
+hardcode_shlibpath_var='unsupported'
+hardcode_automatic='no'
+inherit_rpath='no'
+link_all_deplibs='unknown'
+always_export_symbols='no'
+export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+include_expsyms=''
+prelink_cmds=''
+postlink_cmds=''
+file_list_spec=''
+variables_saved_for_relink='PATH LD_LIBRARY_PATH LD_RUN_PATH GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH'
+need_lib_prefix='no'
+need_version='no'
+version_type='linux'
+runpath_var='LD_RUN_PATH'
+shlibpath_var='LD_LIBRARY_PATH'
+shlibpath_overrides_runpath='no'
+libname_spec='lib$name'
+library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+soname_spec='${libname}${release}${shared_ext}$major'
+install_override_mode=''
+postinstall_cmds=''
+postuninstall_cmds=''
+finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+finish_eval=''
+hardcode_into_libs='yes'
+sys_lib_search_path_spec='/usr/lib/gcc/x86_64-linux-gnu/4.8 /usr/lib/x86_64-linux-gnu /usr/lib /lib/x86_64-linux-gnu /lib '
+sys_lib_dlsearch_path_spec='/lib64 /usr/lib64 /lib /usr/lib /usr/lib/x86_64-linux-gnu/libfakeroot /lib/i386-linux-gnu /usr/lib/i386-linux-gnu /lib/i686-linux-gnu /usr/lib/i686-linux-gnu /usr/local/lib /lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu/mesa-egl /usr/lib/x86_64-linux-gnu/mesa /usr/lib/x86_64-linux-gnu/mir/clientplatform/mesa /lib32 /usr/lib32 /libx32 /usr/libx32 '
+hardcode_action='immediate'
+enable_dlopen='unknown'
+enable_dlopen_self='unknown'
+enable_dlopen_self_static='unknown'
+old_striplib='strip --strip-debug'
+striplib='strip --strip-unneeded'
+
+LTCC='gcc'
+LTCFLAGS='-g -O2'
+compiler='gcc'
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+}
+
+# Quote evaled strings.
+for var in SHELL ECHO PATH_SEPARATOR SED GREP EGREP FGREP LD NM LN_S lt_SP2NL lt_NL2SP reload_flag OBJDUMP deplibs_check_method file_magic_cmd file_magic_glob want_nocaseglob DLLTOOL sharedlib_from_linklib_cmd AR AR_FLAGS archiver_list_spec STRIP RANLIB CC CFLAGS compiler lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl lt_cv_sys_global_symbol_to_c_name_address lt_cv_sys_global_symbol_to_c_name_address_lib_prefix nm_file_list_spec lt_prog_compiler_no_builtin_flag lt_prog_compiler_pic lt_prog_compiler_wl lt_prog_compiler_static lt_cv_prog_compiler_c_o need_locks MANIFEST_TOOL DSYMUTIL NMEDIT LIPO OTOOL OTOOL64 shrext_cmds export_dynamic_flag_spec whole_archive_flag_spec compiler_needs_object with_gnu_ld allow_undefined_flag no_undefined_flag hardcode_libdir_flag_spec hardcode_libdir_separator exclude_expsyms include_expsyms file_list_spec variables_saved_for_relink libname_spec library_names_spec soname_spec install_override_mode finish_eval old_striplib striplib; do
+    case `eval \\$ECHO \\""\\$$var"\\"` in
+    *[\\\`\"\$]*)
+      eval "lt_$var=\\\"\`\$ECHO \"\$$var\" | \$SED \"\$sed_quote_subst\"\`\\\""
+      ;;
+    *)
+      eval "lt_$var=\\\"\$$var\\\""
+      ;;
+    esac
+done
+
+# Double-quote double-evaled strings.
+for var in reload_cmds old_postinstall_cmds old_postuninstall_cmds old_archive_cmds extract_expsyms_cmds old_archive_from_new_cmds old_archive_from_expsyms_cmds archive_cmds archive_expsym_cmds module_cmds module_expsym_cmds export_symbols_cmds prelink_cmds postlink_cmds postinstall_cmds postuninstall_cmds finish_cmds sys_lib_search_path_spec sys_lib_dlsearch_path_spec; do
+    case `eval \\$ECHO \\""\\$$var"\\"` in
+    *[\\\`\"\$]*)
+      eval "lt_$var=\\\"\`\$ECHO \"\$$var\" | \$SED -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+      ;;
+    *)
+      eval "lt_$var=\\\"\$$var\\\""
+      ;;
+    esac
+done
+
+ac_aux_dir='.'
+xsi_shell='yes'
+lt_shell_append='yes'
+
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes INIT.
+if test -n "${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+
+
+    PACKAGE='ntfs-3g'
+    VERSION='2015.3.14'
+    TIMESTAMP=''
+    RM='/bin/rm'
+    ofile='libtool'
+
+
+
+
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+    "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+    "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;;
+    "include/fuse-lite/Makefile") CONFIG_FILES="$CONFIG_FILES include/fuse-lite/Makefile" ;;
+    "include/ntfs-3g/Makefile") CONFIG_FILES="$CONFIG_FILES include/ntfs-3g/Makefile" ;;
+    "libfuse-lite/Makefile") CONFIG_FILES="$CONFIG_FILES libfuse-lite/Makefile" ;;
+    "libntfs-3g/Makefile") CONFIG_FILES="$CONFIG_FILES libntfs-3g/Makefile" ;;
+    "libntfs-3g/libntfs-3g.pc") CONFIG_FILES="$CONFIG_FILES libntfs-3g/libntfs-3g.pc" ;;
+    "libntfs-3g/libntfs-3g.script.so") CONFIG_FILES="$CONFIG_FILES libntfs-3g/libntfs-3g.script.so" ;;
+    "ntfsprogs/Makefile") CONFIG_FILES="$CONFIG_FILES ntfsprogs/Makefile" ;;
+    "ntfsprogs/mkntfs.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/mkntfs.8" ;;
+    "ntfsprogs/ntfscat.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfscat.8" ;;
+    "ntfsprogs/ntfsclone.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfsclone.8" ;;
+    "ntfsprogs/ntfscluster.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfscluster.8" ;;
+    "ntfsprogs/ntfscmp.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfscmp.8" ;;
+    "ntfsprogs/ntfscp.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfscp.8" ;;
+    "ntfsprogs/ntfsfix.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfsfix.8" ;;
+    "ntfsprogs/ntfsinfo.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfsinfo.8" ;;
+    "ntfsprogs/ntfslabel.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfslabel.8" ;;
+    "ntfsprogs/ntfsls.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfsls.8" ;;
+    "ntfsprogs/ntfsprogs.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfsprogs.8" ;;
+    "ntfsprogs/ntfsresize.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfsresize.8" ;;
+    "ntfsprogs/ntfsundelete.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfsundelete.8" ;;
+    "ntfsprogs/ntfsdecrypt.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfsdecrypt.8" ;;
+    "ntfsprogs/ntfswipe.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfswipe.8" ;;
+    "ntfsprogs/ntfstruncate.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfstruncate.8" ;;
+    "ntfsprogs/ntfsfallocate.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfsfallocate.8" ;;
+    "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
+    "src/ntfs-3g.8") CONFIG_FILES="$CONFIG_FILES src/ntfs-3g.8" ;;
+    "src/ntfs-3g.probe.8") CONFIG_FILES="$CONFIG_FILES src/ntfs-3g.probe.8" ;;
+    "src/ntfs-3g.usermap.8") CONFIG_FILES="$CONFIG_FILES src/ntfs-3g.usermap.8" ;;
+    "src/ntfs-3g.secaudit.8") CONFIG_FILES="$CONFIG_FILES src/ntfs-3g.secaudit.8" ;;
+
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp= ac_tmp=
+  trap 'exit_status=$?
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+cat >>"$ac_tmp/subs1.awk" <<\_ACAWK &&
+S["am__EXEEXT_FALSE"]=""
+S["am__EXEEXT_TRUE"]="#"
+S["LTLIBOBJS"]=""
+S["ENABLE_QUARANTINED_FALSE"]=""
+S["ENABLE_QUARANTINED_TRUE"]="#"
+S["ENABLE_EXTRAS_FALSE"]=""
+S["ENABLE_EXTRAS_TRUE"]="#"
+S["ENABLE_NTFSPROGS_FALSE"]="#"
+S["ENABLE_NTFSPROGS_TRUE"]=""
+S["ENABLE_NTFS_3G_FALSE"]="#"
+S["ENABLE_NTFS_3G_TRUE"]=""
+S["ENABLE_MOUNT_HELPER_FALSE"]="#"
+S["ENABLE_MOUNT_HELPER_TRUE"]=""
+S["INSTALL_LIBRARY_FALSE"]="#"
+S["INSTALL_LIBRARY_TRUE"]=""
+S["REALLYSTATIC_FALSE"]=""
+S["REALLYSTATIC_TRUE"]="#"
+S["RUN_LDCONFIG_FALSE"]="#"
+S["RUN_LDCONFIG_TRUE"]=""
+S["NTFS_DEVICE_DEFAULT_IO_OPS_FALSE"]="#"
+S["NTFS_DEVICE_DEFAULT_IO_OPS_TRUE"]=""
+S["WINDOWS_FALSE"]=""
+S["WINDOWS_TRUE"]="#"
+S["GENERATE_LDSCRIPT_FALSE"]=""
+S["GENERATE_LDSCRIPT_TRUE"]="#"
+S["FUSE_INTERNAL_FALSE"]="#"
+S["FUSE_INTERNAL_TRUE"]=""
+S["OUTPUT_FORMAT"]=""
+S["NTFSPROGS_STATIC_LIBS"]=""
+S["LIBNTFS_LIBS"]=""
+S["LIBNTFS_CPPFLAGS"]=""
+S["MKNTFS_LIBS"]=""
+S["MKNTFS_CPPFLAGS"]=""
+S["LIBFUSE_LITE_LIBS"]=" -lpthread"
+S["LIBFUSE_LITE_CFLAGS"]=""
+S["LIBNTFS_3G_VERSION"]="86"
+S["rootlibdir"]="/lib"
+S["rootsbindir"]="/sbin"
+S["rootbindir"]="/bin"
+S["ntfs3gincludedir"]="$(includedir)/ntfs-3g"
+S["pkgconfigdir"]="$(libdir)/pkgconfig"
+S["LIBOBJS"]=""
+S["all_libraries"]=" "
+S["all_includes"]=" "
+S["ENABLE_CRYPTO_FALSE"]=""
+S["ENABLE_CRYPTO_TRUE"]="#"
+S["GNUTLS_LIBS"]=""
+S["GNUTLS_CFLAGS"]=""
+S["LIBGCRYPT_LIBS"]=""
+S["LIBGCRYPT_CFLAGS"]=""
+S["LIBGCRYPT_CONFIG"]=""
+S["FUSE_MODULE_LIBS"]=""
+S["FUSE_MODULE_CFLAGS"]=""
+S["LDCONFIG"]="/sbin/ldconfig"
+S["RM"]="/bin/rm"
+S["MV"]="/bin/mv"
+S["PKG_CONFIG_LIBDIR"]=""
+S["PKG_CONFIG_PATH"]=""
+S["PKG_CONFIG"]="/usr/bin/pkg-config"
+S["OTOOL64"]=""
+S["OTOOL"]=""
+S["LIPO"]=""
+S["NMEDIT"]=""
+S["DSYMUTIL"]=""
+S["MANIFEST_TOOL"]=":"
+S["RANLIB"]="ranlib"
+S["ac_ct_AR"]="ar"
+S["AR"]="ar"
+S["DLLTOOL"]="false"
+S["OBJDUMP"]="objdump"
+S["NM"]="/usr/bin/nm -B"
+S["ac_ct_DUMPBIN"]=""
+S["DUMPBIN"]=""
+S["LD"]="/usr/bin/ld -m elf_x86_64"
+S["FGREP"]="/bin/grep -F"
+S["SED"]="/bin/sed"
+S["LIBTOOL"]="$(SHELL) $(top_builddir)/libtool"
+S["LN_S"]="ln -s"
+S["EGREP"]="/bin/grep -E"
+S["GREP"]="/bin/grep"
+S["CPP"]="gcc -E"
+S["am__fastdepCC_FALSE"]="#"
+S["am__fastdepCC_TRUE"]=""
+S["CCDEPMODE"]="depmode=gcc3"
+S["am__nodep"]="_no"
+S["AMDEPBACKSLASH"]="\\"
+S["AMDEP_FALSE"]="#"
+S["AMDEP_TRUE"]=""
+S["am__quote"]=""
+S["am__include"]="include"
+S["DEPDIR"]=".deps"
+S["OBJEXT"]="o"
+S["EXEEXT"]=""
+S["ac_ct_CC"]="gcc"
+S["CPPFLAGS"]=""
+S["LDFLAGS"]=""
+S["CFLAGS"]="-g -O2 -Wall"
+S["CC"]="gcc"
+S["MAINT"]="#"
+S["MAINTAINER_MODE_FALSE"]=""
+S["MAINTAINER_MODE_TRUE"]="#"
+S["AM_BACKSLASH"]="\\"
+S["AM_DEFAULT_VERBOSITY"]="1"
+S["AM_DEFAULT_V"]="$(AM_DEFAULT_VERBOSITY)"
+S["AM_V"]="$(V)"
+S["am__untar"]="$${TAR-tar} xf -"
+S["am__tar"]="$${TAR-tar} chof - \"$$tardir\""
+S["AMTAR"]="$${TAR-tar}"
+S["am__leading_dot"]="."
+S["SET_MAKE"]=""
+S["AWK"]="gawk"
+S["mkdir_p"]="$(MKDIR_P)"
+S["MKDIR_P"]="/bin/mkdir -p"
+S["INSTALL_STRIP_PROGRAM"]="$(install_sh) -c -s"
+S["STRIP"]="strip"
+S["install_sh"]="${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/install-sh"
+S["MAKEINFO"]="${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing makeinfo"
+S["AUTOHEADER"]="${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing autoheader"
+S["AUTOMAKE"]="${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing automake-1.14"
+S["AUTOCONF"]="${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing autoconf"
+S["ACLOCAL"]="${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing aclocal-1.14"
+S["VERSION"]="2015.3.14"
+S["PACKAGE"]="ntfs-3g"
+S["CYGPATH_W"]="echo"
+S["am__isrc"]=""
+S["INSTALL_DATA"]="${INSTALL} -m 644"
+S["INSTALL_SCRIPT"]="${INSTALL}"
+S["INSTALL_PROGRAM"]="${INSTALL}"
+S["target_os"]="linux-gnu"
+S["target_vendor"]="unknown"
+S["target_cpu"]="x86_64"
+S["target"]="x86_64-unknown-linux-gnu"
+S["host_os"]="linux-gnu"
+S["host_vendor"]="unknown"
+S["host_cpu"]="x86_64"
+S["host"]="x86_64-unknown-linux-gnu"
+S["build_os"]="linux-gnu"
+S["build_vendor"]="unknown"
+S["build_cpu"]="x86_64"
+S["build"]="x86_64-unknown-linux-gnu"
+S["target_alias"]=""
+S["host_alias"]=""
+S["build_alias"]=""
+S["LIBS"]=""
+S["ECHO_T"]=""
+S["ECHO_N"]="-n"
+S["ECHO_C"]=""
+S["DEFS"]="-DHAVE_CONFIG_H"
+S["mandir"]="${datarootdir}/man"
+S["localedir"]="${datarootdir}/locale"
+S["libdir"]="${exec_prefix}/lib"
+S["psdir"]="${docdir}"
+S["pdfdir"]="${docdir}"
+S["dvidir"]="${docdir}"
+S["htmldir"]="${docdir}"
+S["infodir"]="${datarootdir}/info"
+S["docdir"]="${datarootdir}/doc/${PACKAGE_TARNAME}"
+S["oldincludedir"]="/usr/include"
+S["includedir"]="${prefix}/include"
+S["localstatedir"]="${prefix}/var"
+S["sharedstatedir"]="${prefix}/com"
+S["sysconfdir"]="${prefix}/etc"
+S["datadir"]="${datarootdir}"
+S["datarootdir"]="${prefix}/share"
+S["libexecdir"]="${exec_prefix}/libexec"
+S["sbindir"]="${exec_prefix}/sbin"
+S["bindir"]="${exec_prefix}/bin"
+S["program_transform_name"]="s,x,x,"
+S["prefix"]="/usr/local"
+S["exec_prefix"]="${prefix}"
+S["PACKAGE_URL"]=""
+S["PACKAGE_BUGREPORT"]="ntfs-3g-devel@lists.sf.net"
+S["PACKAGE_STRING"]="ntfs-3g 2015.3.14"
+S["PACKAGE_VERSION"]="2015.3.14"
+S["PACKAGE_TARNAME"]="ntfs-3g"
+S["PACKAGE_NAME"]="ntfs-3g"
+S["PATH_SEPARATOR"]=":"
+S["SHELL"]="/bin/bash"
+_ACAWK
+cat >>"$ac_tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+D["PACKAGE_NAME"]=" \"ntfs-3g\""
+D["PACKAGE_TARNAME"]=" \"ntfs-3g\""
+D["PACKAGE_VERSION"]=" \"2015.3.14\""
+D["PACKAGE_STRING"]=" \"ntfs-3g 2015.3.14\""
+D["PACKAGE_BUGREPORT"]=" \"ntfs-3g-devel@lists.sf.net\""
+D["PACKAGE_URL"]=" \"\""
+D["PACKAGE"]=" \"ntfs-3g\""
+D["VERSION"]=" \"2015.3.14\""
+D["STDC_HEADERS"]=" 1"
+D["HAVE_SYS_TYPES_H"]=" 1"
+D["HAVE_SYS_STAT_H"]=" 1"
+D["HAVE_STDLIB_H"]=" 1"
+D["HAVE_STRING_H"]=" 1"
+D["HAVE_MEMORY_H"]=" 1"
+D["HAVE_STRINGS_H"]=" 1"
+D["HAVE_INTTYPES_H"]=" 1"
+D["HAVE_STDINT_H"]=" 1"
+D["HAVE_UNISTD_H"]=" 1"
+D["__EXTENSIONS__"]=" 1"
+D["_ALL_SOURCE"]=" 1"
+D["_GNU_SOURCE"]=" 1"
+D["_POSIX_PTHREAD_SEMANTICS"]=" 1"
+D["_TANDEM_SOURCE"]=" 1"
+D["HAVE_DLFCN_H"]=" 1"
+D["LT_OBJDIR"]=" \".libs/\""
+D["_REENTRANT"]=" 1"
+D["FUSE_INTERNAL"]=" 1"
+D["STDC_HEADERS"]=" 1"
+D["HAVE_CTYPE_H"]=" 1"
+D["HAVE_FCNTL_H"]=" 1"
+D["HAVE_LIBGEN_H"]=" 1"
+D["HAVE_LIBINTL_H"]=" 1"
+D["HAVE_LIMITS_H"]=" 1"
+D["HAVE_LOCALE_H"]=" 1"
+D["HAVE_MNTENT_H"]=" 1"
+D["HAVE_STDDEF_H"]=" 1"
+D["HAVE_STDINT_H"]=" 1"
+D["HAVE_STDLIB_H"]=" 1"
+D["HAVE_STDIO_H"]=" 1"
+D["HAVE_STDARG_H"]=" 1"
+D["HAVE_STRING_H"]=" 1"
+D["HAVE_STRINGS_H"]=" 1"
+D["HAVE_ERRNO_H"]=" 1"
+D["HAVE_TIME_H"]=" 1"
+D["HAVE_UNISTD_H"]=" 1"
+D["HAVE_UTIME_H"]=" 1"
+D["HAVE_WCHAR_H"]=" 1"
+D["HAVE_GETOPT_H"]=" 1"
+D["HAVE_FEATURES_H"]=" 1"
+D["HAVE_REGEX_H"]=" 1"
+D["HAVE_ENDIAN_H"]=" 1"
+D["HAVE_BYTESWAP_H"]=" 1"
+D["HAVE_SYS_PARAM_H"]=" 1"
+D["HAVE_SYS_IOCTL_H"]=" 1"
+D["HAVE_SYS_MOUNT_H"]=" 1"
+D["HAVE_SYS_STAT_H"]=" 1"
+D["HAVE_SYS_TYPES_H"]=" 1"
+D["HAVE_SYS_VFS_H"]=" 1"
+D["HAVE_SYS_STATVFS_H"]=" 1"
+D["HAVE_SYS_SYSMACROS_H"]=" 1"
+D["HAVE_LINUX_MAJOR_H"]=" 1"
+D["HAVE_LINUX_FD_H"]=" 1"
+D["HAVE_LINUX_FS_H"]=" 1"
+D["HAVE_INTTYPES_H"]=" 1"
+D["HAVE_LINUX_HDREG_H"]=" 1"
+D["HAVE_SYSLOG_H"]=" 1"
+D["HAVE_PWD_H"]=" 1"
+D["HAVE_MALLOC_H"]=" 1"
+D["HAVE__BOOL"]=" 1"
+D["HAVE_STDBOOL_H"]=" 1"
+D["WORDS_LITTLEENDIAN"]=" 1"
+D["HAVE_STRUCT_STAT_ST_BLOCKS"]=" 1"
+D["HAVE_ST_BLOCKS"]=" 1"
+D["HAVE_STRUCT_STAT_ST_RDEV"]=" 1"
+D["HAVE_STRUCT_STAT_ST_ATIM"]=" 1"
+D["HAVE_GETMNTENT"]=" 1"
+D["HAVE_MBRTOWC"]=" 1"
+D["LSTAT_FOLLOWS_SLASHED_SYMLINK"]=" 1"
+D["HAVE_STRFTIME"]=" 1"
+D["HAVE_UTIME_H"]=" 1"
+D["HAVE_UTIME_NULL"]=" 1"
+D["HAVE_VPRINTF"]=" 1"
+D["HAVE_ATEXIT"]=" 1"
+D["HAVE_BASENAME"]=" 1"
+D["HAVE_DAEMON"]=" 1"
+D["HAVE_DUP2"]=" 1"
+D["HAVE_FDATASYNC"]=" 1"
+D["HAVE_FFS"]=" 1"
+D["HAVE_GETOPT_LONG"]=" 1"
+D["HAVE_HASMNTOPT"]=" 1"
+D["HAVE_MBSINIT"]=" 1"
+D["HAVE_MEMMOVE"]=" 1"
+D["HAVE_MEMSET"]=" 1"
+D["HAVE_REALPATH"]=" 1"
+D["HAVE_REGCOMP"]=" 1"
+D["HAVE_SETLOCALE"]=" 1"
+D["HAVE_SETXATTR"]=" 1"
+D["HAVE_STRCASECMP"]=" 1"
+D["HAVE_STRCHR"]=" 1"
+D["HAVE_STRDUP"]=" 1"
+D["HAVE_STRERROR"]=" 1"
+D["HAVE_STRNLEN"]=" 1"
+D["HAVE_STRSEP"]=" 1"
+D["HAVE_STRTOL"]=" 1"
+D["HAVE_STRTOUL"]=" 1"
+D["HAVE_SYSCONF"]=" 1"
+D["HAVE_UTIME"]=" 1"
+D["HAVE_UTIMENSAT"]=" 1"
+D["HAVE_GETTIMEOFDAY"]=" 1"
+D["HAVE_CLOCK_GETTIME"]=" 1"
+D["HAVE_FORK"]=" 1"
+D["HAVE_MEMCPY"]=" 1"
+D["HAVE_RANDOM"]=" 1"
+D["HAVE_SNPRINTF"]=" 1"
+  for (key in D) D_is_set[key] = 1
+  FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+[_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ][_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]*([\t (]|$)/ {
+  line = $ 0
+  split(line, arg, " ")
+  if (arg[1] == "#") {
+    defundef = arg[2]
+    mac1 = arg[3]
+  } else {
+    defundef = substr(arg[1], 2)
+    mac1 = arg[2]
+  }
+  split(mac1, mac2, "(") #)
+  macro = mac2[1]
+  prefix = substr(line, 1, index(line, defundef) - 1)
+  if (D_is_set[macro]) {
+    # Preserve the white space surrounding the "#".
+    print prefix "define", macro P[macro] D[macro]
+    next
+  } else {
+    # Replace #undef with comments.  This is necessary, for example,
+    # in the case of _POSIX_SOURCE, which is predefined and required
+    # on some systems where configure will not decide to define it.
+    if (defundef == "undef") {
+      print "/*", prefix defundef, macro, "*/"
+      next
+    }
+  }
+}
+{ print }
+_ACAWK
+  as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$ac_tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+  ac_MKDIR_P=$MKDIR_P
+  case $MKDIR_P in
+  [\\/$]* | ?:[\\/]* ) ;;
+  */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+  esac
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+  ac_datarootdir_hack='
+  s&@datadir@&${datarootdir}&g
+  s&@docdir@&${datarootdir}/doc/${PACKAGE_TARNAME}&g
+  s&@infodir@&${datarootdir}/info&g
+  s&@localedir@&${datarootdir}/locale&g
+  s&@mandir@&${datarootdir}/man&g
+  s&\${datarootdir}&${prefix}/share&g' ;;
+esac
+ac_sed_extra="/^[	 ]*VPATH[	 ]*=[	 ]*/{
+h
+s///
+s/^/:/
+s/[	 ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[	 ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[	 ]*$//
+}
+
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&2;}
+
+  rm -f "$ac_tmp/stdin"
+  case $ac_file in
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+  if test x"$ac_file" != x-; then
+    {
+      $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+    } >"$ac_tmp/config.h" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f "$ac_file"
+      mv "$ac_tmp/config.h" "$ac_file" \
+	|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    fi
+  else
+    $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+      || as_fn_error $? "could not create -" "$LINENO" 5
+  fi
+# Compute "$ac_file"'s index in $config_headers.
+_am_arg="$ac_file"
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$_am_arg" : 'X\(//\)[^/]' \| \
+	 X"$_am_arg" : 'X\(//\)$' \| \
+	 X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$_am_arg" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+  :C)  { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+  esac
+
+
+  case $ac_file$ac_mode in
+    "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
+  # Older Autoconf quotes --file arguments for eval, but not when files
+  # are listed without --file.  Let's play safe and only enable the eval
+  # if we detect the quoting.
+  case $CONFIG_FILES in
+  *\'*) eval set x "$CONFIG_FILES" ;;
+  *)   set x $CONFIG_FILES ;;
+  esac
+  shift
+  for mf
+  do
+    # Strip MF so we end up with the name of the file.
+    mf=`echo "$mf" | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile or not.
+    # We used to match only the files named 'Makefile.in', but
+    # some people rename them; so instead we look at the file content.
+    # Grep'ing the first line is not enough: some people post-process
+    # each Makefile.in and add a new line on top of each file to say so.
+    # Grep'ing the whole file is not good either: AIX grep has a line
+    # limit of 2048, but all sed's we know have understand at least 4000.
+    if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+      dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$mf" : 'X\(//\)[^/]' \| \
+	 X"$mf" : 'X\(//\)$' \| \
+	 X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$mf" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+    else
+      continue
+    fi
+    # Extract the definition of DEPDIR, am__include, and am__quote
+    # from the Makefile without running 'make'.
+    DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+    test -z "$DEPDIR" && continue
+    am__include=`sed -n 's/^am__include = //p' < "$mf"`
+    test -z "$am__include" && continue
+    am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+    # Find all dependency output files, they are included files with
+    # $(DEPDIR) in their names.  We invoke sed twice because it is the
+    # simplest approach to changing $(DEPDIR) to its actual value in the
+    # expansion.
+    for file in `sed -n "
+      s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+	 sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
+      # Make sure the directory exists.
+      test -f "$dirpart/$file" && continue
+      fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$file" : 'X\(//\)[^/]' \| \
+	 X"$file" : 'X\(//\)$' \| \
+	 X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      as_dir=$dirpart/$fdir; as_fn_mkdir_p
+      # echo "creating $dirpart/$file"
+      echo '# dummy' > "$dirpart/$file"
+    done
+  done
+}
+ ;;
+    "libtool":C)
+
+    # See if we are running on zsh, and set the options which allow our
+    # commands through without removal of \ escapes.
+    if test -n "${ZSH_VERSION+set}" ; then
+      setopt NO_GLOB_SUBST
+    fi
+
+    cfgfile="${ofile}T"
+    trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+    $RM "$cfgfile"
+
+    cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+
+# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+#                 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+#                 Foundation, Inc.
+#   Written by Gordon Matzigkeit, 1996
+#
+#   This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can 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.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that 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 GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+# The names of the tagged configurations supported by this script.
+available_tags=""
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Which release of libtool.m4 was used?
+macro_version=$macro_version
+macro_revision=$macro_revision
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# What type of objects to build.
+pic_mode=$pic_mode
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# An echo program that protects backslashes.
+ECHO=$lt_ECHO
+
+# The PATH separator for the build system.
+PATH_SEPARATOR=$lt_PATH_SEPARATOR
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="\$SED -e 1s/^X//"
+
+# A grep program that handles long lines.
+GREP=$lt_GREP
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# A literal string matcher.
+FGREP=$lt_FGREP
+
+# A BSD- or MS-compatible name lister.
+NM=$lt_NM
+
+# Whether we need soft or hard links.
+LN_S=$lt_LN_S
+
+# What is the maximum length of a command?
+max_cmd_len=$max_cmd_len
+
+# Object file suffix (normally "o").
+objext=$ac_objext
+
+# Executable file suffix (normally "").
+exeext=$exeext
+
+# whether the shell understands "unset".
+lt_unset=$lt_unset
+
+# turn spaces into newlines.
+SP2NL=$lt_lt_SP2NL
+
+# turn newlines into spaces.
+NL2SP=$lt_lt_NL2SP
+
+# convert \$build file names to \$host format.
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+
+# convert \$build files to toolchain format.
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+
+# An object symbol dumper.
+OBJDUMP=$lt_OBJDUMP
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method = "file_magic".
+file_magic_cmd=$lt_file_magic_cmd
+
+# How to find potential files when deplibs_check_method = "file_magic".
+file_magic_glob=$lt_file_magic_glob
+
+# Find potential files using nocaseglob when deplibs_check_method = "file_magic".
+want_nocaseglob=$lt_want_nocaseglob
+
+# DLL creation program.
+DLLTOOL=$lt_DLLTOOL
+
+# Command to associate shared and link libraries.
+sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd
+
+# The archiver.
+AR=$lt_AR
+
+# Flags to create an archive.
+AR_FLAGS=$lt_AR_FLAGS
+
+# How to feed a file listing to the archiver.
+archiver_list_spec=$lt_archiver_list_spec
+
+# A symbol stripping program.
+STRIP=$lt_STRIP
+
+# Commands used to install an old-style archive.
+RANLIB=$lt_RANLIB
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Whether to use a lock for old archive extraction.
+lock_old_archive_extraction=$lock_old_archive_extraction
+
+# A C compiler.
+LTCC=$lt_CC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_CFLAGS
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration.
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair.
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# Transform the output of nm in a C name address pair when lib prefix is needed.
+global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
+
+# Specify filename containing input files for \$NM.
+nm_file_list_spec=$lt_nm_file_list_spec
+
+# The root where to search for dependent libraries,and in which our libraries should be installed.
+lt_sysroot=$lt_sysroot
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# Used to examine libraries when file_magic_cmd begins with "file".
+MAGIC_CMD=$MAGIC_CMD
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Manifest tool.
+MANIFEST_TOOL=$lt_MANIFEST_TOOL
+
+# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
+DSYMUTIL=$lt_DSYMUTIL
+
+# Tool to change global to local symbols on Mac OS X.
+NMEDIT=$lt_NMEDIT
+
+# Tool to manipulate fat objects and archives on Mac OS X.
+LIPO=$lt_LIPO
+
+# ldd/readelf like tool for Mach-O binaries on Mac OS X.
+OTOOL=$lt_OTOOL
+
+# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
+OTOOL64=$lt_OTOOL64
+
+# Old archive suffix (normally "a").
+libext=$libext
+
+# Shared library suffix (normally ".so").
+shrext_cmds=$lt_shrext_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at link time.
+variables_saved_for_relink=$lt_variables_saved_for_relink
+
+# Do we need the "lib" prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Library versioning type.
+version_type=$version_type
+
+# Shared library runtime path variable.
+runpath_var=$runpath_var
+
+# Shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Permission mode override for installation of shared libraries.
+install_override_mode=$lt_install_override_mode
+
+# Command to use after installation of a shared archive.
+postinstall_cmds=$lt_postinstall_cmds
+
+# Command to use after uninstallation of a shared archive.
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# As "finish_cmds", except a single script fragment to be evaled but
+# not shown.
+finish_eval=$lt_finish_eval
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Compile-time system search path for libraries.
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries.
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# Commands used to build an old-style archive.
+old_archive_cmds=$lt_old_archive_cmds
+
+# A language specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU compiler?
+with_gcc=$GCC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object=$lt_compiler_needs_object
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld=$lt_with_gnu_ld
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting \${shlibpath_var} if the
+# library is relocated.
+hardcode_direct_absolute=$hardcode_direct_absolute
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=$hardcode_automatic
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=$inherit_rpath
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=$lt_prelink_cmds
+
+# Commands necessary for finishing linking programs.
+postlink_cmds=$lt_postlink_cmds
+
+# Specify filename containing input files.
+file_list_spec=$lt_file_list_spec
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+  case $host_os in
+  aix3*)
+    cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+_LT_EOF
+    ;;
+  esac
+
+
+ltmain="$ac_aux_dir/ltmain.sh"
+
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '$q' "$ltmain" >> "$cfgfile" \
+     || (rm -f "$cfgfile"; exit 1)
+
+  if test x"$xsi_shell" = xyes; then
+  sed -e '/^func_dirname ()$/,/^} # func_dirname /c\
+func_dirname ()\
+{\
+\    case ${1} in\
+\      */*) func_dirname_result="${1%/*}${2}" ;;\
+\      *  ) func_dirname_result="${3}" ;;\
+\    esac\
+} # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_basename ()$/,/^} # func_basename /c\
+func_basename ()\
+{\
+\    func_basename_result="${1##*/}"\
+} # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\
+func_dirname_and_basename ()\
+{\
+\    case ${1} in\
+\      */*) func_dirname_result="${1%/*}${2}" ;;\
+\      *  ) func_dirname_result="${3}" ;;\
+\    esac\
+\    func_basename_result="${1##*/}"\
+} # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_stripname ()$/,/^} # func_stripname /c\
+func_stripname ()\
+{\
+\    # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\
+\    # positional parameters, so assign one to ordinary parameter first.\
+\    func_stripname_result=${3}\
+\    func_stripname_result=${func_stripname_result#"${1}"}\
+\    func_stripname_result=${func_stripname_result%"${2}"}\
+} # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\
+func_split_long_opt ()\
+{\
+\    func_split_long_opt_name=${1%%=*}\
+\    func_split_long_opt_arg=${1#*=}\
+} # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\
+func_split_short_opt ()\
+{\
+\    func_split_short_opt_arg=${1#??}\
+\    func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\
+} # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\
+func_lo2o ()\
+{\
+\    case ${1} in\
+\      *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\
+\      *)    func_lo2o_result=${1} ;;\
+\    esac\
+} # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_xform ()$/,/^} # func_xform /c\
+func_xform ()\
+{\
+    func_xform_result=${1%.*}.lo\
+} # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_arith ()$/,/^} # func_arith /c\
+func_arith ()\
+{\
+    func_arith_result=$(( $* ))\
+} # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_len ()$/,/^} # func_len /c\
+func_len ()\
+{\
+    func_len_result=${#1}\
+} # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+fi
+
+if test x"$lt_shell_append" = xyes; then
+  sed -e '/^func_append ()$/,/^} # func_append /c\
+func_append ()\
+{\
+    eval "${1}+=\\${2}"\
+} # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\
+func_append_quoted ()\
+{\
+\    func_quote_for_eval "${2}"\
+\    eval "${1}+=\\\\ \\$func_quote_for_eval_result"\
+} # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  # Save a `func_append' function call where possible by direct use of '+='
+  sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \
+    && mv -f "$cfgfile.tmp" "$cfgfile" \
+      || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+  test 0 -eq $? || _lt_function_replace_fail=:
+else
+  # Save a `func_append' function call even when '+=' is not available
+  sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \
+    && mv -f "$cfgfile.tmp" "$cfgfile" \
+      || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+  test 0 -eq $? || _lt_function_replace_fail=:
+fi
+
+if test x"$_lt_function_replace_fail" = x":"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5
+$as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;}
+fi
+
+
+   mv -f "$cfgfile" "$ofile" ||
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+
+ ;;
+
+  esac
+done # for ac_tag
+
+
+as_fn_exit 0
diff --git a/config.sub b/config.sub
new file mode 100755
index 0000000000000000000000000000000000000000..66c5074366061bb12d524ec56b75fd1caf9da336
--- /dev/null
+++ b/config.sub
@@ -0,0 +1,1798 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright 1992-2014 Free Software Foundation, Inc.
+
+timestamp='2014-07-28'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+
+
+# Please send patches with a ChangeLog entry to config-patches@gnu.org.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright 1992-2014 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit ;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+  linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+  knetbsd*-gnu* | netbsd*-gnu* | \
+  kopensolaris*-gnu* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  android-linux)
+    os=-linux-android
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+	-apple | -axis | -knuth | -cray | -microblaze*)
+		os=
+		basic_machine=$1
+		;;
+	-bluegene*)
+		os=-cnk
+		;;
+	-sim | -cisco | -oki | -wec | -winbond)
+		os=
+		basic_machine=$1
+		;;
+	-scout)
+		;;
+	-wrs)
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-chorusos*)
+		os=-chorusos
+		basic_machine=$1
+		;;
+	-chorusrdb)
+		os=-chorusrdb
+		basic_machine=$1
+		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco6)
+		os=-sco5v6
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5)
+		os=-sco3.2v5
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5v6*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-udk*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-lynx*178)
+		os=-lynxos178
+		;;
+	-lynx*5)
+		os=-lynxos5
+		;;
+	-lynx*)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-windowsnt*)
+		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+		;;
+	-psos*)
+		os=-psos
+		;;
+	-mint | -mint[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+	# Recognize the basic CPU types without company name.
+	# Some are omitted here because they have special meanings below.
+	1750a | 580 \
+	| a29k \
+	| aarch64 | aarch64_be \
+	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+	| am33_2.0 \
+	| arc | arceb \
+	| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+	| avr | avr32 \
+	| be32 | be64 \
+	| bfin \
+	| c4x | c8051 | clipper \
+	| d10v | d30v | dlx | dsp16xx \
+	| epiphany \
+	| fido | fr30 | frv \
+	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| hexagon \
+	| i370 | i860 | i960 | ia64 \
+	| ip2k | iq2000 \
+	| k1om \
+	| le32 | le64 \
+	| lm32 \
+	| m32c | m32r | m32rle | m68000 | m68k | m88k \
+	| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
+	| mips | mipsbe | mipseb | mipsel | mipsle \
+	| mips16 \
+	| mips64 | mips64el \
+	| mips64octeon | mips64octeonel \
+	| mips64orion | mips64orionel \
+	| mips64r5900 | mips64r5900el \
+	| mips64vr | mips64vrel \
+	| mips64vr4100 | mips64vr4100el \
+	| mips64vr4300 | mips64vr4300el \
+	| mips64vr5000 | mips64vr5000el \
+	| mips64vr5900 | mips64vr5900el \
+	| mipsisa32 | mipsisa32el \
+	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa32r6 | mipsisa32r6el \
+	| mipsisa64 | mipsisa64el \
+	| mipsisa64r2 | mipsisa64r2el \
+	| mipsisa64r6 | mipsisa64r6el \
+	| mipsisa64sb1 | mipsisa64sb1el \
+	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipsr5900 | mipsr5900el \
+	| mipstx39 | mipstx39el \
+	| mn10200 | mn10300 \
+	| moxie \
+	| mt \
+	| msp430 \
+	| nds32 | nds32le | nds32be \
+	| nios | nios2 | nios2eb | nios2el \
+	| ns16k | ns32k \
+	| open8 | or1k | or1knd | or32 \
+	| pdp10 | pdp11 | pj | pjl \
+	| powerpc | powerpc64 | powerpc64le | powerpcle \
+	| pyramid \
+	| rl78 | rx \
+	| score \
+	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+	| sh64 | sh64le \
+	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+	| spu \
+	| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+	| ubicom32 \
+	| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+	| we32k \
+	| x86 | xc16x | xstormy16 | xtensa \
+	| z8k | z80)
+		basic_machine=$basic_machine-unknown
+		;;
+	c54x)
+		basic_machine=tic54x-unknown
+		;;
+	c55x)
+		basic_machine=tic55x-unknown
+		;;
+	c6x)
+		basic_machine=tic6x-unknown
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+		;;
+	ms1)
+		basic_machine=mt-unknown
+		;;
+
+	strongarm | thumb | xscale)
+		basic_machine=arm-unknown
+		;;
+	xgate)
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	xscaleeb)
+		basic_machine=armeb-unknown
+		;;
+
+	xscaleel)
+		basic_machine=armel-unknown
+		;;
+
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+	  basic_machine=$basic_machine-pc
+	  ;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	580-* \
+	| a29k-* \
+	| aarch64-* | aarch64_be-* \
+	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
+	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+	| avr-* | avr32-* \
+	| be32-* | be64-* \
+	| bfin-* | bs2000-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* \
+	| c8051-* | clipper-* | craynv-* | cydra-* \
+	| d10v-* | d30v-* | dlx-* \
+	| elxsi-* \
+	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+	| h8300-* | h8500-* \
+	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| hexagon-* \
+	| i*86-* | i860-* | i960-* | ia64-* \
+	| ip2k-* | iq2000-* \
+	| k1om-* \
+	| le32-* | le64-* \
+	| lm32-* \
+	| m32c-* | m32r-* | m32rle-* \
+	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+	| microblaze-* | microblazeel-* \
+	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+	| mips16-* \
+	| mips64-* | mips64el-* \
+	| mips64octeon-* | mips64octeonel-* \
+	| mips64orion-* | mips64orionel-* \
+	| mips64r5900-* | mips64r5900el-* \
+	| mips64vr-* | mips64vrel-* \
+	| mips64vr4100-* | mips64vr4100el-* \
+	| mips64vr4300-* | mips64vr4300el-* \
+	| mips64vr5000-* | mips64vr5000el-* \
+	| mips64vr5900-* | mips64vr5900el-* \
+	| mipsisa32-* | mipsisa32el-* \
+	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa32r6-* | mipsisa32r6el-* \
+	| mipsisa64-* | mipsisa64el-* \
+	| mipsisa64r2-* | mipsisa64r2el-* \
+	| mipsisa64r6-* | mipsisa64r6el-* \
+	| mipsisa64sb1-* | mipsisa64sb1el-* \
+	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipsr5900-* | mipsr5900el-* \
+	| mipstx39-* | mipstx39el-* \
+	| mmix-* \
+	| mt-* \
+	| msp430-* \
+	| nds32-* | nds32le-* | nds32be-* \
+	| nios-* | nios2-* | nios2eb-* | nios2el-* \
+	| none-* | np1-* | ns16k-* | ns32k-* \
+	| open8-* \
+	| or1k*-* \
+	| orion-* \
+	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+	| pyramid-* \
+	| rl78-* | romp-* | rs6000-* | rx-* \
+	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+	| sparclite-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+	| tahoe-* \
+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+	| tile*-* \
+	| tron-* \
+	| ubicom32-* \
+	| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+	| vax-* \
+	| we32k-* \
+	| x86-* | x86_64-* | xc16x-* | xps100-* \
+	| xstormy16-* | xtensa*-* \
+	| ymp-* \
+	| z8k-* | z80-*)
+		;;
+	# Recognize the basic CPU types without company name, with glob match.
+	xtensa*)
+		basic_machine=$basic_machine-unknown
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	386bsd)
+		basic_machine=i386-unknown
+		os=-bsd
+		;;
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	a29khif)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	abacus)
+		basic_machine=abacus-unknown
+		;;
+	adobe68k)
+		basic_machine=m68010-adobe
+		os=-scout
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amd64)
+		basic_machine=x86_64-pc
+		;;
+	amd64-*)
+		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-unknown
+		;;
+	amigaos | amigados)
+		basic_machine=m68k-unknown
+		os=-amigaos
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-unknown
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	apollo68bsd)
+		basic_machine=m68k-apollo
+		os=-bsd
+		;;
+	aros)
+		basic_machine=i386-pc
+		os=-aros
+		;;
+	aux)
+		basic_machine=m68k-apple
+		os=-aux
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	blackfin)
+		basic_machine=bfin-unknown
+		os=-linux
+		;;
+	blackfin-*)
+		basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	bluegene*)
+		basic_machine=powerpc-ibm
+		os=-cnk
+		;;
+	c54x-*)
+		basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c55x-*)
+		basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c6x-*)
+		basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c90)
+		basic_machine=c90-cray
+		os=-unicos
+		;;
+	cegcc)
+		basic_machine=arm-unknown
+		os=-cegcc
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | j90)
+		basic_machine=j90-cray
+		os=-unicos
+		;;
+	craynv)
+		basic_machine=craynv-cray
+		os=-unicosmp
+		;;
+	cr16 | cr16-*)
+		basic_machine=cr16-unknown
+		os=-elf
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	crisv32 | crisv32-* | etraxfs*)
+		basic_machine=crisv32-axis
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	crx)
+		basic_machine=crx-unknown
+		os=-elf
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	decsystem10* | dec10*)
+		basic_machine=pdp10-dec
+		os=-tops10
+		;;
+	decsystem20* | dec20*)
+		basic_machine=pdp10-dec
+		os=-tops20
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	dicos)
+		basic_machine=i686-pc
+		os=-dicos
+		;;
+	djgpp)
+		basic_machine=i586-pc
+		os=-msdosdjgpp
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2* | dpx2*-bull)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	es1800 | OSE68k | ose68k | ose | OSE)
+		basic_machine=m68k-ericsson
+		os=-ose
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	h8300xray)
+		basic_machine=h8300-hitachi
+		os=-xray
+		;;
+	h8500hms)
+		basic_machine=h8500-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hppa-next)
+		os=-nextstep3
+		;;
+	hppaosf)
+		basic_machine=hppa1.1-hp
+		os=-osf
+		;;
+	hppro)
+		basic_machine=hppa1.1-hp
+		os=-proelf
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		;;
+	i*86v32)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv32
+		;;
+	i*86v4*)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv4
+		;;
+	i*86v)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv
+		;;
+	i*86sol2)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-solaris2
+		;;
+	i386mach)
+		basic_machine=i386-mach
+		os=-mach
+		;;
+	i386-vsta | vsta)
+		basic_machine=i386-unknown
+		os=-vsta
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	m68knommu)
+		basic_machine=m68k-unknown
+		os=-linux
+		;;
+	m68knommu-*)
+		basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	m88k-omron*)
+		basic_machine=m88k-omron
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+	microblaze*)
+		basic_machine=microblaze-xilinx
+		;;
+	mingw64)
+		basic_machine=x86_64-pc
+		os=-mingw64
+		;;
+	mingw32)
+		basic_machine=i686-pc
+		os=-mingw32
+		;;
+	mingw32ce)
+		basic_machine=arm-unknown
+		os=-mingw32ce
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+	mips3*-*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	morphos)
+		basic_machine=powerpc-unknown
+		os=-morphos
+		;;
+	moxiebox)
+		basic_machine=moxie-unknown
+		os=-moxiebox
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	ms1-*)
+		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+		;;
+	msys)
+		basic_machine=i686-pc
+		os=-msys
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	nacl)
+		basic_machine=le32-unknown
+		os=-nacl
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	netbsd386)
+		basic_machine=i386-unknown
+		os=-netbsd
+		;;
+	netwinder)
+		basic_machine=armv4l-rebel
+		os=-linux
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	necv70)
+		basic_machine=v70-nec
+		os=-sysv
+		;;
+	next | m*-next )
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	mon960)
+		basic_machine=i960-intel
+		os=-mon960
+		;;
+	nonstopux)
+		basic_machine=mips-compaq
+		os=-nonstopux
+		;;
+	np1)
+		basic_machine=np1-gould
+		;;
+	neo-tandem)
+		basic_machine=neo-tandem
+		;;
+	nse-tandem)
+		basic_machine=nse-tandem
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	op50n-* | op60c-*)
+		basic_machine=hppa1.1-oki
+		os=-proelf
+		;;
+	openrisc | openrisc-*)
+		basic_machine=or32-unknown
+		;;
+	os400)
+		basic_machine=powerpc-ibm
+		os=-os400
+		;;
+	OSE68000 | ose68000)
+		basic_machine=m68000-ericsson
+		os=-ose
+		;;
+	os68k)
+		basic_machine=m68k-none
+		os=-os68k
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	parisc)
+		basic_machine=hppa-unknown
+		os=-linux
+		;;
+	parisc-*)
+		basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+	pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pc98)
+		basic_machine=i386-pc
+		;;
+	pc98-*)
+		basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium | p5 | k5 | k6 | nexgen | viac3)
+		basic_machine=i586-pc
+		;;
+	pentiumpro | p6 | 6x86 | athlon | athlon_*)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2 | pentiumiii | pentium3)
+		basic_machine=i686-pc
+		;;
+	pentium4)
+		basic_machine=i786-pc
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium4-*)
+		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	power)	basic_machine=power-ibm
+		;;
+	ppc | ppcbe)	basic_machine=powerpc-unknown
+		;;
+	ppc-* | ppcbe-*)
+		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle | ppc-le | powerpc-little)
+		basic_machine=powerpcle-unknown
+		;;
+	ppcle-* | powerpclittle-*)
+		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64)	basic_machine=powerpc64-unknown
+		;;
+	ppc64-* | ppc64p7-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+		basic_machine=powerpc64le-unknown
+		;;
+	ppc64le-* | powerpc64little-*)
+		basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ps2)
+		basic_machine=i386-ibm
+		;;
+	pw32)
+		basic_machine=i586-unknown
+		os=-pw32
+		;;
+	rdos | rdos64)
+		basic_machine=x86_64-pc
+		os=-rdos
+		;;
+	rdos32)
+		basic_machine=i386-pc
+		os=-rdos
+		;;
+	rom68k)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	rm[46]00)
+		basic_machine=mips-siemens
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	s390 | s390-*)
+		basic_machine=s390-ibm
+		;;
+	s390x | s390x-*)
+		basic_machine=s390x-ibm
+		;;
+	sa29200)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	sb1)
+		basic_machine=mipsisa64sb1-unknown
+		;;
+	sb1el)
+		basic_machine=mipsisa64sb1el-unknown
+		;;
+	sde)
+		basic_machine=mipsisa32-sde
+		os=-elf
+		;;
+	sei)
+		basic_machine=mips-sei
+		os=-seiux
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sh5el)
+		basic_machine=sh5le-unknown
+		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
+	sparclite-wrs | simso-wrs)
+		basic_machine=sparclite-wrs
+		os=-vxworks
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	st2000)
+		basic_machine=m68k-tandem
+		;;
+	stratus)
+		basic_machine=i860-stratus
+		os=-sysv4
+		;;
+	strongarm-* | thumb-*)
+		basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun4sol2)
+		basic_machine=sparc-sun
+		os=-solaris2
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	t3e)
+		basic_machine=alphaev5-cray
+		os=-unicos
+		;;
+	t90)
+		basic_machine=t90-cray
+		os=-unicos
+		;;
+	tile*)
+		basic_machine=$basic_machine-unknown
+		os=-linux-gnu
+		;;
+	tx39)
+		basic_machine=mipstx39-unknown
+		;;
+	tx39el)
+		basic_machine=mipstx39el-unknown
+		;;
+	toad1)
+		basic_machine=pdp10-xkl
+		os=-tops20
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	tpf)
+		basic_machine=s390x-ibm
+		os=-tpf
+		;;
+	udi29k)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	v810 | necv810)
+		basic_machine=v810-nec
+		os=-none
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vpp*|vx|vx-*)
+		basic_machine=f301-fujitsu
+		;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	vxworks29k)
+		basic_machine=a29k-wrs
+		os=-vxworks
+		;;
+	w65*)
+		basic_machine=w65-wdc
+		os=-none
+		;;
+	w89k-*)
+		basic_machine=hppa1.1-winbond
+		os=-proelf
+		;;
+	xbox)
+		basic_machine=i686-pc
+		os=-mingw32
+		;;
+	xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	xscale-* | xscalee[bl]-*)
+		basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+		;;
+	ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	z8k-*-coff)
+		basic_machine=z8k-unknown
+		os=-sim
+		;;
+	z80-*-coff)
+		basic_machine=z80-unknown
+		os=-sim
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		basic_machine=hppa1.1-winbond
+		;;
+	op50n)
+		basic_machine=hppa1.1-oki
+		;;
+	op60c)
+		basic_machine=hppa1.1-oki
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	mmix)
+		basic_machine=mmix-knuth
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	vax)
+		basic_machine=vax-dec
+		;;
+	pdp10)
+		# there are many clones, so DEC is not a safe bet
+		basic_machine=pdp10-unknown
+		;;
+	pdp11)
+		basic_machine=pdp11-dec
+		;;
+	we32k)
+		basic_machine=we32k-att
+		;;
+	sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+		basic_machine=sh-unknown
+		;;
+	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+		basic_machine=sparc-sun
+		;;
+	cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	mac | mpw | mac-mpw)
+		basic_machine=m68k-apple
+		;;
+	pmac | pmac-mpw)
+		basic_machine=powerpc-apple
+		;;
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
+		;;
+	*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+	# First match some system type aliases
+	# that might get confused with valid system types.
+	# -solaris* is a basic system type, with this one exception.
+	-auroraux)
+		os=-auroraux
+		;;
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-svr4*)
+		os=-sysv4
+		;;
+	-unixware*)
+		os=-sysv4.2uw
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+		;;
+	# First accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST END IN A *, to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+	      | -sym* | -kopensolaris* | -plan9* \
+	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+	      | -aos* | -aros* \
+	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+	      | -bitrig* | -openbsd* | -solidbsd* \
+	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+	      | -chorusos* | -chorusrdb* | -cegcc* \
+	      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+	      | -linux-newlib* | -linux-musl* | -linux-uclibc* \
+	      | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
+	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto-qnx*)
+		;;
+	-nto*)
+		os=`echo $os | sed -e 's|nto|nto-qnx|'`
+		;;
+	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+		;;
+	-mac*)
+		os=`echo $os | sed -e 's|mac|macos|'`
+		;;
+	-linux-dietlibc)
+		os=-linux-dietlibc
+		;;
+	-linux*)
+		os=`echo $os | sed -e 's|linux|linux-gnu|'`
+		;;
+	-sunos5*)
+		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+		;;
+	-opened*)
+		os=-openedition
+		;;
+	-os400*)
+		os=-os400
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-atheos*)
+		os=-atheos
+		;;
+	-syllable*)
+		os=-syllable
+		;;
+	-386bsd)
+		os=-bsd
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-nova*)
+		os=-rtmk-nova
+		;;
+	-ns2 )
+		os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
+		;;
+	# Preserve the version number of sinix5.
+	-sinix5.*)
+		os=`echo $os | sed -e 's|sinix|sysv|'`
+		;;
+	-sinix*)
+		os=-sysv4
+		;;
+	-tpf*)
+		os=-tpf
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-ose*)
+		os=-ose
+		;;
+	-es1800*)
+		os=-ose
+		;;
+	-xenix)
+		os=-xenix
+		;;
+	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+		os=-mint
+		;;
+	-aros*)
+		os=-aros
+		;;
+	-zvmoe)
+		os=-zvmoe
+		;;
+	-dicos*)
+		os=-dicos
+		;;
+	-nacl*)
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+	score-*)
+		os=-elf
+		;;
+	spu-*)
+		os=-elf
+		;;
+	*-acorn)
+		os=-riscix1.2
+		;;
+	arm*-rebel)
+		os=-linux
+		;;
+	arm*-semi)
+		os=-aout
+		;;
+	c4x-* | tic4x-*)
+		os=-coff
+		;;
+	c8051-*)
+		os=-elf
+		;;
+	hexagon-*)
+		os=-elf
+		;;
+	tic54x-*)
+		os=-coff
+		;;
+	tic55x-*)
+		os=-coff
+		;;
+	tic6x-*)
+		os=-coff
+		;;
+	# This must come before the *-dec entry.
+	pdp10-*)
+		os=-tops20
+		;;
+	pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	m68*-apollo)
+		os=-domain
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		;;
+	m68*-cisco)
+		os=-aout
+		;;
+	mep-*)
+		os=-elf
+		;;
+	mips*-cisco)
+		os=-elf
+		;;
+	mips*-*)
+		os=-elf
+		;;
+	or32-*)
+		os=-coff
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	*-be)
+		os=-beos
+		;;
+	*-haiku)
+		os=-haiku
+		;;
+	*-ibm)
+		os=-aix
+		;;
+	*-knuth)
+		os=-mmixware
+		;;
+	*-wec)
+		os=-proelf
+		;;
+	*-winbond)
+		os=-proelf
+		;;
+	*-oki)
+		os=-proelf
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigaos
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-next )
+		os=-nextstep
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-next)
+		os=-nextstep3
+		;;
+	*-gould)
+		os=-sysv
+		;;
+	*-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+	*-sgi)
+		os=-irix
+		;;
+	*-siemens)
+		os=-sysv4
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=-uxpv
+		;;
+	*-rom68k)
+		os=-coff
+		;;
+	*-*bug)
+		os=-coff
+		;;
+	*-apple)
+		os=-macos
+		;;
+	*-atari*)
+		os=-mint
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-cnk*|-aix*)
+				vendor=ibm
+				;;
+			-beos*)
+				vendor=be
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-mpeix*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-os400*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-tpf*)
+				vendor=ibm
+				;;
+			-vxsim* | -vxworks* | -windiss*)
+				vendor=wrs
+				;;
+			-aux*)
+				vendor=apple
+				;;
+			-hms*)
+				vendor=hitachi
+				;;
+			-mpw* | -macos*)
+				vendor=apple
+				;;
+			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+				vendor=atari
+				;;
+			-vos*)
+				vendor=stratus
+				;;
+		esac
+		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+		;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/configure b/configure
new file mode 100755
index 0000000000000000000000000000000000000000..d41fa0feae437751d29dc5f489bd8a3abad151e7
--- /dev/null
+++ b/configure
@@ -0,0 +1,17629 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69 for ntfs-3g 2015.3.14.
+#
+# Report bugs to <ntfs-3g-devel@lists.sf.net>.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1
+
+  test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || (
+    ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+    ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+    ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+    PATH=/empty FPATH=/empty; export PATH FPATH
+    test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\
+      || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     # Try only shells that exist, to save several forks.
+	     as_shell=$as_dir/$as_base
+	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+	   done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf@gnu.org and
+$0: ntfs-3g-devel@lists.sf.net about your system, including
+$0: any error possibly output before this message. Then
+$0: install a modern shell, or manually run the script
+$0: under such a shell if you do have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='ntfs-3g'
+PACKAGE_TARNAME='ntfs-3g'
+PACKAGE_VERSION='2015.3.14'
+PACKAGE_STRING='ntfs-3g 2015.3.14'
+PACKAGE_BUGREPORT='ntfs-3g-devel@lists.sf.net'
+PACKAGE_URL=''
+
+ac_unique_file="src/ntfs-3g.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_header_list=
+ac_subst_vars='am__EXEEXT_FALSE
+am__EXEEXT_TRUE
+LTLIBOBJS
+ENABLE_QUARANTINED_FALSE
+ENABLE_QUARANTINED_TRUE
+ENABLE_EXTRAS_FALSE
+ENABLE_EXTRAS_TRUE
+ENABLE_NTFSPROGS_FALSE
+ENABLE_NTFSPROGS_TRUE
+ENABLE_NTFS_3G_FALSE
+ENABLE_NTFS_3G_TRUE
+ENABLE_MOUNT_HELPER_FALSE
+ENABLE_MOUNT_HELPER_TRUE
+INSTALL_LIBRARY_FALSE
+INSTALL_LIBRARY_TRUE
+REALLYSTATIC_FALSE
+REALLYSTATIC_TRUE
+RUN_LDCONFIG_FALSE
+RUN_LDCONFIG_TRUE
+NTFS_DEVICE_DEFAULT_IO_OPS_FALSE
+NTFS_DEVICE_DEFAULT_IO_OPS_TRUE
+WINDOWS_FALSE
+WINDOWS_TRUE
+GENERATE_LDSCRIPT_FALSE
+GENERATE_LDSCRIPT_TRUE
+FUSE_INTERNAL_FALSE
+FUSE_INTERNAL_TRUE
+OUTPUT_FORMAT
+NTFSPROGS_STATIC_LIBS
+LIBNTFS_LIBS
+LIBNTFS_CPPFLAGS
+MKNTFS_LIBS
+MKNTFS_CPPFLAGS
+LIBFUSE_LITE_LIBS
+LIBFUSE_LITE_CFLAGS
+LIBNTFS_3G_VERSION
+rootlibdir
+rootsbindir
+rootbindir
+ntfs3gincludedir
+pkgconfigdir
+LIBOBJS
+all_libraries
+all_includes
+ENABLE_CRYPTO_FALSE
+ENABLE_CRYPTO_TRUE
+GNUTLS_LIBS
+GNUTLS_CFLAGS
+LIBGCRYPT_LIBS
+LIBGCRYPT_CFLAGS
+LIBGCRYPT_CONFIG
+FUSE_MODULE_LIBS
+FUSE_MODULE_CFLAGS
+LDCONFIG
+RM
+MV
+PKG_CONFIG_LIBDIR
+PKG_CONFIG_PATH
+PKG_CONFIG
+OTOOL64
+OTOOL
+LIPO
+NMEDIT
+DSYMUTIL
+MANIFEST_TOOL
+RANLIB
+ac_ct_AR
+AR
+DLLTOOL
+OBJDUMP
+NM
+ac_ct_DUMPBIN
+DUMPBIN
+LD
+FGREP
+SED
+LIBTOOL
+LN_S
+EGREP
+GREP
+CPP
+am__fastdepCC_FALSE
+am__fastdepCC_TRUE
+CCDEPMODE
+am__nodep
+AMDEPBACKSLASH
+AMDEP_FALSE
+AMDEP_TRUE
+am__quote
+am__include
+DEPDIR
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+MAINT
+MAINTAINER_MODE_FALSE
+MAINTAINER_MODE_TRUE
+AM_BACKSLASH
+AM_DEFAULT_VERBOSITY
+AM_DEFAULT_V
+AM_V
+am__untar
+am__tar
+AMTAR
+am__leading_dot
+SET_MAKE
+AWK
+mkdir_p
+MKDIR_P
+INSTALL_STRIP_PROGRAM
+STRIP
+install_sh
+MAKEINFO
+AUTOHEADER
+AUTOMAKE
+AUTOCONF
+ACLOCAL
+VERSION
+PACKAGE
+CYGPATH_W
+am__isrc
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+target_os
+target_vendor
+target_cpu
+target
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_silent_rules
+enable_maintainer_mode
+enable_debug
+enable_warnings
+enable_pedantic
+enable_really_static
+enable_mount_helper
+enable_ldscript
+enable_ldconfig
+enable_library
+enable_mtab
+enable_posix_acls
+enable_xattr_mappings
+enable_device_default_io_ops
+enable_ntfs_3g
+enable_ntfsprogs
+enable_crypto
+enable_extras
+enable_quarantined
+enable_nfconv
+enable_dependency_tracking
+enable_shared
+enable_static
+with_pic
+enable_fast_install
+with_gnu_ld
+with_sysroot
+enable_libtool_lock
+with_fuse
+with_libgcrypt_prefix
+with_uuid
+with_hd
+enable_largefile
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP
+PKG_CONFIG
+PKG_CONFIG_PATH
+PKG_CONFIG_LIBDIR
+LDCONFIG
+FUSE_MODULE_CFLAGS
+FUSE_MODULE_LIBS
+GNUTLS_CFLAGS
+GNUTLS_LIBS'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *=)   ac_optarg= ;;
+  *)    ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures ntfs-3g 2015.3.14 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking ...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/ntfs-3g]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+  --target=TARGET   configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of ntfs-3g 2015.3.14:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-option-checking  ignore unrecognized --enable/--with options
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-silent-rules   less verbose build output (undo: "make V=1")
+  --disable-silent-rules  verbose build output (undo: "make V=0")
+  --enable-maintainer-mode
+                          enable make rules and dependencies not useful (and
+                          sometimes confusing) to the casual installer
+  --enable-debug          enable debugging code and output
+  --enable-warnings       enable lots of compiler warnings
+  --enable-pedantic       enable compile pedantic mode
+  --enable-really-static  create fully static binaries
+  --enable-mount-helper   install mount helper [default=enabled for linux]
+  --enable-ldscript       use ldscript instead of .so symlink
+  --disable-ldconfig      do not update dynamic linker cache using ldconfig
+  --disable-library       do not install libntfs-3g but link it into ntfs-3g
+  --disable-mtab          disable and ignore usage of /etc/mtab
+  --enable-posix-acls     enable POSIX ACL support
+  --enable-xattr-mappings enable system extended attributes mappings
+  --disable-device-default-io-ops
+                          install default IO ops
+  --disable-ntfs-3g       disable the ntfs-3g FUSE driver
+  --disable-ntfsprogs     disable ntfsprogs utilities (default=no)
+  --enable-crypto         enable crypto related code and utilities
+                          (default=no)
+  --enable-extras         enable extra ntfsprogs utilities (default=no)
+  --enable-quarantined    enable quarantined ntfsprogs utilities (default=no)
+  --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-dependency-tracking
+                          do not reject slow dependency extractors
+  --disable-dependency-tracking
+                          speeds up one-time build
+  --enable-shared[=PKGS]  build shared libraries [default=yes]
+  --enable-static[=PKGS]  build static libraries [default=yes]
+  --enable-fast-install[=PKGS]
+                          optimize for fast installation [default=yes]
+  --disable-libtool-lock  avoid locking (might break parallel builds)
+  --disable-largefile     omit support for large files
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-pic[=PKGS]       try to use only PIC/non-PIC objects [default=use
+                          both]
+  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
+  --with-sysroot=DIR Search for dependent libraries within DIR
+                        (or the compiler's sysroot if not specified).
+  --with-fuse=<internal|external>
+                          Select FUSE library: internal or external
+                          [default=internal]
+  --with-libgcrypt-prefix=PFX
+                          prefix where LIBGCRYPT is installed (optional)
+
+  --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
+
+  --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
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+  PKG_CONFIG  path to pkg-config utility
+  PKG_CONFIG_PATH
+              directories to add to pkg-config's search path
+  PKG_CONFIG_LIBDIR
+              path overriding pkg-config's built-in search path
+  LDCONFIG    ldconfig utility
+  FUSE_MODULE_CFLAGS
+              C compiler flags for FUSE_MODULE, overriding pkg-config
+  FUSE_MODULE_LIBS
+              linker flags for FUSE_MODULE, overriding pkg-config
+  GNUTLS_CFLAGS
+              C compiler flags for GNUTLS, overriding pkg-config
+  GNUTLS_LIBS linker flags for GNUTLS, overriding pkg-config
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <ntfs-3g-devel@lists.sf.net>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+ntfs-3g configure 2015.3.14
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } > conftest.i && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if eval \${$3+:} false; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_header_compiler=yes
+else
+  ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  ac_header_preproc=yes
+else
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+  yes:no: )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+( $as_echo "## ----------------------------------------- ##
+## Report this to ntfs-3g-devel@lists.sf.net ##
+## ----------------------------------------- ##"
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+       $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=$ac_status
+fi
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 test -x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $2 (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=no"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+	 return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+	    return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_type
+
+# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES
+# ----------------------------------------------------
+# Tries to find if the field MEMBER exists in type AGGR, after including
+# INCLUDES, setting cache variable VAR accordingly.
+ac_fn_c_check_member ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
+$as_echo_n "checking for $2.$3... " >&6; }
+if eval \${$4+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (ac_aggr.$3)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$4=yes"
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (sizeof ac_aggr.$3)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$4=yes"
+else
+  eval "$4=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$4
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_member
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by ntfs-3g $as_me 2015.3.14, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	$as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  # We do not want a PATH search for config.site.
+  case $CONFIG_SITE in #((
+    -*)  ac_site_file1=./$CONFIG_SITE;;
+    */*) ac_site_file1=$CONFIG_SITE;;
+    *)   ac_site_file1=./$CONFIG_SITE;;
+  esac
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file" \
+      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special files
+  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
+  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+as_fn_append ac_header_list " utime.h"
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+LIBNTFS_3G_VERSION="86"
+
+
+# Environment
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+  if test -f "$ac_dir/install-sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f "$ac_dir/install.sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f "$ac_dir/shtool"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if ${ac_cv_build+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if ${ac_cv_host+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
+$as_echo_n "checking target system type... " >&6; }
+if ${ac_cv_target+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$target_alias" = x; then
+  ac_cv_target=$ac_cv_host
+else
+  ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
+    as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
+$as_echo "$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+  test "$program_prefix$program_suffix$program_transform_name" = \
+    NONENONEs,x,x, &&
+  program_prefix=${target_alias}-
+
+# Automake
+am__api_version='1.14'
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+  ./ | .// | /[cC]/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    rm -rf conftest.one conftest.two conftest.dir
+	    echo one > conftest.one
+	    echo two > conftest.two
+	    mkdir conftest.dir
+	    if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+	      test -s conftest.one && test -s conftest.two &&
+	      test -s conftest.dir/conftest.one &&
+	      test -s conftest.dir/conftest.two
+	    then
+	      ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+	      break 3
+	    fi
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+
+  done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
+$as_echo_n "checking whether build environment is sane... " >&6; }
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[\\\"\#\$\&\'\`$am_lf]*)
+    as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;;
+esac
+case $srcdir in
+  *[\\\"\#\$\&\'\`$am_lf\ \	]*)
+    as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;;
+esac
+
+# Do 'set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   am_has_slept=no
+   for am_try in 1 2; do
+     echo "timestamp, slept: $am_has_slept" > conftest.file
+     set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+     if test "$*" = "X"; then
+	# -L didn't work.
+	set X `ls -t "$srcdir/configure" conftest.file`
+     fi
+     if test "$*" != "X $srcdir/configure conftest.file" \
+	&& test "$*" != "X conftest.file $srcdir/configure"; then
+
+	# If neither matched, then we have a broken ls.  This can happen
+	# if, for instance, CONFIG_SHELL is bash and it inherits a
+	# broken ls alias from the environment.  This has actually
+	# happened.  Such a system could not be considered "sane".
+	as_fn_error $? "ls -t appears to fail.  Make sure there is not a broken
+  alias in your environment" "$LINENO" 5
+     fi
+     if test "$2" = conftest.file || test $am_try -eq 2; then
+       break
+     fi
+     # Just in case.
+     sleep 1
+     am_has_slept=yes
+   done
+   test "$2" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   as_fn_error $? "newly created file is older than distributed files!
+Check your system clock" "$LINENO" 5
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+# If we didn't sleep, we still need to ensure time stamps of config.status and
+# generated files are strictly newer.
+am_sleep_pid=
+if grep 'slept: no' conftest.file >/dev/null 2>&1; then
+  ( sleep 1 ) &
+  am_sleep_pid=$!
+fi
+
+rm -f conftest.file
+
+test "$program_prefix" != NONE &&
+  program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+if test x"${MISSING+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+  *)
+    MISSING="\${SHELL} $am_aux_dir/missing" ;;
+  esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --is-lightweight"; then
+  am_missing_run="$MISSING "
+else
+  am_missing_run=
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5
+$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;}
+fi
+
+if test x"${install_sh}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+
+# Installed binaries are usually stripped using 'strip' when the user
+# run "make install-strip".  However 'strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the 'STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
+$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+  if ${ac_cv_path_mkdir+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in mkdir gmkdir; do
+	 for ac_exec_ext in '' $ac_executable_extensions; do
+	   as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue
+	   case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+	     'mkdir (GNU coreutils) '* | \
+	     'mkdir (coreutils) '* | \
+	     'mkdir (fileutils) '4.1*)
+	       ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+	       break 3;;
+	   esac
+	 done
+       done
+  done
+IFS=$as_save_IFS
+
+fi
+
+  test -d ./--version && rmdir ./--version
+  if test "${ac_cv_path_mkdir+set}" = set; then
+    MKDIR_P="$ac_cv_path_mkdir -p"
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for MKDIR_P within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    MKDIR_P="$ac_install_sh -d"
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
+$as_echo "$MKDIR_P" >&6; }
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AWK+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AWK="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$AWK" && break
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+	@echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  SET_MAKE=
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+# Check whether --enable-silent-rules was given.
+if test "${enable_silent_rules+set}" = set; then :
+  enableval=$enable_silent_rules;
+fi
+
+case $enable_silent_rules in # (((
+  yes) AM_DEFAULT_VERBOSITY=0;;
+   no) AM_DEFAULT_VERBOSITY=1;;
+    *) AM_DEFAULT_VERBOSITY=1;;
+esac
+am_make=${MAKE-make}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
+$as_echo_n "checking whether $am_make supports nested variables... " >&6; }
+if ${am_cv_make_support_nested_variables+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if $as_echo 'TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+	@$(TRUE)
+.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
+  am_cv_make_support_nested_variables=yes
+else
+  am_cv_make_support_nested_variables=no
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
+$as_echo "$am_cv_make_support_nested_variables" >&6; }
+if test $am_cv_make_support_nested_variables = yes; then
+    AM_V='$(V)'
+  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+  AM_V=$AM_DEFAULT_VERBOSITY
+  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AM_BACKSLASH='\'
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  am__isrc=' -I$(srcdir)'
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+
+
+# Define the identity of the package.
+
+ PACKAGE=${PACKAGE_NAME}
+ VERSION=${PACKAGE_VERSION}
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+# For better backward compatibility.  To be removed once Automake 1.9.x
+# dies out for good.  For more background, see:
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
+mkdir_p='$(MKDIR_P)'
+
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.  Yes, it's still used
+# in the wild :-(  We should find a proper way to deprecate it ...
+AMTAR='$${TAR-tar}'
+
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar  pax cpio none'
+
+am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
+
+
+
+
+
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes.  So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+  cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present.  This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
+
+Please tell bug-automake@gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message.  This
+can help us improve future automake versions.
+
+END
+  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+    echo 'Configuration will proceed anyway, since you have set the' >&2
+    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+    echo >&2
+  else
+    cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: <http://www.gnu.org/software/coreutils/>.
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+    as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5
+  fi
+fi
+ac_config_headers="$ac_config_headers config.h"
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
+$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
+    # Check whether --enable-maintainer-mode was given.
+if test "${enable_maintainer_mode+set}" = set; then :
+  enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval
+else
+  USE_MAINTAINER_MODE=no
+fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5
+$as_echo "$USE_MAINTAINER_MODE" >&6; }
+   if test $USE_MAINTAINER_MODE = yes; then
+  MAINTAINER_MODE_TRUE=
+  MAINTAINER_MODE_FALSE='#'
+else
+  MAINTAINER_MODE_TRUE='#'
+  MAINTAINER_MODE_FALSE=
+fi
+
+  MAINT=$MAINTAINER_MODE_TRUE
+
+
+
+# Options
+# Check whether --enable-debug was given.
+if test "${enable_debug+set}" = set; then :
+  enableval=$enable_debug;
+else
+  enable_debug="no"
+
+fi
+
+
+# Check whether --enable-warnings was given.
+if test "${enable_warnings+set}" = set; then :
+  enableval=$enable_warnings;
+else
+  enable_warnings="no"
+
+fi
+
+
+# Check whether --enable-pedantic was given.
+if test "${enable_pedantic+set}" = set; then :
+  enableval=$enable_pedantic;
+else
+  enable_pedantic="no"
+
+fi
+
+
+# Check whether --enable-really-static was given.
+if test "${enable_really_static+set}" = set; then :
+  enableval=$enable_really_static;
+else
+  enable_really_static="no"
+
+fi
+
+
+# Check whether --enable-mount-helper was given.
+if test "${enable_mount_helper+set}" = set; then :
+  enableval=$enable_mount_helper;
+else
+
+		case "${target_os}" in
+			linux*) enable_mount_helper="yes" ;;
+			*) enable_mount_helper="no" ;;
+		esac
+
+
+fi
+
+
+# Check whether --enable-ldscript was given.
+if test "${enable_ldscript+set}" = set; then :
+  enableval=$enable_ldscript;
+else
+  enable_ldscript="no"
+
+fi
+
+
+# Check whether --enable-ldconfig was given.
+if test "${enable_ldconfig+set}" = set; then :
+  enableval=$enable_ldconfig;
+else
+  enable_ldconfig="yes"
+
+fi
+
+
+# Check whether --enable-library was given.
+if test "${enable_library+set}" = set; then :
+  enableval=$enable_library;
+else
+  enable_library="yes"
+
+fi
+
+
+# Check whether --enable-mtab was given.
+if test "${enable_mtab+set}" = set; then :
+  enableval=$enable_mtab;
+else
+  enable_mtab="yes"
+
+fi
+
+
+# Check whether --enable-posix-acls was given.
+if test "${enable_posix_acls+set}" = set; then :
+  enableval=$enable_posix_acls;
+else
+  enable_posix_acls="no"
+
+fi
+
+
+# Check whether --enable-xattr-mappings was given.
+if test "${enable_xattr_mappings+set}" = set; then :
+  enableval=$enable_xattr_mappings;
+else
+  enable_xattr_mappings="no"
+
+fi
+
+
+# Check whether --enable-device-default-io-ops was given.
+if test "${enable_device_default_io_ops+set}" = set; then :
+  enableval=$enable_device_default_io_ops;
+else
+  enable_device_default_io_ops="yes"
+
+fi
+
+
+# Check whether --enable-ntfs-3g was given.
+if test "${enable_ntfs_3g+set}" = set; then :
+  enableval=$enable_ntfs_3g;
+else
+  enable_ntfs_3g="yes"
+
+fi
+
+
+# Check whether --enable-ntfsprogs was given.
+if test "${enable_ntfsprogs+set}" = set; then :
+  enableval=$enable_ntfsprogs;
+else
+  enable_ntfsprogs="yes"
+
+fi
+
+
+# Check whether --enable-crypto was given.
+if test "${enable_crypto+set}" = set; then :
+  enableval=$enable_crypto;
+else
+  enable_crypto=no
+
+fi
+
+
+# Check whether --enable-extras was given.
+if test "${enable_extras+set}" = set; then :
+  enableval=$enable_extras;
+else
+  enable_extras="no"
+
+fi
+
+
+# Check whether --enable-quarantined was given.
+if test "${enable_quarantined+set}" = set; then :
+  enableval=$enable_quarantined;
+else
+  enable_quarantined="no"
+
+fi
+
+
+# Check whether --enable-nfconv was given.
+if test "${enable_nfconv+set}" = set; then :
+  enableval=$enable_nfconv; enable_nfconv="no"
+else
+
+		case "${target_os}" in
+			darwin*) enable_nfconv="yes" ;;
+			*) enable_nfconv="no" ;;
+		esac
+
+
+fi
+
+
+# pthread_rwlock_t requires _GNU_SOURCE
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+	@echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5
+$as_echo_n "checking for style of include used by $am_make... " >&6; }
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from 'make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+  am__include=include
+  am__quote=
+  _am_result=GNU
+  ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   case `$am_make -s -f confmf 2> /dev/null` in #(
+   *the\ am__doit\ target*)
+     am__include=.include
+     am__quote="\""
+     _am_result=BSD
+     ;;
+   esac
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5
+$as_echo "$_am_result" >&6; }
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then :
+  enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+  am__nodep='_no'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+  AMDEP_TRUE=
+  AMDEP_FALSE='#'
+else
+  AMDEP_TRUE='#'
+  AMDEP_FALSE=
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an `-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+if test -z "$ac_file"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+  { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+  if { ac_try='./conftest$ac_cv_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
+$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
+if ${am_cv_prog_cc_c_o+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+  # Make sure it works both with $CC and with simple cc.
+  # Following AC_PROG_CC_C_O, we do the test twice because some
+  # compilers refuse to overwrite an existing .o file with -o,
+  # though they will create one.
+  am_cv_prog_cc_c_o=yes
+  for am_i in 1 2; do
+    if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
+   ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); } \
+         && test -f conftest2.$ac_objext; then
+      : OK
+    else
+      am_cv_prog_cc_c_o=no
+      break
+    fi
+  done
+  rm -f core conftest*
+  unset am_i
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
+$as_echo "$am_cv_prog_cc_c_o" >&6; }
+if test "$am_cv_prog_cc_c_o" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+depcc="$CC"   am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CC_dependencies_compiler_type+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named 'D' -- because '-MD' means "put the output
+  # in D".
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CC_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  am__universal=false
+  case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+      # Solaris 10 /bin/sh.
+      echo '/* dummy */' > sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with '-c' and '-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle '-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs.
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # After this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested.
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+      # This compiler won't grok '-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CC_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+  am__fastdepCC_TRUE=
+  am__fastdepCC_FALSE='#'
+else
+  am__fastdepCC_TRUE='#'
+  am__fastdepCC_FALSE=
+fi
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if ${ac_cv_prog_CPP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdc=yes
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+  ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default"
+if test "x$ac_cv_header_minix_config_h" = xyes; then :
+  MINIX=yes
+else
+  MINIX=
+fi
+
+
+  if test "$MINIX" = yes; then
+
+$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h
+
+
+$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h
+
+
+$as_echo "#define _MINIX 1" >>confdefs.h
+
+  fi
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5
+$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; }
+if ${ac_cv_safe_to_define___extensions__+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#         define __EXTENSIONS__ 1
+          $ac_includes_default
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_safe_to_define___extensions__=yes
+else
+  ac_cv_safe_to_define___extensions__=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5
+$as_echo "$ac_cv_safe_to_define___extensions__" >&6; }
+  test $ac_cv_safe_to_define___extensions__ = yes &&
+    $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h
+
+  $as_echo "#define _ALL_SOURCE 1" >>confdefs.h
+
+  $as_echo "#define _GNU_SOURCE 1" >>confdefs.h
+
+  $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
+
+  $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h
+
+
+
+
+# Programs
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  for ac_prog in gcc cc
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in gcc cc
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
+$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
+if ${am_cv_prog_cc_c_o+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+  # Make sure it works both with $CC and with simple cc.
+  # Following AC_PROG_CC_C_O, we do the test twice because some
+  # compilers refuse to overwrite an existing .o file with -o,
+  # though they will create one.
+  am_cv_prog_cc_c_o=yes
+  for am_i in 1 2; do
+    if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
+   ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); } \
+         && test -f conftest2.$ac_objext; then
+      : OK
+    else
+      am_cv_prog_cc_c_o=no
+      break
+    fi
+  done
+  rm -f core conftest*
+  unset am_i
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
+$as_echo "$am_cv_prog_cc_c_o" >&6; }
+if test "$am_cv_prog_cc_c_o" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+depcc="$CC"   am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CC_dependencies_compiler_type+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named 'D' -- because '-MD' means "put the output
+  # in D".
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CC_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  am__universal=false
+  case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+      # Solaris 10 /bin/sh.
+      echo '/* dummy */' > sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with '-c' and '-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle '-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs.
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # After this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested.
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+      # This compiler won't grok '-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CC_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+  am__fastdepCC_TRUE=
+  am__fastdepCC_FALSE='#'
+else
+  am__fastdepCC_TRUE='#'
+  am__fastdepCC_FALSE=
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+$as_echo_n "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+$as_echo "no, using $LN_S" >&6; }
+fi
+
+
+
+case `pwd` in
+  *\ * | *\	*)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
+$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
+esac
+
+
+
+macro_version='2.4.2'
+macro_revision='1.3337'
+
+
+
+
+
+
+
+
+
+
+
+
+
+ltmain="$ac_aux_dir/ltmain.sh"
+
+# Backslashify metacharacters that are still active within
+# double-quoted strings.
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5
+$as_echo_n "checking how to print strings... " >&6; }
+# Test print first, because it will be a builtin if present.
+if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
+   test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='print -r --'
+elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='printf %s\n'
+else
+  # Use this function as a fallback that always works.
+  func_fallback_echo ()
+  {
+    eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+  }
+  ECHO='func_fallback_echo'
+fi
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+    $ECHO ""
+}
+
+case "$ECHO" in
+  printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5
+$as_echo "printf" >&6; } ;;
+  print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5
+$as_echo "print -r" >&6; } ;;
+  *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5
+$as_echo "cat" >&6; } ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
+$as_echo_n "checking for a sed that does not truncate output... " >&6; }
+if ${ac_cv_path_SED+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+            ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+     for ac_i in 1 2 3 4 5 6 7; do
+       ac_script="$ac_script$as_nl$ac_script"
+     done
+     echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
+     { ac_script=; unset ac_script;}
+     if test -z "$SED"; then
+  ac_path_SED_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_SED" || continue
+# Check for GNU ac_path_SED and select it if it is found.
+  # Check for GNU $ac_path_SED
+case `"$ac_path_SED" --version 2>&1` in
+*GNU*)
+  ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo '' >> "conftest.nl"
+    "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_SED_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_SED="$ac_path_SED"
+      ac_path_SED_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_SED_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_SED"; then
+    as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5
+  fi
+else
+  ac_cv_path_SED=$SED
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
+$as_echo "$ac_cv_path_SED" >&6; }
+ SED="$ac_cv_path_SED"
+  rm -f conftest.sed
+
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
+$as_echo_n "checking for fgrep... " >&6; }
+if ${ac_cv_path_FGREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1
+   then ac_cv_path_FGREP="$GREP -F"
+   else
+     if test -z "$FGREP"; then
+  ac_path_FGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in fgrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_FGREP" || continue
+# Check for GNU ac_path_FGREP and select it if it is found.
+  # Check for GNU $ac_path_FGREP
+case `"$ac_path_FGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'FGREP' >> "conftest.nl"
+    "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_FGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_FGREP="$ac_path_FGREP"
+      ac_path_FGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_FGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_FGREP"; then
+    as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_FGREP=$FGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5
+$as_echo "$ac_cv_path_FGREP" >&6; }
+ FGREP="$ac_cv_path_FGREP"
+
+
+test -z "$GREP" && GREP=grep
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then :
+  withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
+$as_echo_n "checking for ld used by $CC... " >&6; }
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [\\/]* | ?:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
+$as_echo_n "checking for GNU ld... " >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
+$as_echo_n "checking for non-GNU ld... " >&6; }
+fi
+if ${lt_cv_path_LD+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$LD"; then
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+	test "$with_gnu_ld" != no && break
+	;;
+      *)
+	test "$with_gnu_ld" != yes && break
+	;;
+      esac
+    fi
+  done
+  IFS="$lt_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+$as_echo "$LD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
+$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
+if ${lt_cv_prog_gnu_ld+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
+$as_echo "$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5
+$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; }
+if ${lt_cv_path_NM+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  lt_nm_to_check="${ac_tool_prefix}nm"
+  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+    lt_nm_to_check="$lt_nm_to_check nm"
+  fi
+  for lt_tmp_nm in $lt_nm_to_check; do
+    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+      IFS="$lt_save_ifs"
+      test -z "$ac_dir" && ac_dir=.
+      tmp_nm="$ac_dir/$lt_tmp_nm"
+      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+	# Check to see if the nm accepts a BSD-compat flag.
+	# Adding the `sed 1q' prevents false positives on HP-UX, which says:
+	#   nm: unknown option "B" ignored
+	# Tru64's nm complains that /dev/null is an invalid object file
+	case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+	*/dev/null* | *'Invalid file or object type'*)
+	  lt_cv_path_NM="$tmp_nm -B"
+	  break
+	  ;;
+	*)
+	  case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+	  */dev/null*)
+	    lt_cv_path_NM="$tmp_nm -p"
+	    break
+	    ;;
+	  *)
+	    lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+	    continue # so that we can try to find one that supports BSD flags
+	    ;;
+	  esac
+	  ;;
+	esac
+      fi
+    done
+    IFS="$lt_save_ifs"
+  done
+  : ${lt_cv_path_NM=no}
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5
+$as_echo "$lt_cv_path_NM" >&6; }
+if test "$lt_cv_path_NM" != "no"; then
+  NM="$lt_cv_path_NM"
+else
+  # Didn't find any BSD compatible name lister, look for dumpbin.
+  if test -n "$DUMPBIN"; then :
+    # Let the user override the test.
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in dumpbin "link -dump"
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_DUMPBIN+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$DUMPBIN"; then
+  ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+DUMPBIN=$ac_cv_prog_DUMPBIN
+if test -n "$DUMPBIN"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5
+$as_echo "$DUMPBIN" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$DUMPBIN" && break
+  done
+fi
+if test -z "$DUMPBIN"; then
+  ac_ct_DUMPBIN=$DUMPBIN
+  for ac_prog in dumpbin "link -dump"
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_DUMPBIN"; then
+  ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN
+if test -n "$ac_ct_DUMPBIN"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5
+$as_echo "$ac_ct_DUMPBIN" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_DUMPBIN" && break
+done
+
+  if test "x$ac_ct_DUMPBIN" = x; then
+    DUMPBIN=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DUMPBIN=$ac_ct_DUMPBIN
+  fi
+fi
+
+    case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in
+    *COFF*)
+      DUMPBIN="$DUMPBIN -symbols"
+      ;;
+    *)
+      DUMPBIN=:
+      ;;
+    esac
+  fi
+
+  if test "$DUMPBIN" != ":"; then
+    NM="$DUMPBIN"
+  fi
+fi
+test -z "$NM" && NM=nm
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
+$as_echo_n "checking the name lister ($NM) interface... " >&6; }
+if ${lt_cv_nm_interface+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_nm_interface="BSD nm"
+  echo "int some_variable = 0;" > conftest.$ac_ext
+  (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5)
+  (eval "$ac_compile" 2>conftest.err)
+  cat conftest.err >&5
+  (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+  (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+  cat conftest.err >&5
+  (eval echo "\"\$as_me:$LINENO: output\"" >&5)
+  cat conftest.out >&5
+  if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+    lt_cv_nm_interface="MS dumpbin"
+  fi
+  rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
+$as_echo "$lt_cv_nm_interface" >&6; }
+
+# find the maximum length of command line arguments
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5
+$as_echo_n "checking the maximum length of command line arguments... " >&6; }
+if ${lt_cv_sys_max_cmd_len+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+    i=0
+  teststring="ABCD"
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
+
+  gnu*)
+    # Under GNU Hurd, this test is not required because there is
+    # no limit to the length of command line arguments.
+    # Libtool will interpret -1 as no limit whatsoever
+    lt_cv_sys_max_cmd_len=-1;
+    ;;
+
+  cygwin* | mingw* | cegcc*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  mint*)
+    # On MiNT this can take a long time and run out of memory.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+    # This has been around since 386BSD, at least.  Likely further.
+    if test -x /sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+    elif test -x /usr/sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+    else
+      lt_cv_sys_max_cmd_len=65536	# usable default for all BSDs
+    fi
+    # And add a safety zone
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    ;;
+
+  interix*)
+    # We know the value 262144 and hardcode it with a safety zone (like BSD)
+    lt_cv_sys_max_cmd_len=196608
+    ;;
+
+  os2*)
+    # The test takes a long time on OS/2.
+    lt_cv_sys_max_cmd_len=8192
+    ;;
+
+  osf*)
+    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+    # nice to cause kernel panics so lets avoid the loop below.
+    # First set a reasonable default.
+    lt_cv_sys_max_cmd_len=16384
+    #
+    if test -x /sbin/sysconfig; then
+      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+        *1*) lt_cv_sys_max_cmd_len=-1 ;;
+      esac
+    fi
+    ;;
+  sco3.2v5*)
+    lt_cv_sys_max_cmd_len=102400
+    ;;
+  sysv5* | sco5v6* | sysv4.2uw2*)
+    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+    if test -n "$kargmax"; then
+      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[	 ]//'`
+    else
+      lt_cv_sys_max_cmd_len=32768
+    fi
+    ;;
+  *)
+    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+    if test -n "$lt_cv_sys_max_cmd_len"; then
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    else
+      # Make teststring a little bigger before we do anything with it.
+      # a 1K string should be a reasonable start.
+      for i in 1 2 3 4 5 6 7 8 ; do
+        teststring=$teststring$teststring
+      done
+      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+      # If test is not a shell built-in, we'll probably end up computing a
+      # maximum length that is only half of the actual maximum length, but
+      # we can't tell.
+      while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \
+	         = "X$teststring$teststring"; } >/dev/null 2>&1 &&
+	      test $i != 17 # 1/2 MB should be enough
+      do
+        i=`expr $i + 1`
+        teststring=$teststring$teststring
+      done
+      # Only check the string length outside the loop.
+      lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+      teststring=
+      # Add a significant safety factor because C++ compilers can tack on
+      # massive amounts of additional arguments before passing them to the
+      # linker.  It appears as though 1/2 is a usable value.
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+    fi
+    ;;
+  esac
+
+fi
+
+if test -n $lt_cv_sys_max_cmd_len ; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5
+$as_echo "$lt_cv_sys_max_cmd_len" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
+$as_echo "none" >&6; }
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+
+
+
+
+
+: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5
+$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; }
+# Try some XSI features
+xsi_shell=no
+( _lt_dummy="a/b/c"
+  test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \
+      = c,a/b,b/c, \
+    && eval 'test $(( 1 + 1 )) -eq 2 \
+    && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
+  && xsi_shell=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5
+$as_echo "$xsi_shell" >&6; }
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5
+$as_echo_n "checking whether the shell understands \"+=\"... " >&6; }
+lt_shell_append=no
+( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \
+    >/dev/null 2>&1 \
+  && lt_shell_append=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5
+$as_echo "$lt_shell_append" >&6; }
+
+
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  lt_unset=unset
+else
+  lt_unset=false
+fi
+
+
+
+
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+  lt_SP2NL='tr \040 \012'
+  lt_NL2SP='tr \015\012 \040\040'
+  ;;
+ *) # EBCDIC based system
+  lt_SP2NL='tr \100 \n'
+  lt_NL2SP='tr \r\n \100\100'
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5
+$as_echo_n "checking how to convert $build file names to $host format... " >&6; }
+if ${lt_cv_to_host_file_cmd+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $host in
+  *-*-mingw* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
+        ;;
+      *-*-cygwin* )
+        lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
+        ;;
+      * ) # otherwise, assume *nix
+        lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
+        ;;
+    esac
+    ;;
+  *-*-cygwin* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
+        ;;
+      *-*-cygwin* )
+        lt_cv_to_host_file_cmd=func_convert_file_noop
+        ;;
+      * ) # otherwise, assume *nix
+        lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
+        ;;
+    esac
+    ;;
+  * ) # unhandled hosts (and "normal" native builds)
+    lt_cv_to_host_file_cmd=func_convert_file_noop
+    ;;
+esac
+
+fi
+
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5
+$as_echo "$lt_cv_to_host_file_cmd" >&6; }
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5
+$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; }
+if ${lt_cv_to_tool_file_cmd+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  #assume ordinary cross tools, or native build.
+lt_cv_to_tool_file_cmd=func_convert_file_noop
+case $host in
+  *-*-mingw* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
+        ;;
+    esac
+    ;;
+esac
+
+fi
+
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5
+$as_echo "$lt_cv_to_tool_file_cmd" >&6; }
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5
+$as_echo_n "checking for $LD option to reload object files... " >&6; }
+if ${lt_cv_ld_reload_flag+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_reload_flag='-r'
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5
+$as_echo "$lt_cv_ld_reload_flag" >&6; }
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    if test "$GCC" != yes; then
+      reload_cmds=false
+    fi
+    ;;
+  darwin*)
+    if test "$GCC" = yes; then
+      reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+    else
+      reload_cmds='$LD$reload_flag -o $output$reload_objs'
+    fi
+    ;;
+esac
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_OBJDUMP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OBJDUMP"; then
+  ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OBJDUMP=$ac_cv_prog_OBJDUMP
+if test -n "$OBJDUMP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
+$as_echo "$OBJDUMP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OBJDUMP"; then
+  ac_ct_OBJDUMP=$OBJDUMP
+  # Extract the first word of "objdump", so it can be a program name with args.
+set dummy objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OBJDUMP"; then
+  ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_OBJDUMP="objdump"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
+if test -n "$ac_ct_OBJDUMP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
+$as_echo "$ac_ct_OBJDUMP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OBJDUMP" = x; then
+    OBJDUMP="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OBJDUMP=$ac_ct_OBJDUMP
+  fi
+else
+  OBJDUMP="$ac_cv_prog_OBJDUMP"
+fi
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5
+$as_echo_n "checking how to recognize dependent libraries... " >&6; }
+if ${lt_cv_deplibs_check_method+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[4-9]*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi[45]*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin*)
+  # func_win32_libid is a shell function defined in ltmain.sh
+  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+  lt_cv_file_magic_cmd='func_win32_libid'
+  ;;
+
+mingw* | pw32*)
+  # Base MSYS/MinGW do not provide the 'file' command needed by
+  # func_win32_libid shell function, so use a weaker test based on 'objdump',
+  # unless we find 'file', for example because we are cross-compiling.
+  # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin.
+  if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then
+    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+    lt_cv_file_magic_cmd='func_win32_libid'
+  else
+    # Keep this pattern in sync with the one in func_win32_libid.
+    lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
+    lt_cv_file_magic_cmd='$OBJDUMP -f'
+  fi
+  ;;
+
+cegcc*)
+  # use the weaker test based on 'objdump'. See mingw*.
+  lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+  lt_cv_file_magic_cmd='$OBJDUMP -f'
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | dragonfly*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+haiku*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20* | hpux11*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  case $host_cpu in
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  hppa*64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'
+    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+    ;;
+  *)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library'
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  esac
+  ;;
+
+interix[3-9]*)
+  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+  lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $LD in
+  *-32|*"-32 ") libmagic=32-bit;;
+  *-n32|*"-n32 ") libmagic=N32;;
+  *-64|*"-64 ") libmagic=64-bit;;
+  *) libmagic=never-match;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+*nto* | *qnx*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+openbsd*)
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+rdos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.3*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  pc)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+
+tpf*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5
+$as_echo "$lt_cv_deplibs_check_method" >&6; }
+
+file_magic_glob=
+want_nocaseglob=no
+if test "$build" = "$host"; then
+  case $host_os in
+  mingw* | pw32*)
+    if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
+      want_nocaseglob=yes
+    else
+      file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"`
+    fi
+    ;;
+  esac
+fi
+
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dlltool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_DLLTOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$DLLTOOL"; then
+  ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+DLLTOOL=$ac_cv_prog_DLLTOOL
+if test -n "$DLLTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5
+$as_echo "$DLLTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DLLTOOL"; then
+  ac_ct_DLLTOOL=$DLLTOOL
+  # Extract the first word of "dlltool", so it can be a program name with args.
+set dummy dlltool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_DLLTOOL"; then
+  ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_DLLTOOL="dlltool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL
+if test -n "$ac_ct_DLLTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5
+$as_echo "$ac_ct_DLLTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_DLLTOOL" = x; then
+    DLLTOOL="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DLLTOOL=$ac_ct_DLLTOOL
+  fi
+else
+  DLLTOOL="$ac_cv_prog_DLLTOOL"
+fi
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5
+$as_echo_n "checking how to associate runtime and link libraries... " >&6; }
+if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_sharedlib_from_linklib_cmd='unknown'
+
+case $host_os in
+cygwin* | mingw* | pw32* | cegcc*)
+  # two different shell functions defined in ltmain.sh
+  # decide which to use based on capabilities of $DLLTOOL
+  case `$DLLTOOL --help 2>&1` in
+  *--identify-strict*)
+    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
+    ;;
+  *)
+    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
+    ;;
+  esac
+  ;;
+*)
+  # fallback: assume linklib IS sharedlib
+  lt_cv_sharedlib_from_linklib_cmd="$ECHO"
+  ;;
+esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5
+$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; }
+sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
+test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  for ac_prog in ar
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AR"; then
+  ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$AR" && break
+  done
+fi
+if test -z "$AR"; then
+  ac_ct_AR=$AR
+  for ac_prog in ar
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_AR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_AR"; then
+  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_AR="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_AR" && break
+done
+
+  if test "x$ac_ct_AR" = x; then
+    AR="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    AR=$ac_ct_AR
+  fi
+fi
+
+: ${AR=ar}
+: ${AR_FLAGS=cru}
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5
+$as_echo_n "checking for archiver @FILE support... " >&6; }
+if ${lt_cv_ar_at_file+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ar_at_file=no
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  echo conftest.$ac_objext > conftest.lst
+      lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5'
+      { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
+  (eval $lt_ar_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+      if test "$ac_status" -eq 0; then
+	# Ensure the archiver fails upon bogus file names.
+	rm -f conftest.$ac_objext libconftest.a
+	{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
+  (eval $lt_ar_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+	if test "$ac_status" -ne 0; then
+          lt_cv_ar_at_file=@
+        fi
+      fi
+      rm -f conftest.* libconftest.a
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5
+$as_echo "$lt_cv_ar_at_file" >&6; }
+
+if test "x$lt_cv_ar_at_file" = xno; then
+  archiver_list_spec=
+else
+  archiver_list_spec=$lt_cv_ar_at_file
+fi
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+test -z "$STRIP" && STRIP=:
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+test -z "$RANLIB" && RANLIB=:
+
+
+
+
+
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  openbsd*)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
+    ;;
+  *)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
+fi
+
+case $host_os in
+  darwin*)
+    lock_old_archive_extraction=yes ;;
+  *)
+    lock_old_archive_extraction=no ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5
+$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; }
+if ${lt_cv_sys_global_symbol_pipe+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[BCDT]'
+  ;;
+cygwin* | mingw* | pw32* | cegcc*)
+  symcode='[ABCDGISTW]'
+  ;;
+hpux*)
+  if test "$host_cpu" = ia64; then
+    symcode='[ABCDEGRST]'
+  fi
+  ;;
+irix* | nonstopux*)
+  symcode='[BCDEGRST]'
+  ;;
+osf*)
+  symcode='[BCDEGQRST]'
+  ;;
+solaris*)
+  symcode='[BDRT]'
+  ;;
+sco3.2v5*)
+  symcode='[DT]'
+  ;;
+sysv4.2uw2*)
+  symcode='[DT]'
+  ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+  symcode='[ABDT]'
+  ;;
+sysv4)
+  symcode='[DFNSTU]'
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+  symcode='[ABCDGIRSTW]' ;;
+esac
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/  {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"lib\2\", (void *) \&\2},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+  opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+  symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+  # Write the raw and C identifiers.
+  if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+    # Fake it for dumpbin and say T for any non-static function
+    # and D for any global variable.
+    # Also find C++ and __fastcall symbols from MSVC++,
+    # which start with @ or ?.
+    lt_cv_sys_global_symbol_pipe="$AWK '"\
+"     {last_section=section; section=\$ 3};"\
+"     /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
+"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+"     \$ 0!~/External *\|/{next};"\
+"     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+"     {if(hide[section]) next};"\
+"     {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
+"     {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
+"     s[1]~/^[@?]/{print s[1], s[1]; next};"\
+"     s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
+"     ' prfx=^$ac_symprfx"
+  else
+    lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[	 ]\($symcode$symcode*\)[	 ][	 ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+  fi
+  lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'"
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+
+  rm -f conftest*
+  cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5
+  (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+	mv -f "$nlist"T "$nlist"
+      else
+	rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+	if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+	  cat <<_LT_EOF > conftest.$ac_ext
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE)
+/* DATA imports from DLLs on WIN32 con't be const, because runtime
+   relocations are performed -- see ld's documentation on pseudo-relocs.  */
+# define LT_DLSYM_CONST
+#elif defined(__osf__)
+/* This system does not cope well with relocations in const data.  */
+# define LT_DLSYM_CONST
+#else
+# define LT_DLSYM_CONST const
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+	  # Now generate the symbol file.
+	  eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+	  cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols.  */
+LT_DLSYM_CONST struct {
+  const char *name;
+  void       *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[] =
+{
+  { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+	  $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+	  cat <<\_LT_EOF >> conftest.$ac_ext
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+	  # Now try linking the two files.
+	  mv conftest.$ac_objext conftstm.$ac_objext
+	  lt_globsym_save_LIBS=$LIBS
+	  lt_globsym_save_CFLAGS=$CFLAGS
+	  LIBS="conftstm.$ac_objext"
+	  CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
+	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest${ac_exeext}; then
+	    pipe_works=yes
+	  fi
+	  LIBS=$lt_globsym_save_LIBS
+	  CFLAGS=$lt_globsym_save_CFLAGS
+	else
+	  echo "cannot find nm_test_func in $nlist" >&5
+	fi
+      else
+	echo "cannot find nm_test_var in $nlist" >&5
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
+    fi
+  else
+    echo "$progname: failed program was:" >&5
+    cat conftest.$ac_ext >&5
+  fi
+  rm -rf conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+
+fi
+
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
+$as_echo "failed" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
+$as_echo "ok" >&6; }
+fi
+
+# Response file support.
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+  nm_file_list_spec='@'
+elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then
+  nm_file_list_spec='@'
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5
+$as_echo_n "checking for sysroot... " >&6; }
+
+# Check whether --with-sysroot was given.
+if test "${with_sysroot+set}" = set; then :
+  withval=$with_sysroot;
+else
+  with_sysroot=no
+fi
+
+
+lt_sysroot=
+case ${with_sysroot} in #(
+ yes)
+   if test "$GCC" = yes; then
+     lt_sysroot=`$CC --print-sysroot 2>/dev/null`
+   fi
+   ;; #(
+ /*)
+   lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"`
+   ;; #(
+ no|'')
+   ;; #(
+ *)
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5
+$as_echo "${with_sysroot}" >&6; }
+   as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5
+   ;;
+esac
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5
+$as_echo "${lt_sysroot:-no}" >&6; }
+
+
+
+
+
+# Check whether --enable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then :
+  enableval=$enable_libtool_lock;
+fi
+
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `/usr/bin/file conftest.$ac_objext` in
+      *ELF-32*)
+	HPUX_IA64_MODE="32"
+	;;
+      *ELF-64*)
+	HPUX_IA64_MODE="64"
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '#line '$LINENO' "configure"' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    if test "$lt_cv_prog_gnu_ld" = yes; then
+      case `/usr/bin/file conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -melf32bsmip"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -melf32bmipn32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -melf64bmip"
+	;;
+      esac
+    else
+      case `/usr/bin/file conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -32"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -n32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -64"
+	  ;;
+      esac
+    fi
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `/usr/bin/file conftest.o` in
+      *32-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_i386_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    LD="${LD-ld} -m elf_i386"
+	    ;;
+	  powerpc64le-*linux*)
+	    LD="${LD-ld} -m elf32lppclinux"
+	    ;;
+	  powerpc64-*linux*)
+	    LD="${LD-ld} -m elf32ppclinux"
+	    ;;
+	  s390x-*linux*)
+	    LD="${LD-ld} -m elf_s390"
+	    ;;
+	  sparc64-*linux*)
+	    LD="${LD-ld} -m elf32_sparc"
+	    ;;
+	esac
+	;;
+      *64-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_x86_64_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    LD="${LD-ld} -m elf_x86_64"
+	    ;;
+	  powerpcle-*linux*)
+	    LD="${LD-ld} -m elf64lppc"
+	    ;;
+	  powerpc-*linux*)
+	    LD="${LD-ld} -m elf64ppc"
+	    ;;
+	  s390*-*linux*|s390*-*tpf*)
+	    LD="${LD-ld} -m elf64_s390"
+	    ;;
+	  sparc*-*linux*)
+	    LD="${LD-ld} -m elf64_sparc"
+	    ;;
+	esac
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5
+$as_echo_n "checking whether the C compiler needs -belf... " >&6; }
+if ${lt_cv_cc_needs_belf+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  lt_cv_cc_needs_belf=yes
+else
+  lt_cv_cc_needs_belf=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+     ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5
+$as_echo "$lt_cv_cc_needs_belf" >&6; }
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+*-*solaris*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `/usr/bin/file conftest.o` in
+    *64-bit*)
+      case $lt_cv_prog_gnu_ld in
+      yes*)
+        case $host in
+        i?86-*-solaris*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
+        sparc*-*-solaris*)
+          LD="${LD-ld} -m elf64_sparc"
+          ;;
+        esac
+        # GNU ld 2.21 introduced _sol2 emulations.  Use them if available.
+        if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
+          LD="${LD-ld}_sol2"
+        fi
+        ;;
+      *)
+	if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+	  LD="${LD-ld} -64"
+	fi
+	;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+esac
+
+need_locks="$enable_libtool_lock"
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args.
+set dummy ${ac_tool_prefix}mt; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_MANIFEST_TOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$MANIFEST_TOOL"; then
+  ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL
+if test -n "$MANIFEST_TOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5
+$as_echo "$MANIFEST_TOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_MANIFEST_TOOL"; then
+  ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL
+  # Extract the first word of "mt", so it can be a program name with args.
+set dummy mt; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_MANIFEST_TOOL"; then
+  ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_MANIFEST_TOOL="mt"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL
+if test -n "$ac_ct_MANIFEST_TOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5
+$as_echo "$ac_ct_MANIFEST_TOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_MANIFEST_TOOL" = x; then
+    MANIFEST_TOOL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL
+  fi
+else
+  MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL"
+fi
+
+test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5
+$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; }
+if ${lt_cv_path_mainfest_tool+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_path_mainfest_tool=no
+  echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5
+  $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
+  cat conftest.err >&5
+  if $GREP 'Manifest Tool' conftest.out > /dev/null; then
+    lt_cv_path_mainfest_tool=yes
+  fi
+  rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5
+$as_echo "$lt_cv_path_mainfest_tool" >&6; }
+if test "x$lt_cv_path_mainfest_tool" != xyes; then
+  MANIFEST_TOOL=:
+fi
+
+
+
+
+
+
+  case $host_os in
+    rhapsody* | darwin*)
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dsymutil; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_DSYMUTIL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$DSYMUTIL"; then
+  ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+DSYMUTIL=$ac_cv_prog_DSYMUTIL
+if test -n "$DSYMUTIL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
+$as_echo "$DSYMUTIL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DSYMUTIL"; then
+  ac_ct_DSYMUTIL=$DSYMUTIL
+  # Extract the first word of "dsymutil", so it can be a program name with args.
+set dummy dsymutil; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_DSYMUTIL"; then
+  ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
+if test -n "$ac_ct_DSYMUTIL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
+$as_echo "$ac_ct_DSYMUTIL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_DSYMUTIL" = x; then
+    DSYMUTIL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DSYMUTIL=$ac_ct_DSYMUTIL
+  fi
+else
+  DSYMUTIL="$ac_cv_prog_DSYMUTIL"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args.
+set dummy ${ac_tool_prefix}nmedit; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_NMEDIT+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$NMEDIT"; then
+  ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+NMEDIT=$ac_cv_prog_NMEDIT
+if test -n "$NMEDIT"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5
+$as_echo "$NMEDIT" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_NMEDIT"; then
+  ac_ct_NMEDIT=$NMEDIT
+  # Extract the first word of "nmedit", so it can be a program name with args.
+set dummy nmedit; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_NMEDIT"; then
+  ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_NMEDIT="nmedit"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT
+if test -n "$ac_ct_NMEDIT"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5
+$as_echo "$ac_ct_NMEDIT" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_NMEDIT" = x; then
+    NMEDIT=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    NMEDIT=$ac_ct_NMEDIT
+  fi
+else
+  NMEDIT="$ac_cv_prog_NMEDIT"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args.
+set dummy ${ac_tool_prefix}lipo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_LIPO+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$LIPO"; then
+  ac_cv_prog_LIPO="$LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+LIPO=$ac_cv_prog_LIPO
+if test -n "$LIPO"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5
+$as_echo "$LIPO" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_LIPO"; then
+  ac_ct_LIPO=$LIPO
+  # Extract the first word of "lipo", so it can be a program name with args.
+set dummy lipo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_LIPO+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_LIPO"; then
+  ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_LIPO="lipo"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO
+if test -n "$ac_ct_LIPO"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5
+$as_echo "$ac_ct_LIPO" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_LIPO" = x; then
+    LIPO=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    LIPO=$ac_ct_LIPO
+  fi
+else
+  LIPO="$ac_cv_prog_LIPO"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_OTOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OTOOL"; then
+  ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL=$ac_cv_prog_OTOOL
+if test -n "$OTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
+$as_echo "$OTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL"; then
+  ac_ct_OTOOL=$OTOOL
+  # Extract the first word of "otool", so it can be a program name with args.
+set dummy otool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_OTOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OTOOL"; then
+  ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_OTOOL="otool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL
+if test -n "$ac_ct_OTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5
+$as_echo "$ac_ct_OTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OTOOL" = x; then
+    OTOOL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OTOOL=$ac_ct_OTOOL
+  fi
+else
+  OTOOL="$ac_cv_prog_OTOOL"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool64; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_OTOOL64+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OTOOL64"; then
+  ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL64=$ac_cv_prog_OTOOL64
+if test -n "$OTOOL64"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5
+$as_echo "$OTOOL64" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL64"; then
+  ac_ct_OTOOL64=$OTOOL64
+  # Extract the first word of "otool64", so it can be a program name with args.
+set dummy otool64; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OTOOL64"; then
+  ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_OTOOL64="otool64"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64
+if test -n "$ac_ct_OTOOL64"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5
+$as_echo "$ac_ct_OTOOL64" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OTOOL64" = x; then
+    OTOOL64=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OTOOL64=$ac_ct_OTOOL64
+  fi
+else
+  OTOOL64="$ac_cv_prog_OTOOL64"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5
+$as_echo_n "checking for -single_module linker flag... " >&6; }
+if ${lt_cv_apple_cc_single_mod+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_apple_cc_single_mod=no
+      if test -z "${LT_MULTI_MODULE}"; then
+	# By default we will add the -single_module flag. You can override
+	# by either setting the environment variable LT_MULTI_MODULE
+	# non-empty at configure time, or by adding -multi_module to the
+	# link flags.
+	rm -rf libconftest.dylib*
+	echo "int foo(void){return 1;}" > conftest.c
+	echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&5
+	$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+	  -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+        _lt_result=$?
+	# If there is a non-empty error log, and "single_module"
+	# appears in it, assume the flag caused a linker warning
+        if test -s conftest.err && $GREP single_module conftest.err; then
+	  cat conftest.err >&5
+	# Otherwise, if the output was created with a 0 exit code from
+	# the compiler, it worked.
+	elif test -f libconftest.dylib && test $_lt_result -eq 0; then
+	  lt_cv_apple_cc_single_mod=yes
+	else
+	  cat conftest.err >&5
+	fi
+	rm -rf libconftest.dylib*
+	rm -f conftest.*
+      fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5
+$as_echo "$lt_cv_apple_cc_single_mod" >&6; }
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5
+$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; }
+if ${lt_cv_ld_exported_symbols_list+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_exported_symbols_list=no
+      save_LDFLAGS=$LDFLAGS
+      echo "_main" > conftest.sym
+      LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  lt_cv_ld_exported_symbols_list=yes
+else
+  lt_cv_ld_exported_symbols_list=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+	LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5
+$as_echo "$lt_cv_ld_exported_symbols_list" >&6; }
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5
+$as_echo_n "checking for -force_load linker flag... " >&6; }
+if ${lt_cv_ld_force_load+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_force_load=no
+      cat > conftest.c << _LT_EOF
+int forced_loaded() { return 2;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5
+      $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5
+      echo "$AR cru libconftest.a conftest.o" >&5
+      $AR cru libconftest.a conftest.o 2>&5
+      echo "$RANLIB libconftest.a" >&5
+      $RANLIB libconftest.a 2>&5
+      cat > conftest.c << _LT_EOF
+int main() { return 0;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5
+      $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+      _lt_result=$?
+      if test -s conftest.err && $GREP force_load conftest.err; then
+	cat conftest.err >&5
+      elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then
+	lt_cv_ld_force_load=yes
+      else
+	cat conftest.err >&5
+      fi
+        rm -f conftest.err libconftest.a conftest conftest.c
+        rm -rf conftest.dSYM
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5
+$as_echo "$lt_cv_ld_force_load" >&6; }
+    case $host_os in
+    rhapsody* | darwin1.[012])
+      _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
+    darwin1.*)
+      _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+    darwin*) # darwin 5.x on
+      # if running on 10.5 or later, the deployment target defaults
+      # to the OS version, if on x86, and 10.4, the deployment
+      # target defaults to 10.4. Don't you love it?
+      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+	10.0,*86*-darwin8*|10.0,*-darwin[91]*)
+	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+	10.[012]*)
+	  _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+	10.*)
+	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+      esac
+    ;;
+  esac
+    if test "$lt_cv_apple_cc_single_mod" = "yes"; then
+      _lt_dar_single_mod='$single_module'
+    fi
+    if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
+      _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
+    else
+      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    fi
+    if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then
+      _lt_dsymutil='~$DSYMUTIL $lib || :'
+    else
+      _lt_dsymutil=
+    fi
+    ;;
+  esac
+
+for ac_header in dlfcn.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_dlfcn_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_DLFCN_H 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+# Set options
+
+
+
+        enable_dlopen=no
+
+
+  enable_win32_dll=no
+
+
+            # Check whether --enable-shared was given.
+if test "${enable_shared+set}" = set; then :
+  enableval=$enable_shared; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_shared=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_shared=yes
+fi
+
+
+
+
+
+
+
+
+
+  # Check whether --enable-static was given.
+if test "${enable_static+set}" = set; then :
+  enableval=$enable_static; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_static=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_static=yes
+fi
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-pic was given.
+if test "${with_pic+set}" = set; then :
+  withval=$with_pic; lt_p=${PACKAGE-default}
+    case $withval in
+    yes|no) pic_mode=$withval ;;
+    *)
+      pic_mode=default
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for lt_pkg in $withval; do
+	IFS="$lt_save_ifs"
+	if test "X$lt_pkg" = "X$lt_p"; then
+	  pic_mode=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  pic_mode=default
+fi
+
+
+test -z "$pic_mode" && pic_mode=default
+
+
+
+
+
+
+
+  # Check whether --enable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then :
+  enableval=$enable_fast_install; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_fast_install=yes ;;
+    no) enable_fast_install=no ;;
+    *)
+      enable_fast_install=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_fast_install=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_fast_install=yes
+fi
+
+
+
+
+
+
+
+
+
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ltmain"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+test -z "$LN_S" && LN_S="ln -s"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5
+$as_echo_n "checking for objdir... " >&6; }
+if ${lt_cv_objdir+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  lt_cv_objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5
+$as_echo "$lt_cv_objdir" >&6; }
+objdir=$lt_cv_objdir
+
+
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define LT_OBJDIR "$lt_cv_objdir/"
+_ACEOF
+
+
+
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5
+$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; }
+if ${lt_cv_path_MAGIC_CMD+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MAGIC_CMD in
+[\\/*] |  ?:[\\/]*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/${ac_tool_prefix}file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+	  MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    $EGREP "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+$as_echo "$MAGIC_CMD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5
+$as_echo_n "checking for file... " >&6; }
+if ${lt_cv_path_MAGIC_CMD+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MAGIC_CMD in
+[\\/*] |  ?:[\\/]*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/file"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+	  MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    $EGREP "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+$as_echo "$MAGIC_CMD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  else
+    MAGIC_CMD=:
+  fi
+fi
+
+  fi
+  ;;
+esac
+
+# Use C for the default configuration in the libtool script
+
+lt_save_CC="$CC"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+objext=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+
+lt_prog_compiler_no_builtin_flag=
+
+if test "$GCC" = yes; then
+  case $cc_basename in
+  nvcc*)
+    lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;;
+  *)
+    lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;;
+  esac
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
+if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_rtti_exceptions=no
+   ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="-fno-rtti -fno-exceptions"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_rtti_exceptions=yes
+     fi
+   fi
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+    lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
+else
+    :
+fi
+
+fi
+
+
+
+
+
+
+  lt_prog_compiler_wl=
+lt_prog_compiler_pic=
+lt_prog_compiler_static=
+
+
+  if test "$GCC" = yes; then
+    lt_prog_compiler_wl='-Wl,'
+    lt_prog_compiler_static='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	lt_prog_compiler_static='-Bstatic'
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            lt_prog_compiler_pic='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the `-m68020' flag to GCC prevents building anything better,
+            # like `-m68040'.
+            lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      lt_prog_compiler_pic='-DDLL_EXPORT'
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_prog_compiler_pic='-fno-common'
+      ;;
+
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      lt_prog_compiler_static=
+      ;;
+
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+	# +Z the default
+	;;
+      *)
+	lt_prog_compiler_pic='-fPIC'
+	;;
+      esac
+      ;;
+
+    interix[3-9]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      lt_prog_compiler_can_build_shared=no
+      enable_shared=no
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      lt_prog_compiler_pic='-fPIC -shared'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	lt_prog_compiler_pic=-Kconform_pic
+      fi
+      ;;
+
+    *)
+      lt_prog_compiler_pic='-fPIC'
+      ;;
+    esac
+
+    case $cc_basename in
+    nvcc*) # Cuda Compiler Driver 2.2
+      lt_prog_compiler_wl='-Xlinker '
+      if test -n "$lt_prog_compiler_pic"; then
+        lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic"
+      fi
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      lt_prog_compiler_wl='-Wl,'
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	lt_prog_compiler_static='-Bstatic'
+      else
+	lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_prog_compiler_pic='-DDLL_EXPORT'
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      lt_prog_compiler_wl='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+	# +Z the default
+	;;
+      *)
+	lt_prog_compiler_pic='+Z'
+	;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      lt_prog_compiler_static='${wl}-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      lt_prog_compiler_wl='-Wl,'
+      # PIC (with -KPIC) is the default.
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    linux* | k*bsd*-gnu | kopensolaris*-gnu)
+      case $cc_basename in
+      # old Intel for x86_64 which still supported -KPIC.
+      ecc*)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-KPIC'
+	lt_prog_compiler_static='-static'
+        ;;
+      # icc used to be incompatible with GCC.
+      # ICC 10 doesn't accept -KPIC any more.
+      icc* | ifort*)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-fPIC'
+	lt_prog_compiler_static='-static'
+        ;;
+      # Lahey Fortran 8.1.
+      lf95*)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='--shared'
+	lt_prog_compiler_static='--static'
+	;;
+      nagfor*)
+	# NAG Fortran compiler
+	lt_prog_compiler_wl='-Wl,-Wl,,'
+	lt_prog_compiler_pic='-PIC'
+	lt_prog_compiler_static='-Bstatic'
+	;;
+      pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+	# which looks to be a dead project)
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-fpic'
+	lt_prog_compiler_static='-Bstatic'
+        ;;
+      ccc*)
+        lt_prog_compiler_wl='-Wl,'
+        # All Alpha code is PIC.
+        lt_prog_compiler_static='-non_shared'
+        ;;
+      xl* | bgxl* | bgf* | mpixl*)
+	# IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
+	lt_prog_compiler_wl='-Wl,'
+	lt_prog_compiler_pic='-qpic'
+	lt_prog_compiler_static='-qstaticlink'
+	;;
+      *)
+	case `$CC -V 2>&1 | sed 5q` in
+	*Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*)
+	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
+	  lt_prog_compiler_pic='-KPIC'
+	  lt_prog_compiler_static='-Bstatic'
+	  lt_prog_compiler_wl=''
+	  ;;
+	*Sun\ F* | *Sun*Fortran*)
+	  lt_prog_compiler_pic='-KPIC'
+	  lt_prog_compiler_static='-Bstatic'
+	  lt_prog_compiler_wl='-Qoption ld '
+	  ;;
+	*Sun\ C*)
+	  # Sun C 5.9
+	  lt_prog_compiler_pic='-KPIC'
+	  lt_prog_compiler_static='-Bstatic'
+	  lt_prog_compiler_wl='-Wl,'
+	  ;;
+        *Intel*\ [CF]*Compiler*)
+	  lt_prog_compiler_wl='-Wl,'
+	  lt_prog_compiler_pic='-fPIC'
+	  lt_prog_compiler_static='-static'
+	  ;;
+	*Portland\ Group*)
+	  lt_prog_compiler_wl='-Wl,'
+	  lt_prog_compiler_pic='-fpic'
+	  lt_prog_compiler_static='-Bstatic'
+	  ;;
+	esac
+	;;
+      esac
+      ;;
+
+    newsos6)
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      lt_prog_compiler_pic='-fPIC -shared'
+      ;;
+
+    osf3* | osf4* | osf5*)
+      lt_prog_compiler_wl='-Wl,'
+      # All OSF/1 code is PIC.
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    rdos*)
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    solaris*)
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
+	lt_prog_compiler_wl='-Qoption ld ';;
+      *)
+	lt_prog_compiler_wl='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      lt_prog_compiler_wl='-Qoption ld '
+      lt_prog_compiler_pic='-PIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+	lt_prog_compiler_pic='-Kconform_pic'
+	lt_prog_compiler_static='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    unicos*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_can_build_shared=no
+      ;;
+
+    uts4*)
+      lt_prog_compiler_pic='-pic'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    *)
+      lt_prog_compiler_can_build_shared=no
+      ;;
+    esac
+  fi
+
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    lt_prog_compiler_pic=
+    ;;
+  *)
+    lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
+    ;;
+esac
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
+$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
+if ${lt_cv_prog_compiler_pic+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_pic=$lt_prog_compiler_pic
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5
+$as_echo "$lt_cv_prog_compiler_pic" >&6; }
+lt_prog_compiler_pic=$lt_cv_prog_compiler_pic
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
+if ${lt_cv_prog_compiler_pic_works+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_pic_works=no
+   ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$lt_prog_compiler_pic -DPIC"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_pic_works=yes
+     fi
+   fi
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5
+$as_echo "$lt_cv_prog_compiler_pic_works" >&6; }
+
+if test x"$lt_cv_prog_compiler_pic_works" = xyes; then
+    case $lt_prog_compiler_pic in
+     "" | " "*) ;;
+     *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
+     esac
+else
+    lt_prog_compiler_pic=
+     lt_prog_compiler_can_build_shared=no
+fi
+
+fi
+
+
+
+
+
+
+
+
+
+
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
+if ${lt_cv_prog_compiler_static_works+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_static_works=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_cv_prog_compiler_static_works=yes
+       fi
+     else
+       lt_cv_prog_compiler_static_works=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5
+$as_echo "$lt_cv_prog_compiler_static_works" >&6; }
+
+if test x"$lt_cv_prog_compiler_static_works" = xyes; then
+    :
+else
+    lt_prog_compiler_static=
+fi
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if ${lt_cv_prog_compiler_c_o+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_c_o=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if ${lt_cv_prog_compiler_c_o+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_c_o=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
+$as_echo_n "checking if we can lock with hard links... " >&6; }
+  hard_links=yes
+  $RM conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
+$as_echo "$hard_links" >&6; }
+  if test "$hard_links" = no; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+
+  runpath_var=
+  allow_undefined_flag=
+  always_export_symbols=no
+  archive_cmds=
+  archive_expsym_cmds=
+  compiler_needs_object=no
+  enable_shared_with_static_runtimes=no
+  export_dynamic_flag_spec=
+  export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  hardcode_automatic=no
+  hardcode_direct=no
+  hardcode_direct_absolute=no
+  hardcode_libdir_flag_spec=
+  hardcode_libdir_separator=
+  hardcode_minus_L=no
+  hardcode_shlibpath_var=unsupported
+  inherit_rpath=no
+  link_all_deplibs=unknown
+  module_cmds=
+  module_expsym_cmds=
+  old_archive_from_new_cmds=
+  old_archive_from_expsyms_cmds=
+  thread_safe_flag_spec=
+  whole_archive_flag_spec=
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  include_expsyms=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  # Exclude shared library initialization/finalization symbols.
+  extract_expsyms_cmds=
+
+  case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+  esac
+
+  ld_shlibs=yes
+
+  # On some targets, GNU ld is compatible enough with the native linker
+  # that we're better off using the native interface for both.
+  lt_use_gnu_ld_interface=no
+  if test "$with_gnu_ld" = yes; then
+    case $host_os in
+      aix*)
+	# The AIX port of GNU ld has always aspired to compatibility
+	# with the native linker.  However, as the warning in the GNU ld
+	# block says, versions before 2.19.5* couldn't really create working
+	# shared libraries, regardless of the interface used.
+	case `$LD -v 2>&1` in
+	  *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+	  *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;;
+	  *\ \(GNU\ Binutils\)\ [3-9]*) ;;
+	  *)
+	    lt_use_gnu_ld_interface=yes
+	    ;;
+	esac
+	;;
+      *)
+	lt_use_gnu_ld_interface=yes
+	;;
+    esac
+  fi
+
+  if test "$lt_use_gnu_ld_interface" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    export_dynamic_flag_spec='${wl}--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+      whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+    else
+      whole_archive_flag_spec=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v 2>&1` in
+      *GNU\ gold*) supports_anon_versioning=yes ;;
+      *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix[3-9]*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+	ld_shlibs=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.19, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to install binutils
+*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+*** You will then need to restart the configuration process.
+
+_LT_EOF
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            archive_expsym_cmds=''
+        ;;
+      m68k)
+            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            hardcode_libdir_flag_spec='-L$libdir'
+            hardcode_minus_L=yes
+        ;;
+      esac
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	allow_undefined_flag=unsupported
+	# Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+	# support --undefined.  This deserves some investigation.  FIXME
+	archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
+      # as there is no search path for DLLs.
+      hardcode_libdir_flag_spec='-L$libdir'
+      export_dynamic_flag_spec='${wl}--export-all-symbols'
+      allow_undefined_flag=unsupported
+      always_export_symbols=no
+      enable_shared_with_static_runtimes=yes
+      export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
+      exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'
+
+      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+        archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+	# If the export-symbols file already is a .def file (1st line
+	# is EXPORTS), use it as is; otherwise, prepend...
+	archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	  cp $export_symbols $output_objdir/$soname.def;
+	else
+	  echo EXPORTS > $output_objdir/$soname.def;
+	  cat $export_symbols >> $output_objdir/$soname.def;
+	fi~
+	$CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    haiku*)
+      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      link_all_deplibs=yes
+      ;;
+
+    interix[3-9]*)
+      hardcode_direct=no
+      hardcode_shlibpath_var=no
+      hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+      export_dynamic_flag_spec='${wl}-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+      tmp_diet=no
+      if test "$host_os" = linux-dietlibc; then
+	case $cc_basename in
+	  diet\ *) tmp_diet=yes;;	# linux-dietlibc with static linking (!diet-dyn)
+	esac
+      fi
+      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+	 && test "$tmp_diet" = no
+      then
+	tmp_addflag=' $pic_flag'
+	tmp_sharedflag='-shared'
+	case $cc_basename,$host_cpu in
+        pgcc*)				# Portland Group C compiler
+	  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  tmp_addflag=' $pic_flag'
+	  ;;
+	pgf77* | pgf90* | pgf95* | pgfortran*)
+					# Portland Group f77 and f90 compilers
+	  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  tmp_addflag=' $pic_flag -Mnomain' ;;
+	ecc*,ia64* | icc*,ia64*)	# Intel C compiler on ia64
+	  tmp_addflag=' -i_dynamic' ;;
+	efc*,ia64* | ifort*,ia64*)	# Intel Fortran compiler on ia64
+	  tmp_addflag=' -i_dynamic -nofor_main' ;;
+	ifc* | ifort*)			# Intel Fortran compiler
+	  tmp_addflag=' -nofor_main' ;;
+	lf95*)				# Lahey Fortran 8.1
+	  whole_archive_flag_spec=
+	  tmp_sharedflag='--shared' ;;
+	xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+	  tmp_sharedflag='-qmkshrobj'
+	  tmp_addflag= ;;
+	nvcc*)	# Cuda Compiler Driver 2.2
+	  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  compiler_needs_object=yes
+	  ;;
+	esac
+	case `$CC -V 2>&1 | sed 5q` in
+	*Sun\ C*)			# Sun C 5.9
+	  whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+	  compiler_needs_object=yes
+	  tmp_sharedflag='-G' ;;
+	*Sun\ F*)			# Sun Fortran 8.3
+	  tmp_sharedflag='-G' ;;
+	esac
+	archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+        if test "x$supports_anon_versioning" = xyes; then
+          archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+	    cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+	    echo "local: *; };" >> $output_objdir/$libname.ver~
+	    $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+        fi
+
+	case $cc_basename in
+	xlf* | bgf* | bgxlf* | mpixlf*)
+	  # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+	  whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive'
+	  hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+	  archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
+	  if test "x$supports_anon_versioning" = xyes; then
+	    archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+	      cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+	      echo "local: *; };" >> $output_objdir/$libname.ver~
+	      $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+	  fi
+	  ;;
+	esac
+      else
+        ld_shlibs=no
+      fi
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+	wlarc=
+      else
+	archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+	ld_shlibs=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+	ld_shlibs=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+	;;
+	*)
+	  # For security reasons, it is highly recommended that you always
+	  # use absolute paths for naming shared libraries, and exclude the
+	  # DT_RUNPATH tag from executables and libraries.  But doing so
+	  # requires that you compile everything twice, which is a pain.
+	  if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+	    archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	    archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+	  else
+	    ld_shlibs=no
+	  fi
+	;;
+      esac
+      ;;
+
+    sunos4*)
+      archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	ld_shlibs=no
+      fi
+      ;;
+    esac
+
+    if test "$ld_shlibs" = no; then
+      runpath_var=
+      hardcode_libdir_flag_spec=
+      export_dynamic_flag_spec=
+      whole_archive_flag_spec=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      allow_undefined_flag=unsupported
+      always_export_symbols=yes
+      archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      hardcode_minus_L=yes
+      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+	# Neither direct hardcoding nor static linking is supported with a
+	# broken collect2.
+	hardcode_direct=unsupported
+      fi
+      ;;
+
+    aix[4-9]*)
+      if test "$host_cpu" = ia64; then
+	# On IA64, the linker does run time linking by default, so we don't
+	# have to do anything special.
+	aix_use_runtimelinking=no
+	exp_sym_flag='-Bexport'
+	no_entry_flag=""
+      else
+	# If we're using GNU nm, then we don't want the "-C" option.
+	# -C means demangle to AIX nm, but means don't demangle with GNU nm
+	# Also, AIX nm treats weak defined symbols like other global
+	# defined symbols, whereas GNU nm marks them as "W".
+	if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+	  export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	else
+	  export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	fi
+	aix_use_runtimelinking=no
+
+	# Test if we are trying to use run time linking or normal
+	# AIX style linking. If -brtl is somewhere in LDFLAGS, we
+	# need to do runtime linking.
+	case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+	  for ld_flag in $LDFLAGS; do
+	  if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+	    aix_use_runtimelinking=yes
+	    break
+	  fi
+	  done
+	  ;;
+	esac
+
+	exp_sym_flag='-bexport'
+	no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      archive_cmds=''
+      hardcode_direct=yes
+      hardcode_direct_absolute=yes
+      hardcode_libdir_separator=':'
+      link_all_deplibs=yes
+      file_list_spec='${wl}-f,'
+
+      if test "$GCC" = yes; then
+	case $host_os in aix4.[012]|aix4.[012].*)
+	# We only want to do this on AIX 4.2 and lower, the check
+	# below for broken collect2 doesn't work under 4.3+
+	  collect2name=`${CC} -print-prog-name=collect2`
+	  if test -f "$collect2name" &&
+	   strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+	  then
+	  # We have reworked collect2
+	  :
+	  else
+	  # We have old collect2
+	  hardcode_direct=unsupported
+	  # It fails to find uninstalled libraries when the uninstalled
+	  # path is not listed in the libpath.  Setting hardcode_minus_L
+	  # to unsupported forces relinking
+	  hardcode_minus_L=yes
+	  hardcode_libdir_flag_spec='-L$libdir'
+	  hardcode_libdir_separator=
+	  fi
+	  ;;
+	esac
+	shared_flag='-shared'
+	if test "$aix_use_runtimelinking" = yes; then
+	  shared_flag="$shared_flag "'${wl}-G'
+	fi
+      else
+	# not using gcc
+	if test "$host_cpu" = ia64; then
+	# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+	# chokes on -Wl,-G. The following line is correct:
+	  shared_flag='-G'
+	else
+	  if test "$aix_use_runtimelinking" = yes; then
+	    shared_flag='${wl}-G'
+	  else
+	    shared_flag='${wl}-bM:SRE'
+	  fi
+	fi
+      fi
+
+      export_dynamic_flag_spec='${wl}-bexpall'
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      always_export_symbols=yes
+      if test "$aix_use_runtimelinking" = yes; then
+	# Warning - without using the other runtime loading flags (-brtl),
+	# -berok will link without error, but may produce a broken library.
+	allow_undefined_flag='-berok'
+        # Determine the default libpath from the value encoded in an
+        # empty executable.
+        if test "${lt_cv_aix_libpath+set}" = set; then
+  aix_libpath=$lt_cv_aix_libpath
+else
+  if ${lt_cv_aix_libpath_+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+  lt_aix_libpath_sed='
+      /Import File Strings/,/^$/ {
+	  /^0/ {
+	      s/^0  *\([^ ]*\) *$/\1/
+	      p
+	  }
+      }'
+  lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  # Check for a 64-bit object if we didn't find anything.
+  if test -z "$lt_cv_aix_libpath_"; then
+    lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+  if test -z "$lt_cv_aix_libpath_"; then
+    lt_cv_aix_libpath_="/usr/lib:/lib"
+  fi
+
+fi
+
+  aix_libpath=$lt_cv_aix_libpath_
+fi
+
+        hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+        archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+      else
+	if test "$host_cpu" = ia64; then
+	  hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+	  allow_undefined_flag="-z nodefs"
+	  archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+	else
+	 # Determine the default libpath from the value encoded in an
+	 # empty executable.
+	 if test "${lt_cv_aix_libpath+set}" = set; then
+  aix_libpath=$lt_cv_aix_libpath
+else
+  if ${lt_cv_aix_libpath_+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+  lt_aix_libpath_sed='
+      /Import File Strings/,/^$/ {
+	  /^0/ {
+	      s/^0  *\([^ ]*\) *$/\1/
+	      p
+	  }
+      }'
+  lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  # Check for a 64-bit object if we didn't find anything.
+  if test -z "$lt_cv_aix_libpath_"; then
+    lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+  if test -z "$lt_cv_aix_libpath_"; then
+    lt_cv_aix_libpath_="/usr/lib:/lib"
+  fi
+
+fi
+
+  aix_libpath=$lt_cv_aix_libpath_
+fi
+
+	 hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+	  # Warning - without using the other run time loading flags,
+	  # -berok will link without error, but may produce a broken library.
+	  no_undefined_flag=' ${wl}-bernotok'
+	  allow_undefined_flag=' ${wl}-berok'
+	  if test "$with_gnu_ld" = yes; then
+	    # We only use this code for GNU lds that support --whole-archive.
+	    whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+	  else
+	    # Exported symbols can be pulled into shared objects from archives
+	    whole_archive_flag_spec='$convenience'
+	  fi
+	  archive_cmds_need_lc=yes
+	  # This is similar to how AIX traditionally builds its shared libraries.
+	  archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+	fi
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            archive_expsym_cmds=''
+        ;;
+      m68k)
+            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            hardcode_libdir_flag_spec='-L$libdir'
+            hardcode_minus_L=yes
+        ;;
+      esac
+      ;;
+
+    bsdi[45]*)
+      export_dynamic_flag_spec=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      case $cc_basename in
+      cl*)
+	# Native MSVC
+	hardcode_libdir_flag_spec=' '
+	allow_undefined_flag=unsupported
+	always_export_symbols=yes
+	file_list_spec='@'
+	# Tell ltmain to make .lib files, not .a files.
+	libext=lib
+	# Tell ltmain to make .dll files, not .so files.
+	shrext_cmds=".dll"
+	# FIXME: Setting linknames here is a bad hack.
+	archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames='
+	archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	    sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp;
+	  else
+	    sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp;
+	  fi~
+	  $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+	  linknames='
+	# The linker will not automatically build a static lib if we build a DLL.
+	# _LT_TAGVAR(old_archive_from_new_cmds, )='true'
+	enable_shared_with_static_runtimes=yes
+	exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+	export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+	# Don't use ranlib
+	old_postinstall_cmds='chmod 644 $oldlib'
+	postlink_cmds='lt_outputfile="@OUTPUT@"~
+	  lt_tool_outputfile="@TOOL_OUTPUT@"~
+	  case $lt_outputfile in
+	    *.exe|*.EXE) ;;
+	    *)
+	      lt_outputfile="$lt_outputfile.exe"
+	      lt_tool_outputfile="$lt_tool_outputfile.exe"
+	      ;;
+	  esac~
+	  if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then
+	    $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+	    $RM "$lt_outputfile.manifest";
+	  fi'
+	;;
+      *)
+	# Assume MSVC wrapper
+	hardcode_libdir_flag_spec=' '
+	allow_undefined_flag=unsupported
+	# Tell ltmain to make .lib files, not .a files.
+	libext=lib
+	# Tell ltmain to make .dll files, not .so files.
+	shrext_cmds=".dll"
+	# FIXME: Setting linknames here is a bad hack.
+	archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+	# The linker will automatically build a .lib file if we build a DLL.
+	old_archive_from_new_cmds='true'
+	# FIXME: Should let the user specify the lib program.
+	old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
+	enable_shared_with_static_runtimes=yes
+	;;
+      esac
+      ;;
+
+    darwin* | rhapsody*)
+
+
+  archive_cmds_need_lc=no
+  hardcode_direct=no
+  hardcode_automatic=yes
+  hardcode_shlibpath_var=unsupported
+  if test "$lt_cv_ld_force_load" = "yes"; then
+    whole_archive_flag_spec='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+
+  else
+    whole_archive_flag_spec=''
+  fi
+  link_all_deplibs=yes
+  allow_undefined_flag="$_lt_dar_allow_undefined"
+  case $cc_basename in
+     ifort*) _lt_dar_can_shared=yes ;;
+     *) _lt_dar_can_shared=$GCC ;;
+  esac
+  if test "$_lt_dar_can_shared" = "yes"; then
+    output_verbose_link_cmd=func_echo_all
+    archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+    module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+    archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+    module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+
+  else
+  ld_shlibs=no
+  fi
+
+      ;;
+
+    dgux*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_shlibpath_var=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2.*)
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly*)
+      archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    hpux9*)
+      if test "$GCC" = yes; then
+	archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+	archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+      hardcode_libdir_separator=:
+      hardcode_direct=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      hardcode_minus_L=yes
+      export_dynamic_flag_spec='${wl}-E'
+      ;;
+
+    hpux10*)
+      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+	archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test "$with_gnu_ld" = no; then
+	hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+	hardcode_libdir_separator=:
+	hardcode_direct=yes
+	hardcode_direct_absolute=yes
+	export_dynamic_flag_spec='${wl}-E'
+	# hardcode_minus_L: Not really in the search PATH,
+	# but as the default location of the library.
+	hardcode_minus_L=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+	case $host_cpu in
+	hppa*64*)
+	  archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	esac
+      else
+	case $host_cpu in
+	hppa*64*)
+	  archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+
+	  # Older versions of the 11.00 compiler do not understand -b yet
+	  # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5
+$as_echo_n "checking if $CC understands -b... " >&6; }
+if ${lt_cv_prog_compiler__b+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler__b=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS -b"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_cv_prog_compiler__b=yes
+       fi
+     else
+       lt_cv_prog_compiler__b=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5
+$as_echo "$lt_cv_prog_compiler__b" >&6; }
+
+if test x"$lt_cv_prog_compiler__b" = xyes; then
+    archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+else
+    archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+fi
+
+	  ;;
+	esac
+      fi
+      if test "$with_gnu_ld" = no; then
+	hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+	hardcode_libdir_separator=:
+
+	case $host_cpu in
+	hppa*64*|ia64*)
+	  hardcode_direct=no
+	  hardcode_shlibpath_var=no
+	  ;;
+	*)
+	  hardcode_direct=yes
+	  hardcode_direct_absolute=yes
+	  export_dynamic_flag_spec='${wl}-E'
+
+	  # hardcode_minus_L: Not really in the search PATH,
+	  # but as the default location of the library.
+	  hardcode_minus_L=yes
+	  ;;
+	esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+	archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	# Try to use the -exported_symbol ld option, if it does not
+	# work, assume that -exports_file does not work either and
+	# implicitly export all symbols.
+	# This should be the same for all languages, so no per-tag cache variable.
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5
+$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; }
+if ${lt_cv_irix_exported_symbol+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  save_LDFLAGS="$LDFLAGS"
+	   LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
+	   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int foo (void) { return 0; }
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  lt_cv_irix_exported_symbol=yes
+else
+  lt_cv_irix_exported_symbol=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+           LDFLAGS="$save_LDFLAGS"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5
+$as_echo "$lt_cv_irix_exported_symbol" >&6; }
+	if test "$lt_cv_irix_exported_symbol" = yes; then
+          archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
+	fi
+      else
+	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      inherit_rpath=yes
+      link_all_deplibs=yes
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+	archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    newsos6)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      hardcode_shlibpath_var=no
+      ;;
+
+    *nto* | *qnx*)
+      ;;
+
+    openbsd*)
+      if test -f /usr/libexec/ld.so; then
+	hardcode_direct=yes
+	hardcode_shlibpath_var=no
+	hardcode_direct_absolute=yes
+	if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+	  archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+	  hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+	  export_dynamic_flag_spec='${wl}-E'
+	else
+	  case $host_os in
+	   openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+	     archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+	     hardcode_libdir_flag_spec='-R$libdir'
+	     ;;
+	   *)
+	     archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	     hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+	     ;;
+	  esac
+	fi
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    os2*)
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_minus_L=yes
+      allow_undefined_flag=unsupported
+      archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
+
+    osf3*)
+      if test "$GCC" = yes; then
+	allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+	allow_undefined_flag=' -expect_unresolved \*'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      ;;
+
+    osf4* | osf5*)	# as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+	allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+	archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      else
+	allow_undefined_flag=' -expect_unresolved \*'
+	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+	archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+	$CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
+
+	# Both c and cxx compiler support -rpath directly
+	hardcode_libdir_flag_spec='-rpath $libdir'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_separator=:
+      ;;
+
+    solaris*)
+      no_undefined_flag=' -z defs'
+      if test "$GCC" = yes; then
+	wlarc='${wl}'
+	archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+      else
+	case `$CC -V 2>&1` in
+	*"Compilers 5.0"*)
+	  wlarc=''
+	  archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+	  ;;
+	*)
+	  wlarc='${wl}'
+	  archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+	  ;;
+	esac
+      fi
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_shlibpath_var=no
+      case $host_os in
+      solaris2.[0-5] | solaris2.[0-5].*) ;;
+      *)
+	# The compiler driver will combine and reorder linker options,
+	# but understands `-z linker_flag'.  GCC discards it without `$wl',
+	# but is careful enough not to reorder.
+	# Supported since Solaris 2.6 (maybe 2.5.1?)
+	if test "$GCC" = yes; then
+	  whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+	else
+	  whole_archive_flag_spec='-z allextract$convenience -z defaultextract'
+	fi
+	;;
+      esac
+      link_all_deplibs=yes
+      ;;
+
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+	# Use $CC to link under sequent, because it throws in some extra .o
+	# files that make .init and .fini sections work.
+	archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+	sni)
+	  archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  hardcode_direct=yes # is this really true???
+	;;
+	siemens)
+	  ## LD is ld it makes a PLAMLIB
+	  ## CC just makes a GrossModule.
+	  archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+	  reload_cmds='$CC -r -o $output$reload_objs'
+	  hardcode_direct=no
+        ;;
+	motorola)
+	  archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+	;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      hardcode_shlibpath_var=no
+      ;;
+
+    sysv4.3*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_shlibpath_var=no
+      export_dynamic_flag_spec='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	hardcode_shlibpath_var=no
+	runpath_var=LD_RUN_PATH
+	hardcode_runpath_var=yes
+	ld_shlibs=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+      no_undefined_flag='${wl}-z,text'
+      archive_cmds_need_lc=no
+      hardcode_shlibpath_var=no
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+	archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We can NOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      no_undefined_flag='${wl}-z,text'
+      allow_undefined_flag='${wl}-z,nodefs'
+      archive_cmds_need_lc=no
+      hardcode_shlibpath_var=no
+      hardcode_libdir_flag_spec='${wl}-R,$libdir'
+      hardcode_libdir_separator=':'
+      link_all_deplibs=yes
+      export_dynamic_flag_spec='${wl}-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+	archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_shlibpath_var=no
+      ;;
+
+    *)
+      ld_shlibs=no
+      ;;
+    esac
+
+    if test x$host_vendor = xsni; then
+      case $host in
+      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+	export_dynamic_flag_spec='${wl}-Blargedynsym'
+	;;
+      esac
+    fi
+  fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5
+$as_echo "$ld_shlibs" >&6; }
+test "$ld_shlibs" = no && can_build_shared=no
+
+with_gnu_ld=$with_gnu_ld
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc" in
+x|xyes)
+  # Assume -lc should be added
+  archive_cmds_need_lc=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $archive_cmds in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
+$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
+if ${lt_cv_archive_cmds_need_lc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  $RM conftest*
+	echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+	if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } 2>conftest.err; then
+	  soname=conftest
+	  lib=conftest
+	  libobjs=conftest.$ac_objext
+	  deplibs=
+	  wl=$lt_prog_compiler_wl
+	  pic_flag=$lt_prog_compiler_pic
+	  compiler_flags=-v
+	  linker_flags=-v
+	  verstring=
+	  output_objdir=.
+	  libname=conftest
+	  lt_save_allow_undefined_flag=$allow_undefined_flag
+	  allow_undefined_flag=
+	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
+  (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+	  then
+	    lt_cv_archive_cmds_need_lc=no
+	  else
+	    lt_cv_archive_cmds_need_lc=yes
+	  fi
+	  allow_undefined_flag=$lt_save_allow_undefined_flag
+	else
+	  cat conftest.err 1>&5
+	fi
+	$RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5
+$as_echo "$lt_cv_archive_cmds_need_lc" >&6; }
+      archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
+$as_echo_n "checking dynamic linker characteristics... " >&6; }
+
+if test "$GCC" = yes; then
+  case $host_os in
+    darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+    *) lt_awk_arg="/^libraries:/" ;;
+  esac
+  case $host_os in
+    mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;;
+    *) lt_sed_strip_eq="s,=/,/,g" ;;
+  esac
+  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
+  case $lt_search_path_spec in
+  *\;*)
+    # if the path contains ";" then we assume it to be the separator
+    # otherwise default to the standard path separator (i.e. ":") - it is
+    # assumed that no part of a normal pathname contains ";" but that should
+    # okay in the real world where ";" in dirpaths is itself problematic.
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
+    ;;
+  *)
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
+    ;;
+  esac
+  # Ok, now we have the path, separated by spaces, we can step through it
+  # and add multilib dir if necessary.
+  lt_tmp_lt_search_path_spec=
+  lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+  for lt_sys_path in $lt_search_path_spec; do
+    if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+    else
+      test -d "$lt_sys_path" && \
+	lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+    fi
+  done
+  lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
+BEGIN {RS=" "; FS="/|\n";} {
+  lt_foo="";
+  lt_count=0;
+  for (lt_i = NF; lt_i > 0; lt_i--) {
+    if ($lt_i != "" && $lt_i != ".") {
+      if ($lt_i == "..") {
+        lt_count++;
+      } else {
+        if (lt_count == 0) {
+          lt_foo="/" $lt_i lt_foo;
+        } else {
+          lt_count--;
+        }
+      }
+    }
+  }
+  if (lt_foo != "") { lt_freq[lt_foo]++; }
+  if (lt_freq[lt_foo] == 1) { print lt_foo; }
+}'`
+  # AWK program above erroneously prepends '/' to C:/dos/paths
+  # for these hosts.
+  case $host_os in
+    mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+      $SED 's,/\([A-Za-z]:\),\1,g'` ;;
+  esac
+  sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
+else
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix[4-9]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[01] | aix4.[01].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+	   echo ' yes '
+	   echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
+	:
+      else
+	can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  case $host_cpu in
+  powerpc)
+    # Since July 2007 AmigaOS4 officially supports .so libraries.
+    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    ;;
+  m68k)
+    library_names_spec='$libname.ixlibrary $libname.a'
+    # Create ${libname}_ixlibrary.a entries in /sys/libs.
+    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+    ;;
+  esac
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[45]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$cc_basename in
+  yes,*)
+    # gcc
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname~
+      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+      fi'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+
+      sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"
+      ;;
+    mingw* | cegcc*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    dynamic_linker='Win32 ld.exe'
+    ;;
+
+  *,cl*)
+    # Native MSVC
+    libname_spec='$name'
+    soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+    library_names_spec='${libname}.dll.lib'
+
+    case $build_os in
+    mingw*)
+      sys_lib_search_path_spec=
+      lt_save_ifs=$IFS
+      IFS=';'
+      for lt_path in $LIB
+      do
+        IFS=$lt_save_ifs
+        # Let DOS variable expansion print the short 8.3 style file name.
+        lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
+        sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
+      done
+      IFS=$lt_save_ifs
+      # Convert to MSYS style.
+      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'`
+      ;;
+    cygwin*)
+      # Convert to unix form, then to dos form, then back to unix form
+      # but this time dos style (no spaces!) so that the unix form looks
+      # like /cygdrive/c/PROGRA~1:/cygdr...
+      sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
+      sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
+      sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      ;;
+    *)
+      sys_lib_search_path_spec="$LIB"
+      if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
+        # It is most probably a Windows format PATH.
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      # FIXME: find the short name or the path components, as spaces are
+      # common. (e.g. "Program Files" -> "PROGRA~1")
+      ;;
+    esac
+
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+    dynamic_linker='Win32 link.exe'
+    ;;
+
+  *)
+    # Assume MSVC wrapper
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    dynamic_linker='Win32 ld.exe'
+    ;;
+  esac
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[23].*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2.*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[01]* | freebsdelf3.[01]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+  freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+haiku*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  dynamic_linker="$host_os runtime_loader"
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  hppa*64*)
+    shrext_cmds='.sl'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+  postinstall_cmds='chmod 555 $lib'
+  # or fails outright, so override atomically:
+  install_override_mode=555
+  ;;
+
+interix[3-9]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+	if test "$lt_cv_prog_gnu_ld" = yes; then
+		version_type=linux # correct to gnu/linux during the next big refactor
+	else
+		version_type=irix
+	fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+
+  # Some binutils ld are patched to set DT_RUNPATH
+  if ${lt_cv_shlibpath_overrides_runpath+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_shlibpath_overrides_runpath=no
+    save_LDFLAGS=$LDFLAGS
+    save_libdir=$libdir
+    eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
+	 LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  if  ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then :
+  lt_cv_shlibpath_overrides_runpath=yes
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+    LDFLAGS=$save_LDFLAGS
+    libdir=$save_libdir
+
+fi
+
+  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Add ABI-specific directories to the system library path.
+  sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib"
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra"
+
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+*nto* | *qnx*)
+  version_type=qnx
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='ldqnx.so'
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*)	need_version=yes ;;
+    *)				need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[89] | openbsd2.[89].*)
+	shlibpath_overrides_runpath=no
+	;;
+      *)
+	shlibpath_overrides_runpath=yes
+	;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux # correct to gnu/linux during the next big refactor
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+	;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+tpf*)
+  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+uts4*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
+$as_echo "$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+  sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+  sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
+$as_echo_n "checking how to hardcode library paths into programs... " >&6; }
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" ||
+   test -n "$runpath_var" ||
+   test "X$hardcode_automatic" = "Xyes" ; then
+
+  # We can hardcode non-existent directories.
+  if test "$hardcode_direct" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no &&
+     test "$hardcode_minus_L" != no; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action=unsupported
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5
+$as_echo "$hardcode_action" >&6; }
+
+if test "$hardcode_action" = relink ||
+   test "$inherit_rpath" = yes; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+
+
+
+
+
+  if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen="load_add_on"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  mingw* | pw32* | cegcc*)
+    lt_cv_dlopen="LoadLibrary"
+    lt_cv_dlopen_libs=
+    ;;
+
+  cygwin*)
+    lt_cv_dlopen="dlopen"
+    lt_cv_dlopen_libs=
+    ;;
+
+  darwin*)
+  # if libdl is installed we need to link against it
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if ${ac_cv_lib_dl_dlopen+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dl_dlopen=yes
+else
+  ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+
+    lt_cv_dlopen="dyld"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+
+fi
+
+    ;;
+
+  *)
+    ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
+if test "x$ac_cv_func_shl_load" = xyes; then :
+  lt_cv_dlopen="shl_load"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
+$as_echo_n "checking for shl_load in -ldld... " >&6; }
+if ${ac_cv_lib_dld_shl_load+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+int
+main ()
+{
+return shl_load ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dld_shl_load=yes
+else
+  ac_cv_lib_dld_shl_load=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
+$as_echo "$ac_cv_lib_dld_shl_load" >&6; }
+if test "x$ac_cv_lib_dld_shl_load" = xyes; then :
+  lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
+else
+  ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen"
+if test "x$ac_cv_func_dlopen" = xyes; then :
+  lt_cv_dlopen="dlopen"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if ${ac_cv_lib_dl_dlopen+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dl_dlopen=yes
+else
+  ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
+$as_echo_n "checking for dlopen in -lsvld... " >&6; }
+if ${ac_cv_lib_svld_dlopen+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_svld_dlopen=yes
+else
+  ac_cv_lib_svld_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
+$as_echo "$ac_cv_lib_svld_dlopen" >&6; }
+if test "x$ac_cv_lib_svld_dlopen" = xyes; then :
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
+$as_echo_n "checking for dld_link in -ldld... " >&6; }
+if ${ac_cv_lib_dld_dld_link+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link ();
+int
+main ()
+{
+return dld_link ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dld_dld_link=yes
+else
+  ac_cv_lib_dld_dld_link=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
+$as_echo "$ac_cv_lib_dld_dld_link" >&6; }
+if test "x$ac_cv_lib_dld_dld_link" = xyes; then :
+  lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+    ;;
+  esac
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  else
+    enable_dlopen=no
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS="$CPPFLAGS"
+    test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS="$LDFLAGS"
+    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS="$LIBS"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5
+$as_echo_n "checking whether a program can dlopen itself... " >&6; }
+if ${lt_cv_dlopen_self+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  	  if test "$cross_compiling" = yes; then :
+  lt_cv_dlopen_self=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW		DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW	DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW	0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+/* When -fvisbility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else
+        {
+	  if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+	}
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}
+_LT_EOF
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self=no
+  fi
+fi
+rm -fr conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5
+$as_echo "$lt_cv_dlopen_self" >&6; }
+
+    if test "x$lt_cv_dlopen_self" = xyes; then
+      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5
+$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; }
+if ${lt_cv_dlopen_self_static+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  	  if test "$cross_compiling" = yes; then :
+  lt_cv_dlopen_self_static=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW		DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW	DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW	0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+/* When -fvisbility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else
+        {
+	  if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+	}
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}
+_LT_EOF
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self_static=no
+  fi
+fi
+rm -fr conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5
+$as_echo "$lt_cv_dlopen_self_static" >&6; }
+    fi
+
+    CPPFLAGS="$save_CPPFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+    LIBS="$save_LIBS"
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+striplib=
+old_striplib=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5
+$as_echo_n "checking whether stripping libraries is possible... " >&6; }
+if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+  case $host_os in
+  darwin*)
+    if test -n "$STRIP" ; then
+      striplib="$STRIP -x"
+      old_striplib="$STRIP -S"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+    else
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    fi
+    ;;
+  *)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    ;;
+  esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+  # Report which library types will actually be built
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5
+$as_echo_n "checking if libtool supports shared libraries... " >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5
+$as_echo "$can_build_shared" >&6; }
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5
+$as_echo_n "checking whether to build shared libraries... " >&6; }
+  test "$can_build_shared" = "no" && enable_shared=no
+
+  # On AIX, shared libraries and static libraries use the same namespace, and
+  # are all built from PIC.
+  case $host_os in
+  aix3*)
+    test "$enable_shared" = yes && enable_static=no
+    if test -n "$RANLIB"; then
+      archive_cmds="$archive_cmds~\$RANLIB \$lib"
+      postinstall_cmds='$RANLIB $lib'
+    fi
+    ;;
+
+  aix[4-9]*)
+    if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+      test "$enable_shared" = yes && enable_static=no
+    fi
+    ;;
+  esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5
+$as_echo "$enable_shared" >&6; }
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5
+$as_echo_n "checking whether to build static libraries... " >&6; }
+  # Make sure either enable_shared or enable_static is yes.
+  test "$enable_shared" = yes || enable_static=yes
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5
+$as_echo "$enable_static" >&6; }
+
+
+
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+        ac_config_commands="$ac_config_commands libtool"
+
+
+
+
+# Only expand once:
+
+
+
+
+
+
+
+
+
+
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+	if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PKG_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_PKG_CONFIG"; then
+  ac_pt_PKG_CONFIG=$PKG_CONFIG
+  # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ac_pt_PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
+if test -n "$ac_pt_PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
+$as_echo "$ac_pt_PKG_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_pt_PKG_CONFIG" = x; then
+    PKG_CONFIG=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    PKG_CONFIG=$ac_pt_PKG_CONFIG
+  fi
+else
+  PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
+fi
+
+fi
+if test -n "$PKG_CONFIG"; then
+	_pkg_min_version=0.9.0
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
+$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
+	if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	else
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		PKG_CONFIG=""
+	fi
+fi
+
+# Extract the first word of "mv", so it can be a program name with args.
+set dummy mv; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_MV+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MV in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_MV="$MV" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_MV="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+MV=$ac_cv_path_MV
+if test -n "$MV"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MV" >&5
+$as_echo "$MV" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+# Extract the first word of "rm", so it can be a program name with args.
+set dummy rm; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_RM+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $RM in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_RM="$RM" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_RM="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+RM=$ac_cv_path_RM
+if test -n "$RM"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RM" >&5
+$as_echo "$RM" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+# Extract the first word of "sed", so it can be a program name with args.
+set dummy sed; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_SED+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $SED in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_SED="$SED" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_SED="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+SED=$ac_cv_path_SED
+if test -n "$SED"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SED" >&5
+$as_echo "$SED" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+# Extract the first word of "ldconfig", so it can be a program name with args.
+set dummy ldconfig; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_LDCONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $LDCONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_LDCONFIG="$LDCONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /sbin /usr/sbin $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_LDCONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_LDCONFIG" && ac_cv_path_LDCONFIG="true"
+  ;;
+esac
+fi
+LDCONFIG=$ac_cv_path_LDCONFIG
+if test -n "$LDCONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LDCONFIG" >&5
+$as_echo "$LDCONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+# Environment
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking Windows OS" >&5
+$as_echo_n "checking Windows OS... " >&6; }
+case "${target}" in
+*-mingw32*|*-winnt*|*-cygwin*)
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	WINDOWS="yes"
+
+$as_echo "#define WINDOWS 1" >>confdefs.h
+
+	;;
+*)
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	WINDOWS="no"
+	;;
+esac
+
+if test "x${enable_ntfs_3g}" = "xyes"; then
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking fuse compatibility" >&5
+$as_echo_n "checking fuse compatibility... " >&6; }
+	case "${target_os}" in
+	linux*|solaris*)
+
+# Check whether --with-fuse was given.
+if test "${with_fuse+set}" = set; then :
+  withval=$with_fuse;
+else
+  with_fuse="internal"
+
+fi
+
+		;;
+	darwin*|netbsd*|kfreebsd*-gnu)
+		with_fuse="external"
+		;;
+	freebsd*)
+		as_fn_error $? "Please see FreeBSD support at http://www.freshports.org/sysutils/fusefs-ntfs" "$LINENO" 5
+		;;
+	*)
+		as_fn_error $? "ntfs-3g can be built for Linux, FreeBSD, Mac OS X, NetBSD, and Solaris only." "$LINENO" 5
+		;;
+	esac
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_fuse}" >&5
+$as_echo "${with_fuse}" >&6; }
+else
+        with_fuse="none"
+fi
+
+case "${target_os}" in
+solaris*)
+	if test "x$GCC" != "xyes" ; then
+		as_fn_error $? "ntfs-3g can be built only with gcc on Solaris. Install it by 'pkg install gcc-dev' and retry.)" "$LINENO" 5
+	fi
+	;;
+esac
+
+if test "${enable_ldscript}" = "yes"; then
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking Output format" >&5
+$as_echo_n "checking Output format... " >&6; }
+	OUTPUT_FORMAT="$(${CC} ${CFLAGS} ${LDFLAGS} -Wl,--verbose 2>&1 | ${SED} -n 's/^OUTPUT_FORMAT("\([^"]*\)",.*/\1/p')"
+	if test -z "${OUTPUT_FORMAT}"; then
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: None" >&5
+$as_echo "None" >&6; }
+	else
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${OUTPUT_FORMAT}" >&5
+$as_echo "${OUTPUT_FORMAT}" >&6; }
+		OUTPUT_FORMAT="OUTPUT_FORMAT ( ${OUTPUT_FORMAT} )"
+	fi
+fi
+
+# Libraries
+if test "${with_fuse}" = "internal"; then
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
+$as_echo_n "checking for pthread_create in -lpthread... " >&6; }
+if ${ac_cv_lib_pthread_pthread_create+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_create ();
+int
+main ()
+{
+return pthread_create ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_pthread_pthread_create=yes
+else
+  ac_cv_lib_pthread_pthread_create=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
+$as_echo "$ac_cv_lib_pthread_pthread_create" >&6; }
+if test "x$ac_cv_lib_pthread_pthread_create" = xyes; then :
+  LIBFUSE_LITE_LIBS="${LIBFUSE_LITE_LIBS} -lpthread"
+else
+  as_fn_error $? "Cannot find pthread library" "$LINENO" 5
+
+fi
+
+
+$as_echo "#define _REENTRANT 1" >>confdefs.h
+
+	# required so that we re-compile anything
+
+$as_echo "#define FUSE_INTERNAL 1" >>confdefs.h
+
+
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking Solaris OS" >&5
+$as_echo_n "checking Solaris OS... " >&6; }
+	ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+			#if !((defined(sun) || defined(__sun)) && (defined(__SVR4) || defined(__svr4__)))
+				#error "Not a Solaris system."
+				#endif
+
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+			LIBFUSE_LITE_CFLAGS="${LIBFUSE_LITE_CFLAGS} -std=c99 -D__SOLARIS__ -D_XOPEN_SOURCE=600 -D__EXTENSIONS__"
+			LIBFUSE_LITE_LIBS="${LIBFUSE_LITE_LIBS} -lxnet"
+
+else
+
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+	ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+elif test "${with_fuse}" = "external"; then
+	if test -z "$PKG_CONFIG"; then
+		# Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PKG_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no"
+  ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+	fi
+	test "x${PKG_CONFIG}" = "xno" && as_fn_error $? "pkg-config wasn't found! Please install from your vendor, or see http://pkg-config.freedesktop.org/wiki/" "$LINENO" 5
+	# 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_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for FUSE_MODULE" >&5
+$as_echo_n "checking for FUSE_MODULE... " >&6; }
+
+if test -n "$FUSE_MODULE_CFLAGS"; then
+    pkg_cv_FUSE_MODULE_CFLAGS="$FUSE_MODULE_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"fuse >= 2.6.0\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "fuse >= 2.6.0") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_FUSE_MODULE_CFLAGS=`$PKG_CONFIG --cflags "fuse >= 2.6.0" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$FUSE_MODULE_LIBS"; then
+    pkg_cv_FUSE_MODULE_LIBS="$FUSE_MODULE_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"fuse >= 2.6.0\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "fuse >= 2.6.0") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_FUSE_MODULE_LIBS=`$PKG_CONFIG --libs "fuse >= 2.6.0" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        FUSE_MODULE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "fuse >= 2.6.0" 2>&1`
+        else
+	        FUSE_MODULE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "fuse >= 2.6.0" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$FUSE_MODULE_PKG_ERRORS" >&5
+
+
+			as_fn_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" "$LINENO" 5
+
+
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+			as_fn_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" "$LINENO" 5
+
+
+else
+	FUSE_MODULE_CFLAGS=$pkg_cv_FUSE_MODULE_CFLAGS
+	FUSE_MODULE_LIBS=$pkg_cv_FUSE_MODULE_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+	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
+
+
+# Check whether --with-libgcrypt-prefix was given.
+if test "${with_libgcrypt_prefix+set}" = set; then :
+  withval=$with_libgcrypt_prefix; libgcrypt_config_prefix="$withval"
+else
+  libgcrypt_config_prefix=""
+fi
+
+  if test x$libgcrypt_config_prefix != x ; then
+     if test x${LIBGCRYPT_CONFIG+set} != xset ; then
+        LIBGCRYPT_CONFIG=$libgcrypt_config_prefix/bin/libgcrypt-config
+     fi
+  fi
+
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}libgcrypt-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}libgcrypt-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_LIBGCRYPT_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $LIBGCRYPT_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_LIBGCRYPT_CONFIG="$LIBGCRYPT_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_LIBGCRYPT_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+LIBGCRYPT_CONFIG=$ac_cv_path_LIBGCRYPT_CONFIG
+if test -n "$LIBGCRYPT_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBGCRYPT_CONFIG" >&5
+$as_echo "$LIBGCRYPT_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_LIBGCRYPT_CONFIG"; then
+  ac_pt_LIBGCRYPT_CONFIG=$LIBGCRYPT_CONFIG
+  # Extract the first word of "libgcrypt-config", so it can be a program name with args.
+set dummy libgcrypt-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ac_pt_LIBGCRYPT_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ac_pt_LIBGCRYPT_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ac_pt_LIBGCRYPT_CONFIG="$ac_pt_LIBGCRYPT_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_ac_pt_LIBGCRYPT_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ac_pt_LIBGCRYPT_CONFIG=$ac_cv_path_ac_pt_LIBGCRYPT_CONFIG
+if test -n "$ac_pt_LIBGCRYPT_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_LIBGCRYPT_CONFIG" >&5
+$as_echo "$ac_pt_LIBGCRYPT_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_pt_LIBGCRYPT_CONFIG" = x; then
+    LIBGCRYPT_CONFIG="no"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    LIBGCRYPT_CONFIG=$ac_pt_LIBGCRYPT_CONFIG
+  fi
+else
+  LIBGCRYPT_CONFIG="$ac_cv_path_LIBGCRYPT_CONFIG"
+fi
+
+  tmp=1.2.2
+  if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then
+     req_libgcrypt_api=`echo "$tmp"     | sed 's/\(.*\):\(.*\)/\1/'`
+     min_libgcrypt_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'`
+  else
+     req_libgcrypt_api=0
+     min_libgcrypt_version="$tmp"
+  fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBGCRYPT - version >= $min_libgcrypt_version" >&5
+$as_echo_n "checking for LIBGCRYPT - version >= $min_libgcrypt_version... " >&6; }
+  ok=no
+  if test "$LIBGCRYPT_CONFIG" != "no" ; then
+    req_major=`echo $min_libgcrypt_version | \
+               sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'`
+    req_minor=`echo $min_libgcrypt_version | \
+               sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'`
+    req_micro=`echo $min_libgcrypt_version | \
+               sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'`
+    libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version`
+    major=`echo $libgcrypt_config_version | \
+               sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1/'`
+    minor=`echo $libgcrypt_config_version | \
+               sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\2/'`
+    micro=`echo $libgcrypt_config_version | \
+               sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\3/'`
+    if test "$major" -gt "$req_major"; then
+        ok=yes
+    else
+        if test "$major" -eq "$req_major"; then
+            if test "$minor" -gt "$req_minor"; then
+               ok=yes
+            else
+               if test "$minor" -eq "$req_minor"; then
+                   if test "$micro" -ge "$req_micro"; then
+                     ok=yes
+                   fi
+               fi
+            fi
+        fi
+    fi
+  fi
+  if test $ok = yes; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($libgcrypt_config_version)" >&5
+$as_echo "yes ($libgcrypt_config_version)" >&6; }
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  fi
+  if test $ok = yes; then
+     # If we have a recent libgcrypt, we should also check that the
+     # API is compatible
+     if test "$req_libgcrypt_api" -gt 0 ; then
+        tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0`
+        if test "$tmp" -gt 0 ; then
+           { $as_echo "$as_me:${as_lineno-$LINENO}: checking LIBGCRYPT API version" >&5
+$as_echo_n "checking LIBGCRYPT API version... " >&6; }
+           if test "$req_libgcrypt_api" -eq "$tmp" ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: result: okay" >&5
+$as_echo "okay" >&6; }
+           else
+             ok=no
+             { $as_echo "$as_me:${as_lineno-$LINENO}: result: does not match. want=$req_libgcrypt_api got=$tmp" >&5
+$as_echo "does not match. want=$req_libgcrypt_api got=$tmp" >&6; }
+           fi
+        fi
+     fi
+  fi
+  if test $ok = yes; then
+    LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags`
+    LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs`
+     have_libgcrypt=true
+    libgcrypt_config_host=`$LIBGCRYPT_CONFIG --host 2>/dev/null || echo none`
+    if test x"$libgcrypt_config_host" != xnone ; then
+      if test x"$libgcrypt_config_host" != x"$host" ; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
+***
+*** The config script $LIBGCRYPT_CONFIG was
+*** built for $libgcrypt_config_host and thus may not match the
+*** used host $host.
+*** You may want to use the configure option --with-libgcrypt-prefix
+*** to specify a matching config script.
+***" >&5
+$as_echo "$as_me: WARNING:
+***
+*** The config script $LIBGCRYPT_CONFIG was
+*** built for $libgcrypt_config_host and thus may not match the
+*** used host $host.
+*** You may want to use the configure option --with-libgcrypt-prefix
+*** to specify a matching config script.
+***" >&2;}
+      fi
+    fi
+  else
+    LIBGCRYPT_CFLAGS=""
+    LIBGCRYPT_LIBS=""
+
+		if test "$enable_crypto" = "yes"; then
+			as_fn_error $? "ntfsprogs crypto code requires the gcrypt library." "$LINENO" 5
+		else
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ntfsprogs crypto code requires the gcrypt library." >&5
+$as_echo "$as_me: WARNING: ntfsprogs crypto code requires the gcrypt library." >&2;}
+		fi
+
+  fi
+
+
+
+	have_libgnutls=false
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNUTLS" >&5
+$as_echo_n "checking for GNUTLS... " >&6; }
+
+if test -n "$GNUTLS_CFLAGS"; then
+    pkg_cv_GNUTLS_CFLAGS="$GNUTLS_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gnutls >= 1.4.4\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "gnutls >= 1.4.4") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_GNUTLS_CFLAGS=`$PKG_CONFIG --cflags "gnutls >= 1.4.4" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$GNUTLS_LIBS"; then
+    pkg_cv_GNUTLS_LIBS="$GNUTLS_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gnutls >= 1.4.4\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "gnutls >= 1.4.4") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_GNUTLS_LIBS=`$PKG_CONFIG --libs "gnutls >= 1.4.4" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        GNUTLS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gnutls >= 1.4.4" 2>&1`
+        else
+	        GNUTLS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gnutls >= 1.4.4" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$GNUTLS_PKG_ERRORS" >&5
+
+	if test "$enable_crypto" = "yes"; then
+			as_fn_error $? "ntfsprogs crypto code requires the gnutls library." "$LINENO" 5
+		else
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ntfsprogs crypto code requires the gnutls library." >&5
+$as_echo "$as_me: WARNING: ntfsprogs crypto code requires the gnutls library." >&2;}
+		fi
+
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	if test "$enable_crypto" = "yes"; then
+			as_fn_error $? "ntfsprogs crypto code requires the gnutls library." "$LINENO" 5
+		else
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ntfsprogs crypto code requires the gnutls library." >&5
+$as_echo "$as_me: WARNING: ntfsprogs crypto code requires the gnutls library." >&2;}
+		fi
+
+else
+	GNUTLS_CFLAGS=$pkg_cv_GNUTLS_CFLAGS
+	GNUTLS_LIBS=$pkg_cv_GNUTLS_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	 have_libgnutls=true
+fi
+	if test "$have_libgcrypt" = "true"; then
+		if test "$have_libgnutls" = "true"; then
+			compile_crypto=true
+
+$as_echo "#define ENABLE_CRYPTO 1" >>confdefs.h
+
+		fi
+	fi
+fi
+ if $compile_crypto; then
+  ENABLE_CRYPTO_TRUE=
+  ENABLE_CRYPTO_FALSE='#'
+else
+  ENABLE_CRYPTO_TRUE='#'
+  ENABLE_CRYPTO_FALSE=
+fi
+
+
+# add --with-extra-includes and --with-extra-libs switch to ./configure
+all_libraries="$all_libraries $USER_LDFLAGS"
+all_includes="$all_includes $USER_INCLUDES"
+
+
+
+# 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.
+
+# Check whether --with-uuid was given.
+if test "${with_uuid+set}" = set; then :
+  withval=$with_uuid; if test "$with_uuid" = "yes"; then
+		extrapath=default
+	elif test "$with_uuid" = "no"; then
+		extrapath=
+	else
+		extrapath=$with_uuid
+	fi
+else
+  extrapath=default
+
+fi
+
+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
+
+	search_for_luuid="yes"
+	ac_fn_c_check_header_mongrel "$LINENO" "uuid/uuid.h" "ac_cv_header_uuid_uuid_h" "$ac_includes_default"
+if test "x$ac_cv_header_uuid_uuid_h" = xyes; then :
+
+else
+
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ntfsprogs DCE compliant UUID generation code requires the uuid library." >&5
+$as_echo "$as_me: WARNING: ntfsprogs DCE compliant UUID generation code requires the uuid library." >&2;}
+			search_for_luuid="no"
+
+fi
+
+
+
+	if test "x$search_for_luuid" != "xno"; then
+		# Look for uuid_generate in the standard C library.
+		ac_fn_c_check_func "$LINENO" "uuid_generate" "ac_cv_func_uuid_generate"
+if test "x$ac_cv_func_uuid_generate" = xyes; then :
+
+
+$as_echo "#define ENABLE_UUID 1" >>confdefs.h
+
+				search_for_luuid="no"
+
+fi
+
+	fi
+
+	if test "x$search_for_luuid" != "xno"; then
+		# Look for uuid_generate in the 'uuid' library.
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_generate in -luuid" >&5
+$as_echo_n "checking for uuid_generate in -luuid... " >&6; }
+if ${ac_cv_lib_uuid_uuid_generate+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-luuid  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char uuid_generate ();
+int
+main ()
+{
+return uuid_generate ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_uuid_uuid_generate=yes
+else
+  ac_cv_lib_uuid_uuid_generate=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_generate" >&5
+$as_echo "$ac_cv_lib_uuid_uuid_generate" >&6; }
+if test "x$ac_cv_lib_uuid_uuid_generate" = xyes; then :
+
+
+$as_echo "#define ENABLE_UUID 1" >>confdefs.h
+
+				MKNTFS_LIBS="$MKNTFS_LIBS -luuid"
+				search_for_luuid="no"
+
+fi
+
+	fi
+
+	if test "x$search_for_luuid" != "xno"; then
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ntfsprogs DCE compliant UUID generation code requires the uuid library." >&5
+$as_echo "$as_me: WARNING: ntfsprogs DCE compliant UUID generation code requires the uuid library." >&2;}
+	fi
+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.
+
+# Check whether --with-hd was given.
+if test "${with_hd+set}" = set; then :
+  withval=$with_hd; if test "$with_hd" = "yes"; then
+		extrapath2=default
+	elif test "$with_hd" = "no"; then
+		extrapath2=
+	else
+		extrapath2=$with_hd
+	fi
+else
+  extrapath2=default
+
+fi
+
+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_fn_c_check_header_mongrel "$LINENO" "hd.h" "ac_cv_header_hd_h" "$ac_includes_default"
+if test "x$ac_cv_header_hd_h" = xyes; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for hd_list in -lhd" >&5
+$as_echo_n "checking for hd_list in -lhd... " >&6; }
+if ${ac_cv_lib_hd_hd_list+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lhd  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char hd_list ();
+int
+main ()
+{
+return hd_list ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_hd_hd_list=yes
+else
+  ac_cv_lib_hd_hd_list=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_hd_hd_list" >&5
+$as_echo "$ac_cv_lib_hd_hd_list" >&6; }
+if test "x$ac_cv_lib_hd_hd_list" = xyes; then :
+
+$as_echo "#define ENABLE_HD 1" >>confdefs.h
+
+			LIBNTFS_LIBS="$LIBNTFS_LIBS -lhd"
+			NTFSPROGS_STATIC_LIBS="$NTFSPROGS_STATIC_LIBS -lhd"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ntfsprogs Windows compliant geometry code requires the hd library." >&5
+$as_echo "$as_me: WARNING: ntfsprogs Windows compliant geometry code requires the hd library." >&2;}
+fi
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ntfsprogs Windows compliant geometry code requires the hd library." >&5
+$as_echo "$as_me: WARNING: ntfsprogs Windows compliant geometry code requires the hd library." >&2;}
+fi
+
+
+fi
+
+# Checks for header files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdc=yes
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+for ac_header in 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/mkdev.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/fs.h inttypes.h linux/hdreg.h \
+	machine/endian.h windows.h syslog.h pwd.h malloc.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+# Checks for typedefs, structures, and compiler characteristics.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5
+$as_echo_n "checking for stdbool.h that conforms to C99... " >&6; }
+if ${ac_cv_header_stdbool_h+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+             #include <stdbool.h>
+             #ifndef bool
+              "error: bool is not defined"
+             #endif
+             #ifndef false
+              "error: false is not defined"
+             #endif
+             #if false
+              "error: false is not 0"
+             #endif
+             #ifndef true
+              "error: true is not defined"
+             #endif
+             #if true != 1
+              "error: true is not 1"
+             #endif
+             #ifndef __bool_true_false_are_defined
+              "error: __bool_true_false_are_defined is not defined"
+             #endif
+
+             struct s { _Bool s: 1; _Bool t; } s;
+
+             char a[true == 1 ? 1 : -1];
+             char b[false == 0 ? 1 : -1];
+             char c[__bool_true_false_are_defined == 1 ? 1 : -1];
+             char d[(bool) 0.5 == true ? 1 : -1];
+             /* See body of main program for 'e'.  */
+             char f[(_Bool) 0.0 == false ? 1 : -1];
+             char g[true];
+             char h[sizeof (_Bool)];
+             char i[sizeof s.t];
+             enum { j = false, k = true, l = false * true, m = true * 256 };
+             /* The following fails for
+                HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */
+             _Bool n[m];
+             char o[sizeof n == m * sizeof n[0] ? 1 : -1];
+             char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1];
+             /* Catch a bug in an HP-UX C compiler.  See
+                http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html
+                http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html
+              */
+             _Bool q = true;
+             _Bool *pq = &q;
+
+int
+main ()
+{
+
+             bool e = &s;
+             *pq |= q;
+             *pq |= ! q;
+             /* Refer to every declared value, to avoid compiler optimizations.  */
+             return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l
+                     + !m + !n + !o + !p + !q + !pq);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdbool_h=yes
+else
+  ac_cv_header_stdbool_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5
+$as_echo "$ac_cv_header_stdbool_h" >&6; }
+   ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default"
+if test "x$ac_cv_type__Bool" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE__BOOL 1
+_ACEOF
+
+
+fi
+
+
+if test $ac_cv_header_stdbool_h = yes; then
+
+$as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
+$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
+if ${ac_cv_c_bigendian+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_c_bigendian=unknown
+    # See if we're dealing with a universal compiler.
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifndef __APPLE_CC__
+	       not a universal capable compiler
+	     #endif
+	     typedef int dummy;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+	# Check for potential -arch flags.  It is not universal unless
+	# there are at least two -arch flags with different values.
+	ac_arch=
+	ac_prev=
+	for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
+	 if test -n "$ac_prev"; then
+	   case $ac_word in
+	     i?86 | x86_64 | ppc | ppc64)
+	       if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
+		 ac_arch=$ac_word
+	       else
+		 ac_cv_c_bigendian=universal
+		 break
+	       fi
+	       ;;
+	   esac
+	   ac_prev=
+	 elif test "x$ac_word" = "x-arch"; then
+	   ac_prev=arch
+	 fi
+       done
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    if test $ac_cv_c_bigendian = unknown; then
+      # See if sys/param.h defines the BYTE_ORDER macro.
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+	     #include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
+		     && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
+		     && LITTLE_ENDIAN)
+	      bogus endian macros
+	     #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  # It does; now see whether it defined to BIG_ENDIAN or not.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+		#include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+		 not big endian
+		#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_bigendian=yes
+else
+  ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    fi
+    if test $ac_cv_c_bigendian = unknown; then
+      # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <limits.h>
+
+int
+main ()
+{
+#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
+	      bogus endian macros
+	     #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  # It does; now see whether it defined to _BIG_ENDIAN or not.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <limits.h>
+
+int
+main ()
+{
+#ifndef _BIG_ENDIAN
+		 not big endian
+		#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_bigendian=yes
+else
+  ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    fi
+    if test $ac_cv_c_bigendian = unknown; then
+      # Compile a test program.
+      if test "$cross_compiling" = yes; then :
+  # Try to guess by grepping values from an object file.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+short int ascii_mm[] =
+		  { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+		short int ascii_ii[] =
+		  { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+		int use_ascii (int i) {
+		  return ascii_mm[i] + ascii_ii[i];
+		}
+		short int ebcdic_ii[] =
+		  { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+		short int ebcdic_mm[] =
+		  { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+		int use_ebcdic (int i) {
+		  return ebcdic_mm[i] + ebcdic_ii[i];
+		}
+		extern int foo;
+
+int
+main ()
+{
+return use_ascii (foo) == use_ebcdic (foo);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
+	      ac_cv_c_bigendian=yes
+	    fi
+	    if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+	      if test "$ac_cv_c_bigendian" = unknown; then
+		ac_cv_c_bigendian=no
+	      else
+		# finding both strings is unlikely to happen, but who knows?
+		ac_cv_c_bigendian=unknown
+	      fi
+	    fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+
+	     /* Are we little or big endian?  From Harbison&Steele.  */
+	     union
+	     {
+	       long int l;
+	       char c[sizeof (long int)];
+	     } u;
+	     u.l = 1;
+	     return u.c[sizeof (long int) - 1] == 1;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_c_bigendian=no
+else
+  ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+    fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
+$as_echo "$ac_cv_c_bigendian" >&6; }
+ case $ac_cv_c_bigendian in #(
+   yes)
+     $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h
+;; #(
+   no)
+
+
+$as_echo "#define WORDS_LITTLEENDIAN 1" >>confdefs.h
+
+
+	 ;; #(
+   universal)
+
+$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
+
+     ;; #(
+   *)
+     as_fn_error $? "unknown endianness
+ presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
+ esac
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5
+$as_echo_n "checking for an ANSI C-conforming const... " >&6; }
+if ${ac_cv_c_const+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+#ifndef __cplusplus
+  /* Ultrix mips cc rejects this sort of thing.  */
+  typedef int charset[2];
+  const charset cs = { 0, 0 };
+  /* SunOS 4.1.1 cc rejects this.  */
+  char const *const *pcpcc;
+  char **ppc;
+  /* NEC SVR4.0.2 mips cc rejects this.  */
+  struct point {int x, y;};
+  static struct point const zero = {0,0};
+  /* AIX XL C 1.02.0.0 rejects this.
+     It does not let you subtract one const X* pointer from another in
+     an arm of an if-expression whose if-part is not a constant
+     expression */
+  const char *g = "string";
+  pcpcc = &g + (g ? g-g : 0);
+  /* HPUX 7.0 cc rejects these. */
+  ++pcpcc;
+  ppc = (char**) pcpcc;
+  pcpcc = (char const *const *) ppc;
+  { /* SCO 3.2v4 cc rejects this sort of thing.  */
+    char tx;
+    char *t = &tx;
+    char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+    *t++ = 0;
+    if (s) return 0;
+  }
+  { /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
+    int x[] = {25, 17};
+    const int *foo = &x[0];
+    ++foo;
+  }
+  { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+    typedef const int *iptr;
+    iptr p = 0;
+    ++p;
+  }
+  { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying
+       "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+    struct s { int j; const int *ap[3]; } bx;
+    struct s *b = &bx; b->j = 5;
+  }
+  { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+    const int foo = 10;
+    if (!foo) return 0;
+  }
+  return !cs[0] && !zero.x;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_const=yes
+else
+  ac_cv_c_const=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5
+$as_echo "$ac_cv_c_const" >&6; }
+if test $ac_cv_c_const = no; then
+
+$as_echo "#define const /**/" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
+$as_echo_n "checking for inline... " >&6; }
+if ${ac_cv_c_inline+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_inline=$ac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  test "$ac_cv_c_inline" != no && break
+done
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
+$as_echo "$ac_cv_c_inline" >&6; }
+
+case $ac_cv_c_inline in
+  inline | yes) ;;
+  *)
+    case $ac_cv_c_inline in
+      no) ac_val=;;
+      *) ac_val=$ac_cv_c_inline;;
+    esac
+    cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+    ;;
+esac
+
+ac_fn_c_check_type "$LINENO" "off_t" "ac_cv_type_off_t" "$ac_includes_default"
+if test "x$ac_cv_type_off_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define off_t long int
+_ACEOF
+
+fi
+
+ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
+if test "x$ac_cv_type_size_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned int
+_ACEOF
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct stat" "st_blocks" "ac_cv_member_struct_stat_st_blocks" "$ac_includes_default"
+if test "x$ac_cv_member_struct_stat_st_blocks" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_BLOCKS 1
+_ACEOF
+
+
+$as_echo "#define HAVE_ST_BLOCKS 1" >>confdefs.h
+
+else
+  case " $LIBOBJS " in
+  *" fileblocks.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS fileblocks.$ac_objext"
+ ;;
+esac
+
+fi
+
+
+ac_fn_c_check_member "$LINENO" "struct stat" "st_rdev" "ac_cv_member_struct_stat_st_rdev" "$ac_includes_default"
+if test "x$ac_cv_member_struct_stat_st_rdev" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_RDEV 1
+_ACEOF
+
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct stat" "st_atim" "ac_cv_member_struct_stat_st_atim" "$ac_includes_default"
+if test "x$ac_cv_member_struct_stat_st_atim" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_ATIM 1
+_ACEOF
+
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct stat" "st_atimespec" "ac_cv_member_struct_stat_st_atimespec" "$ac_includes_default"
+if test "x$ac_cv_member_struct_stat_st_atimespec" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_ATIMESPEC 1
+_ACEOF
+
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct stat" "st_atimensec" "ac_cv_member_struct_stat_st_atimensec" "$ac_includes_default"
+if test "x$ac_cv_member_struct_stat_st_atimensec" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_ATIMENSEC 1
+_ACEOF
+
+
+fi
+
+
+# For the 'nfconv' patch (Mac OS X only):
+case "${target_os}" in
+darwin*)
+	if test "${enable_nfconv}" = "yes"; then
+		ac_fn_c_check_header_mongrel "$LINENO" "CoreFoundation/CoreFoundation.h" "ac_cv_header_CoreFoundation_CoreFoundation_h" "$ac_includes_default"
+if test "x$ac_cv_header_CoreFoundation_CoreFoundation_h" = xyes; then :
+
+				LDFLAGS="${LDFLAGS} -framework CoreFoundation"
+
+$as_echo "#define ENABLE_NFCONV 1" >>confdefs.h
+
+
+else
+  as_fn_error $? "Cannot find CoreFoundation required for 'nfconv' functionality Mac OS X. You may use the --disable-nfconv 'configure' option to avoid this error." "$LINENO" 5
+
+fi
+
+
+	fi
+	;;
+esac
+
+# Checks for library functions.
+# getmntent is in the standard C library on UNICOS, in -lsun on Irix 4,
+# -lseq on Dynix/PTX, -lgen on Unixware.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing getmntent" >&5
+$as_echo_n "checking for library containing getmntent... " >&6; }
+if ${ac_cv_search_getmntent+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getmntent ();
+int
+main ()
+{
+return getmntent ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' sun seq gen; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_getmntent=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_getmntent+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_getmntent+:} false; then :
+
+else
+  ac_cv_search_getmntent=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_getmntent" >&5
+$as_echo "$ac_cv_search_getmntent" >&6; }
+ac_res=$ac_cv_search_getmntent
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+  ac_cv_func_getmntent=yes
+
+$as_echo "#define HAVE_GETMNTENT 1" >>confdefs.h
+
+else
+  ac_cv_func_getmntent=no
+fi
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mbrtowc and mbstate_t are properly declared" >&5
+$as_echo_n "checking whether mbrtowc and mbstate_t are properly declared... " >&6; }
+if ${ac_cv_func_mbrtowc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <wchar.h>
+int
+main ()
+{
+wchar_t wc;
+	      char const s[] = "";
+	      size_t n = 1;
+	      mbstate_t state;
+	      return ! (sizeof state && (mbrtowc) (&wc, s, n, &state));
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_func_mbrtowc=yes
+else
+  ac_cv_func_mbrtowc=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_mbrtowc" >&5
+$as_echo "$ac_cv_func_mbrtowc" >&6; }
+  if test $ac_cv_func_mbrtowc = yes; then
+
+$as_echo "#define HAVE_MBRTOWC 1" >>confdefs.h
+
+  fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working memcmp" >&5
+$as_echo_n "checking for working memcmp... " >&6; }
+if ${ac_cv_func_memcmp_working+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  ac_cv_func_memcmp_working=no
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+
+  /* Some versions of memcmp are not 8-bit clean.  */
+  char c0 = '\100', c1 = '\200', c2 = '\201';
+  if (memcmp(&c0, &c2, 1) >= 0 || memcmp(&c1, &c2, 1) >= 0)
+    return 1;
+
+  /* The Next x86 OpenStep bug shows up only when comparing 16 bytes
+     or more and with at least one buffer not starting on a 4-byte boundary.
+     William Lewis provided this test program.   */
+  {
+    char foo[21];
+    char bar[21];
+    int i;
+    for (i = 0; i < 4; i++)
+      {
+	char *a = foo + i;
+	char *b = bar + i;
+	strcpy (a, "--------01111111");
+	strcpy (b, "--------10000000");
+	if (memcmp (a, b, 16) >= 0)
+	  return 1;
+      }
+    return 0;
+  }
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_func_memcmp_working=yes
+else
+  ac_cv_func_memcmp_working=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_memcmp_working" >&5
+$as_echo "$ac_cv_func_memcmp_working" >&6; }
+test $ac_cv_func_memcmp_working = no && case " $LIBOBJS " in
+  *" memcmp.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS memcmp.$ac_objext"
+ ;;
+esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether lstat correctly handles trailing slash" >&5
+$as_echo_n "checking whether lstat correctly handles trailing slash... " >&6; }
+if ${ac_cv_func_lstat_dereferences_slashed_symlink+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  rm -f conftest.sym conftest.file
+echo >conftest.file
+if test "$as_ln_s" = "ln -s" && ln -s conftest.file conftest.sym; then
+  if test "$cross_compiling" = yes; then :
+  ac_cv_func_lstat_dereferences_slashed_symlink=no
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+struct stat sbuf;
+     /* Linux will dereference the symlink and fail, as required by POSIX.
+	That is better in the sense that it means we will not
+	have to compile and use the lstat wrapper.  */
+     return lstat ("conftest.sym/", &sbuf) == 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_func_lstat_dereferences_slashed_symlink=yes
+else
+  ac_cv_func_lstat_dereferences_slashed_symlink=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+else
+  # If the `ln -s' command failed, then we probably don't even
+  # have an lstat function.
+  ac_cv_func_lstat_dereferences_slashed_symlink=no
+fi
+rm -f conftest.sym conftest.file
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_lstat_dereferences_slashed_symlink" >&5
+$as_echo "$ac_cv_func_lstat_dereferences_slashed_symlink" >&6; }
+
+test $ac_cv_func_lstat_dereferences_slashed_symlink = yes &&
+
+cat >>confdefs.h <<_ACEOF
+#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1
+_ACEOF
+
+
+if test "x$ac_cv_func_lstat_dereferences_slashed_symlink" = xno; then
+  case " $LIBOBJS " in
+  *" lstat.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS lstat.$ac_objext"
+ ;;
+esac
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stat accepts an empty string" >&5
+$as_echo_n "checking whether stat accepts an empty string... " >&6; }
+if ${ac_cv_func_stat_empty_string_bug+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  ac_cv_func_stat_empty_string_bug=yes
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+struct stat sbuf;
+  return stat ("", &sbuf) == 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_func_stat_empty_string_bug=no
+else
+  ac_cv_func_stat_empty_string_bug=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_stat_empty_string_bug" >&5
+$as_echo "$ac_cv_func_stat_empty_string_bug" >&6; }
+if test $ac_cv_func_stat_empty_string_bug = yes; then
+  case " $LIBOBJS " in
+  *" stat.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS stat.$ac_objext"
+ ;;
+esac
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STAT_EMPTY_STRING_BUG 1
+_ACEOF
+
+fi
+
+for ac_func in strftime
+do :
+  ac_fn_c_check_func "$LINENO" "strftime" "ac_cv_func_strftime"
+if test "x$ac_cv_func_strftime" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_STRFTIME 1
+_ACEOF
+
+else
+  # strftime is in -lintl on SCO UNIX.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for strftime in -lintl" >&5
+$as_echo_n "checking for strftime in -lintl... " >&6; }
+if ${ac_cv_lib_intl_strftime+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lintl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char strftime ();
+int
+main ()
+{
+return strftime ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_intl_strftime=yes
+else
+  ac_cv_lib_intl_strftime=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_strftime" >&5
+$as_echo "$ac_cv_lib_intl_strftime" >&6; }
+if test "x$ac_cv_lib_intl_strftime" = xyes; then :
+  $as_echo "#define HAVE_STRFTIME 1" >>confdefs.h
+
+LIBS="-lintl $LIBS"
+fi
+
+fi
+done
+
+
+
+
+  for ac_header in $ac_header_list
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether utime accepts a null argument" >&5
+$as_echo_n "checking whether utime accepts a null argument... " >&6; }
+if ${ac_cv_func_utime_null+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  rm -f conftest.data; >conftest.data
+# Sequent interprets utime(file, 0) to mean use start of epoch.  Wrong.
+if test "$cross_compiling" = yes; then :
+  ac_cv_func_utime_null='guessing yes'
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+	       #ifdef HAVE_UTIME_H
+	       # include <utime.h>
+	       #endif
+int
+main ()
+{
+struct stat s, t;
+  return ! (stat ("conftest.data", &s) == 0
+	    && utime ("conftest.data", 0) == 0
+	    && stat ("conftest.data", &t) == 0
+	    && t.st_mtime >= s.st_mtime
+	    && t.st_mtime - s.st_mtime < 120);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_func_utime_null=yes
+else
+  ac_cv_func_utime_null=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_utime_null" >&5
+$as_echo "$ac_cv_func_utime_null" >&6; }
+if test "x$ac_cv_func_utime_null" != xno; then
+  ac_cv_func_utime_null=yes
+
+$as_echo "#define HAVE_UTIME_NULL 1" >>confdefs.h
+
+fi
+rm -f conftest.data
+
+for ac_func in vprintf
+do :
+  ac_fn_c_check_func "$LINENO" "vprintf" "ac_cv_func_vprintf"
+if test "x$ac_cv_func_vprintf" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_VPRINTF 1
+_ACEOF
+
+ac_fn_c_check_func "$LINENO" "_doprnt" "ac_cv_func__doprnt"
+if test "x$ac_cv_func__doprnt" = xyes; then :
+
+$as_echo "#define HAVE_DOPRNT 1" >>confdefs.h
+
+fi
+
+fi
+done
+
+
+for ac_func in  \
+	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 \
+
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+# Check whether --enable-largefile was given.
+if test "${enable_largefile+set}" = set; then :
+  enableval=$enable_largefile;
+fi
+
+if test "$enable_largefile" != no; then
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
+$as_echo_n "checking for special C compiler options needed for large files... " >&6; }
+if ${ac_cv_sys_largefile_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_sys_largefile_CC=no
+     if test "$GCC" != yes; then
+       ac_save_CC=$CC
+       while :; do
+	 # IRIX 6.2 and later do not support large files by default,
+	 # so use the C compiler's -n32 option if that helps.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+	 if ac_fn_c_try_compile "$LINENO"; then :
+  break
+fi
+rm -f core conftest.err conftest.$ac_objext
+	 CC="$CC -n32"
+	 if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_largefile_CC=' -n32'; break
+fi
+rm -f core conftest.err conftest.$ac_objext
+	 break
+       done
+       CC=$ac_save_CC
+       rm -f conftest.$ac_ext
+    fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
+$as_echo "$ac_cv_sys_largefile_CC" >&6; }
+  if test "$ac_cv_sys_largefile_CC" != no; then
+    CC=$CC$ac_cv_sys_largefile_CC
+  fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
+if ${ac_cv_sys_file_offset_bits+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  while :; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_file_offset_bits=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_file_offset_bits=64; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  ac_cv_sys_file_offset_bits=unknown
+  break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
+$as_echo "$ac_cv_sys_file_offset_bits" >&6; }
+case $ac_cv_sys_file_offset_bits in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
+_ACEOF
+;;
+esac
+rm -rf conftest*
+  if test $ac_cv_sys_file_offset_bits = unknown; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
+$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; }
+if ${ac_cv_sys_large_files+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  while :; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_large_files=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _LARGE_FILES 1
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_large_files=1; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  ac_cv_sys_large_files=unknown
+  break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
+$as_echo "$ac_cv_sys_large_files" >&6; }
+case $ac_cv_sys_large_files in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _LARGE_FILES $ac_cv_sys_large_files
+_ACEOF
+;;
+esac
+rm -rf conftest*
+  fi
+
+
+fi
+
+
+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"
+
+$as_echo "#define ENABLE_DEBUG 1" >>confdefs.h
+
+fi
+
+test "${enable_device_default_io_ops}" = "no" &&
+$as_echo "#define NO_NTFS_DEVICE_DEFAULT_IO_OPS 1" >>confdefs.h
+
+
+test "${enable_mtab}" = "no" &&
+$as_echo "#define IGNORE_MTAB 1" >>confdefs.h
+
+test "${enable_posix_acls}" != "no" &&
+$as_echo "#define POSIXACLS 1" >>confdefs.h
+
+test "${enable_xattr_mappings}" != "no" &&
+$as_echo "#define XATTR_MAPPINGS 1" >>confdefs.h
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if test "${with_fuse}" = "internal"; then
+  FUSE_INTERNAL_TRUE=
+  FUSE_INTERNAL_FALSE='#'
+else
+  FUSE_INTERNAL_TRUE='#'
+  FUSE_INTERNAL_FALSE=
+fi
+
+ if test "${enable_ldscript}" = "yes"; then
+  GENERATE_LDSCRIPT_TRUE=
+  GENERATE_LDSCRIPT_FALSE='#'
+else
+  GENERATE_LDSCRIPT_TRUE='#'
+  GENERATE_LDSCRIPT_FALSE=
+fi
+
+ if test "${WINDOWS}" = "yes"; then
+  WINDOWS_TRUE=
+  WINDOWS_FALSE='#'
+else
+  WINDOWS_TRUE='#'
+  WINDOWS_FALSE=
+fi
+
+ if test "${enable_device_default_io_ops}" = "yes"; then
+  NTFS_DEVICE_DEFAULT_IO_OPS_TRUE=
+  NTFS_DEVICE_DEFAULT_IO_OPS_FALSE='#'
+else
+  NTFS_DEVICE_DEFAULT_IO_OPS_TRUE='#'
+  NTFS_DEVICE_DEFAULT_IO_OPS_FALSE=
+fi
+
+ if test "${enable_ldconfig}" = "yes"; then
+  RUN_LDCONFIG_TRUE=
+  RUN_LDCONFIG_FALSE='#'
+else
+  RUN_LDCONFIG_TRUE='#'
+  RUN_LDCONFIG_FALSE=
+fi
+
+ if test "${enable_really_static}" = "yes"; then
+  REALLYSTATIC_TRUE=
+  REALLYSTATIC_FALSE='#'
+else
+  REALLYSTATIC_TRUE='#'
+  REALLYSTATIC_FALSE=
+fi
+
+ if test "${enable_library}" = "yes"; then
+  INSTALL_LIBRARY_TRUE=
+  INSTALL_LIBRARY_FALSE='#'
+else
+  INSTALL_LIBRARY_TRUE='#'
+  INSTALL_LIBRARY_FALSE=
+fi
+
+ if test "${enable_mount_helper}" = "yes"; then
+  ENABLE_MOUNT_HELPER_TRUE=
+  ENABLE_MOUNT_HELPER_FALSE='#'
+else
+  ENABLE_MOUNT_HELPER_TRUE='#'
+  ENABLE_MOUNT_HELPER_FALSE=
+fi
+
+ if test "${enable_ntfs_3g}" = "yes"; then
+  ENABLE_NTFS_3G_TRUE=
+  ENABLE_NTFS_3G_FALSE='#'
+else
+  ENABLE_NTFS_3G_TRUE='#'
+  ENABLE_NTFS_3G_FALSE=
+fi
+
+ if test "${enable_ntfsprogs}" = "yes"; then
+  ENABLE_NTFSPROGS_TRUE=
+  ENABLE_NTFSPROGS_FALSE='#'
+else
+  ENABLE_NTFSPROGS_TRUE='#'
+  ENABLE_NTFSPROGS_FALSE=
+fi
+
+ if test "${enable_extras}" = "yes"; then
+  ENABLE_EXTRAS_TRUE=
+  ENABLE_EXTRAS_FALSE='#'
+else
+  ENABLE_EXTRAS_TRUE='#'
+  ENABLE_EXTRAS_FALSE=
+fi
+
+ if test "${enable_quarantined}" = "yes"; then
+  ENABLE_QUARANTINED_TRUE=
+  ENABLE_QUARANTINED_FALSE='#'
+else
+  ENABLE_QUARANTINED_TRUE='#'
+  ENABLE_QUARANTINED_FALSE=
+fi
+
+
+# workaround for <autoconf-2.60
+if test -z "${docdir}"; then
+	docdir="\$(datarootdir)/doc/\$(PACKAGE_NAME)"
+
+fi
+# workaround for <automake-1.10
+if test -z "${MKDIR_P}"; then
+	MKDIR_P="\$(mkdir_p)"
+
+fi
+
+# generate files
+ac_config_files="$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 src/Makefile src/ntfs-3g.8 src/ntfs-3g.probe.8 src/ntfs-3g.usermap.8 src/ntfs-3g.secaudit.8"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    if test "x$cache_file" != "x/dev/null"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+      if test ! -f "$cache_file" || test -h "$cache_file"; then
+	cat confcache >"$cache_file"
+      else
+        case $cache_file in #(
+        */* | ?:*)
+	  mv -f confcache "$cache_file"$$ &&
+	  mv -f "$cache_file"$$ "$cache_file" ;; #(
+        *)
+	  mv -f confcache "$cache_file" ;;
+	esac
+      fi
+    fi
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5
+$as_echo_n "checking that generated files are newer than configure... " >&6; }
+   if test -n "$am_sleep_pid"; then
+     # Hide warnings about reused PIDs.
+     wait $am_sleep_pid 2>/dev/null
+   fi
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5
+$as_echo "done" >&6; }
+ if test -n "$EXEEXT"; then
+  am__EXEEXT_TRUE=
+  am__EXEEXT_FALSE='#'
+else
+  am__EXEEXT_TRUE='#'
+  am__EXEEXT_FALSE=
+fi
+
+if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
+  as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+  as_fn_error $? "conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+  as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+  as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_CRYPTO_TRUE}" && test -z "${ENABLE_CRYPTO_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_CRYPTO\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+if test -z "${FUSE_INTERNAL_TRUE}" && test -z "${FUSE_INTERNAL_FALSE}"; then
+  as_fn_error $? "conditional \"FUSE_INTERNAL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${GENERATE_LDSCRIPT_TRUE}" && test -z "${GENERATE_LDSCRIPT_FALSE}"; then
+  as_fn_error $? "conditional \"GENERATE_LDSCRIPT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WINDOWS_TRUE}" && test -z "${WINDOWS_FALSE}"; then
+  as_fn_error $? "conditional \"WINDOWS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${NTFS_DEVICE_DEFAULT_IO_OPS_TRUE}" && test -z "${NTFS_DEVICE_DEFAULT_IO_OPS_FALSE}"; then
+  as_fn_error $? "conditional \"NTFS_DEVICE_DEFAULT_IO_OPS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${RUN_LDCONFIG_TRUE}" && test -z "${RUN_LDCONFIG_FALSE}"; then
+  as_fn_error $? "conditional \"RUN_LDCONFIG\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${REALLYSTATIC_TRUE}" && test -z "${REALLYSTATIC_FALSE}"; then
+  as_fn_error $? "conditional \"REALLYSTATIC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${INSTALL_LIBRARY_TRUE}" && test -z "${INSTALL_LIBRARY_FALSE}"; then
+  as_fn_error $? "conditional \"INSTALL_LIBRARY\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_MOUNT_HELPER_TRUE}" && test -z "${ENABLE_MOUNT_HELPER_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_MOUNT_HELPER\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_NTFS_3G_TRUE}" && test -z "${ENABLE_NTFS_3G_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_NTFS_3G\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_NTFSPROGS_TRUE}" && test -z "${ENABLE_NTFSPROGS_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_NTFSPROGS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_EXTRAS_TRUE}" && test -z "${ENABLE_EXTRAS_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_EXTRAS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_QUARANTINED_TRUE}" && test -z "${ENABLE_QUARANTINED_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_QUARANTINED\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by ntfs-3g $as_me 2015.3.14, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+      --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <ntfs-3g-devel@lists.sf.net>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+ntfs-3g config.status 2015.3.14
+configured by $0, generated by GNU Autoconf 2.69,
+  with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=?*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  --*=)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    $as_echo "$ac_cs_config"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    '') as_fn_error $? "missing file argument" ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`'
+macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`'
+enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`'
+enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`'
+pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`'
+enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`'
+SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`'
+ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`'
+PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`'
+host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`'
+host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`'
+host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`'
+build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`'
+build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`'
+build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`'
+SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`'
+Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`'
+GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`'
+EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`'
+FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`'
+LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`'
+NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`'
+LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`'
+max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`'
+ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`'
+exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`'
+lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`'
+lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`'
+lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`'
+lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`'
+lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`'
+reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`'
+reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`'
+OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`'
+deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`'
+file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`'
+file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`'
+want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`'
+DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`'
+sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`'
+AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`'
+AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`'
+archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`'
+STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`'
+RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`'
+old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`'
+lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`'
+CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`'
+CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`'
+compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`'
+GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`'
+nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`'
+lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`'
+objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`'
+MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`'
+need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`'
+MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`'
+DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`'
+NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`'
+LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`'
+OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`'
+OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`'
+libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`'
+shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`'
+extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`'
+export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`'
+whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`'
+compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`'
+old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`'
+archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`'
+module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`'
+allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`'
+no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`'
+hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`'
+hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`'
+hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`'
+hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`'
+hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`'
+inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`'
+link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`'
+always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`'
+export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`'
+exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`'
+include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`'
+prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`'
+postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`'
+file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`'
+variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`'
+need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`'
+need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`'
+version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`'
+runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`'
+libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`'
+library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`'
+soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`'
+install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`'
+postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`'
+finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`'
+hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`'
+sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`'
+sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`'
+hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`'
+enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`'
+old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`'
+striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`'
+
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+\$1
+_LTECHO_EOF'
+}
+
+# Quote evaled strings.
+for var in SHELL \
+ECHO \
+PATH_SEPARATOR \
+SED \
+GREP \
+EGREP \
+FGREP \
+LD \
+NM \
+LN_S \
+lt_SP2NL \
+lt_NL2SP \
+reload_flag \
+OBJDUMP \
+deplibs_check_method \
+file_magic_cmd \
+file_magic_glob \
+want_nocaseglob \
+DLLTOOL \
+sharedlib_from_linklib_cmd \
+AR \
+AR_FLAGS \
+archiver_list_spec \
+STRIP \
+RANLIB \
+CC \
+CFLAGS \
+compiler \
+lt_cv_sys_global_symbol_pipe \
+lt_cv_sys_global_symbol_to_cdecl \
+lt_cv_sys_global_symbol_to_c_name_address \
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
+nm_file_list_spec \
+lt_prog_compiler_no_builtin_flag \
+lt_prog_compiler_pic \
+lt_prog_compiler_wl \
+lt_prog_compiler_static \
+lt_cv_prog_compiler_c_o \
+need_locks \
+MANIFEST_TOOL \
+DSYMUTIL \
+NMEDIT \
+LIPO \
+OTOOL \
+OTOOL64 \
+shrext_cmds \
+export_dynamic_flag_spec \
+whole_archive_flag_spec \
+compiler_needs_object \
+with_gnu_ld \
+allow_undefined_flag \
+no_undefined_flag \
+hardcode_libdir_flag_spec \
+hardcode_libdir_separator \
+exclude_expsyms \
+include_expsyms \
+file_list_spec \
+variables_saved_for_relink \
+libname_spec \
+library_names_spec \
+soname_spec \
+install_override_mode \
+finish_eval \
+old_striplib \
+striplib; do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[\\\\\\\`\\"\\\$]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+# Double-quote double-evaled strings.
+for var in reload_cmds \
+old_postinstall_cmds \
+old_postuninstall_cmds \
+old_archive_cmds \
+extract_expsyms_cmds \
+old_archive_from_new_cmds \
+old_archive_from_expsyms_cmds \
+archive_cmds \
+archive_expsym_cmds \
+module_cmds \
+module_expsym_cmds \
+export_symbols_cmds \
+prelink_cmds \
+postlink_cmds \
+postinstall_cmds \
+postuninstall_cmds \
+finish_cmds \
+sys_lib_search_path_spec \
+sys_lib_dlsearch_path_spec; do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[\\\\\\\`\\"\\\$]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+ac_aux_dir='$ac_aux_dir'
+xsi_shell='$xsi_shell'
+lt_shell_append='$lt_shell_append'
+
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+
+
+    PACKAGE='$PACKAGE'
+    VERSION='$VERSION'
+    TIMESTAMP='$TIMESTAMP'
+    RM='$RM'
+    ofile='$ofile'
+
+
+
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+    "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+    "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;;
+    "include/fuse-lite/Makefile") CONFIG_FILES="$CONFIG_FILES include/fuse-lite/Makefile" ;;
+    "include/ntfs-3g/Makefile") CONFIG_FILES="$CONFIG_FILES include/ntfs-3g/Makefile" ;;
+    "libfuse-lite/Makefile") CONFIG_FILES="$CONFIG_FILES libfuse-lite/Makefile" ;;
+    "libntfs-3g/Makefile") CONFIG_FILES="$CONFIG_FILES libntfs-3g/Makefile" ;;
+    "libntfs-3g/libntfs-3g.pc") CONFIG_FILES="$CONFIG_FILES libntfs-3g/libntfs-3g.pc" ;;
+    "libntfs-3g/libntfs-3g.script.so") CONFIG_FILES="$CONFIG_FILES libntfs-3g/libntfs-3g.script.so" ;;
+    "ntfsprogs/Makefile") CONFIG_FILES="$CONFIG_FILES ntfsprogs/Makefile" ;;
+    "ntfsprogs/mkntfs.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/mkntfs.8" ;;
+    "ntfsprogs/ntfscat.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfscat.8" ;;
+    "ntfsprogs/ntfsclone.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfsclone.8" ;;
+    "ntfsprogs/ntfscluster.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfscluster.8" ;;
+    "ntfsprogs/ntfscmp.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfscmp.8" ;;
+    "ntfsprogs/ntfscp.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfscp.8" ;;
+    "ntfsprogs/ntfsfix.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfsfix.8" ;;
+    "ntfsprogs/ntfsinfo.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfsinfo.8" ;;
+    "ntfsprogs/ntfslabel.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfslabel.8" ;;
+    "ntfsprogs/ntfsls.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfsls.8" ;;
+    "ntfsprogs/ntfsprogs.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfsprogs.8" ;;
+    "ntfsprogs/ntfsresize.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfsresize.8" ;;
+    "ntfsprogs/ntfsundelete.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfsundelete.8" ;;
+    "ntfsprogs/ntfsdecrypt.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfsdecrypt.8" ;;
+    "ntfsprogs/ntfswipe.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfswipe.8" ;;
+    "ntfsprogs/ntfstruncate.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfstruncate.8" ;;
+    "ntfsprogs/ntfsfallocate.8") CONFIG_FILES="$CONFIG_FILES ntfsprogs/ntfsfallocate.8" ;;
+    "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
+    "src/ntfs-3g.8") CONFIG_FILES="$CONFIG_FILES src/ntfs-3g.8" ;;
+    "src/ntfs-3g.probe.8") CONFIG_FILES="$CONFIG_FILES src/ntfs-3g.probe.8" ;;
+    "src/ntfs-3g.usermap.8") CONFIG_FILES="$CONFIG_FILES src/ntfs-3g.usermap.8" ;;
+    "src/ntfs-3g.secaudit.8") CONFIG_FILES="$CONFIG_FILES src/ntfs-3g.secaudit.8" ;;
+
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp= ac_tmp=
+  trap 'exit_status=$?
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=[	 ]*/{
+h
+s///
+s/^/:/
+s/[	 ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[	 ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+  ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_tt"; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any.  Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[	 ]*#[	 ]*define[	 ][	 ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  for (key in D) D_is_set[key] = 1
+  FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+  line = \$ 0
+  split(line, arg, " ")
+  if (arg[1] == "#") {
+    defundef = arg[2]
+    mac1 = arg[3]
+  } else {
+    defundef = substr(arg[1], 2)
+    mac1 = arg[2]
+  }
+  split(mac1, mac2, "(") #)
+  macro = mac2[1]
+  prefix = substr(line, 1, index(line, defundef) - 1)
+  if (D_is_set[macro]) {
+    # Preserve the white space surrounding the "#".
+    print prefix "define", macro P[macro] D[macro]
+    next
+  } else {
+    # Replace #undef with comments.  This is necessary, for example,
+    # in the case of _POSIX_SOURCE, which is predefined and required
+    # on some systems where configure will not decide to define it.
+    if (defundef == "undef") {
+      print "/*", prefix defundef, macro, "*/"
+      next
+    }
+  }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+  as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$ac_tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+  ac_MKDIR_P=$MKDIR_P
+  case $MKDIR_P in
+  [\\/$]* | ?:[\\/]* ) ;;
+  */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&2;}
+
+  rm -f "$ac_tmp/stdin"
+  case $ac_file in
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+  if test x"$ac_file" != x-; then
+    {
+      $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+    } >"$ac_tmp/config.h" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f "$ac_file"
+      mv "$ac_tmp/config.h" "$ac_file" \
+	|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    fi
+  else
+    $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+      || as_fn_error $? "could not create -" "$LINENO" 5
+  fi
+# Compute "$ac_file"'s index in $config_headers.
+_am_arg="$ac_file"
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$_am_arg" : 'X\(//\)[^/]' \| \
+	 X"$_am_arg" : 'X\(//\)$' \| \
+	 X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$_am_arg" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+  :C)  { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+  esac
+
+
+  case $ac_file$ac_mode in
+    "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
+  # Older Autoconf quotes --file arguments for eval, but not when files
+  # are listed without --file.  Let's play safe and only enable the eval
+  # if we detect the quoting.
+  case $CONFIG_FILES in
+  *\'*) eval set x "$CONFIG_FILES" ;;
+  *)   set x $CONFIG_FILES ;;
+  esac
+  shift
+  for mf
+  do
+    # Strip MF so we end up with the name of the file.
+    mf=`echo "$mf" | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile or not.
+    # We used to match only the files named 'Makefile.in', but
+    # some people rename them; so instead we look at the file content.
+    # Grep'ing the first line is not enough: some people post-process
+    # each Makefile.in and add a new line on top of each file to say so.
+    # Grep'ing the whole file is not good either: AIX grep has a line
+    # limit of 2048, but all sed's we know have understand at least 4000.
+    if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+      dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$mf" : 'X\(//\)[^/]' \| \
+	 X"$mf" : 'X\(//\)$' \| \
+	 X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$mf" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+    else
+      continue
+    fi
+    # Extract the definition of DEPDIR, am__include, and am__quote
+    # from the Makefile without running 'make'.
+    DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+    test -z "$DEPDIR" && continue
+    am__include=`sed -n 's/^am__include = //p' < "$mf"`
+    test -z "$am__include" && continue
+    am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+    # Find all dependency output files, they are included files with
+    # $(DEPDIR) in their names.  We invoke sed twice because it is the
+    # simplest approach to changing $(DEPDIR) to its actual value in the
+    # expansion.
+    for file in `sed -n "
+      s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+	 sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
+      # Make sure the directory exists.
+      test -f "$dirpart/$file" && continue
+      fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$file" : 'X\(//\)[^/]' \| \
+	 X"$file" : 'X\(//\)$' \| \
+	 X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      as_dir=$dirpart/$fdir; as_fn_mkdir_p
+      # echo "creating $dirpart/$file"
+      echo '# dummy' > "$dirpart/$file"
+    done
+  done
+}
+ ;;
+    "libtool":C)
+
+    # See if we are running on zsh, and set the options which allow our
+    # commands through without removal of \ escapes.
+    if test -n "${ZSH_VERSION+set}" ; then
+      setopt NO_GLOB_SUBST
+    fi
+
+    cfgfile="${ofile}T"
+    trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+    $RM "$cfgfile"
+
+    cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+
+# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+#                 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+#                 Foundation, Inc.
+#   Written by Gordon Matzigkeit, 1996
+#
+#   This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can 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.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that 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 GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+# The names of the tagged configurations supported by this script.
+available_tags=""
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Which release of libtool.m4 was used?
+macro_version=$macro_version
+macro_revision=$macro_revision
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# What type of objects to build.
+pic_mode=$pic_mode
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# An echo program that protects backslashes.
+ECHO=$lt_ECHO
+
+# The PATH separator for the build system.
+PATH_SEPARATOR=$lt_PATH_SEPARATOR
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="\$SED -e 1s/^X//"
+
+# A grep program that handles long lines.
+GREP=$lt_GREP
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# A literal string matcher.
+FGREP=$lt_FGREP
+
+# A BSD- or MS-compatible name lister.
+NM=$lt_NM
+
+# Whether we need soft or hard links.
+LN_S=$lt_LN_S
+
+# What is the maximum length of a command?
+max_cmd_len=$max_cmd_len
+
+# Object file suffix (normally "o").
+objext=$ac_objext
+
+# Executable file suffix (normally "").
+exeext=$exeext
+
+# whether the shell understands "unset".
+lt_unset=$lt_unset
+
+# turn spaces into newlines.
+SP2NL=$lt_lt_SP2NL
+
+# turn newlines into spaces.
+NL2SP=$lt_lt_NL2SP
+
+# convert \$build file names to \$host format.
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+
+# convert \$build files to toolchain format.
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+
+# An object symbol dumper.
+OBJDUMP=$lt_OBJDUMP
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method = "file_magic".
+file_magic_cmd=$lt_file_magic_cmd
+
+# How to find potential files when deplibs_check_method = "file_magic".
+file_magic_glob=$lt_file_magic_glob
+
+# Find potential files using nocaseglob when deplibs_check_method = "file_magic".
+want_nocaseglob=$lt_want_nocaseglob
+
+# DLL creation program.
+DLLTOOL=$lt_DLLTOOL
+
+# Command to associate shared and link libraries.
+sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd
+
+# The archiver.
+AR=$lt_AR
+
+# Flags to create an archive.
+AR_FLAGS=$lt_AR_FLAGS
+
+# How to feed a file listing to the archiver.
+archiver_list_spec=$lt_archiver_list_spec
+
+# A symbol stripping program.
+STRIP=$lt_STRIP
+
+# Commands used to install an old-style archive.
+RANLIB=$lt_RANLIB
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Whether to use a lock for old archive extraction.
+lock_old_archive_extraction=$lock_old_archive_extraction
+
+# A C compiler.
+LTCC=$lt_CC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_CFLAGS
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration.
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair.
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# Transform the output of nm in a C name address pair when lib prefix is needed.
+global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
+
+# Specify filename containing input files for \$NM.
+nm_file_list_spec=$lt_nm_file_list_spec
+
+# The root where to search for dependent libraries,and in which our libraries should be installed.
+lt_sysroot=$lt_sysroot
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# Used to examine libraries when file_magic_cmd begins with "file".
+MAGIC_CMD=$MAGIC_CMD
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Manifest tool.
+MANIFEST_TOOL=$lt_MANIFEST_TOOL
+
+# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
+DSYMUTIL=$lt_DSYMUTIL
+
+# Tool to change global to local symbols on Mac OS X.
+NMEDIT=$lt_NMEDIT
+
+# Tool to manipulate fat objects and archives on Mac OS X.
+LIPO=$lt_LIPO
+
+# ldd/readelf like tool for Mach-O binaries on Mac OS X.
+OTOOL=$lt_OTOOL
+
+# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
+OTOOL64=$lt_OTOOL64
+
+# Old archive suffix (normally "a").
+libext=$libext
+
+# Shared library suffix (normally ".so").
+shrext_cmds=$lt_shrext_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at link time.
+variables_saved_for_relink=$lt_variables_saved_for_relink
+
+# Do we need the "lib" prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Library versioning type.
+version_type=$version_type
+
+# Shared library runtime path variable.
+runpath_var=$runpath_var
+
+# Shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Permission mode override for installation of shared libraries.
+install_override_mode=$lt_install_override_mode
+
+# Command to use after installation of a shared archive.
+postinstall_cmds=$lt_postinstall_cmds
+
+# Command to use after uninstallation of a shared archive.
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# As "finish_cmds", except a single script fragment to be evaled but
+# not shown.
+finish_eval=$lt_finish_eval
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Compile-time system search path for libraries.
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries.
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# Commands used to build an old-style archive.
+old_archive_cmds=$lt_old_archive_cmds
+
+# A language specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU compiler?
+with_gcc=$GCC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object=$lt_compiler_needs_object
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld=$lt_with_gnu_ld
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting \${shlibpath_var} if the
+# library is relocated.
+hardcode_direct_absolute=$hardcode_direct_absolute
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=$hardcode_automatic
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=$inherit_rpath
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=$lt_prelink_cmds
+
+# Commands necessary for finishing linking programs.
+postlink_cmds=$lt_postlink_cmds
+
+# Specify filename containing input files.
+file_list_spec=$lt_file_list_spec
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+  case $host_os in
+  aix3*)
+    cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+_LT_EOF
+    ;;
+  esac
+
+
+ltmain="$ac_aux_dir/ltmain.sh"
+
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '$q' "$ltmain" >> "$cfgfile" \
+     || (rm -f "$cfgfile"; exit 1)
+
+  if test x"$xsi_shell" = xyes; then
+  sed -e '/^func_dirname ()$/,/^} # func_dirname /c\
+func_dirname ()\
+{\
+\    case ${1} in\
+\      */*) func_dirname_result="${1%/*}${2}" ;;\
+\      *  ) func_dirname_result="${3}" ;;\
+\    esac\
+} # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_basename ()$/,/^} # func_basename /c\
+func_basename ()\
+{\
+\    func_basename_result="${1##*/}"\
+} # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\
+func_dirname_and_basename ()\
+{\
+\    case ${1} in\
+\      */*) func_dirname_result="${1%/*}${2}" ;;\
+\      *  ) func_dirname_result="${3}" ;;\
+\    esac\
+\    func_basename_result="${1##*/}"\
+} # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_stripname ()$/,/^} # func_stripname /c\
+func_stripname ()\
+{\
+\    # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\
+\    # positional parameters, so assign one to ordinary parameter first.\
+\    func_stripname_result=${3}\
+\    func_stripname_result=${func_stripname_result#"${1}"}\
+\    func_stripname_result=${func_stripname_result%"${2}"}\
+} # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\
+func_split_long_opt ()\
+{\
+\    func_split_long_opt_name=${1%%=*}\
+\    func_split_long_opt_arg=${1#*=}\
+} # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\
+func_split_short_opt ()\
+{\
+\    func_split_short_opt_arg=${1#??}\
+\    func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\
+} # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\
+func_lo2o ()\
+{\
+\    case ${1} in\
+\      *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\
+\      *)    func_lo2o_result=${1} ;;\
+\    esac\
+} # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_xform ()$/,/^} # func_xform /c\
+func_xform ()\
+{\
+    func_xform_result=${1%.*}.lo\
+} # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_arith ()$/,/^} # func_arith /c\
+func_arith ()\
+{\
+    func_arith_result=$(( $* ))\
+} # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_len ()$/,/^} # func_len /c\
+func_len ()\
+{\
+    func_len_result=${#1}\
+} # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+fi
+
+if test x"$lt_shell_append" = xyes; then
+  sed -e '/^func_append ()$/,/^} # func_append /c\
+func_append ()\
+{\
+    eval "${1}+=\\${2}"\
+} # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\
+func_append_quoted ()\
+{\
+\    func_quote_for_eval "${2}"\
+\    eval "${1}+=\\\\ \\$func_quote_for_eval_result"\
+} # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  # Save a `func_append' function call where possible by direct use of '+='
+  sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \
+    && mv -f "$cfgfile.tmp" "$cfgfile" \
+      || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+  test 0 -eq $? || _lt_function_replace_fail=:
+else
+  # Save a `func_append' function call even when '+=' is not available
+  sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \
+    && mv -f "$cfgfile.tmp" "$cfgfile" \
+      || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+  test 0 -eq $? || _lt_function_replace_fail=:
+fi
+
+if test x"$_lt_function_replace_fail" = x":"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5
+$as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;}
+fi
+
+
+   mv -f "$cfgfile" "$ofile" ||
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+
+ ;;
+
+  esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+
+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."
+
diff --git a/configure.ac b/configure.ac
new file mode 100755
index 0000000000000000000000000000000000000000..6f293784b369b7a2c0f561a9424fb8f27b211491
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,686 @@
+#
+# configure.ac - Source file to generate "./configure" to prepare package for
+#		 compilation.
+#
+# Copyright (c) 2000-2013 Anton Altaparmakov
+# Copyright (c) 2003 Jan Kratochvil
+# Copyright (c) 2005-2009 Szabolcs Szakacsits
+# Copyright (C) 2007-2008 Alon Bar-Lev
+#
+# 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
+
+# Autoconf
+AC_PREREQ(2.59)
+AC_INIT([ntfs-3g],[2015.3.14],[ntfs-3g-devel@lists.sf.net])
+LIBNTFS_3G_VERSION="86"
+AC_CONFIG_SRCDIR([src/ntfs-3g.c])
+
+# Environment
+AC_CANONICAL_HOST
+AC_CANONICAL_TARGET
+
+# Automake
+AM_INIT_AUTOMAKE([${PACKAGE_NAME}], [${PACKAGE_VERSION}])
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+AM_MAINTAINER_MODE
+
+# Options
+AC_ARG_ENABLE(
+	[debug],
+	[AS_HELP_STRING([--enable-debug],[enable 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(
+	[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(
+	[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
+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]
+)
+
+AC_PROG_INSTALL
+PKG_PROG_PKG_CONFIG
+
+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])
+
+# 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
+
+if test "x${enable_ntfs_3g}" = "xyes"; 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}])
+else
+        with_fuse="none"
+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 ],
+	[
+		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)
+
+# add --with-extra-includes and --with-extra-libs switch to ./configure
+all_libraries="$all_libraries $USER_LDFLAGS"
+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
+
+	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
+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.]),
+	)
+fi
+
+# Checks for header files.
+AC_HEADER_STDC
+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/mkdev.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/fs.h inttypes.h linux/hdreg.h \
+	machine/endian.h windows.h syslog.h pwd.h malloc.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_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
+AC_FUNC_MBRTOWC
+AC_FUNC_MEMCMP
+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
+
+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 "${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"])
+
+# 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
+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
+	src/Makefile
+	src/ntfs-3g.8
+	src/ntfs-3g.probe.8
+	src/ntfs-3g.usermap.8
+	src/ntfs-3g.secaudit.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."
+
diff --git a/depcomp b/depcomp
new file mode 100755
index 0000000000000000000000000000000000000000..4ebd5b3a2f2d689de95251c9424e2763aa159de5
--- /dev/null
+++ b/depcomp
@@ -0,0 +1,791 @@
+#! /bin/sh
+# depcomp - compile a program generating dependencies as side-effects
+
+scriptversion=2013-05-30.07; # UTC
+
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
+
+case $1 in
+  '')
+    echo "$0: No command.  Try '$0 --help' for more information." 1>&2
+    exit 1;
+    ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: depcomp [--help] [--version] PROGRAM [ARGS]
+
+Run PROGRAMS ARGS to compile a file, generating dependencies
+as side-effects.
+
+Environment variables:
+  depmode     Dependency tracking mode.
+  source      Source file read by 'PROGRAMS ARGS'.
+  object      Object file output by 'PROGRAMS ARGS'.
+  DEPDIR      directory where to store dependencies.
+  depfile     Dependency file to output.
+  tmpdepfile  Temporary file to use when outputting dependencies.
+  libtool     Whether libtool is used (yes/no).
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "depcomp $scriptversion"
+    exit $?
+    ;;
+esac
+
+# Get the directory component of the given path, and save it in the
+# global variables '$dir'.  Note that this directory component will
+# be either empty or ending with a '/' character.  This is deliberate.
+set_dir_from ()
+{
+  case $1 in
+    */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
+      *) dir=;;
+  esac
+}
+
+# Get the suffix-stripped basename of the given path, and save it the
+# global variable '$base'.
+set_base_from ()
+{
+  base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
+}
+
+# If no dependency file was actually created by the compiler invocation,
+# we still have to create a dummy depfile, to avoid errors with the
+# Makefile "include basename.Plo" scheme.
+make_dummy_depfile ()
+{
+  echo "#dummy" > "$depfile"
+}
+
+# Factor out some common post-processing of the generated depfile.
+# Requires the auxiliary global variable '$tmpdepfile' to be set.
+aix_post_process_depfile ()
+{
+  # If the compiler actually managed to produce a dependency file,
+  # post-process it.
+  if test -f "$tmpdepfile"; then
+    # Each line is of the form 'foo.o: dependency.h'.
+    # Do two passes, one to just change these to
+    #   $object: dependency.h
+    # and one to simply output
+    #   dependency.h:
+    # which is needed to avoid the deleted-header problem.
+    { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
+      sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
+    } > "$depfile"
+    rm -f "$tmpdepfile"
+  else
+    make_dummy_depfile
+  fi
+}
+
+# A tabulation character.
+tab='	'
+# A newline character.
+nl='
+'
+# Character ranges might be problematic outside the C locale.
+# These definitions help.
+upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
+lower=abcdefghijklmnopqrstuvwxyz
+digits=0123456789
+alpha=${upper}${lower}
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+  echo "depcomp: Variables source, object and depmode must be set" 1>&2
+  exit 1
+fi
+
+# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
+depfile=${depfile-`echo "$object" |
+  sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Avoid interferences from the environment.
+gccflag= dashmflag=
+
+# Some modes work just like other modes, but use different flags.  We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write.  Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+  # HP compiler uses -M and no extra arg.
+  gccflag=-M
+  depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+  # This is just like dashmstdout with a different argument.
+  dashmflag=-xM
+  depmode=dashmstdout
+fi
+
+cygpath_u="cygpath -u -f -"
+if test "$depmode" = msvcmsys; then
+  # This is just like msvisualcpp but w/o cygpath translation.
+  # Just convert the backslash-escaped backslashes to single forward
+  # slashes to satisfy depend.m4
+  cygpath_u='sed s,\\\\,/,g'
+  depmode=msvisualcpp
+fi
+
+if test "$depmode" = msvc7msys; then
+  # This is just like msvc7 but w/o cygpath translation.
+  # Just convert the backslash-escaped backslashes to single forward
+  # slashes to satisfy depend.m4
+  cygpath_u='sed s,\\\\,/,g'
+  depmode=msvc7
+fi
+
+if test "$depmode" = xlc; then
+  # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
+  gccflag=-qmakedep=gcc,-MF
+  depmode=gcc
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want.  Yay!  Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff.  Hmm.
+## Unfortunately, FreeBSD c89 acceptance of flags depends upon
+## the command line argument order; so add the flags where they
+## appear in depend2.am.  Note that the slowdown incurred here
+## affects only configure: in makefiles, %FASTDEP% shortcuts this.
+  for arg
+  do
+    case $arg in
+    -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
+    *)  set fnord "$@" "$arg" ;;
+    esac
+    shift # fnord
+    shift # $arg
+  done
+  "$@"
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  mv "$tmpdepfile" "$depfile"
+  ;;
+
+gcc)
+## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
+## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
+## (see the conditional assignment to $gccflag above).
+## There are various ways to get dependency output from gcc.  Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+##   up in a subdir.  Having to rename by hand is ugly.
+##   (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+##   -MM, not -M (despite what the docs say).  Also, it might not be
+##   supported by the other compilers which use the 'gcc' depmode.
+## - Using -M directly means running the compiler twice (even worse
+##   than renaming).
+  if test -z "$gccflag"; then
+    gccflag=-MD,
+  fi
+  "$@" -Wp,"$gccflag$tmpdepfile"
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  # The second -e expression handles DOS-style file names with drive
+  # letters.
+  sed -e 's/^[^:]*: / /' \
+      -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the "deleted header file" problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header).  We avoid this by adding
+## dummy dependencies for each header file.  Too bad gcc doesn't do
+## this for us directly.
+## Some versions of gcc put a space before the ':'.  On the theory
+## that the space means something, we add a space to the output as
+## well.  hp depmode also adds that space, but also prefixes the VPATH
+## to the object.  Take care to not repeat it in the output.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+  tr ' ' "$nl" < "$tmpdepfile" \
+    | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
+    | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+sgi)
+  if test "$libtool" = yes; then
+    "$@" "-Wp,-MDupdate,$tmpdepfile"
+  else
+    "$@" -MDupdate "$tmpdepfile"
+  fi
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+
+  if test -f "$tmpdepfile"; then  # yes, the sourcefile depend on other files
+    echo "$object : \\" > "$depfile"
+    # Clip off the initial element (the dependent).  Don't try to be
+    # clever and replace this with sed code, as IRIX sed won't handle
+    # lines with more than a fixed number of characters (4096 in
+    # IRIX 6.2 sed, 8192 in IRIX 6.5).  We also remove comment lines;
+    # the IRIX cc adds comments like '#:fec' to the end of the
+    # dependency line.
+    tr ' ' "$nl" < "$tmpdepfile" \
+      | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
+      | tr "$nl" ' ' >> "$depfile"
+    echo >> "$depfile"
+    # The second pass generates a dummy entry for each header file.
+    tr ' ' "$nl" < "$tmpdepfile" \
+      | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+      >> "$depfile"
+  else
+    make_dummy_depfile
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+xlc)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+aix)
+  # The C for AIX Compiler uses -M and outputs the dependencies
+  # in a .u file.  In older versions, this file always lives in the
+  # current directory.  Also, the AIX compiler puts '$object:' at the
+  # start of each line; $object doesn't have directory information.
+  # Version 6 uses the directory in both cases.
+  set_dir_from "$object"
+  set_base_from "$object"
+  if test "$libtool" = yes; then
+    tmpdepfile1=$dir$base.u
+    tmpdepfile2=$base.u
+    tmpdepfile3=$dir.libs/$base.u
+    "$@" -Wc,-M
+  else
+    tmpdepfile1=$dir$base.u
+    tmpdepfile2=$dir$base.u
+    tmpdepfile3=$dir$base.u
+    "$@" -M
+  fi
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+    exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  aix_post_process_depfile
+  ;;
+
+tcc)
+  # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
+  # FIXME: That version still under development at the moment of writing.
+  #        Make that this statement remains true also for stable, released
+  #        versions.
+  # It will wrap lines (doesn't matter whether long or short) with a
+  # trailing '\', as in:
+  #
+  #   foo.o : \
+  #    foo.c \
+  #    foo.h \
+  #
+  # It will put a trailing '\' even on the last line, and will use leading
+  # spaces rather than leading tabs (at least since its commit 0394caf7
+  # "Emit spaces for -MD").
+  "$@" -MD -MF "$tmpdepfile"
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
+  # We have to change lines of the first kind to '$object: \'.
+  sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
+  # And for each line of the second kind, we have to emit a 'dep.h:'
+  # dummy dependency, to avoid the deleted-header problem.
+  sed -n -e 's|^  *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+## The order of this option in the case statement is important, since the
+## shell code in configure will try each of these formats in the order
+## listed in this file.  A plain '-MD' option would be understood by many
+## compilers, so we must ensure this comes after the gcc and icc options.
+pgcc)
+  # Portland's C compiler understands '-MD'.
+  # Will always output deps to 'file.d' where file is the root name of the
+  # source file under compilation, even if file resides in a subdirectory.
+  # The object file name does not affect the name of the '.d' file.
+  # pgcc 10.2 will output
+  #    foo.o: sub/foo.c sub/foo.h
+  # and will wrap long lines using '\' :
+  #    foo.o: sub/foo.c ... \
+  #     sub/foo.h ... \
+  #     ...
+  set_dir_from "$object"
+  # Use the source, not the object, to determine the base name, since
+  # that's sadly what pgcc will do too.
+  set_base_from "$source"
+  tmpdepfile=$base.d
+
+  # For projects that build the same source file twice into different object
+  # files, the pgcc approach of using the *source* file root name can cause
+  # problems in parallel builds.  Use a locking strategy to avoid stomping on
+  # the same $tmpdepfile.
+  lockdir=$base.d-lock
+  trap "
+    echo '$0: caught signal, cleaning up...' >&2
+    rmdir '$lockdir'
+    exit 1
+  " 1 2 13 15
+  numtries=100
+  i=$numtries
+  while test $i -gt 0; do
+    # mkdir is a portable test-and-set.
+    if mkdir "$lockdir" 2>/dev/null; then
+      # This process acquired the lock.
+      "$@" -MD
+      stat=$?
+      # Release the lock.
+      rmdir "$lockdir"
+      break
+    else
+      # If the lock is being held by a different process, wait
+      # until the winning process is done or we timeout.
+      while test -d "$lockdir" && test $i -gt 0; do
+        sleep 1
+        i=`expr $i - 1`
+      done
+    fi
+    i=`expr $i - 1`
+  done
+  trap - 1 2 13 15
+  if test $i -le 0; then
+    echo "$0: failed to acquire lock after $numtries attempts" >&2
+    echo "$0: check lockdir '$lockdir'" >&2
+    exit 1
+  fi
+
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  # Each line is of the form `foo.o: dependent.h',
+  # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+  # Do two passes, one to just change these to
+  # `$object: dependent.h' and one to simply `dependent.h:'.
+  sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process this invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
+    | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp2)
+  # The "hp" stanza above does not work with aCC (C++) and HP's ia64
+  # compilers, which have integrated preprocessors.  The correct option
+  # to use with these is +Maked; it writes dependencies to a file named
+  # 'foo.d', which lands next to the object file, wherever that
+  # happens to be.
+  # Much of this is similar to the tru64 case; see comments there.
+  set_dir_from  "$object"
+  set_base_from "$object"
+  if test "$libtool" = yes; then
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir.libs/$base.d
+    "$@" -Wc,+Maked
+  else
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir$base.d
+    "$@" +Maked
+  fi
+  stat=$?
+  if test $stat -ne 0; then
+     rm -f "$tmpdepfile1" "$tmpdepfile2"
+     exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  if test -f "$tmpdepfile"; then
+    sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
+    # Add 'dependent.h:' lines.
+    sed -ne '2,${
+               s/^ *//
+               s/ \\*$//
+               s/$/:/
+               p
+             }' "$tmpdepfile" >> "$depfile"
+  else
+    make_dummy_depfile
+  fi
+  rm -f "$tmpdepfile" "$tmpdepfile2"
+  ;;
+
+tru64)
+  # The Tru64 compiler uses -MD to generate dependencies as a side
+  # effect.  'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
+  # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+  # dependencies in 'foo.d' instead, so we check for that too.
+  # Subdirectories are respected.
+  set_dir_from  "$object"
+  set_base_from "$object"
+
+  if test "$libtool" = yes; then
+    # Libtool generates 2 separate objects for the 2 libraries.  These
+    # two compilations output dependencies in $dir.libs/$base.o.d and
+    # in $dir$base.o.d.  We have to check for both files, because
+    # one of the two compilations can be disabled.  We should prefer
+    # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
+    # automatically cleaned when .libs/ is deleted, while ignoring
+    # the former would cause a distcleancheck panic.
+    tmpdepfile1=$dir$base.o.d          # libtool 1.5
+    tmpdepfile2=$dir.libs/$base.o.d    # Likewise.
+    tmpdepfile3=$dir.libs/$base.d      # Compaq CCC V6.2-504
+    "$@" -Wc,-MD
+  else
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir$base.d
+    tmpdepfile3=$dir$base.d
+    "$@" -MD
+  fi
+
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+    exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  # Same post-processing that is required for AIX mode.
+  aix_post_process_depfile
+  ;;
+
+msvc7)
+  if test "$libtool" = yes; then
+    showIncludes=-Wc,-showIncludes
+  else
+    showIncludes=-showIncludes
+  fi
+  "$@" $showIncludes > "$tmpdepfile"
+  stat=$?
+  grep -v '^Note: including file: ' "$tmpdepfile"
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  # The first sed program below extracts the file names and escapes
+  # backslashes for cygpath.  The second sed program outputs the file
+  # name when reading, but also accumulates all include files in the
+  # hold buffer in order to output them again at the end.  This only
+  # works with sed implementations that can handle large buffers.
+  sed < "$tmpdepfile" -n '
+/^Note: including file:  *\(.*\)/ {
+  s//\1/
+  s/\\/\\\\/g
+  p
+}' | $cygpath_u | sort -u | sed -n '
+s/ /\\ /g
+s/\(.*\)/'"$tab"'\1 \\/p
+s/.\(.*\) \\/\1:/
+H
+$ {
+  s/.*/'"$tab"'/
+  G
+  p
+}' >> "$depfile"
+  echo >> "$depfile" # make sure the fragment doesn't end with a backslash
+  rm -f "$tmpdepfile"
+  ;;
+
+msvc7msys)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+#nosideeffect)
+  # This comment above is used by automake to tell side-effect
+  # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout, regardless of -o.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove '-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  test -z "$dashmflag" && dashmflag=-M
+  # Require at least two characters before searching for ':'
+  # in the target name.  This is to cope with DOS-style filenames:
+  # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
+  "$@" $dashmflag |
+    sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process this sed invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  tr ' ' "$nl" < "$tmpdepfile" \
+    | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
+    | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+dashXmstdout)
+  # This case only exists to satisfy depend.m4.  It is never actually
+  # run, as this mode is specially recognized in the preamble.
+  exit 1
+  ;;
+
+makedepend)
+  "$@" || exit $?
+  # Remove any Libtool call
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+  # X makedepend
+  shift
+  cleared=no eat=no
+  for arg
+  do
+    case $cleared in
+    no)
+      set ""; shift
+      cleared=yes ;;
+    esac
+    if test $eat = yes; then
+      eat=no
+      continue
+    fi
+    case "$arg" in
+    -D*|-I*)
+      set fnord "$@" "$arg"; shift ;;
+    # Strip any option that makedepend may not understand.  Remove
+    # the object too, otherwise makedepend will parse it as a source file.
+    -arch)
+      eat=yes ;;
+    -*|$object)
+      ;;
+    *)
+      set fnord "$@" "$arg"; shift ;;
+    esac
+  done
+  obj_suffix=`echo "$object" | sed 's/^.*\././'`
+  touch "$tmpdepfile"
+  ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
+  rm -f "$depfile"
+  # makedepend may prepend the VPATH from the source file name to the object.
+  # No need to regex-escape $object, excess matching of '.' is harmless.
+  sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process the last invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  sed '1,2d' "$tmpdepfile" \
+    | tr ' ' "$nl" \
+    | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
+    | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile" "$tmpdepfile".bak
+  ;;
+
+cpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove '-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  "$@" -E \
+    | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+             -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+    | sed '$ s: \\$::' > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  cat < "$tmpdepfile" >> "$depfile"
+  sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvisualcpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  IFS=" "
+  for arg
+  do
+    case "$arg" in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+        set fnord "$@"
+        shift
+        shift
+        ;;
+    *)
+        set fnord "$@" "$arg"
+        shift
+        shift
+        ;;
+    esac
+  done
+  "$@" -E 2>/dev/null |
+  sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
+  echo "$tab" >> "$depfile"
+  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvcmsys)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+none)
+  exec "$@"
+  ;;
+
+*)
+  echo "Unknown depmode $depmode" 1>&2
+  exit 1
+  ;;
+esac
+
+exit 0
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/include/Makefile b/include/Makefile
new file mode 100755
index 0000000000000000000000000000000000000000..1790fb91cd1f1fbd008f74459ee2eb65b4faa95a
--- /dev/null
+++ b/include/Makefile
@@ -0,0 +1,639 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# include/Makefile.  Generated from Makefile.in by configure.
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/ntfs-3g
+pkgincludedir = $(includedir)/ntfs-3g
+pkglibdir = $(libdir)/ntfs-3g
+pkglibexecdir = $(libexecdir)/ntfs-3g
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = x86_64-unknown-linux-gnu
+host_triplet = x86_64-unknown-linux-gnu
+target_triplet = x86_64-unknown-linux-gnu
+subdir = include
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_$(V))
+am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY))
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+	ctags-recursive dvi-recursive html-recursive info-recursive \
+	install-data-recursive install-dvi-recursive \
+	install-exec-recursive install-html-recursive \
+	install-info-recursive install-pdf-recursive \
+	install-ps-recursive install-recursive installcheck-recursive \
+	installdirs-recursive pdf-recursive ps-recursive \
+	tags-recursive uninstall-recursive
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
+  distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+  $(RECURSIVE_TARGETS) \
+  $(RECURSIVE_CLEAN_TARGETS) \
+  $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+	distdir
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+  dir0=`pwd`; \
+  sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+  sed_rest='s,^[^/]*/*,,'; \
+  sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+  sed_butlast='s,/*[^/]*$$,,'; \
+  while test -n "$$dir1"; do \
+    first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+    if test "$$first" != "."; then \
+      if test "$$first" = ".."; then \
+        dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+        dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+      else \
+        first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+        if test "$$first2" = "$$first"; then \
+          dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+        else \
+          dir2="../$$dir2"; \
+        fi; \
+        dir0="$$dir0"/"$$first"; \
+      fi; \
+    fi; \
+    dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+  done; \
+  reldir="$$dir2"
+ACLOCAL = ${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing aclocal-1.14
+AMTAR = $${TAR-tar}
+AM_DEFAULT_VERBOSITY = 1
+AR = ar
+AUTOCONF = ${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing autoconf
+AUTOHEADER = ${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing autoheader
+AUTOMAKE = ${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing automake-1.14
+AWK = gawk
+CC = gcc
+CCDEPMODE = depmode=gcc3
+CFLAGS = -g -O2 -Wall
+CPP = gcc -E
+CPPFLAGS = 
+CYGPATH_W = echo
+DEFS = -DHAVE_CONFIG_H
+DEPDIR = .deps
+DLLTOOL = false
+DSYMUTIL = 
+DUMPBIN = 
+ECHO_C = 
+ECHO_N = -n
+ECHO_T = 
+EGREP = /bin/grep -E
+EXEEXT = 
+FGREP = /bin/grep -F
+FUSE_MODULE_CFLAGS = 
+FUSE_MODULE_LIBS = 
+GNUTLS_CFLAGS = 
+GNUTLS_LIBS = 
+GREP = /bin/grep
+INSTALL = /usr/bin/install -c
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
+LD = /usr/bin/ld -m elf_x86_64
+LDCONFIG = /sbin/ldconfig
+LDFLAGS = 
+LIBFUSE_LITE_CFLAGS = 
+LIBFUSE_LITE_LIBS =  -lpthread
+LIBGCRYPT_CFLAGS = 
+LIBGCRYPT_CONFIG = 
+LIBGCRYPT_LIBS = 
+LIBNTFS_3G_VERSION = 86
+LIBNTFS_CPPFLAGS = 
+LIBNTFS_LIBS = 
+LIBOBJS = 
+LIBS = 
+LIBTOOL = $(SHELL) $(top_builddir)/libtool
+LIPO = 
+LN_S = ln -s
+LTLIBOBJS = 
+MAINT = #
+MAKEINFO = ${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing makeinfo
+MANIFEST_TOOL = :
+MKDIR_P = /bin/mkdir -p
+MKNTFS_CPPFLAGS = 
+MKNTFS_LIBS = 
+MV = /bin/mv
+NM = /usr/bin/nm -B
+NMEDIT = 
+NTFSPROGS_STATIC_LIBS = 
+OBJDUMP = objdump
+OBJEXT = o
+OTOOL = 
+OTOOL64 = 
+OUTPUT_FORMAT = 
+PACKAGE = ntfs-3g
+PACKAGE_BUGREPORT = ntfs-3g-devel@lists.sf.net
+PACKAGE_NAME = ntfs-3g
+PACKAGE_STRING = ntfs-3g 2015.3.14
+PACKAGE_TARNAME = ntfs-3g
+PACKAGE_URL = 
+PACKAGE_VERSION = 2015.3.14
+PATH_SEPARATOR = :
+PKG_CONFIG = /usr/bin/pkg-config
+PKG_CONFIG_LIBDIR = 
+PKG_CONFIG_PATH = 
+RANLIB = ranlib
+RM = /bin/rm
+SED = /bin/sed
+SET_MAKE = 
+SHELL = /bin/bash
+STRIP = strip
+VERSION = 2015.3.14
+abs_builddir = /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/include
+abs_srcdir = /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/include
+abs_top_builddir = /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14
+abs_top_srcdir = /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14
+ac_ct_AR = ar
+ac_ct_CC = gcc
+ac_ct_DUMPBIN = 
+all_includes =  
+all_libraries =  
+am__include = include
+am__leading_dot = .
+am__quote = 
+am__tar = $${TAR-tar} chof - "$$tardir"
+am__untar = $${TAR-tar} xf -
+bindir = ${exec_prefix}/bin
+build = x86_64-unknown-linux-gnu
+build_alias = 
+build_cpu = x86_64
+build_os = linux-gnu
+build_vendor = unknown
+builddir = .
+datadir = ${datarootdir}
+datarootdir = ${prefix}/share
+docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
+dvidir = ${docdir}
+exec_prefix = ${prefix}
+host = x86_64-unknown-linux-gnu
+host_alias = 
+host_cpu = x86_64
+host_os = linux-gnu
+host_vendor = unknown
+htmldir = ${docdir}
+includedir = ${prefix}/include
+infodir = ${datarootdir}/info
+install_sh = ${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localedir = ${datarootdir}/locale
+localstatedir = ${prefix}/var
+mandir = ${datarootdir}/man
+mkdir_p = $(MKDIR_P)
+ntfs3gincludedir = $(includedir)/ntfs-3g
+oldincludedir = /usr/include
+pdfdir = ${docdir}
+pkgconfigdir = $(libdir)/pkgconfig
+prefix = /usr/local
+program_transform_name = s,x,x,
+psdir = ${docdir}
+rootbindir = /bin
+rootlibdir = /lib
+rootsbindir = /sbin
+sbindir = ${exec_prefix}/sbin
+sharedstatedir = ${prefix}/com
+srcdir = .
+sysconfdir = ${prefix}/etc
+target = x86_64-unknown-linux-gnu
+target_alias = 
+target_cpu = x86_64
+target_os = linux-gnu
+target_vendor = unknown
+top_build_prefix = ../
+top_builddir = ..
+top_srcdir = ..
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+SUBDIRS = ntfs-3g fuse-lite
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: # $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu include/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: # $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): # $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+#     (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+	@fail=; \
+	if $(am__make_keepgoing); then \
+	  failcom='fail=yes'; \
+	else \
+	  failcom='exit 1'; \
+	fi; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-recursive
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-recursive
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-recursive
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+	@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    $(am__make_dryrun) \
+	      || test -d "$(distdir)/$$subdir" \
+	      || $(MKDIR_P) "$(distdir)/$$subdir" \
+	      || exit 1; \
+	    dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+	    $(am__relativize); \
+	    new_distdir=$$reldir; \
+	    dir1=$$subdir; dir2="$(top_distdir)"; \
+	    $(am__relativize); \
+	    new_top_distdir=$$reldir; \
+	    echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+	    echo "     am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+	    ($(am__cd) $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$new_top_distdir" \
+	        distdir="$$new_distdir" \
+		am__remove_distdir=: \
+		am__skip_length_check=: \
+		am__skip_mode_fix=: \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(am__recursive_targets) install-am install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
+	check-am clean clean-generic clean-libtool cscopelist-am ctags \
+	ctags-am distclean distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am install-man \
+	install-pdf install-pdf-am install-ps install-ps-am \
+	install-strip installcheck installcheck-am installdirs \
+	installdirs-am maintainer-clean maintainer-clean-generic \
+	mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
+	ps ps-am tags tags-am uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/include/Makefile.am b/include/Makefile.am
new file mode 100755
index 0000000000000000000000000000000000000000..0fa17025850685b5d693287117832fb003ea622b
--- /dev/null
+++ b/include/Makefile.am
@@ -0,0 +1,4 @@
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+SUBDIRS = ntfs-3g fuse-lite
diff --git a/include/Makefile.in b/include/Makefile.in
new file mode 100755
index 0000000000000000000000000000000000000000..048d6aa5979588addef82e817ad7fabcfb0f4abb
--- /dev/null
+++ b/include/Makefile.in
@@ -0,0 +1,639 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = include
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+	ctags-recursive dvi-recursive html-recursive info-recursive \
+	install-data-recursive install-dvi-recursive \
+	install-exec-recursive install-html-recursive \
+	install-info-recursive install-pdf-recursive \
+	install-ps-recursive install-recursive installcheck-recursive \
+	installdirs-recursive pdf-recursive ps-recursive \
+	tags-recursive uninstall-recursive
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
+  distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+  $(RECURSIVE_TARGETS) \
+  $(RECURSIVE_CLEAN_TARGETS) \
+  $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+	distdir
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+  dir0=`pwd`; \
+  sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+  sed_rest='s,^[^/]*/*,,'; \
+  sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+  sed_butlast='s,/*[^/]*$$,,'; \
+  while test -n "$$dir1"; do \
+    first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+    if test "$$first" != "."; then \
+      if test "$$first" = ".."; then \
+        dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+        dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+      else \
+        first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+        if test "$$first2" = "$$first"; then \
+          dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+        else \
+          dir2="../$$dir2"; \
+        fi; \
+        dir0="$$dir0"/"$$first"; \
+      fi; \
+    fi; \
+    dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+  done; \
+  reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FUSE_MODULE_CFLAGS = @FUSE_MODULE_CFLAGS@
+FUSE_MODULE_LIBS = @FUSE_MODULE_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDCONFIG = @LDCONFIG@
+LDFLAGS = @LDFLAGS@
+LIBFUSE_LITE_CFLAGS = @LIBFUSE_LITE_CFLAGS@
+LIBFUSE_LITE_LIBS = @LIBFUSE_LITE_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBNTFS_3G_VERSION = @LIBNTFS_3G_VERSION@
+LIBNTFS_CPPFLAGS = @LIBNTFS_CPPFLAGS@
+LIBNTFS_LIBS = @LIBNTFS_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MKNTFS_CPPFLAGS = @MKNTFS_CPPFLAGS@
+MKNTFS_LIBS = @MKNTFS_LIBS@
+MV = @MV@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NTFSPROGS_STATIC_LIBS = @NTFSPROGS_STATIC_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+OUTPUT_FORMAT = @OUTPUT_FORMAT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+RM = @RM@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+all_includes = @all_includes@
+all_libraries = @all_libraries@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+ntfs3gincludedir = @ntfs3gincludedir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgconfigdir = @pkgconfigdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+rootbindir = @rootbindir@
+rootlibdir = @rootlibdir@
+rootsbindir = @rootsbindir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+SUBDIRS = ntfs-3g fuse-lite
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu include/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+#     (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+	@fail=; \
+	if $(am__make_keepgoing); then \
+	  failcom='fail=yes'; \
+	else \
+	  failcom='exit 1'; \
+	fi; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-recursive
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-recursive
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-recursive
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+	@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    $(am__make_dryrun) \
+	      || test -d "$(distdir)/$$subdir" \
+	      || $(MKDIR_P) "$(distdir)/$$subdir" \
+	      || exit 1; \
+	    dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+	    $(am__relativize); \
+	    new_distdir=$$reldir; \
+	    dir1=$$subdir; dir2="$(top_distdir)"; \
+	    $(am__relativize); \
+	    new_top_distdir=$$reldir; \
+	    echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+	    echo "     am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+	    ($(am__cd) $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$new_top_distdir" \
+	        distdir="$$new_distdir" \
+		am__remove_distdir=: \
+		am__skip_length_check=: \
+		am__skip_mode_fix=: \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(am__recursive_targets) install-am install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
+	check-am clean clean-generic clean-libtool cscopelist-am ctags \
+	ctags-am distclean distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am install-man \
+	install-pdf install-pdf-am install-ps install-ps-am \
+	install-strip installcheck installcheck-am installdirs \
+	installdirs-am maintainer-clean maintainer-clean-generic \
+	mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
+	ps ps-am tags tags-am uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/include/fuse-lite/Makefile b/include/fuse-lite/Makefile
new file mode 100755
index 0000000000000000000000000000000000000000..e84fa1e27d8c3831bb32ac52a7ab5f54c5fa6d64
--- /dev/null
+++ b/include/fuse-lite/Makefile
@@ -0,0 +1,534 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# include/fuse-lite/Makefile.  Generated from Makefile.in by configure.
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/ntfs-3g
+pkgincludedir = $(includedir)/ntfs-3g
+pkglibdir = $(libdir)/ntfs-3g
+pkglibexecdir = $(libexecdir)/ntfs-3g
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = x86_64-unknown-linux-gnu
+host_triplet = x86_64-unknown-linux-gnu
+target_triplet = x86_64-unknown-linux-gnu
+subdir = include/fuse-lite
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+	$(noinst_HEADERS)
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_$(V))
+am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY))
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+HEADERS = $(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = ${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing aclocal-1.14
+AMTAR = $${TAR-tar}
+AM_DEFAULT_VERBOSITY = 1
+AR = ar
+AUTOCONF = ${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing autoconf
+AUTOHEADER = ${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing autoheader
+AUTOMAKE = ${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing automake-1.14
+AWK = gawk
+CC = gcc
+CCDEPMODE = depmode=gcc3
+CFLAGS = -g -O2 -Wall
+CPP = gcc -E
+CPPFLAGS = 
+CYGPATH_W = echo
+DEFS = -DHAVE_CONFIG_H
+DEPDIR = .deps
+DLLTOOL = false
+DSYMUTIL = 
+DUMPBIN = 
+ECHO_C = 
+ECHO_N = -n
+ECHO_T = 
+EGREP = /bin/grep -E
+EXEEXT = 
+FGREP = /bin/grep -F
+FUSE_MODULE_CFLAGS = 
+FUSE_MODULE_LIBS = 
+GNUTLS_CFLAGS = 
+GNUTLS_LIBS = 
+GREP = /bin/grep
+INSTALL = /usr/bin/install -c
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
+LD = /usr/bin/ld -m elf_x86_64
+LDCONFIG = /sbin/ldconfig
+LDFLAGS = 
+LIBFUSE_LITE_CFLAGS = 
+LIBFUSE_LITE_LIBS =  -lpthread
+LIBGCRYPT_CFLAGS = 
+LIBGCRYPT_CONFIG = 
+LIBGCRYPT_LIBS = 
+LIBNTFS_3G_VERSION = 86
+LIBNTFS_CPPFLAGS = 
+LIBNTFS_LIBS = 
+LIBOBJS = 
+LIBS = 
+LIBTOOL = $(SHELL) $(top_builddir)/libtool
+LIPO = 
+LN_S = ln -s
+LTLIBOBJS = 
+MAINT = #
+MAKEINFO = ${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing makeinfo
+MANIFEST_TOOL = :
+MKDIR_P = /bin/mkdir -p
+MKNTFS_CPPFLAGS = 
+MKNTFS_LIBS = 
+MV = /bin/mv
+NM = /usr/bin/nm -B
+NMEDIT = 
+NTFSPROGS_STATIC_LIBS = 
+OBJDUMP = objdump
+OBJEXT = o
+OTOOL = 
+OTOOL64 = 
+OUTPUT_FORMAT = 
+PACKAGE = ntfs-3g
+PACKAGE_BUGREPORT = ntfs-3g-devel@lists.sf.net
+PACKAGE_NAME = ntfs-3g
+PACKAGE_STRING = ntfs-3g 2015.3.14
+PACKAGE_TARNAME = ntfs-3g
+PACKAGE_URL = 
+PACKAGE_VERSION = 2015.3.14
+PATH_SEPARATOR = :
+PKG_CONFIG = /usr/bin/pkg-config
+PKG_CONFIG_LIBDIR = 
+PKG_CONFIG_PATH = 
+RANLIB = ranlib
+RM = /bin/rm
+SED = /bin/sed
+SET_MAKE = 
+SHELL = /bin/bash
+STRIP = strip
+VERSION = 2015.3.14
+abs_builddir = /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/include/fuse-lite
+abs_srcdir = /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/include/fuse-lite
+abs_top_builddir = /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14
+abs_top_srcdir = /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14
+ac_ct_AR = ar
+ac_ct_CC = gcc
+ac_ct_DUMPBIN = 
+all_includes =  
+all_libraries =  
+am__include = include
+am__leading_dot = .
+am__quote = 
+am__tar = $${TAR-tar} chof - "$$tardir"
+am__untar = $${TAR-tar} xf -
+bindir = ${exec_prefix}/bin
+build = x86_64-unknown-linux-gnu
+build_alias = 
+build_cpu = x86_64
+build_os = linux-gnu
+build_vendor = unknown
+builddir = .
+datadir = ${datarootdir}
+datarootdir = ${prefix}/share
+docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
+dvidir = ${docdir}
+exec_prefix = ${prefix}
+host = x86_64-unknown-linux-gnu
+host_alias = 
+host_cpu = x86_64
+host_os = linux-gnu
+host_vendor = unknown
+htmldir = ${docdir}
+includedir = ${prefix}/include
+infodir = ${datarootdir}/info
+install_sh = ${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localedir = ${datarootdir}/locale
+localstatedir = ${prefix}/var
+mandir = ${datarootdir}/man
+mkdir_p = $(MKDIR_P)
+ntfs3gincludedir = $(includedir)/ntfs-3g
+oldincludedir = /usr/include
+pdfdir = ${docdir}
+pkgconfigdir = $(libdir)/pkgconfig
+prefix = /usr/local
+program_transform_name = s,x,x,
+psdir = ${docdir}
+rootbindir = /bin
+rootlibdir = /lib
+rootsbindir = /sbin
+sbindir = ${exec_prefix}/sbin
+sharedstatedir = ${prefix}/com
+srcdir = .
+sysconfdir = ${prefix}/etc
+target = x86_64-unknown-linux-gnu
+target_alias = 
+target_cpu = x86_64
+target_os = linux-gnu
+target_vendor = unknown
+top_build_prefix = ../../
+top_builddir = ../..
+top_srcdir = ../..
+MAINTAINERCLEANFILES = Makefile.in
+noinst_HEADERS = \
+	fuse.h			\
+	fuse_common.h		\
+	fuse_lowlevel.h		\
+	fuse_lowlevel_compat.h	\
+	fuse_opt.h		\
+	fuse_kernel.h
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: # $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/fuse-lite/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu include/fuse-lite/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: # $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): # $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+	clean-libtool cscopelist-am ctags ctags-am distclean \
+	distclean-generic distclean-libtool distclean-tags distdir dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-data install-data-am install-dvi install-dvi-am \
+	install-exec install-exec-am install-html install-html-am \
+	install-info install-info-am install-man install-pdf \
+	install-pdf-am install-ps install-ps-am install-strip \
+	installcheck installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-generic \
+	mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+	uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/include/fuse-lite/Makefile.am b/include/fuse-lite/Makefile.am
new file mode 100755
index 0000000000000000000000000000000000000000..15a84bbf5d6f3af56c1c7f754e074a79cfe65593
--- /dev/null
+++ b/include/fuse-lite/Makefile.am
@@ -0,0 +1,10 @@
+
+MAINTAINERCLEANFILES = Makefile.in
+
+noinst_HEADERS = 		\
+	fuse.h			\
+	fuse_common.h		\
+	fuse_lowlevel.h		\
+	fuse_lowlevel_compat.h	\
+	fuse_opt.h		\
+	fuse_kernel.h
diff --git a/include/fuse-lite/Makefile.in b/include/fuse-lite/Makefile.in
new file mode 100755
index 0000000000000000000000000000000000000000..9bc340fb3caaab389da9d4e4bb19c635df9f5287
--- /dev/null
+++ b/include/fuse-lite/Makefile.in
@@ -0,0 +1,534 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = include/fuse-lite
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+	$(noinst_HEADERS)
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+HEADERS = $(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FUSE_MODULE_CFLAGS = @FUSE_MODULE_CFLAGS@
+FUSE_MODULE_LIBS = @FUSE_MODULE_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDCONFIG = @LDCONFIG@
+LDFLAGS = @LDFLAGS@
+LIBFUSE_LITE_CFLAGS = @LIBFUSE_LITE_CFLAGS@
+LIBFUSE_LITE_LIBS = @LIBFUSE_LITE_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBNTFS_3G_VERSION = @LIBNTFS_3G_VERSION@
+LIBNTFS_CPPFLAGS = @LIBNTFS_CPPFLAGS@
+LIBNTFS_LIBS = @LIBNTFS_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MKNTFS_CPPFLAGS = @MKNTFS_CPPFLAGS@
+MKNTFS_LIBS = @MKNTFS_LIBS@
+MV = @MV@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NTFSPROGS_STATIC_LIBS = @NTFSPROGS_STATIC_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+OUTPUT_FORMAT = @OUTPUT_FORMAT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+RM = @RM@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+all_includes = @all_includes@
+all_libraries = @all_libraries@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+ntfs3gincludedir = @ntfs3gincludedir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgconfigdir = @pkgconfigdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+rootbindir = @rootbindir@
+rootlibdir = @rootlibdir@
+rootsbindir = @rootsbindir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+MAINTAINERCLEANFILES = Makefile.in
+noinst_HEADERS = \
+	fuse.h			\
+	fuse_common.h		\
+	fuse_lowlevel.h		\
+	fuse_lowlevel_compat.h	\
+	fuse_opt.h		\
+	fuse_kernel.h
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/fuse-lite/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu include/fuse-lite/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+	clean-libtool cscopelist-am ctags ctags-am distclean \
+	distclean-generic distclean-libtool distclean-tags distdir dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-data install-data-am install-dvi install-dvi-am \
+	install-exec install-exec-am install-html install-html-am \
+	install-info install-info-am install-man install-pdf \
+	install-pdf-am install-ps install-ps-am install-strip \
+	installcheck installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-generic \
+	mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+	uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/include/fuse-lite/fuse.h b/include/fuse-lite/fuse.h
new file mode 100755
index 0000000000000000000000000000000000000000..2e3d53d85f792651d08f6bc498faf8941d3ddd62
--- /dev/null
+++ b/include/fuse-lite/fuse.h
@@ -0,0 +1,694 @@
+/*
+  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
+	 */
+	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_ */
diff --git a/include/fuse-lite/fuse_common.h b/include/fuse-lite/fuse_common.h
new file mode 100755
index 0000000000000000000000000000000000000000..8a3f1df3bd6cb3a065fd70f661104c92dd0726f3
--- /dev/null
+++ b/include/fuse-lite/fuse_common.h
@@ -0,0 +1,244 @@
+/*
+  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
+ */
+#define FUSE_CAP_DONT_MASK	(1 << 6)
+#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_ */
diff --git a/include/fuse-lite/fuse_kernel.h b/include/fuse-lite/fuse_kernel.h
new file mode 100755
index 0000000000000000000000000000000000000000..c031b04f7ffa5cce83f42ae6793137d5a6c83957
--- /dev/null
+++ b/include/fuse-lite/fuse_kernel.h
@@ -0,0 +1,439 @@
+/*
+    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
+ */
+#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)
+
+/**
+ * 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)
diff --git a/include/fuse-lite/fuse_lowlevel.h b/include/fuse-lite/fuse_lowlevel.h
new file mode 100755
index 0000000000000000000000000000000000000000..8c84d9656030bc5a273d5410bfcb4c2581f8888d
--- /dev/null
+++ b/include/fuse-lite/fuse_lowlevel.h
@@ -0,0 +1,1414 @@
+/*
+  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_LOWLEVEL_H_
+#define _FUSE_LOWLEVEL_H_
+
+/** @file
+ *
+ * Low level API
+ */
+
+#include "fuse_common.h"
+
+#include <utime.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include <sys/uio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ----------------------------------------------------------- *
+ * Miscellaneous definitions				       *
+ * ----------------------------------------------------------- */
+
+/** The node ID of the root inode */
+#define FUSE_ROOT_ID 1
+
+/** Inode number type */
+typedef unsigned long fuse_ino_t;
+
+/** Request pointer type */
+typedef struct fuse_req *fuse_req_t;
+
+/**
+ * Session
+ *
+ * This provides hooks for processing requests, and exiting
+ */
+struct fuse_session;
+
+/**
+ * Channel
+ *
+ * A communication channel, providing hooks for sending and receiving
+ * messages
+ */
+struct fuse_chan;
+
+/** Directory entry parameters supplied to fuse_reply_entry() */
+struct fuse_entry_param {
+	/** Unique inode number
+	 *
+	 * In lookup, zero means negative entry (from version 2.5)
+	 * Returning ENOENT also means negative entry, but by setting zero
+	 * ino the kernel may cache negative entries for entry_timeout
+	 * seconds.
+	 */
+	fuse_ino_t ino;
+
+	/** Generation number for this entry.
+	 *
+	 * The ino/generation pair should be unique for the filesystem's
+	 * lifetime. It must be non-zero, otherwise FUSE will treat it as an
+	 * error.
+	 */
+	unsigned long generation;
+
+	/** Inode attributes.
+	 *
+	 * Even if attr_timeout == 0, attr must be correct. For example,
+	 * for open(), FUSE uses attr.st_size from lookup() to determine
+	 * how many bytes to request. If this value is not correct,
+	 * incorrect data will be returned.
+	 */
+	struct stat attr;
+
+	/** Validity timeout (in seconds) for the attributes */
+	double attr_timeout;
+
+	/** Validity timeout (in seconds) for the name */
+	double entry_timeout;
+};
+
+/** Additional context associated with requests */
+struct fuse_ctx {
+	/** 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;
+
+	/** Umask of the calling process (introduced in version 2.8) */
+	mode_t umask;
+};
+
+/* 'to_set' flags in setattr */
+#define FUSE_SET_ATTR_MODE	(1 << 0)
+#define FUSE_SET_ATTR_UID	(1 << 1)
+#define FUSE_SET_ATTR_GID	(1 << 2)
+#define FUSE_SET_ATTR_SIZE	(1 << 3)
+#define FUSE_SET_ATTR_ATIME	(1 << 4)
+#define FUSE_SET_ATTR_MTIME	(1 << 5)
+#define FUSE_SET_ATTR_ATIME_NOW	(1 << 7)
+#define FUSE_SET_ATTR_MTIME_NOW	(1 << 8)
+
+/* ----------------------------------------------------------- *
+ * Request methods and replies				       *
+ * ----------------------------------------------------------- */
+
+/**
+ * Low level filesystem operations
+ *
+ * Most of the methods (with the exception of init and destroy)
+ * receive a request handle (fuse_req_t) as their first argument.
+ * This handle must be passed to one of the specified reply functions.
+ *
+ * This may be done inside the method invocation, or after the call
+ * has returned.  The request handle is valid until one of the reply
+ * functions is called.
+ *
+ * Other pointer arguments (name, fuse_file_info, etc) are not valid
+ * after the call has returned, so if they are needed later, their
+ * contents have to be copied.
+ *
+ * The filesystem sometimes needs to handle a return value of -ENOENT
+ * from the reply function, which means, that the request was
+ * interrupted, and the reply discarded.  For example if
+ * fuse_reply_open() return -ENOENT means, that the release method for
+ * this file will not be called.
+ */
+struct fuse_lowlevel_ops {
+	/**
+	 * Initialize filesystem
+	 *
+	 * Called before any other filesystem method
+	 *
+	 * There's no reply to this function
+	 *
+	 * @param userdata the user data passed to fuse_lowlevel_new()
+	 */
+	void (*init) (void *userdata, struct fuse_conn_info *conn);
+
+	/**
+	 * Clean up filesystem
+	 *
+	 * Called on filesystem exit
+	 *
+	 * There's no reply to this function
+	 *
+	 * @param userdata the user data passed to fuse_lowlevel_new()
+	 */
+	void (*destroy) (void *userdata);
+
+	/**
+	 * Look up a directory entry by name and get its attributes.
+	 *
+	 * Valid replies:
+	 *   fuse_reply_entry
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param parent inode number of the parent directory
+	 * @param name the name to look up
+	 */
+	void (*lookup) (fuse_req_t req, fuse_ino_t parent, const char *name);
+
+	/**
+	 * Forget about an inode
+	 *
+	 * The nlookup parameter indicates the number of lookups
+	 * previously performed on this inode.
+	 *
+	 * If the filesystem implements inode lifetimes, it is recommended
+	 * that inodes acquire a single reference on each lookup, and lose
+	 * nlookup references on each forget.
+	 *
+	 * The filesystem may ignore forget calls, if the inodes don't
+	 * need to have a limited lifetime.
+	 *
+	 * On unmount it is not guaranteed, that all referenced inodes
+	 * will receive a forget message.
+	 *
+	 * Valid replies:
+	 *   fuse_reply_none
+	 *
+	 * @param req request handle
+	 * @param ino the inode number
+	 * @param nlookup the number of lookups to forget
+	 */
+	void (*forget) (fuse_req_t req, fuse_ino_t ino, unsigned long nlookup);
+
+	/**
+	 * Get file attributes
+	 *
+	 * Valid replies:
+	 *   fuse_reply_attr
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param ino the inode number
+	 * @param fi for future use, currently always NULL
+	 */
+	void (*getattr) (fuse_req_t req, fuse_ino_t ino,
+			 struct fuse_file_info *fi);
+
+	/**
+	 * Set file attributes
+	 *
+	 * In the 'attr' argument only members indicated by the 'to_set'
+	 * bitmask contain valid values.  Other members contain undefined
+	 * values.
+	 *
+	 * If the setattr was invoked from the ftruncate() system call
+	 * under Linux kernel versions 2.6.15 or later, the fi->fh will
+	 * contain the value set by the open method or will be undefined
+	 * if the open method didn't set any value.  Otherwise (not
+	 * ftruncate call, or kernel version earlier than 2.6.15) the fi
+	 * parameter will be NULL.
+	 *
+	 * Valid replies:
+	 *   fuse_reply_attr
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param ino the inode number
+	 * @param attr the attributes
+	 * @param to_set bit mask of attributes which should be set
+	 * @param fi file information, or NULL
+	 *
+	 * Changed in version 2.5:
+	 *     file information filled in for ftruncate
+	 */
+	void (*setattr) (fuse_req_t req, fuse_ino_t ino, struct stat *attr,
+			 int to_set, struct fuse_file_info *fi);
+
+	/**
+	 * Read symbolic link
+	 *
+	 * Valid replies:
+	 *   fuse_reply_readlink
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param ino the inode number
+	 */
+	void (*readlink) (fuse_req_t req, fuse_ino_t ino);
+
+	/**
+	 * Create file node
+	 *
+	 * Create a regular file, character device, block device, fifo or
+	 * socket node.
+	 *
+	 * Valid replies:
+	 *   fuse_reply_entry
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param parent inode number of the parent directory
+	 * @param name to create
+	 * @param mode file type and mode with which to create the new file
+	 * @param rdev the device number (only valid if created file is a device)
+	 */
+	void (*mknod) (fuse_req_t req, fuse_ino_t parent, const char *name,
+		       mode_t mode, dev_t rdev);
+
+	/**
+	 * Create a directory
+	 *
+	 * Valid replies:
+	 *   fuse_reply_entry
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param parent inode number of the parent directory
+	 * @param name to create
+	 * @param mode with which to create the new file
+	 */
+	void (*mkdir) (fuse_req_t req, fuse_ino_t parent, const char *name,
+		       mode_t mode);
+
+	/**
+	 * Remove a file
+	 *
+	 * Valid replies:
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param parent inode number of the parent directory
+	 * @param name to remove
+	 */
+	void (*unlink) (fuse_req_t req, fuse_ino_t parent, const char *name);
+
+	/**
+	 * Remove a directory
+	 *
+	 * Valid replies:
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param parent inode number of the parent directory
+	 * @param name to remove
+	 */
+	void (*rmdir) (fuse_req_t req, fuse_ino_t parent, const char *name);
+
+	/**
+	 * Create a symbolic link
+	 *
+	 * Valid replies:
+	 *   fuse_reply_entry
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param link the contents of the symbolic link
+	 * @param parent inode number of the parent directory
+	 * @param name to create
+	 */
+	void (*symlink) (fuse_req_t req, const char *link, fuse_ino_t parent,
+			 const char *name);
+
+	/** Rename a file
+	 *
+	 * Valid replies:
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param parent inode number of the old parent directory
+	 * @param name old name
+	 * @param newparent inode number of the new parent directory
+	 * @param newname new name
+	 */
+	void (*rename) (fuse_req_t req, fuse_ino_t parent, const char *name,
+			fuse_ino_t newparent, const char *newname);
+
+	/**
+	 * Create a hard link
+	 *
+	 * Valid replies:
+	 *   fuse_reply_entry
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param ino the old inode number
+	 * @param newparent inode number of the new parent directory
+	 * @param newname new name to create
+	 */
+	void (*link) (fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,
+		      const char *newname);
+
+	/**
+	 * Open a file
+	 *
+	 * Open flags (with the exception of O_CREAT, O_EXCL, O_NOCTTY and
+	 * O_TRUNC) are available in fi->flags.
+	 *
+	 * Filesystem may store an arbitrary file handle (pointer, index,
+	 * etc) in fi->fh, and use this in other all other file operations
+	 * (read, write, flush, release, fsync).
+	 *
+	 * Filesystem may also implement stateless file I/O and not store
+	 * anything in fi->fh.
+	 *
+	 * There are also some flags (direct_io, keep_cache) which the
+	 * filesystem may set in fi, to change the way the file is opened.
+	 * See fuse_file_info structure in <fuse_common.h> for more details.
+	 *
+	 * Valid replies:
+	 *   fuse_reply_open
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param ino the inode number
+	 * @param fi file information
+	 */
+	void (*open) (fuse_req_t req, fuse_ino_t ino,
+		      struct fuse_file_info *fi);
+
+	/**
+	 * Read data
+	 *
+	 * Read should send 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 file
+	 * has been opened in 'direct_io' mode, in which case the return
+	 * value of the read system call will reflect the return value of
+	 * this operation.
+	 *
+	 * fi->fh will contain the value set by the open method, or will
+	 * be undefined if the open method didn't set any value.
+	 *
+	 * Valid replies:
+	 *   fuse_reply_buf
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param ino the inode number
+	 * @param size number of bytes to read
+	 * @param off offset to read from
+	 * @param fi file information
+	 */
+	void (*read) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
+		      struct fuse_file_info *fi);
+
+	/**
+	 * Write data
+	 *
+	 * Write should return exactly the number of bytes requested
+	 * except on error.  An exception to this is when the file has
+	 * been opened in 'direct_io' mode, in which case the return value
+	 * of the write system call will reflect the return value of this
+	 * operation.
+	 *
+	 * fi->fh will contain the value set by the open method, or will
+	 * be undefined if the open method didn't set any value.
+	 *
+	 * Valid replies:
+	 *   fuse_reply_write
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param ino the inode number
+	 * @param buf data to write
+	 * @param size number of bytes to write
+	 * @param off offset to write to
+	 * @param fi file information
+	 */
+	void (*write) (fuse_req_t req, fuse_ino_t ino, const char *buf,
+		       size_t size, off_t off, struct fuse_file_info *fi);
+
+	/**
+	 * Flush method
+	 *
+	 * This is called on each close() of the opened file.
+	 *
+	 * Since file descriptors can be duplicated (dup, dup2, fork), for
+	 * one open call there may be many flush calls.
+	 *
+	 * Filesystems shouldn't assume that flush will always be called
+	 * after some writes, or that if will be called at all.
+	 *
+	 * fi->fh will contain the value set by the open method, or will
+	 * be undefined if the open method didn't set any value.
+	 *
+	 * NOTE: the name of the method is misleading, since (unlike
+	 * fsync) the filesystem is not forced to flush pending writes.
+	 * One reason to flush data, is if the filesystem wants to return
+	 * write errors.
+	 *
+	 * If the filesystem supports file locking operations (setlk,
+	 * getlk) it should remove all locks belonging to 'fi->owner'.
+	 *
+	 * Valid replies:
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param ino the inode number
+	 * @param fi file information
+	 */
+	void (*flush) (fuse_req_t req, fuse_ino_t ino,
+		       struct fuse_file_info *fi);
+
+	/**
+	 * 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.
+	 *
+	 * The filesystem may reply with an error, but error values are
+	 * not returned to close() or munmap() which triggered the
+	 * release.
+	 *
+	 * fi->fh will contain the value set by the open method, or will
+	 * be undefined if the open method didn't set any value.
+	 * fi->flags will contain the same flags as for open.
+	 *
+	 * Valid replies:
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param ino the inode number
+	 * @param fi file information
+	 */
+	void (*release) (fuse_req_t req, fuse_ino_t ino,
+			 struct fuse_file_info *fi);
+
+	/**
+	 * Synchronize file contents
+	 *
+	 * If the datasync parameter is non-zero, then only the user data
+	 * should be flushed, not the meta data.
+	 *
+	 * Valid replies:
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param ino the inode number
+	 * @param datasync flag indicating if only data should be flushed
+	 * @param fi file information
+	 */
+	void (*fsync) (fuse_req_t req, fuse_ino_t ino, int datasync,
+		       struct fuse_file_info *fi);
+
+	/**
+	 * Open a directory
+	 *
+	 * Filesystem may store an arbitrary file handle (pointer, index,
+	 * etc) in fi->fh, and use this in other all other directory
+	 * stream operations (readdir, releasedir, fsyncdir).
+	 *
+	 * Filesystem may also implement stateless directory I/O and not
+	 * store anything in fi->fh, though that makes it impossible to
+	 * implement standard conforming directory stream operations in
+	 * case the contents of the directory can change between opendir
+	 * and releasedir.
+	 *
+	 * Valid replies:
+	 *   fuse_reply_open
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param ino the inode number
+	 * @param fi file information
+	 */
+	void (*opendir) (fuse_req_t req, fuse_ino_t ino,
+			 struct fuse_file_info *fi);
+
+	/**
+	 * Read directory
+	 *
+	 * Send a buffer filled using fuse_add_direntry(), with size not
+	 * exceeding the requested size.  Send an empty buffer on end of
+	 * stream.
+	 *
+	 * fi->fh will contain the value set by the opendir method, or
+	 * will be undefined if the opendir method didn't set any value.
+	 *
+	 * Valid replies:
+	 *   fuse_reply_buf
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param ino the inode number
+	 * @param size maximum number of bytes to send
+	 * @param off offset to continue reading the directory stream
+	 * @param fi file information
+	 */
+	void (*readdir) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
+			 struct fuse_file_info *fi);
+
+	/**
+	 * Release an open directory
+	 *
+	 * For every opendir call there will be exactly one releasedir
+	 * call.
+	 *
+	 * fi->fh will contain the value set by the opendir method, or
+	 * will be undefined if the opendir method didn't set any value.
+	 *
+	 * Valid replies:
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param ino the inode number
+	 * @param fi file information
+	 */
+	void (*releasedir) (fuse_req_t req, fuse_ino_t ino,
+			    struct fuse_file_info *fi);
+
+	/**
+	 * Synchronize directory contents
+	 *
+	 * If the datasync parameter is non-zero, then only the directory
+	 * contents should be flushed, not the meta data.
+	 *
+	 * fi->fh will contain the value set by the opendir method, or
+	 * will be undefined if the opendir method didn't set any value.
+	 *
+	 * Valid replies:
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param ino the inode number
+	 * @param datasync flag indicating if only data should be flushed
+	 * @param fi file information
+	 */
+	void (*fsyncdir) (fuse_req_t req, fuse_ino_t ino, int datasync,
+			  struct fuse_file_info *fi);
+
+	/**
+	 * Get file system statistics
+	 *
+	 * Valid replies:
+	 *   fuse_reply_statfs
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param ino the inode number, zero means "undefined"
+	 */
+	void (*statfs) (fuse_req_t req, fuse_ino_t ino);
+
+	/**
+	 * Set an extended attribute
+	 *
+	 * Valid replies:
+	 *   fuse_reply_err
+	 */
+	void (*setxattr) (fuse_req_t req, fuse_ino_t ino, const char *name,
+			  const char *value, size_t size, int flags);
+
+	/**
+	 * Get an extended attribute
+	 *
+	 * If size is zero, the size of the value should be sent with
+	 * fuse_reply_xattr.
+	 *
+	 * If the size is non-zero, and the value fits in the buffer, the
+	 * value should be sent with fuse_reply_buf.
+	 *
+	 * If the size is too small for the value, the ERANGE error should
+	 * be sent.
+	 *
+	 * Valid replies:
+	 *   fuse_reply_buf
+	 *   fuse_reply_xattr
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param ino the inode number
+	 * @param name of the extended attribute
+	 * @param size maximum size of the value to send
+	 */
+	void (*getxattr) (fuse_req_t req, fuse_ino_t ino, const char *name,
+			  size_t size);
+
+	/**
+	 * List extended attribute names
+	 *
+	 * If size is zero, the total size of the attribute list should be
+	 * sent with fuse_reply_xattr.
+	 *
+	 * If the size is non-zero, and the null character separated
+	 * attribute list fits in the buffer, the list should be sent with
+	 * fuse_reply_buf.
+	 *
+	 * If the size is too small for the list, the ERANGE error should
+	 * be sent.
+	 *
+	 * Valid replies:
+	 *   fuse_reply_buf
+	 *   fuse_reply_xattr
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param ino the inode number
+	 * @param size maximum size of the list to send
+	 */
+	void (*listxattr) (fuse_req_t req, fuse_ino_t ino, size_t size);
+
+	/**
+	 * Remove an extended attribute
+	 *
+	 * Valid replies:
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param ino the inode number
+	 * @param name of the extended attribute
+	 */
+	void (*removexattr) (fuse_req_t req, fuse_ino_t ino, const char *name);
+
+	/**
+	 * 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
+	 *
+	 * Valid replies:
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param ino the inode number
+	 * @param mask requested access mode
+	 */
+	void (*access) (fuse_req_t req, fuse_ino_t ino, int mask);
+
+	/**
+	 * Create and open a file
+	 *
+	 * If the file does not exist, first create it with the specified
+	 * mode, and then open it.
+	 *
+	 * Open flags (with the exception of O_NOCTTY) are available in
+	 * fi->flags.
+	 *
+	 * Filesystem may store an arbitrary file handle (pointer, index,
+	 * etc) in fi->fh, and use this in other all other file operations
+	 * (read, write, flush, release, fsync).
+	 *
+	 * There are also some flags (direct_io, keep_cache) which the
+	 * filesystem may set in fi, to change the way the file is opened.
+	 * See fuse_file_info structure in <fuse_common.h> for more details.
+	 *
+	 * 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
+	 *
+	 * Valid replies:
+	 *   fuse_reply_create
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param parent inode number of the parent directory
+	 * @param name to create
+	 * @param mode file type and mode with which to create the new file
+	 * @param fi file information
+	 */
+	void (*create) (fuse_req_t req, fuse_ino_t parent, const char *name,
+			mode_t mode, struct fuse_file_info *fi);
+
+	/**
+	 * Test for a POSIX file lock
+	 *
+	 * Introduced in version 2.6
+	 *
+	 * Valid replies:
+	 *   fuse_reply_lock
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param ino the inode number
+	 * @param fi file information
+	 * @param lock the region/type to test
+	 */
+	void (*getlk) (fuse_req_t req, fuse_ino_t ino,
+		       struct fuse_file_info *fi, struct flock *lock);
+
+	/**
+	 * Acquire, modify or release a POSIX file lock
+	 *
+	 * For POSIX threads (NPTL) there's a 1-1 relation between pid and
+	 * owner, but otherwise this is not always the case.  For checking
+	 * lock ownership, 'fi->owner' must be used.  The l_pid field in
+	 * 'struct flock' should only be used to fill in this field in
+	 * getlk().
+	 *
+	 * Note: if the locking methods are not implemented, the kernel
+	 * will still allow file locking to work locally.  Hence these are
+	 * only interesting for network filesystems and similar.
+	 *
+	 * Introduced in version 2.6
+	 *
+	 * Valid replies:
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param ino the inode number
+	 * @param fi file information
+	 * @param lock the region/type to test
+	 * @param sleep locking operation may sleep
+	 */
+	void (*setlk) (fuse_req_t req, fuse_ino_t ino,
+		       struct fuse_file_info *fi,
+		       struct flock *lock, int sleep);
+
+	/**
+	 * 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
+	 *
+	 * Valid replies:
+	 *   fuse_reply_bmap
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param ino the inode number
+	 * @param blocksize unit of block index
+	 * @param idx block index within file
+	 */
+	void (*bmap) (fuse_req_t req, fuse_ino_t ino, size_t blocksize,
+		      uint64_t idx);
+	/**
+	 * Ioctl
+	 *
+	 * Note: For unrestricted ioctls (not allowed for FUSE
+	 * servers), data in and out areas can be discovered by giving
+	 * iovs and setting FUSE_IOCTL_RETRY in @flags.  For
+	 * restricted ioctls, kernel prepares in/out data area
+	 * according to the information encoded in cmd.
+	 *
+	 * Introduced in version 2.8
+	 *
+	 * Valid replies:
+	 *   fuse_reply_ioctl_retry
+	 *   fuse_reply_ioctl
+	 *   fuse_reply_ioctl_iov
+	 *   fuse_reply_err
+	 *
+	 * @param req request handle
+	 * @param ino the inode number
+	 * @param cmd ioctl command
+	 * @param arg ioctl argument
+	 * @param fi file information
+	 * @param flags for FUSE_IOCTL_* flags
+	 * @param in_buf data fetched from the caller
+	 * @param in_bufsz number of fetched bytes
+	 * @param out_bufsz maximum size of output data
+	 */
+	void (*ioctl) (fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
+		       struct fuse_file_info *fi, unsigned flags,
+		       const void *in_buf, size_t in_bufsz, size_t out_bufsz);
+
+};
+
+/**
+ * Reply with an error code or success
+ *
+ * Possible requests:
+ *   all except forget
+ *
+ * unlink, rmdir, rename, flush, release, fsync, fsyncdir, setxattr,
+ * removexattr and setlk may send a zero code
+ *
+ * @param req request handle
+ * @param err the positive error value, or zero for success
+ * @return zero for success, -errno for failure to send reply
+ */
+int fuse_reply_err(fuse_req_t req, int err);
+
+/**
+ * Don't send reply
+ *
+ * Possible requests:
+ *   forget
+ *
+ * @param req request handle
+ */
+void fuse_reply_none(fuse_req_t req);
+
+/**
+ * Reply with a directory entry
+ *
+ * Possible requests:
+ *   lookup, mknod, mkdir, symlink, link
+ *
+ * @param req request handle
+ * @param e the entry parameters
+ * @return zero for success, -errno for failure to send reply
+ */
+int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e);
+
+/**
+ * Reply with a directory entry and open parameters
+ *
+ * currently the following members of 'fi' are used:
+ *   fh, direct_io, keep_cache
+ *
+ * Possible requests:
+ *   create
+ *
+ * @param req request handle
+ * @param e the entry parameters
+ * @param fi file information
+ * @return zero for success, -errno for failure to send reply
+ */
+int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e,
+		      const struct fuse_file_info *fi);
+
+/**
+ * Reply with attributes
+ *
+ * Possible requests:
+ *   getattr, setattr
+ *
+ * @param req request handle
+ * @param the attributes
+ * @param attr_timeout	validity timeout (in seconds) for the attributes
+ * @return zero for success, -errno for failure to send reply
+ */
+int fuse_reply_attr(fuse_req_t req, const struct stat *attr,
+		    double attr_timeout);
+
+/**
+ * Reply with the contents of a symbolic link
+ *
+ * Possible requests:
+ *   readlink
+ *
+ * @param req request handle
+ * @param link symbolic link contents
+ * @return zero for success, -errno for failure to send reply
+ */
+int fuse_reply_readlink(fuse_req_t req, const char *link);
+
+/**
+ * Reply with open parameters
+ *
+ * currently the following members of 'fi' are used:
+ *   fh, direct_io, keep_cache
+ *
+ * Possible requests:
+ *   open, opendir
+ *
+ * @param req request handle
+ * @param fi file information
+ * @return zero for success, -errno for failure to send reply
+ */
+int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *fi);
+
+/**
+ * Reply with number of bytes written
+ *
+ * Possible requests:
+ *   write
+ *
+ * @param req request handle
+ * @param count the number of bytes written
+ * @return zero for success, -errno for failure to send reply
+ */
+int fuse_reply_write(fuse_req_t req, size_t count);
+
+/**
+ * Reply with data
+ *
+ * Possible requests:
+ *   read, readdir, getxattr, listxattr
+ *
+ * @param req request handle
+ * @param buf buffer containing data
+ * @param size the size of data in bytes
+ * @return zero for success, -errno for failure to send reply
+ */
+int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size);
+
+#ifdef POSIXACLS
+/**
+ * Reply with data vector
+ *
+ * Possible requests:
+ *   read, readdir, getxattr, listxattr
+ *
+ * @param req request handle
+ * @param iov the vector containing the data
+ * @param count the size of vector
+ * @return zero for success, -errno for failure to send reply
+ */
+int fuse_reply_iov(fuse_req_t req, const struct iovec *iov, int count);
+#endif
+
+/**
+ * Reply with filesystem statistics
+ *
+ * Possible requests:
+ *   statfs
+ *
+ * @param req request handle
+ * @param stbuf filesystem statistics
+ * @return zero for success, -errno for failure to send reply
+ */
+int fuse_reply_statfs(fuse_req_t req, const struct statvfs *stbuf);
+
+/**
+ * Reply with needed buffer size
+ *
+ * Possible requests:
+ *   getxattr, listxattr
+ *
+ * @param req request handle
+ * @param count the buffer size needed in bytes
+ * @return zero for success, -errno for failure to send reply
+ */
+int fuse_reply_xattr(fuse_req_t req, size_t count);
+
+/**
+ * Reply with file lock information
+ *
+ * Possible requests:
+ *   getlk
+ *
+ * @param req request handle
+ * @param lock the lock information
+ * @return zero for success, -errno for failure to send reply
+ */
+int fuse_reply_lock(fuse_req_t req, struct flock *lock);
+
+/**
+ * Reply with block index
+ *
+ * Possible requests:
+ *   bmap
+ *
+ * @param req request handle
+ * @param idx block index within device
+ * @return zero for success, -errno for failure to send reply
+ */
+int fuse_reply_bmap(fuse_req_t req, uint64_t idx);
+
+/* ----------------------------------------------------------- *
+ * Filling a buffer in readdir				       *
+ * ----------------------------------------------------------- */
+
+/**
+ * Add a directory entry to the buffer
+ *
+ * Buffer needs to be large enough to hold the entry.  Of it's not,
+ * then the entry is not filled in but the size of the entry is still
+ * returned.  The caller can check this by comparing the bufsize
+ * parameter with the returned entry size.  If the entry size is
+ * larger than the buffer size, the operation failed.
+ *
+ * From the 'stbuf' argument the st_ino field and bits 12-15 of the
+ * st_mode field are used.  The other fields are ignored.
+ *
+ * Note: offsets do not necessarily represent physical offsets, and
+ * could be any marker, that enables the implementation to find a
+ * specific point in the directory stream.
+ *
+ * @param req request handle
+ * @param buf the point where the new entry will be added to the buffer
+ * @param bufsize remaining size of the buffer
+ * @param the name of the entry
+ * @param stbuf the file attributes
+ * @param off the offset of the next entry
+ * @return the space needed for the entry
+ */
+size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize,
+			 const char *name, const struct stat *stbuf,
+			 off_t off);
+
+/**
+ * Reply to finish ioctl
+ *
+ * Possible requests:
+ * ioctl
+ *
+ * @param req request handle
+ * @param result result to be passed to the caller
+ * @param buf buffer containing output data
+ * @param size length of output data
+ */
+int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size);
+
+
+/* ----------------------------------------------------------- *
+ * Utility functions					       *
+ * ----------------------------------------------------------- */
+
+/**
+ * Get the userdata from the request
+ *
+ * @param req request handle
+ * @return the user data passed to fuse_lowlevel_new()
+ */
+void *fuse_req_userdata(fuse_req_t req);
+
+/**
+ * Get the context from the request
+ *
+ * The pointer returned by this function will only be valid for the
+ * request's lifetime
+ *
+ * @param req request handle
+ * @return the context structure
+ */
+const struct fuse_ctx *fuse_req_ctx(fuse_req_t req);
+
+/**
+ * Callback function for an interrupt
+ *
+ * @param req interrupted request
+ * @param data user data
+ */
+typedef void (*fuse_interrupt_func_t)(fuse_req_t req, void *data);
+
+/**
+ * Register/unregister callback for an interrupt
+ *
+ * If an interrupt has already happened, then the callback function is
+ * called from within this function, hence it's not possible for
+ * interrupts to be lost.
+ *
+ * @param req request handle
+ * @param func the callback function or NULL for unregister
+ * @parm data user data passed to the callback function
+ */
+void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func,
+			     void *data);
+
+/**
+ * Check if a request has already been interrupted
+ *
+ * @param req request handle
+ * @return 1 if the request has been interrupted, 0 otherwise
+ */
+int fuse_req_interrupted(fuse_req_t req);
+
+/* ----------------------------------------------------------- *
+ * Filesystem setup					       *
+ * ----------------------------------------------------------- */
+
+#ifdef __SOLARIS__
+
+/* Deprecated, don't use */
+int fuse_lowlevel_is_lib_option(const char *opt);
+
+#endif /* __SOLARIS__ */
+
+/**
+ * Create a low level session
+ *
+ * @param args argument vector
+ * @param op the low level filesystem operations
+ * @param op_size sizeof(struct fuse_lowlevel_ops)
+ * @param userdata user data
+ * @return the created session object, or NULL on failure
+ */
+struct fuse_session *fuse_lowlevel_new(struct fuse_args *args,
+				       const struct fuse_lowlevel_ops *op,
+				       size_t op_size, void *userdata);
+
+/* ----------------------------------------------------------- *
+ * Session interface					       *
+ * ----------------------------------------------------------- */
+
+/**
+ * Session operations
+ *
+ * This is used in session creation
+ */
+struct fuse_session_ops {
+	/**
+	 * Hook to process a request (mandatory)
+	 *
+	 * @param data user data passed to fuse_session_new()
+	 * @param buf buffer containing the raw request
+	 * @param len request length
+	 * @param ch channel on which the request was received
+	 */
+	void (*process) (void *data, const char *buf, size_t len,
+			 struct fuse_chan *ch);
+
+	/**
+	 * Hook for session exit and reset (optional)
+	 *
+	 * @param data user data passed to fuse_session_new()
+	 * @param val exited status (1 - exited, 0 - not exited)
+	 */
+	void (*exit) (void *data, int val);
+
+	/**
+	 * Hook for querying the current exited status (optional)
+	 *
+	 * @param data user data passed to fuse_session_new()
+	 * @return 1 if exited, 0 if not exited
+	 */
+	int (*exited) (void *data);
+
+	/**
+	 * Hook for cleaning up the channel on destroy (optional)
+	 *
+	 * @param data user data passed to fuse_session_new()
+	 */
+	void (*destroy) (void *data);
+};
+
+/**
+ * Create a new session
+ *
+ * @param op session operations
+ * @param data user data
+ * @return new session object, or NULL on failure
+ */
+struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data);
+
+/**
+ * Assign a channel to a session
+ *
+ * Note: currently only a single channel may be assigned.  This may
+ * change in the future
+ *
+ * If a session is destroyed, the assigned channel is also destroyed
+ *
+ * @param se the session
+ * @param ch the channel
+ */
+void fuse_session_add_chan(struct fuse_session *se, struct fuse_chan *ch);
+
+/**
+ * Remove a channel from a session
+ *
+ * If the channel is not assigned to a session, then this is a no-op
+ *
+ * @param ch the channel to remove
+ */
+void fuse_session_remove_chan(struct fuse_chan *ch);
+
+/**
+ * Iterate over the channels assigned to a session
+ *
+ * The iterating function needs to start with a NULL channel, and
+ * after that needs to pass the previously returned channel to the
+ * function.
+ *
+ * @param se the session
+ * @param ch the previous channel, or NULL
+ * @return the next channel, or NULL if no more channels exist
+ */
+struct fuse_chan *fuse_session_next_chan(struct fuse_session *se,
+					 struct fuse_chan *ch);
+
+/**
+ * Process a raw request
+ *
+ * @param se the session
+ * @param buf buffer containing the raw request
+ * @param len request length
+ * @param ch channel on which the request was received
+ */
+void fuse_session_process(struct fuse_session *se, const char *buf, size_t len,
+			  struct fuse_chan *ch);
+
+/**
+ * Destroy a session
+ *
+ * @param se the session
+ */
+void fuse_session_destroy(struct fuse_session *se);
+
+/**
+ * Exit a session
+ *
+ * @param se the session
+ */
+void fuse_session_exit(struct fuse_session *se);
+
+/**
+ * Reset the exited status of a session
+ *
+ * @param se the session
+ */
+void fuse_session_reset(struct fuse_session *se);
+
+/**
+ * Query the exited status of a session
+ *
+ * @param se the session
+ * @return 1 if exited, 0 if not exited
+ */
+int fuse_session_exited(struct fuse_session *se);
+
+/**
+ * Enter a single threaded event loop
+ *
+ * @param se the session
+ * @return 0 on success, -1 on error
+ */
+int fuse_session_loop(struct fuse_session *se);
+
+/**
+ * Enter a multi-threaded event loop
+ *
+ * @param se the session
+ * @return 0 on success, -1 on error
+ */
+int fuse_session_loop_mt(struct fuse_session *se);
+
+/* ----------------------------------------------------------- *
+ * Channel interface					       *
+ * ----------------------------------------------------------- */
+
+/**
+ * Channel operations
+ *
+ * This is used in channel creation
+ */
+struct fuse_chan_ops {
+	/**
+	 * Hook for receiving a raw request
+	 *
+	 * @param ch pointer to the channel
+	 * @param buf the buffer to store the request in
+	 * @param size the size of the buffer
+	 * @return the actual size of the raw request, or -1 on error
+	 */
+	int (*receive)(struct fuse_chan **chp, char *buf, size_t size);
+
+	/**
+	 * Hook for sending a raw reply
+	 *
+	 * A return value of -ENOENT means, that the request was
+	 * interrupted, and the reply was discarded
+	 *
+	 * @param ch the channel
+	 * @param iov vector of blocks
+	 * @param count the number of blocks in vector
+	 * @return zero on success, -errno on failure
+	 */
+	int (*send)(struct fuse_chan *ch, const struct iovec iov[],
+		    size_t count);
+
+	/**
+	 * Destroy the channel
+	 *
+	 * @param ch the channel
+	 */
+	void (*destroy)(struct fuse_chan *ch);
+};
+
+/**
+ * Create a new channel
+ *
+ * @param op channel operations
+ * @param fd file descriptor of the channel
+ * @param bufsize the minimal receive buffer size
+ * @param data user data
+ * @return the new channel object, or NULL on failure
+ */
+struct fuse_chan *fuse_chan_new(struct fuse_chan_ops *op, int fd,
+				size_t bufsize, void *data);
+
+/**
+ * Query the file descriptor of the channel
+ *
+ * @param ch the channel
+ * @return the file descriptor passed to fuse_chan_new()
+ */
+int fuse_chan_fd(struct fuse_chan *ch);
+
+/**
+ * Query the minimal receive buffer size
+ *
+ * @param ch the channel
+ * @return the buffer size passed to fuse_chan_new()
+ */
+size_t fuse_chan_bufsize(struct fuse_chan *ch);
+
+/**
+ * Query the user data
+ *
+ * @param ch the channel
+ * @return the user data passed to fuse_chan_new()
+ */
+void *fuse_chan_data(struct fuse_chan *ch);
+
+/**
+ * Query the session to which this channel is assigned
+ *
+ * @param ch the channel
+ * @return the session, or NULL if the channel is not assigned
+ */
+struct fuse_session *fuse_chan_session(struct fuse_chan *ch);
+
+/**
+ * Receive a raw request
+ *
+ * A return value of -ENODEV means, that the filesystem was unmounted
+ *
+ * @param ch pointer to the channel
+ * @param buf the buffer to store the request in
+ * @param size the size of the buffer
+ * @return the actual size of the raw request, or -errno on error
+ */
+int fuse_chan_recv(struct fuse_chan **ch, char *buf, size_t size);
+
+/**
+ * Send a raw reply
+ *
+ * A return value of -ENOENT means, that the request was
+ * interrupted, and the reply was discarded
+ *
+ * @param ch the channel
+ * @param iov vector of blocks
+ * @param count the number of blocks in vector
+ * @return zero on success, -errno on failure
+ */
+int fuse_chan_send(struct fuse_chan *ch, const struct iovec iov[],
+		   size_t count);
+
+/**
+ * Destroy a channel
+ *
+ * @param ch the channel
+ */
+void fuse_chan_destroy(struct fuse_chan *ch);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FUSE_LOWLEVEL_H_ */
diff --git a/include/fuse-lite/fuse_lowlevel_compat.h b/include/fuse-lite/fuse_lowlevel_compat.h
new file mode 100755
index 0000000000000000000000000000000000000000..753d46bc9097e47e61e5d83d8c7e3457bffb1459
--- /dev/null
+++ b/include/fuse-lite/fuse_lowlevel_compat.h
@@ -0,0 +1,16 @@
+/*
+  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);
+
diff --git a/include/fuse-lite/fuse_opt.h b/include/fuse-lite/fuse_opt.h
new file mode 100755
index 0000000000000000000000000000000000000000..7ae08af647416daddaa17c454f612cd764e7a710
--- /dev/null
+++ b/include/fuse-lite/fuse_opt.h
@@ -0,0 +1,261 @@
+/*
+  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_ */
diff --git a/include/ntfs-3g/Makefile b/include/ntfs-3g/Makefile
new file mode 100755
index 0000000000000000000000000000000000000000..e526b297da62fe2ecd002ce0799a3577decddf7e
--- /dev/null
+++ b/include/ntfs-3g/Makefile
@@ -0,0 +1,635 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# include/ntfs-3g/Makefile.  Generated from Makefile.in by configure.
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/ntfs-3g
+pkgincludedir = $(includedir)/ntfs-3g
+pkglibdir = $(libdir)/ntfs-3g
+pkglibexecdir = $(libexecdir)/ntfs-3g
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = x86_64-unknown-linux-gnu
+host_triplet = x86_64-unknown-linux-gnu
+target_triplet = x86_64-unknown-linux-gnu
+subdir = include/ntfs-3g
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+	$(am__noinst_HEADERS_DIST) $(am__ntfs3ginclude_HEADERS_DIST)
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_$(V))
+am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY))
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__noinst_HEADERS_DIST = 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 realpath.h \
+	reparse.h runlist.h security.h support.h types.h unistr.h \
+	volume.h xattrs.h
+am__ntfs3ginclude_HEADERS_DIST = 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 realpath.h \
+	reparse.h runlist.h security.h support.h types.h unistr.h \
+	volume.h xattrs.h
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+am__installdirs = "$(DESTDIR)$(ntfs3gincludedir)"
+HEADERS = $(noinst_HEADERS) $(ntfs3ginclude_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = ${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing aclocal-1.14
+AMTAR = $${TAR-tar}
+AM_DEFAULT_VERBOSITY = 1
+AR = ar
+AUTOCONF = ${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing autoconf
+AUTOHEADER = ${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing autoheader
+AUTOMAKE = ${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing automake-1.14
+AWK = gawk
+CC = gcc
+CCDEPMODE = depmode=gcc3
+CFLAGS = -g -O2 -Wall
+CPP = gcc -E
+CPPFLAGS = 
+CYGPATH_W = echo
+DEFS = -DHAVE_CONFIG_H
+DEPDIR = .deps
+DLLTOOL = false
+DSYMUTIL = 
+DUMPBIN = 
+ECHO_C = 
+ECHO_N = -n
+ECHO_T = 
+EGREP = /bin/grep -E
+EXEEXT = 
+FGREP = /bin/grep -F
+FUSE_MODULE_CFLAGS = 
+FUSE_MODULE_LIBS = 
+GNUTLS_CFLAGS = 
+GNUTLS_LIBS = 
+GREP = /bin/grep
+INSTALL = /usr/bin/install -c
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
+LD = /usr/bin/ld -m elf_x86_64
+LDCONFIG = /sbin/ldconfig
+LDFLAGS = 
+LIBFUSE_LITE_CFLAGS = 
+LIBFUSE_LITE_LIBS =  -lpthread
+LIBGCRYPT_CFLAGS = 
+LIBGCRYPT_CONFIG = 
+LIBGCRYPT_LIBS = 
+LIBNTFS_3G_VERSION = 86
+LIBNTFS_CPPFLAGS = 
+LIBNTFS_LIBS = 
+LIBOBJS = 
+LIBS = 
+LIBTOOL = $(SHELL) $(top_builddir)/libtool
+LIPO = 
+LN_S = ln -s
+LTLIBOBJS = 
+MAINT = #
+MAKEINFO = ${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing makeinfo
+MANIFEST_TOOL = :
+MKDIR_P = /bin/mkdir -p
+MKNTFS_CPPFLAGS = 
+MKNTFS_LIBS = 
+MV = /bin/mv
+NM = /usr/bin/nm -B
+NMEDIT = 
+NTFSPROGS_STATIC_LIBS = 
+OBJDUMP = objdump
+OBJEXT = o
+OTOOL = 
+OTOOL64 = 
+OUTPUT_FORMAT = 
+PACKAGE = ntfs-3g
+PACKAGE_BUGREPORT = ntfs-3g-devel@lists.sf.net
+PACKAGE_NAME = ntfs-3g
+PACKAGE_STRING = ntfs-3g 2015.3.14
+PACKAGE_TARNAME = ntfs-3g
+PACKAGE_URL = 
+PACKAGE_VERSION = 2015.3.14
+PATH_SEPARATOR = :
+PKG_CONFIG = /usr/bin/pkg-config
+PKG_CONFIG_LIBDIR = 
+PKG_CONFIG_PATH = 
+RANLIB = ranlib
+RM = /bin/rm
+SED = /bin/sed
+SET_MAKE = 
+SHELL = /bin/bash
+STRIP = strip
+VERSION = 2015.3.14
+abs_builddir = /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/include/ntfs-3g
+abs_srcdir = /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/include/ntfs-3g
+abs_top_builddir = /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14
+abs_top_srcdir = /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14
+ac_ct_AR = ar
+ac_ct_CC = gcc
+ac_ct_DUMPBIN = 
+all_includes =  
+all_libraries =  
+am__include = include
+am__leading_dot = .
+am__quote = 
+am__tar = $${TAR-tar} chof - "$$tardir"
+am__untar = $${TAR-tar} xf -
+bindir = ${exec_prefix}/bin
+build = x86_64-unknown-linux-gnu
+build_alias = 
+build_cpu = x86_64
+build_os = linux-gnu
+build_vendor = unknown
+builddir = .
+datadir = ${datarootdir}
+datarootdir = ${prefix}/share
+docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
+dvidir = ${docdir}
+exec_prefix = ${prefix}
+host = x86_64-unknown-linux-gnu
+host_alias = 
+host_cpu = x86_64
+host_os = linux-gnu
+host_vendor = unknown
+htmldir = ${docdir}
+includedir = ${prefix}/include
+infodir = ${datarootdir}/info
+install_sh = ${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localedir = ${datarootdir}/locale
+localstatedir = ${prefix}/var
+mandir = ${datarootdir}/man
+mkdir_p = $(MKDIR_P)
+ntfs3gincludedir = $(includedir)/ntfs-3g
+oldincludedir = /usr/include
+pdfdir = ${docdir}
+pkgconfigdir = $(libdir)/pkgconfig
+prefix = /usr/local
+program_transform_name = s,x,x,
+psdir = ${docdir}
+rootbindir = /bin
+rootlibdir = /lib
+rootsbindir = /sbin
+sbindir = ${exec_prefix}/sbin
+sharedstatedir = ${prefix}/com
+srcdir = .
+sysconfdir = ${prefix}/etc
+target = x86_64-unknown-linux-gnu
+target_alias = 
+target_cpu = x86_64
+target_os = linux-gnu
+target_vendor = unknown
+top_build_prefix = ../../
+top_builddir = ../..
+top_srcdir = ../..
+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	\
+	realpath.h	\
+	reparse.h	\
+	runlist.h	\
+	security.h	\
+	support.h	\
+	types.h		\
+	unistr.h	\
+	volume.h 	\
+	xattrs.h
+
+ntfs3ginclude_HEADERS = $(headers)
+#noinst_HEADERS = $(headers)
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: # $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/ntfs-3g/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu include/ntfs-3g/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: # $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): # $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+install-ntfs3gincludeHEADERS: $(ntfs3ginclude_HEADERS)
+	@$(NORMAL_INSTALL)
+	@list='$(ntfs3ginclude_HEADERS)'; test -n "$(ntfs3gincludedir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(ntfs3gincludedir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(ntfs3gincludedir)" || exit 1; \
+	fi; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(ntfs3gincludedir)'"; \
+	  $(INSTALL_HEADER) $$files "$(DESTDIR)$(ntfs3gincludedir)" || exit $$?; \
+	done
+
+uninstall-ntfs3gincludeHEADERS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(ntfs3ginclude_HEADERS)'; test -n "$(ntfs3gincludedir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	dir='$(DESTDIR)$(ntfs3gincludedir)'; $(am__uninstall_files_from_dir)
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(HEADERS)
+installdirs:
+	for dir in "$(DESTDIR)$(ntfs3gincludedir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-ntfs3gincludeHEADERS
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-ntfs3gincludeHEADERS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+	clean-libtool cscopelist-am ctags ctags-am distclean \
+	distclean-generic distclean-libtool distclean-tags distdir dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-data install-data-am install-dvi install-dvi-am \
+	install-exec install-exec-am install-html install-html-am \
+	install-info install-info-am install-man \
+	install-ntfs3gincludeHEADERS install-pdf install-pdf-am \
+	install-ps install-ps-am install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-generic \
+	mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+	uninstall-am uninstall-ntfs3gincludeHEADERS
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/include/ntfs-3g/Makefile.am b/include/ntfs-3g/Makefile.am
new file mode 100755
index 0000000000000000000000000000000000000000..11761bcbfd731d8cc2b6ddbb330b5717ef51c4ff
--- /dev/null
+++ b/include/ntfs-3g/Makefile.am
@@ -0,0 +1,49 @@
+
+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	\
+	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
+
diff --git a/include/ntfs-3g/Makefile.in b/include/ntfs-3g/Makefile.in
new file mode 100755
index 0000000000000000000000000000000000000000..13a5bcda14d757b9aa7935647774425565616b8a
--- /dev/null
+++ b/include/ntfs-3g/Makefile.in
@@ -0,0 +1,635 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = include/ntfs-3g
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+	$(am__noinst_HEADERS_DIST) $(am__ntfs3ginclude_HEADERS_DIST)
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__noinst_HEADERS_DIST = 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 realpath.h \
+	reparse.h runlist.h security.h support.h types.h unistr.h \
+	volume.h xattrs.h
+am__ntfs3ginclude_HEADERS_DIST = 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 realpath.h \
+	reparse.h runlist.h security.h support.h types.h unistr.h \
+	volume.h xattrs.h
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+am__installdirs = "$(DESTDIR)$(ntfs3gincludedir)"
+HEADERS = $(noinst_HEADERS) $(ntfs3ginclude_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FUSE_MODULE_CFLAGS = @FUSE_MODULE_CFLAGS@
+FUSE_MODULE_LIBS = @FUSE_MODULE_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDCONFIG = @LDCONFIG@
+LDFLAGS = @LDFLAGS@
+LIBFUSE_LITE_CFLAGS = @LIBFUSE_LITE_CFLAGS@
+LIBFUSE_LITE_LIBS = @LIBFUSE_LITE_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBNTFS_3G_VERSION = @LIBNTFS_3G_VERSION@
+LIBNTFS_CPPFLAGS = @LIBNTFS_CPPFLAGS@
+LIBNTFS_LIBS = @LIBNTFS_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MKNTFS_CPPFLAGS = @MKNTFS_CPPFLAGS@
+MKNTFS_LIBS = @MKNTFS_LIBS@
+MV = @MV@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NTFSPROGS_STATIC_LIBS = @NTFSPROGS_STATIC_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+OUTPUT_FORMAT = @OUTPUT_FORMAT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+RM = @RM@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+all_includes = @all_includes@
+all_libraries = @all_libraries@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+ntfs3gincludedir = @ntfs3gincludedir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgconfigdir = @pkgconfigdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+rootbindir = @rootbindir@
+rootlibdir = @rootlibdir@
+rootsbindir = @rootsbindir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+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	\
+	realpath.h	\
+	reparse.h	\
+	runlist.h	\
+	security.h	\
+	support.h	\
+	types.h		\
+	unistr.h	\
+	volume.h 	\
+	xattrs.h
+
+@INSTALL_LIBRARY_TRUE@ntfs3ginclude_HEADERS = $(headers)
+@INSTALL_LIBRARY_FALSE@noinst_HEADERS = $(headers)
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/ntfs-3g/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu include/ntfs-3g/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+install-ntfs3gincludeHEADERS: $(ntfs3ginclude_HEADERS)
+	@$(NORMAL_INSTALL)
+	@list='$(ntfs3ginclude_HEADERS)'; test -n "$(ntfs3gincludedir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(ntfs3gincludedir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(ntfs3gincludedir)" || exit 1; \
+	fi; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(ntfs3gincludedir)'"; \
+	  $(INSTALL_HEADER) $$files "$(DESTDIR)$(ntfs3gincludedir)" || exit $$?; \
+	done
+
+uninstall-ntfs3gincludeHEADERS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(ntfs3ginclude_HEADERS)'; test -n "$(ntfs3gincludedir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	dir='$(DESTDIR)$(ntfs3gincludedir)'; $(am__uninstall_files_from_dir)
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(HEADERS)
+installdirs:
+	for dir in "$(DESTDIR)$(ntfs3gincludedir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-ntfs3gincludeHEADERS
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-ntfs3gincludeHEADERS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+	clean-libtool cscopelist-am ctags ctags-am distclean \
+	distclean-generic distclean-libtool distclean-tags distdir dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-data install-data-am install-dvi install-dvi-am \
+	install-exec install-exec-am install-html install-html-am \
+	install-info install-info-am install-man \
+	install-ntfs3gincludeHEADERS install-pdf install-pdf-am \
+	install-ps install-ps-am install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-generic \
+	mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+	uninstall-am uninstall-ntfs3gincludeHEADERS
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/include/ntfs-3g/acls.h b/include/ntfs-3g/acls.h
new file mode 100755
index 0000000000000000000000000000000000000000..38d2cd64a8587ea24885f84de8e94b3dd5b1ffe7
--- /dev/null
+++ b/include/ntfs-3g/acls.h
@@ -0,0 +1,203 @@
+/*
+ *
+ * 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
+
+/*
+ *	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 */
+
+/*
+ *	JPA The following must be in some library...
+ *	but did not found out where
+ */
+
+#define endian_rev16(x) (((x >> 8) & 255) | ((x & 255) << 8))
+#define endian_rev32(x) (((x >> 24) & 255) | ((x >> 8) & 0xff00) \
+		| ((x & 0xff00) << 8) | ((x & 255) << 24))
+
+#define cpu_to_be16(x) endian_rev16(cpu_to_le16(x))
+#define cpu_to_be32(x) endian_rev32(cpu_to_le32(x))
+
+/*
+ *		Macro definitions needed to share code with secaudit
+ */
+
+#define NTFS_FIND_USID(map,uid,buf) ntfs_find_usid(map,uid,buf)
+#define NTFS_FIND_GSID(map,gid,buf) ntfs_find_gsid(map,gid,buf)
+#define NTFS_FIND_USER(map,usid) ntfs_find_user(map,usid)
+#define NTFS_FIND_GROUP(map,gsid) ntfs_find_group(map,gsid)
+
+
+/*
+ *		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 */
+
+/*
+ *		A type large enough to hold any SID
+ */
+
+typedef char BIGSID[40];
+
+/*
+ *		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 */
+
diff --git a/include/ntfs-3g/attrib.h b/include/ntfs-3g/attrib.h
new file mode 100755
index 0000000000000000000000000000000000000000..b3752a608bc2fd1f879896d4ae79346aa2d06e26
--- /dev/null
+++ b/include/ntfs-3g/attrib.h
@@ -0,0 +1,403 @@
+/*
+ * attrib.h - Exports for attribute handling. Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2000-2004 Anton Altaparmakov
+ * Copyright (c) 2004-2005 Yura Pakhuchiy
+ * Copyright (c) 2006-2007 Szabolcs Szakacsits
+ * 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_ATTRIB_H
+#define _NTFS_ATTRIB_H
+
+/* Forward declarations */
+typedef struct _ntfs_attr ntfs_attr;
+typedef struct _ntfs_attr_search_ctx ntfs_attr_search_ctx;
+
+#include "types.h"
+#include "inode.h"
+#include "unistr.h"
+#include "runlist.h"
+#include "volume.h"
+#include "debug.h"
+#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()
+ *
+ * Special return values for ntfs_rl_vcn_to_lcn() and ntfs_attr_vcn_to_lcn().
+ *
+ * TODO: Describe them.
+ */
+typedef enum {
+	LCN_HOLE		= -1,	/* Keep this as highest value or die! */
+	LCN_RL_NOT_MAPPED	= -2,
+	LCN_ENOENT		= -3,
+	LCN_EINVAL		= -4,
+	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
+ * @attr:	attribute record in @mrec where to begin/continue search
+ * @is_first:	if true lookup_attr() begins search with @attr, else after @attr
+ *
+ * Structure must be initialized to zero before the first call to one of the
+ * attribute search functions. Initialize @mrec to point to the mft record to
+ * search, and @attr to point to the first attribute within @mrec (not necessary
+ * if calling the _first() functions), and set @is_first to TRUE (not necessary
+ * if calling the _first() functions).
+ *
+ * If @is_first is TRUE, the search begins with @attr. If @is_first is FALSE,
+ * the search begins after @attr. This is so that, after the first call to one
+ * of the search attribute functions, we can call the function again, without
+ * any modification of the search context, to automagically get the next
+ * matching attribute.
+ */
+struct _ntfs_attr_search_ctx {
+	MFT_RECORD *mrec;
+	ATTR_RECORD *attr;
+	BOOL is_first;
+	ntfs_inode *ntfs_ino;
+	ATTR_LIST_ENTRY *al_entry;
+	ntfs_inode *base_ntfs_ino;
+	MFT_RECORD *base_mrec;
+	ATTR_RECORD *base_attr;
+};
+
+extern void ntfs_attr_reinit_search_ctx(ntfs_attr_search_ctx *ctx);
+extern ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(ntfs_inode *ni,
+		MFT_RECORD *mrec);
+extern void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx);
+
+extern int ntfs_attr_lookup(const ATTR_TYPES type, const ntfschar *name,
+		const u32 name_len, const IGNORE_CASE_BOOL ic,
+		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);
+
+/**
+ * ntfs_attrs_walk - syntactic sugar for walking all attributes in an inode
+ * @ctx:	initialised attribute search context
+ *
+ * Syntactic sugar for walking attributes in an inode.
+ *
+ * Return 0 on success and -1 on error with errno set to the error code from
+ * ntfs_attr_lookup().
+ *
+ * Example: When you want to enumerate all attributes in an open ntfs inode
+ *	    @ni, you can simply do:
+ *
+ *	int err;
+ *	ntfs_attr_search_ctx *ctx = ntfs_attr_get_search_ctx(ni, NULL);
+ *	if (!ctx)
+ *		// Error code is in errno. Handle this case.
+ *	while (!(err = ntfs_attrs_walk(ctx))) {
+ *		ATTR_RECORD *attr = ctx->attr;
+ *		// attr now contains the next attribute. Do whatever you want
+ *		// with it and then just continue with the while loop.
+ *	}
+ *	if (err && errno != ENOENT)
+ *		// Ooops. An error occurred! You should handle this case.
+ *	// Now finished with all attributes in the inode.
+ */
+static __inline__ int ntfs_attrs_walk(ntfs_attr_search_ctx *ctx)
+{
+	return ntfs_attr_lookup(AT_UNUSED, NULL, 0, CASE_SENSITIVE, 0,
+			NULL, 0, ctx);
+}
+
+/**
+ * struct ntfs_attr - ntfs in memory non-resident attribute structure
+ * @rl:			if not NULL, the decompressed runlist
+ * @ni:			base ntfs inode to which this attribute belongs
+ * @type:		attribute type
+ * @name:		Unicode name of the attribute
+ * @name_len:		length of @name in Unicode characters
+ * @state:		NTFS attribute specific flags describing this attribute
+ * @allocated_size:	copy from the attribute record
+ * @data_size:		copy from the attribute record
+ * @initialized_size:	copy from the attribute record
+ * @compressed_size:	copy from the attribute record
+ * @compression_block_size:		size of a compression block (cb)
+ * @compression_block_size_bits:	log2 of the size of a cb
+ * @compression_block_clusters:		number of clusters per cb
+ *
+ * This structure exists purely to provide a mechanism of caching the runlist
+ * of an attribute. If you want to operate on a particular attribute extent,
+ * you should not be using this structure at all. If you want to work with a
+ * resident attribute, you should not be using this structure at all. As a
+ * fail-safe check make sure to test NAttrNonResident() and if it is false, you
+ * know you shouldn't be using this structure.
+ *
+ * If you want to work on a resident attribute or on a specific attribute
+ * extent, you should use ntfs_lookup_attr() to retrieve the attribute (extent)
+ * record, edit that, and then write back the mft record (or set the
+ * corresponding ntfs inode dirty for delayed write back).
+ *
+ * @rl is the decompressed runlist of the attribute described by this
+ * structure. Obviously this only makes sense if the attribute is not resident,
+ * i.e. NAttrNonResident() is true. If the runlist hasn't been decompressed yet
+ * @rl is NULL, so be prepared to cope with @rl == NULL.
+ *
+ * @ni is the base ntfs inode of the attribute described by this structure.
+ *
+ * @type is the attribute type (see layout.h for the definition of ATTR_TYPES),
+ * @name and @name_len are the little endian Unicode name and the name length
+ * in Unicode characters of the attribute, respectively.
+ *
+ * @state contains NTFS attribute specific flags describing this attribute
+ * structure. See ntfs_attr_state_bits above.
+ */
+struct _ntfs_attr {
+	runlist_element *rl;
+	ntfs_inode *ni;
+	ATTR_TYPES type;
+	ATTR_FLAGS data_flags;
+	ntfschar *name;
+	u32 name_len;
+	unsigned long state;
+	s64 allocated_size;
+	s64 data_size;
+	s64 initialized_size;
+	s64 compressed_size;
+	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
+ */
+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)
+#define   set_nattr_flag(na, flag)	  set_bit(NA_##flag, (na)->state)
+#define clear_nattr_flag(na, flag)	clear_bit(NA_##flag, (na)->state)
+
+#define NAttrInitialized(na)		 test_nattr_flag(na, Initialized)
+#define NAttrSetInitialized(na)		  set_nattr_flag(na, Initialized)
+#define NAttrClearInitialized(na)	clear_nattr_flag(na, Initialized)
+
+#define NAttrNonResident(na)		 test_nattr_flag(na, NonResident)
+#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 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
+
+/**
+ * union attr_val - Union of all known attribute values
+ *
+ * For convenience. Used in the attr structure.
+ */
+typedef union {
+	u8 _default;	/* Unnamed u8 to serve as default when just using
+			   a_val without specifying any of the below. */
+	STANDARD_INFORMATION std_inf;
+	ATTR_LIST_ENTRY al_entry;
+	FILE_NAME_ATTR filename;
+	OBJECT_ID_ATTR obj_id;
+	SECURITY_DESCRIPTOR_ATTR sec_desc;
+	VOLUME_NAME vol_name;
+	VOLUME_INFORMATION vol_inf;
+	DATA_ATTR data;
+	INDEX_ROOT index_root;
+	INDEX_BLOCK index_blk;
+	BITMAP_ATTR bmp;
+	REPARSE_POINT reparse;
+	EA_INFORMATION ea_inf;
+	EA_ATTR ea;
+	PROPERTY_SET property_set;
+	LOGGED_UTILITY_STREAM logged_util_stream;
+	EFS_ATTR_HEADER efs;
+} 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 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);
+
+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);
+
+extern s64 ntfs_attr_mst_pread(ntfs_attr *na, const s64 pos,
+		const s64 bk_cnt, const u32 bk_size, void *dst);
+extern s64 ntfs_attr_mst_pwrite(ntfs_attr *na, const s64 pos,
+		s64 bk_cnt, const u32 bk_size, void *src);
+
+extern int ntfs_attr_map_runlist(ntfs_attr *na, VCN vcn);
+extern int ntfs_attr_map_whole_runlist(ntfs_attr *na);
+
+extern LCN ntfs_attr_vcn_to_lcn(ntfs_attr *na, const VCN vcn);
+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_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,
+		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);
+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);
+extern int ntfs_attr_rm(ntfs_attr *na);
+
+extern int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size);
+
+extern int ntfs_resident_attr_value_resize(MFT_RECORD *m, ATTR_RECORD *a,
+		const u32 new_size);
+
+extern int ntfs_attr_record_move_to(ntfs_attr_search_ctx *ctx, ntfs_inode *ni);
+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);
+
+/**
+ * get_attribute_value_length - return the length of the value of an attribute
+ * @a:	pointer to a buffer containing the attribute record
+ *
+ * Return the byte size of the attribute value of the attribute @a (as it
+ * would be after eventual decompression and filling in of holes if sparse).
+ * If we return 0, check errno. If errno is 0 the actual length was 0,
+ * otherwise errno describes the error.
+ *
+ * FIXME: Describe possible errnos.
+ */
+extern s64 ntfs_get_attribute_value_length(const ATTR_RECORD *a);
+
+/**
+ * get_attribute_value - return the attribute value of an attribute
+ * @vol:	volume on which the attribute is present
+ * @a:		attribute to get the value of
+ * @b:		destination buffer for the attribute value
+ *
+ * Make a copy of the attribute value of the attribute @a into the destination
+ * buffer @b. Note, that the size of @b has to be at least equal to the value
+ * returned by get_attribute_value_length(@a).
+ *
+ * Return number of bytes copied. If this is zero check errno. If errno is 0
+ * 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);
+
+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);
+
+#endif /* defined _NTFS_ATTRIB_H */
+
diff --git a/include/ntfs-3g/attrlist.h b/include/ntfs-3g/attrlist.h
new file mode 100755
index 0000000000000000000000000000000000000000..2952e48b86577b41c8a1283b458006755ee4c312
--- /dev/null
+++ b/include/ntfs-3g/attrlist.h
@@ -0,0 +1,51 @@
+/*
+ * attrlist.h - Exports for attribute list attribute handling.  
+ * 		Originated from Linux-NTFS project.
+ *
+ * Copyright (c) 2004 Anton Altaparmakov
+ * Copyright (c) 2004 Yura Pakhuchiy
+ *
+ * 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_ATTRLIST_H
+#define _NTFS_ATTRLIST_H
+
+#include "attrib.h"
+
+extern int ntfs_attrlist_need(ntfs_inode *ni);
+
+extern int ntfs_attrlist_entry_add(ntfs_inode *ni, ATTR_RECORD *attr);
+extern int ntfs_attrlist_entry_rm(ntfs_attr_search_ctx *ctx);
+
+/**
+ * ntfs_attrlist_mark_dirty - set the attribute list dirty
+ * @ni:		ntfs inode which base inode contain dirty attribute list
+ *
+ * Set the attribute list dirty so it is written out later (at the latest at
+ * ntfs_inode_close() time).
+ *
+ * This function cannot fail.
+ */
+static __inline__ void ntfs_attrlist_mark_dirty(ntfs_inode *ni)
+{
+	if (ni->nr_extents == -1)
+		NInoAttrListSetDirty(ni->base_ni);
+	else
+		NInoAttrListSetDirty(ni);
+}
+
+#endif /* defined _NTFS_ATTRLIST_H */
diff --git a/include/ntfs-3g/bitmap.h b/include/ntfs-3g/bitmap.h
new file mode 100755
index 0000000000000000000000000000000000000000..10b5f6c5b47c196d02627a0dcf58d1be33aa0cf0
--- /dev/null
+++ b/include/ntfs-3g/bitmap.h
@@ -0,0 +1,96 @@
+/*
+ * bitmap.h - Exports for bitmap handling. Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2000-2004 Anton Altaparmakov
+ * Copyright (c) 2004-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
+ * 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_BITMAP_H
+#define _NTFS_BITMAP_H
+
+#include "types.h"
+#include "attrib.h"
+
+/*
+ * NOTES:
+ *
+ * - Operations are 8-bit only to ensure the functions work both on little
+ *   and big endian machines! So don't make them 32-bit ops!
+ * - bitmap starts at bit = 0 and ends at bit = bitmap size - 1.
+ * - _Caller_ has to make sure that the bit to operate on is less than the
+ *   size of the bitmap.
+ */
+
+extern void ntfs_bit_set(u8 *bitmap, const u64 bit, const u8 new_value);
+extern char ntfs_bit_get(const u8 *bitmap, const u64 bit);
+extern char ntfs_bit_get_and_set(u8 *bitmap, const u64 bit, const u8 new_value);
+extern int  ntfs_bitmap_set_run(ntfs_attr *na, s64 start_bit, s64 count);
+extern int  ntfs_bitmap_clear_run(ntfs_attr *na, s64 start_bit, s64 count);
+
+/**
+ * ntfs_bitmap_set_bit - set a bit in a bitmap
+ * @na:		attribute containing the bitmap
+ * @bit:	bit to set
+ *
+ * Set the @bit in the bitmap described by the attribute @na.
+ *
+ * On success return 0 and on error return -1 with errno set to the error code.
+ */
+static __inline__ int ntfs_bitmap_set_bit(ntfs_attr *na, s64 bit)
+{
+	return ntfs_bitmap_set_run(na, bit, 1);
+}
+
+/**
+ * ntfs_bitmap_clear_bit - clear a bit in a bitmap
+ * @na:		attribute containing the bitmap
+ * @bit:	bit to clear
+ *
+ * Clear @bit in the bitmap described by the attribute @na.
+ *
+ * On success return 0 and on error return -1 with errno set to the error code.
+ */
+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 */
+
diff --git a/include/ntfs-3g/bootsect.h b/include/ntfs-3g/bootsect.h
new file mode 100755
index 0000000000000000000000000000000000000000..a299e821efac1d532f7fbefaea0362c1cba1e013
--- /dev/null
+++ b/include/ntfs-3g/bootsect.h
@@ -0,0 +1,42 @@
+/*
+ * 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
+ * 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_BOOTSECT_H
+#define _NTFS_BOOTSECT_H
+
+#include "types.h"
+#include "volume.h"
+#include "layout.h"
+
+/**
+ * ntfs_boot_sector_is_ntfs - check a boot sector for describing an ntfs volume
+ * @b:		buffer containing the boot sector
+ *
+ * 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.
+ */
+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);
+
+#endif /* defined _NTFS_BOOTSECT_H */
+
diff --git a/include/ntfs-3g/cache.h b/include/ntfs-3g/cache.h
new file mode 100755
index 0000000000000000000000000000000000000000..be63b1a4bd7f37907e5f83745fd8500763aa26a5
--- /dev/null
+++ b/include/ntfs-3g/cache.h
@@ -0,0 +1,118 @@
+/*
+ * 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_ */
+
diff --git a/include/ntfs-3g/collate.h b/include/ntfs-3g/collate.h
new file mode 100755
index 0000000000000000000000000000000000000000..fe38383509aee30e50a9ce547030b653c87ce16d
--- /dev/null
+++ b/include/ntfs-3g/collate.h
@@ -0,0 +1,34 @@
+/*
+ * collate.h - Defines for NTFS collation handling.  Originated from the Linux-NTFS
+ *             project.
+ *
+ * Copyright (c) 2004 Anton Altaparmakov
+ * Copyright (c) 2005 Yura Pakhuchiy
+ *
+ * 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_COLLATE_H
+#define _NTFS_COLLATE_H
+
+#include "types.h"
+#include "volume.h"
+
+#define NTFS_COLLATION_ERROR -2
+
+extern COLLATE ntfs_get_collate_function(COLLATION_RULES);
+
+#endif /* _NTFS_COLLATE_H */
diff --git a/include/ntfs-3g/compat.h b/include/ntfs-3g/compat.h
new file mode 100755
index 0000000000000000000000000000000000000000..ece7ba8fe13bad16aeb9d8ed775bdd1b54a93068
--- /dev/null
+++ b/include/ntfs-3g/compat.h
@@ -0,0 +1,75 @@
+/*
+ * compat.h - Tweaks for Windows compatibility.
+ *
+ * Copyright (c) 2002 Richard Russon
+ * Copyright (c) 2002-2004 Anton Altaparmakov
+ * Copyright (c) 2008-2009 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
+ * 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_COMPAT_H
+#define _NTFS_COMPAT_H
+
+#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 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
+
+#define HAVE_STDIO_H		/* mimic config.h */
+#define HAVE_STDARG_H
+
+#define atoll			_atoi64
+#define fdatasync		commit
+#define __inline__		inline
+#define __attribute__(X)	/*nothing*/
+
+#else /* !defined WINDOWS */
+
+#ifndef O_BINARY
+#define O_BINARY		0		/* unix is binary by default */
+#endif
+
+#endif /* defined WINDOWS */
+
+#endif /* defined _NTFS_COMPAT_H */
+
diff --git a/include/ntfs-3g/compress.h b/include/ntfs-3g/compress.h
new file mode 100755
index 0000000000000000000000000000000000000000..c256932169c9bb4fcc189cd5e9585f402f47b36a
--- /dev/null
+++ b/include/ntfs-3g/compress.h
@@ -0,0 +1,41 @@
+/*
+ * compress.h - Exports for compressed attribute handling. 
+ * 		Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2004 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
+ */
+
+#ifndef _NTFS_COMPRESS_H
+#define _NTFS_COMPRESS_H
+
+#include "types.h"
+#include "attrib.h"
+
+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 */
+
diff --git a/include/ntfs-3g/debug.h b/include/ntfs-3g/debug.h
new file mode 100755
index 0000000000000000000000000000000000000000..f7f3c6fb4ebead8fd5123ae52dcd2bbc73c29df6
--- /dev/null
+++ b/include/ntfs-3g/debug.h
@@ -0,0 +1,47 @@
+/*
+ * debug.h - Debugging output functions. Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2002-2004 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
+ */
+
+#ifndef _NTFS_DEBUG_H
+#define _NTFS_DEBUG_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "logging.h"
+
+struct _runlist_element;
+
+#ifdef DEBUG
+extern void ntfs_debug_runlist_dump(const struct _runlist_element *rl);
+#else
+static __inline__ void ntfs_debug_runlist_dump(const struct _runlist_element *rl __attribute__((unused))) {}
+#endif
+
+#define NTFS_BUG(msg)							\
+{									\
+	int ___i = 1;							\
+	ntfs_log_critical("Bug in %s(): %s\n", __FUNCTION__, msg);	\
+	ntfs_log_debug("Forcing segmentation fault!");			\
+	___i = ((int*)NULL)[___i];					\
+}
+
+#endif /* defined _NTFS_DEBUG_H */
diff --git a/include/ntfs-3g/device.h b/include/ntfs-3g/device.h
new file mode 100755
index 0000000000000000000000000000000000000000..c7cc9b64f696dec00674ecd9f31ca255ccfd7de4
--- /dev/null
+++ b/include/ntfs-3g/device.h
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ *
+ * 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_DEVICE_H
+#define _NTFS_DEVICE_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "device_io.h"
+#include "types.h"
+#include "support.h"
+#include "volume.h"
+
+/**
+ * enum ntfs_device_state_bits -
+ *
+ * Defined bits for the state field in the ntfs_device structure.
+ */
+typedef enum {
+	ND_Open,	/* 1: Device is open. */
+	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)
+#define   set_ndev_flag(nd, flag)	    set_bit(ND_##flag, (nd)->d_state)
+#define clear_ndev_flag(nd, flag)	  clear_bit(ND_##flag, (nd)->d_state)
+
+#define NDevOpen(nd)		 test_ndev_flag(nd, Open)
+#define NDevSetOpen(nd)		  set_ndev_flag(nd, Open)
+#define NDevClearOpen(nd)	clear_ndev_flag(nd, Open)
+
+#define NDevReadOnly(nd)	 test_ndev_flag(nd, ReadOnly)
+#define NDevSetReadOnly(nd)	  set_ndev_flag(nd, ReadOnly)
+#define NDevClearReadOnly(nd)	clear_ndev_flag(nd, ReadOnly)
+
+#define NDevDirty(nd)		 test_ndev_flag(nd, Dirty)
+#define NDevSetDirty(nd)	  set_ndev_flag(nd, Dirty)
+#define NDevClearDirty(nd)	clear_ndev_flag(nd, Dirty)
+
+#define NDevBlock(nd)		 test_ndev_flag(nd, Block)
+#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. */
+	unsigned long d_state;			/* State of the 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;
+
+/**
+ * struct ntfs_device_operations -
+ *
+ * The ntfs device operations defining all operations that can be performed on
+ * the low level device described by an ntfs device structure.
+ */
+struct ntfs_device_operations {
+	int (*open)(struct ntfs_device *dev, int flags);
+	int (*close)(struct ntfs_device *dev);
+	s64 (*seek)(struct ntfs_device *dev, s64 offset, int whence);
+	s64 (*read)(struct ntfs_device *dev, void *buf, s64 count);
+	s64 (*write)(struct ntfs_device *dev, const void *buf, s64 count);
+	s64 (*pread)(struct ntfs_device *dev, void *buf, s64 count, s64 offset);
+	s64 (*pwrite)(struct ntfs_device *dev, const void *buf, s64 count,
+			s64 offset);
+	int (*sync)(struct ntfs_device *dev);
+	int (*stat)(struct ntfs_device *dev, struct stat *buf);
+	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);
+extern s64 ntfs_pwrite(struct ntfs_device *dev, const s64 pos, s64 count,
+		const void *b);
+
+extern s64 ntfs_mst_pread(struct ntfs_device *dev, const s64 pos, s64 count,
+		const u32 bksize, void *b);
+extern s64 ntfs_mst_pwrite(struct ntfs_device *dev, const s64 pos, s64 count,
+		const u32 bksize, void *b);
+
+extern s64 ntfs_cluster_read(const ntfs_volume *vol, const s64 lcn,
+		const s64 count, void *b);
+extern s64 ntfs_cluster_write(const ntfs_volume *vol, const s64 lcn,
+		const s64 count, const void *b);
+
+extern s64 ntfs_device_size_get(struct ntfs_device *dev, int block_size);
+extern s64 ntfs_device_partition_start_sector_get(struct ntfs_device *dev);
+extern int ntfs_device_heads_get(struct ntfs_device *dev);
+extern int ntfs_device_sectors_per_track_get(struct ntfs_device *dev);
+extern int ntfs_device_sector_size_get(struct ntfs_device *dev);
+extern int ntfs_device_block_size_set(struct ntfs_device *dev, int block_size);
+
+#endif /* defined _NTFS_DEVICE_H */
diff --git a/include/ntfs-3g/device_io.h b/include/ntfs-3g/device_io.h
new file mode 100755
index 0000000000000000000000000000000000000000..66ad2439fb1961a3491193e5c7c84ea0ebcaba05
--- /dev/null
+++ b/include/ntfs-3g/device_io.h
@@ -0,0 +1,88 @@
+/*
+ * device_io.h - Exports for default device io. Originated from the Linux-NTFS project.
+ *
+ * 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
+ * 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_DEVICE_IO_H
+#define _NTFS_DEVICE_IO_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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 HAVE_WINDOWS_H
+
+/* Not for Windows use standard Unix style low level device operations. */
+#define ntfs_device_default_io_ops ntfs_device_unix_io_ops
+
+#else /* HAVE_WINDOWS_H */
+
+#ifndef HDIO_GETGEO
+#	define HDIO_GETGEO	0x301
+/**
+ * struct hd_geometry -
+ */
+struct hd_geometry {
+	unsigned char heads;
+	unsigned char sectors;
+	unsigned short cylinders;
+	unsigned long start;
+};
+#endif
+#ifndef BLKGETSIZE
+#	define BLKGETSIZE	0x1260
+#endif
+#ifndef BLKSSZGET
+#	define BLKSSZGET	0x1268
+#endif
+#ifndef BLKGETSIZE64
+#	define BLKGETSIZE64	0x80041272
+#endif
+#ifndef BLKBSZSET
+#	define BLKBSZSET	0x40041271
+#endif
+
+/* On Windows (and 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 */
+
+
+/* Forward declaration. */
+struct ntfs_device_operations;
+
+extern struct ntfs_device_operations ntfs_device_default_io_ops;
+
+#endif /* NO_NTFS_DEVICE_DEFAULT_IO_OPS */
+
+#endif /* defined _NTFS_DEVICE_IO_H */
+
diff --git a/include/ntfs-3g/dir.h b/include/ntfs-3g/dir.h
new file mode 100755
index 0000000000000000000000000000000000000000..a99c1ae0d733c7e130f03025658974b574e9f258
--- /dev/null
+++ b/include/ntfs-3g/dir.h
@@ -0,0 +1,129 @@
+/*
+ * dir.h - Exports for directory handling. Originated from the Linux-NTFS project.
+ *
+ * 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
+ * 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_DIR_H
+#define _NTFS_DIR_H
+
+#include "types.h"
+
+#define PATH_SEP '/'
+
+/*
+ * We do not have these under DJGPP, so define our version that do not conflict
+ * with other S_IFs defined under DJGPP.
+ */
+#ifdef DJGPP
+#ifndef S_IFLNK
+#define S_IFLNK  0120000
+#endif
+#ifndef S_ISLNK
+#define S_ISLNK(m)  (((m) & S_IFMT) == S_IFLNK)
+#endif
+#ifndef S_IFSOCK
+#define S_IFSOCK 0140000
+#endif
+#ifndef S_ISSOCK
+#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+#endif
+#endif
+
+/*
+ * The little endian Unicode strings $I30, $SII, $SDH, $O, $Q, $R
+ * as a global constant.
+ */
+extern ntfschar NTFS_INDEX_I30[5];
+extern ntfschar NTFS_INDEX_SII[5];
+extern ntfschar NTFS_INDEX_SDH[5];
+extern ntfschar NTFS_INDEX_O[3];
+extern ntfschar NTFS_INDEX_Q[3];
+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 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,
+		u8 name_len);
+
+extern int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
+		u8 name_len);
+
+/*
+ * File types (adapted from include <linux/fs.h>)
+ */
+#define NTFS_DT_UNKNOWN		0
+#define NTFS_DT_FIFO		1
+#define NTFS_DT_CHR		2
+#define NTFS_DT_DIR		4
+#define NTFS_DT_BLK		6
+#define NTFS_DT_REG		8
+#define NTFS_DT_LNK		10
+#define NTFS_DT_SOCK		12
+#define NTFS_DT_WHT		14
+
+/*
+ * This is the "ntfs_filldir" function type, used by ntfs_readdir() to let
+ * the caller specify what kind of dirent layout it wants to have.
+ * This allows the caller to read directories into their application or
+ * to have different dirent layouts depending on the binary type.
+ */
+typedef int (*ntfs_filldir_t)(void *dirent, const ntfschar *name,
+		const int name_len, const int name_type, const s64 pos,
+		const MFT_REF mref, const unsigned dt_type);
+
+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);
+
+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);
+
+#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 */
+
diff --git a/include/ntfs-3g/ea.h b/include/ntfs-3g/ea.h
new file mode 100755
index 0000000000000000000000000000000000000000..1936aab493b0bf11bc79b8508a52c11dcd5f67fb
--- /dev/null
+++ b/include/ntfs-3g/ea.h
@@ -0,0 +1,33 @@
+/*
+ *
+ * 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 EA_H
+#define EA_H
+
+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 */
diff --git a/include/ntfs-3g/efs.h b/include/ntfs-3g/efs.h
new file mode 100755
index 0000000000000000000000000000000000000000..6eada0675959339ff3a6dbcd173292a6de12d9d1
--- /dev/null
+++ b/include/ntfs-3g/efs.h
@@ -0,0 +1,30 @@
+/*
+ *
+ * Copyright (c) 2009 Martin Bene
+ *
+ * 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 EFS_H
+#define EFS_H
+
+int ntfs_get_efs_info(ntfs_inode *ni, char *value, size_t size);
+
+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 /* EFS_H */
diff --git a/include/ntfs-3g/endians.h b/include/ntfs-3g/endians.h
new file mode 100755
index 0000000000000000000000000000000000000000..f00089372ba8ad99d6973b989da99b4efe4faafb
--- /dev/null
+++ b/include/ntfs-3g/endians.h
@@ -0,0 +1,205 @@
+/*
+ * endians.h - Definitions related to handling of byte ordering. 
+ *             Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2000-2005 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
+ */
+
+#ifndef _NTFS_ENDIANS_H
+#define _NTFS_ENDIANS_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * Notes:
+ *	We define the conversion functions including typecasts since the
+ * defaults don't necessarily perform appropriate typecasts.
+ *	Also, using our own functions means that we can change them if it
+ * turns out that we do need to use the unaligned access macros on
+ * architectures requiring aligned memory accesses...
+ */
+
+#ifdef HAVE_ENDIAN_H
+#include <endian.h>
+#endif
+#ifdef HAVE_SYS_ENDIAN_H
+#include <sys/endian.h>
+#endif
+#ifdef HAVE_MACHINE_ENDIAN_H
+#include <machine/endian.h>
+#endif
+#ifdef HAVE_SYS_BYTEORDER_H
+#include <sys/byteorder.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#define __BYTE_ORDER BYTE_ORDER
+
+#ifndef __BYTE_ORDER
+#	if defined(_BYTE_ORDER)
+#		define __BYTE_ORDER _BYTE_ORDER
+#		define __LITTLE_ENDIAN _LITTLE_ENDIAN
+#		define __BIG_ENDIAN _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__)
+#		define __BYTE_ORDER __BYTE_ORDER__
+#		define __LITTLE_ENDIAN __LITTLE_ENDIAN__
+#		define __BIG_ENDIAN __BIG_ENDIAN__
+#	elif (defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)) || \
+			defined(WORDS_LITTLEENDIAN)
+#		define __BYTE_ORDER 1
+#		define __LITTLE_ENDIAN 1
+#		define __BIG_ENDIAN 0
+#	elif (!defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN)) || \
+			defined(WORDS_BIGENDIAN)
+#		define __BYTE_ORDER 0
+#		define __LITTLE_ENDIAN 1
+#		define __BIG_ENDIAN 0
+#	else
+#		error "__BYTE_ORDER is not defined."
+#	endif
+#endif
+
+#define __ntfs_bswap_constant_16(x)		\
+	  (u16)((((u16)(x) & 0xff00) >> 8) |	\
+		(((u16)(x) & 0x00ff) << 8))
+
+#define __ntfs_bswap_constant_32(x)			\
+	  (u32)((((u32)(x) & 0xff000000u) >> 24) |	\
+		(((u32)(x) & 0x00ff0000u) >>  8) |	\
+		(((u32)(x) & 0x0000ff00u) <<  8) |	\
+		(((u32)(x) & 0x000000ffu) << 24))
+
+#define __ntfs_bswap_constant_64(x)				\
+	  (u64)((((u64)(x) & 0xff00000000000000ull) >> 56) |	\
+		(((u64)(x) & 0x00ff000000000000ull) >> 40) |	\
+		(((u64)(x) & 0x0000ff0000000000ull) >> 24) |	\
+		(((u64)(x) & 0x000000ff00000000ull) >>  8) |	\
+		(((u64)(x) & 0x00000000ff000000ull) <<  8) |	\
+		(((u64)(x) & 0x0000000000ff0000ull) << 24) |	\
+		(((u64)(x) & 0x000000000000ff00ull) << 40) |	\
+		(((u64)(x) & 0x00000000000000ffull) << 56))
+
+#ifdef HAVE_BYTESWAP_H
+#	include <byteswap.h>
+#else
+#	define bswap_16(x) __ntfs_bswap_constant_16(x)
+#	define bswap_32(x) __ntfs_bswap_constant_32(x)
+#	define bswap_64(x) __ntfs_bswap_constant_64(x)
+#endif
+
+#if defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN)
+
+#define __le16_to_cpu(x) (x)
+#define __le32_to_cpu(x) (x)
+#define __le64_to_cpu(x) (x)
+
+#define __cpu_to_le16(x) (x)
+#define __cpu_to_le32(x) (x)
+#define __cpu_to_le64(x) (x)
+
+#define __constant_le16_to_cpu(x) (x)
+#define __constant_le32_to_cpu(x) (x)
+#define __constant_le64_to_cpu(x) (x)
+
+#define __constant_cpu_to_le16(x) (x)
+#define __constant_cpu_to_le32(x) (x)
+#define __constant_cpu_to_le64(x) (x)
+
+#elif defined(__BIG_ENDIAN) && (__BYTE_ORDER == __BIG_ENDIAN)
+
+#define __le16_to_cpu(x) bswap_16(x)
+#define __le32_to_cpu(x) bswap_32(x)
+#define __le64_to_cpu(x) bswap_64(x)
+
+#define __cpu_to_le16(x) bswap_16(x)
+#define __cpu_to_le32(x) bswap_32(x)
+#define __cpu_to_le64(x) bswap_64(x)
+
+#define __constant_le16_to_cpu(x) __ntfs_bswap_constant_16((u16)(x))
+#define __constant_le32_to_cpu(x) __ntfs_bswap_constant_32((u32)(x))
+#define __constant_le64_to_cpu(x) __ntfs_bswap_constant_64((u64)(x))
+
+#define __constant_cpu_to_le16(x) __ntfs_bswap_constant_16((u16)(x))
+#define __constant_cpu_to_le32(x) __ntfs_bswap_constant_32((u32)(x))
+#define __constant_cpu_to_le64(x) __ntfs_bswap_constant_64((u64)(x))
+
+#else
+
+#error "You must define __BYTE_ORDER to be __LITTLE_ENDIAN or __BIG_ENDIAN."
+
+#endif
+
+/* Unsigned from LE to CPU conversion. */
+
+#define le16_to_cpu(x)		(u16)__le16_to_cpu((u16)(x))
+#define le32_to_cpu(x)		(u32)__le32_to_cpu((u32)(x))
+#define le64_to_cpu(x)		(u64)__le64_to_cpu((u64)(x))
+
+#define le16_to_cpup(x)		(u16)__le16_to_cpu(*(const u16*)(x))
+#define le32_to_cpup(x)		(u32)__le32_to_cpu(*(const u32*)(x))
+#define le64_to_cpup(x)		(u64)__le64_to_cpu(*(const u64*)(x))
+
+/* Signed from LE to CPU conversion. */
+
+#define sle16_to_cpu(x)		(s16)__le16_to_cpu((s16)(x))
+#define sle32_to_cpu(x)		(s32)__le32_to_cpu((s32)(x))
+#define sle64_to_cpu(x)		(s64)__le64_to_cpu((s64)(x))
+
+#define sle16_to_cpup(x)	(s16)__le16_to_cpu(*(s16*)(x))
+#define sle32_to_cpup(x)	(s32)__le32_to_cpu(*(s32*)(x))
+#define sle64_to_cpup(x)	(s64)__le64_to_cpu(*(s64*)(x))
+
+/* Unsigned from CPU to LE conversion. */
+
+#define cpu_to_le16(x)		(u16)__cpu_to_le16((u16)(x))
+#define cpu_to_le32(x)		(u32)__cpu_to_le32((u32)(x))
+#define cpu_to_le64(x)		(u64)__cpu_to_le64((u64)(x))
+
+#define cpu_to_le16p(x)		(u16)__cpu_to_le16(*(u16*)(x))
+#define cpu_to_le32p(x)		(u32)__cpu_to_le32(*(u32*)(x))
+#define cpu_to_le64p(x)		(u64)__cpu_to_le64(*(u64*)(x))
+
+/* Signed from CPU to LE conversion. */
+
+#define cpu_to_sle16(x)		(s16)__cpu_to_le16((s16)(x))
+#define cpu_to_sle32(x)		(s32)__cpu_to_le32((s32)(x))
+#define cpu_to_sle64(x)		(s64)__cpu_to_le64((s64)(x))
+
+#define cpu_to_sle16p(x)	(s16)__cpu_to_le16(*(s16*)(x))
+#define cpu_to_sle32p(x)	(s32)__cpu_to_le32(*(s32*)(x))
+#define cpu_to_sle64p(x)	(s64)__cpu_to_le64(*(s64*)(x))
+
+/* Constant endianness conversion defines. */
+
+#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)	__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 */
diff --git a/include/ntfs-3g/index.h b/include/ntfs-3g/index.h
new file mode 100755
index 0000000000000000000000000000000000000000..c0e7618038a1a33e355a158e6a946f15117795b6
--- /dev/null
+++ b/include/ntfs-3g/index.h
@@ -0,0 +1,167 @@
+/*
+ * index.h - Defines for NTFS index handling.  Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2004 Anton Altaparmakov
+ * Copyright (c) 2004-2005 Richard Russon
+ * Copyright (c) 2005 Yura Pakhuchiy
+ * Copyright (c) 2006-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
+ * 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_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"
+#include "inode.h"
+#include "mft.h"
+
+#define  VCN_INDEX_ROOT_PARENT  ((VCN)-2)
+
+#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
+ * @name:		name of the index described by this context
+ * @name_len:		length of the index name
+ * @entry:		index entry (points into @ir or @ia)
+ * @data:		index entry data (points into @entry)
+ * @data_len:		length in bytes of @data
+ * @is_in_root:		TRUE if @entry is in @ir or FALSE if it is in @ia
+ * @ir:			index root if @is_in_root or NULL otherwise
+ * @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
+ * @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
+ * @median:		move to the parent if splitting index blocks
+ * @ib_dirty:		TRUE if index block was changed
+ * @block_size:		index block size
+ * @vcn_size_bits:	VCN size bits for this index block
+ *
+ * @ni is the inode this context belongs to.
+ *
+ * @entry is the index entry described by this context.  @data and @data_len
+ * are the index entry data and its length in bytes, respectively.  @data
+ * 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
+ * @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,
+ * 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.
+ *
+ * To obtain a context call ntfs_index_ctx_get().
+ *
+ * When finished with the @entry and its @data, call ntfs_index_ctx_put() to
+ * free the context and other associated resources.
+ *
+ * If the index entry was modified, call ntfs_index_entry_mark_dirty() before
+ * the call to ntfs_index_ctx_put() to ensure that the changes are written
+ * to disk.
+ */
+typedef struct {
+	ntfs_inode *ni;
+	ntfschar *name;
+	u32 name_len;
+	INDEX_ENTRY *entry;
+	void *data;
+	u16 data_len;
+	COLLATE collate;
+	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 parent_vcn[MAX_PARENT_VCN]; /* entry's parent nodes */
+	int pindex;	     /* maximum it's the number of the parent nodes  */
+	BOOL ib_dirty;
+	u32 block_size;
+	u8 vcn_size_bits;
+} ntfs_index_context;
+
+extern ntfs_index_context *ntfs_index_ctx_get(ntfs_inode *ni,
+						ntfschar *name, u32 name_len);
+extern void ntfs_index_ctx_put(ntfs_index_context *ictx);
+extern void ntfs_index_ctx_reinit(ntfs_index_context *ictx);
+
+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 INDEX_ROOT *ntfs_index_root_get(ntfs_inode *ni, ATTR_RECORD *attr);
+
+extern VCN ntfs_ie_get_vcn(INDEX_ENTRY *ie);
+
+extern void ntfs_index_entry_mark_dirty(ntfs_index_context *ictx);
+
+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 */
+
diff --git a/include/ntfs-3g/inode.h b/include/ntfs-3g/inode.h
new file mode 100755
index 0000000000000000000000000000000000000000..5a6f7da66e1210fb3062b474167cbca4d76ce693
--- /dev/null
+++ b/include/ntfs-3g/inode.h
@@ -0,0 +1,225 @@
+/*
+ * 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) 2004-2005 Richard Russon
+ * Copyright (c) 2006-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
+ * 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_INODE_H
+#define _NTFS_INODE_H
+
+/* Forward declaration */
+typedef struct _ntfs_inode ntfs_inode;
+
+#include "types.h"
+#include "layout.h"
+#include "support.h"
+#include "volume.h"
+#include "ntfstime.h"
+
+/**
+ * enum ntfs_inode_state_bits -
+ *
+ * Defined bits for the state field in the ntfs_inode structure.
+ * (f) = files only, (d) = directories only
+ */
+typedef enum {
+	NI_Dirty,		/* 1: Mft record needs to be written to disk. */
+
+	/* The NI_AttrList* tests only make sense for base inodes. */
+	NI_AttrList,		/* 1: Mft record contains an attribute list. */
+	NI_AttrListDirty,	/* 1: Attribute list needs to be written to the
+				      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)
+#define   set_nino_flag(ni, flag)	    set_bit(NI_##flag, (ni)->state)
+#define clear_nino_flag(ni, flag)	  clear_bit(NI_##flag, (ni)->state)
+
+#define test_and_set_nino_flag(ni, flag)	\
+				   test_and_set_bit(NI_##flag, (ni)->state)
+#define test_and_clear_nino_flag(ni, flag)	\
+				 test_and_clear_bit(NI_##flag, (ni)->state)
+
+#define NInoDirty(ni)				  test_nino_flag(ni, Dirty)
+#define NInoSetDirty(ni)			   set_nino_flag(ni, Dirty)
+#define NInoClearDirty(ni)			 clear_nino_flag(ni, Dirty)
+#define NInoTestAndSetDirty(ni)		  test_and_set_nino_flag(ni, Dirty)
+#define NInoTestAndClearDirty(ni)	test_and_clear_nino_flag(ni, Dirty)
+
+#define NInoAttrList(ni)			  test_nino_flag(ni, AttrList)
+#define NInoSetAttrList(ni)			   set_nino_flag(ni, AttrList)
+#define NInoClearAttrList(ni)			 clear_nino_flag(ni, AttrList)
+
+
+#define  test_nino_al_flag(ni, flag)	 test_nino_flag(ni, AttrList##flag)
+#define   set_nino_al_flag(ni, flag)	  set_nino_flag(ni, AttrList##flag)
+#define clear_nino_al_flag(ni, flag)	clear_nino_flag(ni, AttrList##flag)
+
+#define test_and_set_nino_al_flag(ni, flag)	\
+				 test_and_set_nino_flag(ni, AttrList##flag)
+#define test_and_clear_nino_al_flag(ni, flag)	\
+			       test_and_clear_nino_flag(ni, AttrList##flag)
+
+#define NInoAttrListDirty(ni)			    test_nino_al_flag(ni, Dirty)
+#define NInoAttrListSetDirty(ni)		     set_nino_al_flag(ni, Dirty)
+#define NInoAttrListClearDirty(ni)		   clear_nino_al_flag(ni, Dirty)
+#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 NInoFileNameTestAndSetDirty(ni)		\
+				      test_and_set_nino_flag(ni, FileNameDirty)
+#define NInoFileNameTestAndClearDirty(ni)	\
+				    test_and_clear_nino_flag(ni, FileNameDirty)
+
+/**
+ * struct _ntfs_inode - The NTFS in-memory inode structure.
+ *
+ * It is just used as an extension to the fields already provided in the VFS
+ * inode.
+ */
+struct _ntfs_inode {
+	u64 mft_no;		/* Inode / mft record number. */
+	MFT_RECORD *mrec;	/* The actual mft record of the inode. */
+	ntfs_volume *vol;	/* Pointer to the ntfs volume of this inode. */
+	unsigned long state;	/* NTFS specific flags describing this inode.
+				   See ntfs_inode_state_bits above. */
+	FILE_ATTR_FLAGS flags;	/* Flags describing the file.
+				   (Copy from STANDARD_INFORMATION) */
+	/*
+	 * Attribute list support (for use by the attribute lookup functions).
+	 * Setup during ntfs_open_inode() for all inodes with attribute lists.
+	 * Only valid if NI_AttrList is set in state.
+	 */
+	u32 attr_list_size;	/* Length of attribute list value in bytes. */
+	u8 *attr_list;		/* Attribute list value itself. */
+	/* Below fields are always valid. */
+	s32 nr_extents;		/* For a base mft record, the number of
+				   attached extent inodes (0 if none), for
+				   extent records this is -1. */
+	union {		/* This union is only used if nr_extents != 0. */
+		ntfs_inode **extent_nis;/* For nr_extents > 0, array of the
+					   ntfs inodes of the extent mft
+					   records belonging to this base
+					   inode which have been loaded. */
+		ntfs_inode *base_ni;	/* For nr_extents == -1, the ntfs
+					   inode of the base mft record. */
+	};
+
+	/* Below fields are valid only for base inode. */
+
+	/*
+	 * 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) */
+	s64 allocated_size;	/* Allocated size stored in the filename
+				   index. (NOTE: Equal to allocated size of
+				   the unnamed data attribute for normal or
+				   encrypted files and to compressed size
+				   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;
+};
+
+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 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 int ntfs_inode_sync(ntfs_inode *ni);
+
+extern int ntfs_inode_add_attrlist(ntfs_inode *ni);
+
+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 */
diff --git a/include/ntfs-3g/ioctl.h b/include/ntfs-3g/ioctl.h
new file mode 100755
index 0000000000000000000000000000000000000000..4ed6c01085626dc1296badb1066740624cb5cf2e
--- /dev/null
+++ b/include/ntfs-3g/ioctl.h
@@ -0,0 +1,30 @@
+/*
+ *
+ * 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
+
+int ntfs_ioctl(ntfs_inode *ni, int cmd, void *arg,
+                        unsigned int flags, void *data);
+
+#endif /* IOCTL_H */
diff --git a/include/ntfs-3g/layout.h b/include/ntfs-3g/layout.h
new file mode 100755
index 0000000000000000000000000000000000000000..5b5fff6e90224aed826bd2acce6226bda8ce5dd6
--- /dev/null
+++ b/include/ntfs-3g/layout.h
@@ -0,0 +1,2663 @@
+/*
+ * layout.h - Ntfs on-disk layout structures.  Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2000-2005 Anton Altaparmakov
+ * Copyright (c)      2005 Yura Pakhuchiy
+ * 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
+ * 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_LAYOUT_H
+#define _NTFS_LAYOUT_H
+
+#include "types.h"
+#include "endians.h"
+#include "support.h"
+
+/* The NTFS oem_id */
+#define magicNTFS	const_cpu_to_le64(0x202020205346544e)	/* "NTFS    " */
+#define NTFS_SB_MAGIC	0x5346544e				/* 'NTFS' */
+
+/*
+ * Location of bootsector on partition:
+ *	The standard NTFS_BOOT_SECTOR is on sector 0 of the partition.
+ *	On NT4 and above there is one backup copy of the boot sector to
+ *	be found on the last sector of the partition (not normally accessible
+ *	from within Windows as the bootsector contained number of sectors
+ *	value is one less than the actual value!).
+ *	On versions of NT 3.51 and earlier, the backup copy was located at
+ *	number of sectors/2 (integer divide), i.e. in the middle of the volume.
+ */
+
+/**
+ * struct BIOS_PARAMETER_BLOCK - BIOS parameter block (bpb) structure.
+ */
+typedef struct {
+	u16 bytes_per_sector;		/* Size of a sector in bytes. */
+	u8  sectors_per_cluster;	/* Size of a cluster in sectors. */
+	u16 reserved_sectors;		/* zero */
+	u8  fats;			/* zero */
+	u16 root_entries;		/* zero */
+	u16 sectors;			/* zero */
+	u8  media_type;			/* 0xf8 = hard disk */
+	u16 sectors_per_fat;		/* zero */
+/*0x0d*/u16 sectors_per_track;		/* Required to boot Windows. */
+/*0x0f*/u16 heads;			/* Required to boot Windows. */
+/*0x11*/u32 hidden_sectors;		/* Offset to the start of the partition
+					   relative to the disk in sectors.
+					   Required to boot Windows. */
+/*0x15*/u32 large_sectors;		/* zero */
+/* sizeof() = 25 (0x19) bytes */
+} __attribute__((__packed__)) BIOS_PARAMETER_BLOCK;
+
+/**
+ * struct NTFS_BOOT_SECTOR - NTFS boot sector structure.
+ */
+typedef struct {
+	u8  jump[3];			/* Irrelevant (jump to boot up code).*/
+	u64 oem_id;			/* Magic "NTFS    ". */
+/*0x0b*/BIOS_PARAMETER_BLOCK bpb;	/* See BIOS_PARAMETER_BLOCK. */
+	u8 physical_drive;		/* 0x00 floppy, 0x80 hard disk */
+	u8 current_head;		/* zero */
+	u8 extended_boot_signature; 	/* 0x80 */
+	u8 reserved2;			/* zero */
+/*0x28*/s64 number_of_sectors;		/* Number of sectors in volume. Gives
+					   maximum volume size of 2^63 sectors.
+					   Assuming standard sector size of 512
+					   bytes, the maximum byte size is
+					   approx. 4.7x10^21 bytes. (-; */
+	s64 mft_lcn;			/* Cluster location of mft data. */
+	s64 mftmirr_lcn;		/* Cluster location of copy of mft. */
+	s8  clusters_per_mft_record;	/* Mft record size in clusters. */
+	u8  reserved0[3];		/* zero */
+	s8  clusters_per_index_record;	/* Index block size in clusters. */
+	u8  reserved1[3];		/* zero */
+	u64 volume_serial_number;	/* Irrelevant (serial number). */
+	u32 checksum;			/* Boot sector checksum. */
+/*0x54*/u8  bootstrap[426];		/* Irrelevant (boot up code). */
+	u16 end_of_sector_marker;	/* End of bootsector magic. Always is
+					   0xaa55 in little endian. */
+/* sizeof() = 512 (0x200) bytes */
+} __attribute__((__packed__)) NTFS_BOOT_SECTOR;
+
+/**
+ * enum NTFS_RECORD_TYPES -
+ *
+ * Magic identifiers present at the beginning of all ntfs record containing
+ * records (like mft records for example).
+ */
+typedef enum {
+	/* Found in $MFT/$DATA. */
+	magic_FILE = const_cpu_to_le32(0x454c4946), /* Mft entry. */
+	magic_INDX = const_cpu_to_le32(0x58444e49), /* Index buffer. */
+	magic_HOLE = const_cpu_to_le32(0x454c4f48), /* ? (NTFS 3.0+?) */
+
+	/* Found in $LogFile/$DATA. */
+	magic_RSTR = const_cpu_to_le32(0x52545352), /* Restart page. */
+	magic_RCRD = const_cpu_to_le32(0x44524352), /* Log record page. */
+
+	/* Found in $LogFile/$DATA.  (May be found in $MFT/$DATA, also?) */
+	magic_CHKD = const_cpu_to_le32(0x444b4843), /* Modified by chkdsk. */
+
+	/* Found in all ntfs record containing records. */
+	magic_BAAD = const_cpu_to_le32(0x44414142), /* Failed multi sector
+						       transfer was detected. */
+
+	/*
+	 * Found in $LogFile/$DATA when a page is full or 0xff bytes and is
+	 * thus not initialized.  User has to initialize the page before using
+	 * it.
+	 */
+	magic_empty = const_cpu_to_le32(0xffffffff),/* Record is empty and has
+						       to be initialized before
+						       it can be used. */
+} NTFS_RECORD_TYPES;
+
+/*
+ * Generic magic comparison macros. Finally found a use for the ## preprocessor
+ * operator! (-8
+ */
+#define ntfs_is_magic(x, m)	(   (u32)(x) == (u32)magic_##m )
+#define ntfs_is_magicp(p, m)	( *(u32*)(p) == (u32)magic_##m )
+
+/*
+ * Specialised magic comparison macros for the NTFS_RECORD_TYPES defined above.
+ */
+#define ntfs_is_file_record(x)	( ntfs_is_magic (x, FILE) )
+#define ntfs_is_file_recordp(p)	( ntfs_is_magicp(p, FILE) )
+#define ntfs_is_mft_record(x)	( ntfs_is_file_record(x) )
+#define ntfs_is_mft_recordp(p)	( ntfs_is_file_recordp(p) )
+#define ntfs_is_indx_record(x)	( ntfs_is_magic (x, INDX) )
+#define ntfs_is_indx_recordp(p)	( ntfs_is_magicp(p, INDX) )
+#define ntfs_is_hole_record(x)	( ntfs_is_magic (x, HOLE) )
+#define ntfs_is_hole_recordp(p)	( ntfs_is_magicp(p, HOLE) )
+
+#define ntfs_is_rstr_record(x)	( ntfs_is_magic (x, RSTR) )
+#define ntfs_is_rstr_recordp(p)	( ntfs_is_magicp(p, RSTR) )
+#define ntfs_is_rcrd_record(x)	( ntfs_is_magic (x, RCRD) )
+#define ntfs_is_rcrd_recordp(p)	( ntfs_is_magicp(p, RCRD) )
+
+#define ntfs_is_chkd_record(x)	( ntfs_is_magic (x, CHKD) )
+#define ntfs_is_chkd_recordp(p)	( ntfs_is_magicp(p, CHKD) )
+
+#define ntfs_is_baad_record(x)	( ntfs_is_magic (x, BAAD) )
+#define ntfs_is_baad_recordp(p)	( ntfs_is_magicp(p, BAAD) )
+
+#define ntfs_is_empty_record(x)		( ntfs_is_magic (x, empty) )
+#define ntfs_is_empty_recordp(p)	( ntfs_is_magicp(p, empty) )
+
+
+#define NTFS_BLOCK_SIZE		512
+#define NTFS_BLOCK_SIZE_BITS	9
+
+/**
+ * struct NTFS_RECORD -
+ *
+ * The Update Sequence Array (usa) is an array of the u16 values which belong
+ * to the end of each sector protected by the update sequence record in which
+ * this array is contained. Note that the first entry is the Update Sequence
+ * Number (usn), a cyclic counter of how many times the protected record has
+ * been written to disk. The values 0 and -1 (ie. 0xffff) are not used. All
+ * last u16's of each sector have to be equal to the usn (during reading) or
+ * are set to it (during writing). If they are not, an incomplete multi sector
+ * transfer has occurred when the data was written.
+ * The maximum size for the update sequence array is fixed to:
+ *	maximum size = usa_ofs + (usa_count * 2) = 510 bytes
+ * The 510 bytes comes from the fact that the last u16 in the array has to
+ * (obviously) finish before the last u16 of the first 512-byte sector.
+ * This formula can be used as a consistency check in that usa_ofs +
+ * (usa_count * 2) has to be less than or equal to 510.
+ */
+typedef struct {
+	NTFS_RECORD_TYPES magic;/* A four-byte magic identifying the
+				   record type and/or status. */
+	u16 usa_ofs;		/* Offset to the Update Sequence Array (usa)
+				   from the start of the ntfs record. */
+	u16 usa_count;		/* Number of u16 sized entries in the usa
+				   including the Update Sequence Number (usn),
+				   thus the number of fixups is the usa_count
+				   minus 1. */
+} __attribute__((__packed__)) NTFS_RECORD;
+
+/**
+ * enum NTFS_SYSTEM_FILES - System files mft record numbers.
+ *
+ * All these files are always marked as used in the bitmap attribute of the
+ * mft; presumably in order to avoid accidental allocation for random other
+ * mft records. Also, the sequence number for each of the system files is
+ * always equal to their mft record number and it is never modified.
+ */
+typedef enum {
+	FILE_MFT	= 0,	/* Master file table (mft). Data attribute
+				   contains the entries and bitmap attribute
+				   records which ones are in use (bit==1). */
+	FILE_MFTMirr	= 1,	/* Mft mirror: copy of first four mft records
+				   in data attribute. If cluster size > 4kiB,
+				   copy of first N mft records, with
+					N = cluster_size / mft_record_size. */
+	FILE_LogFile	= 2,	/* Journalling log in data attribute. */
+	FILE_Volume	= 3,	/* Volume name attribute and volume information
+				   attribute (flags and ntfs version). Windows
+				   refers to this file as volume DASD (Direct
+				   Access Storage Device). */
+	FILE_AttrDef	= 4,	/* Array of attribute definitions in data
+				   attribute. */
+	FILE_root	= 5,	/* Root directory. */
+	FILE_Bitmap	= 6,	/* Allocation bitmap of all clusters (lcns) in
+				   data attribute. */
+	FILE_Boot	= 7,	/* Boot sector (always at cluster 0) in data
+				   attribute. */
+	FILE_BadClus	= 8,	/* Contains all bad clusters in the non-resident
+				   data attribute. */
+	FILE_Secure	= 9,	/* Shared security descriptors in data attribute
+				   and two indexes into the descriptors.
+				   Appeared in Windows 2000. Before that, this
+				   file was named $Quota but was unused. */
+	FILE_UpCase	= 10,	/* Uppercase equivalents of all 65536 Unicode
+				   characters in data attribute. */
+	FILE_Extend	= 11,	/* Directory containing other system files (eg.
+				   $ObjId, $Quota, $Reparse and $UsnJrnl). This
+				   is new to NTFS3.0. */
+	FILE_reserved12	= 12,	/* Reserved for future use (records 12-15). */
+	FILE_reserved13	= 13,
+	FILE_reserved14	= 14,
+	FILE_mft_data	= 15,	/* Reserved for first extent of $MFT:$DATA */
+	FILE_first_user	= 16,	/* First user file, used as test limit for
+				   whether to allow opening a file or not. */
+} NTFS_SYSTEM_FILES;
+
+/**
+ * enum MFT_RECORD_FLAGS -
+ *
+ * These are the so far known MFT_RECORD_* flags (16-bit) which contain
+ * information about the mft record in which they are present.
+ * 
+ * MFT_RECORD_IS_4 exists on all $Extend sub-files.
+ * It seems that it marks it is a metadata file with MFT record >24, however,
+ * it is unknown if it is limited to metadata files only.
+ *
+ * MFT_RECORD_IS_VIEW_INDEX exists on every metafile with a non directory
+ * index, that means an INDEX_ROOT and an INDEX_ALLOCATION with a name other
+ * than "$I30". It is unknown if it is limited to metadata files only.
+ */
+typedef enum {
+	MFT_RECORD_IN_USE		= const_cpu_to_le16(0x0001),
+	MFT_RECORD_IS_DIRECTORY		= const_cpu_to_le16(0x0002),
+	MFT_RECORD_IS_4			= const_cpu_to_le16(0x0004),
+	MFT_RECORD_IS_VIEW_INDEX	= const_cpu_to_le16(0x0008),
+	MFT_REC_SPACE_FILLER		= 0xffff, /* Just to make flags
+						     16-bit. */
+} __attribute__((__packed__)) MFT_RECORD_FLAGS;
+
+/*
+ * mft references (aka file references or file record segment references) are
+ * used whenever a structure needs to refer to a record in the mft.
+ *
+ * A reference consists of a 48-bit index into the mft and a 16-bit sequence
+ * number used to detect stale references.
+ *
+ * For error reporting purposes we treat the 48-bit index as a signed quantity.
+ *
+ * The sequence number is a circular counter (skipping 0) describing how many
+ * times the referenced mft record has been (re)used. This has to match the
+ * sequence number of the mft record being referenced, otherwise the reference
+ * is considered stale and removed (FIXME: only ntfsck or the driver itself?).
+ *
+ * If the sequence number is zero it is assumed that no sequence number
+ * consistency checking should be performed.
+ *
+ * FIXME: Since inodes are 32-bit as of now, the driver needs to always check
+ * for high_part being 0 and if not either BUG(), cause a panic() or handle
+ * the situation in some other way. This shouldn't be a problem as a volume has
+ * to become HUGE in order to need more than 32-bits worth of mft records.
+ * Assuming the standard mft record size of 1kb only the records (never mind
+ * the non-resident attributes, etc.) would require 4Tb of space on their own
+ * for the first 32 bits worth of records. This is only if some strange person
+ * doesn't decide to foul play and make the mft sparse which would be a really
+ * horrible thing to do as it would trash our current driver implementation. )-:
+ * Do I hear screams "we want 64-bit inodes!" ?!? (-;
+ *
+ * FIXME: The mft zone is defined as the first 12% of the volume. This space is
+ * reserved so that the mft can grow contiguously and hence doesn't become
+ * fragmented. Volume free space includes the empty part of the mft zone and
+ * when the volume's free 88% are used up, the mft zone is shrunk by a factor
+ * of 2, thus making more space available for more files/data. This process is
+ * repeated every time there is no more free space except for the mft zone until
+ * there really is no more free space.
+ */
+
+/*
+ * Typedef the MFT_REF as a 64-bit value for easier handling.
+ * Also define two unpacking macros to get to the reference (MREF) and
+ * sequence number (MSEQNO) respectively.
+ * The _LE versions are to be applied on little endian MFT_REFs.
+ * Note: The _LE versions will return a CPU endian formatted value!
+ */
+#define MFT_REF_MASK_CPU 0x0000ffffffffffffULL
+#define MFT_REF_MASK_LE const_cpu_to_le64(MFT_REF_MASK_CPU)
+
+typedef u64 MFT_REF;
+typedef le64 leMFT_REF;   /* a little-endian MFT_MREF */
+
+#define MK_MREF(m, s)	((MFT_REF)(((MFT_REF)(s) << 48) |		\
+					((MFT_REF)(m) & MFT_REF_MASK_CPU)))
+#define MK_LE_MREF(m, s) const_cpu_to_le64(((MFT_REF)(((MFT_REF)(s) << 48) | \
+					((MFT_REF)(m) & MFT_REF_MASK_CPU))))
+
+#define MREF(x)		((u64)((x) & MFT_REF_MASK_CPU))
+#define MSEQNO(x)	((u16)(((x) >> 48) & 0xffff))
+#define MREF_LE(x)	((u64)(const_le64_to_cpu(x) & MFT_REF_MASK_CPU))
+#define MSEQNO_LE(x)	((u16)((const_le64_to_cpu(x) >> 48) & 0xffff))
+
+#define IS_ERR_MREF(x)	(((x) & 0x0000800000000000ULL) ? 1 : 0)
+#define ERR_MREF(x)	((u64)((s64)(x)))
+#define MREF_ERR(x)	((int)((s64)(x)))
+
+/**
+ * struct MFT_RECORD - An MFT record layout (NTFS 3.1+)
+ *
+ * The mft record header present at the beginning of every record in the mft.
+ * This is followed by a sequence of variable length attribute records which
+ * is terminated by an attribute of type AT_END which is a truncated attribute
+ * in that it only consists of the attribute type code AT_END and none of the
+ * other members of the attribute structure are present.
+ */
+typedef struct {
+/*Ofs*/
+/*  0	NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
+	NTFS_RECORD_TYPES magic;/* Usually the magic is "FILE". */
+	u16 usa_ofs;		/* See NTFS_RECORD definition above. */
+	u16 usa_count;		/* See NTFS_RECORD definition above. */
+
+/*  8*/	LSN lsn;		/* $LogFile sequence number for this record.
+				   Changed every time the record is modified. */
+/* 16*/	u16 sequence_number;	/* Number of times this mft record has been
+				   reused. (See description for MFT_REF
+				   above.) NOTE: The increment (skipping zero)
+				   is done when the file is deleted. NOTE: If
+				   this is zero it is left zero. */
+/* 18*/	u16 link_count;		/* Number of hard links, i.e. the number of
+				   directory entries referencing this record.
+				   NOTE: Only used in mft base records.
+				   NOTE: When deleting a directory entry we
+				   check the link_count and if it is 1 we
+				   delete the file. Otherwise we delete the
+				   FILE_NAME_ATTR being referenced by the
+				   directory entry from the mft record and
+				   decrement the link_count.
+				   FIXME: Careful with Win32 + DOS names! */
+/* 20*/	u16 attrs_offset;	/* Byte offset to the first attribute in this
+				   mft record from the start of the mft record.
+				   NOTE: Must be aligned to 8-byte boundary. */
+/* 22*/	MFT_RECORD_FLAGS flags;	/* Bit array of MFT_RECORD_FLAGS. When a file
+				   is deleted, the MFT_RECORD_IN_USE flag is
+				   set to zero. */
+/* 24*/	u32 bytes_in_use;	/* Number of bytes used in this mft record.
+				   NOTE: Must be aligned to 8-byte boundary. */
+/* 28*/	u32 bytes_allocated;	/* Number of bytes allocated for this mft
+				   record. This should be equal to the mft
+				   record size. */
+/* 32*/	MFT_REF base_mft_record; /* This is zero for base mft records.
+				   When it is not zero it is a mft reference
+				   pointing to the base mft record to which
+				   this record belongs (this is then used to
+				   locate the attribute list attribute present
+				   in the base record which describes this
+				   extension record and hence might need
+				   modification when the extension record
+				   itself is modified, also locating the
+				   attribute list also means finding the other
+				   potential extents, belonging to the non-base
+				   mft record). */
+/* 40*/	u16 next_attr_instance; /* The instance number that will be
+				   assigned to the next attribute added to this
+				   mft record. NOTE: Incremented each time
+				   after it is used. NOTE: Every time the mft
+				   record is reused this number is set to zero.
+				   NOTE: The first instance number is always 0.
+				 */
+/* The below fields are specific to NTFS 3.1+ (Windows XP and above): */
+/* 42*/ u16 reserved;		/* Reserved/alignment. */
+/* 44*/ u32 mft_record_number;	/* Number of this mft record. */
+/* sizeof() = 48 bytes */
+/*
+ * When (re)using the mft record, we place the update sequence array at this
+ * offset, i.e. before we start with the attributes. This also makes sense,
+ * otherwise we could run into problems with the update sequence array
+ * containing in itself the last two bytes of a sector which would mean that
+ * multi sector transfer protection wouldn't work. As you can't protect data
+ * by overwriting it since you then can't get it back...
+ * When reading we obviously use the data from the ntfs record header.
+ */
+} __attribute__((__packed__)) MFT_RECORD;
+
+/**
+ * struct MFT_RECORD_OLD - An MFT record layout (NTFS <=3.0)
+ *
+ * This is the version without the NTFS 3.1+ specific fields.
+ */
+typedef struct {
+/*Ofs*/
+/*  0	NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
+	NTFS_RECORD_TYPES magic;/* Usually the magic is "FILE". */
+	u16 usa_ofs;		/* See NTFS_RECORD definition above. */
+	u16 usa_count;		/* See NTFS_RECORD definition above. */
+
+/*  8*/	LSN lsn;		/* $LogFile sequence number for this record.
+				   Changed every time the record is modified. */
+/* 16*/	u16 sequence_number;	/* Number of times this mft record has been
+				   reused. (See description for MFT_REF
+				   above.) NOTE: The increment (skipping zero)
+				   is done when the file is deleted. NOTE: If
+				   this is zero it is left zero. */
+/* 18*/	u16 link_count;		/* Number of hard links, i.e. the number of
+				   directory entries referencing this record.
+				   NOTE: Only used in mft base records.
+				   NOTE: When deleting a directory entry we
+				   check the link_count and if it is 1 we
+				   delete the file. Otherwise we delete the
+				   FILE_NAME_ATTR being referenced by the
+				   directory entry from the mft record and
+				   decrement the link_count.
+				   FIXME: Careful with Win32 + DOS names! */
+/* 20*/	u16 attrs_offset;	/* Byte offset to the first attribute in this
+				   mft record from the start of the mft record.
+				   NOTE: Must be aligned to 8-byte boundary. */
+/* 22*/	MFT_RECORD_FLAGS flags;	/* Bit array of MFT_RECORD_FLAGS. When a file
+				   is deleted, the MFT_RECORD_IN_USE flag is
+				   set to zero. */
+/* 24*/	u32 bytes_in_use;	/* Number of bytes used in this mft record.
+				   NOTE: Must be aligned to 8-byte boundary. */
+/* 28*/	u32 bytes_allocated;	/* Number of bytes allocated for this mft
+				   record. This should be equal to the mft
+				   record size. */
+/* 32*/	MFT_REF base_mft_record; /* This is zero for base mft records.
+				   When it is not zero it is a mft reference
+				   pointing to the base mft record to which
+				   this record belongs (this is then used to
+				   locate the attribute list attribute present
+				   in the base record which describes this
+				   extension record and hence might need
+				   modification when the extension record
+				   itself is modified, also locating the
+				   attribute list also means finding the other
+				   potential extents, belonging to the non-base
+				   mft record). */
+/* 40*/	u16 next_attr_instance; /* The instance number that will be
+				   assigned to the next attribute added to this
+				   mft record. NOTE: Incremented each time
+				   after it is used. NOTE: Every time the mft
+				   record is reused this number is set to zero.
+				   NOTE: The first instance number is always 0.
+				 */
+/* sizeof() = 42 bytes */
+/*
+ * When (re)using the mft record, we place the update sequence array at this
+ * offset, i.e. before we start with the attributes. This also makes sense,
+ * otherwise we could run into problems with the update sequence array
+ * containing in itself the last two bytes of a sector which would mean that
+ * multi sector transfer protection wouldn't work. As you can't protect data
+ * by overwriting it since you then can't get it back...
+ * When reading we obviously use the data from the ntfs record header.
+ */
+} __attribute__((__packed__)) MFT_RECORD_OLD;
+
+/**
+ * enum ATTR_TYPES - System defined attributes (32-bit).
+ *
+ * Each attribute type has a corresponding attribute name (Unicode string of
+ * maximum 64 character length) as described by the attribute definitions
+ * present in the data attribute of the $AttrDef system file.
+ * 
+ * On NTFS 3.0 volumes the names are just as the types are named in the below
+ * enum exchanging AT_ for the dollar sign ($). If that isn't a revealing
+ * choice of symbol... (-;
+ */
+typedef enum {
+	AT_UNUSED			= const_cpu_to_le32(         0),
+	AT_STANDARD_INFORMATION		= const_cpu_to_le32(      0x10),
+	AT_ATTRIBUTE_LIST		= const_cpu_to_le32(      0x20),
+	AT_FILE_NAME			= const_cpu_to_le32(      0x30),
+	AT_OBJECT_ID			= const_cpu_to_le32(      0x40),
+	AT_SECURITY_DESCRIPTOR		= const_cpu_to_le32(      0x50),
+	AT_VOLUME_NAME			= const_cpu_to_le32(      0x60),
+	AT_VOLUME_INFORMATION		= const_cpu_to_le32(      0x70),
+	AT_DATA				= const_cpu_to_le32(      0x80),
+	AT_INDEX_ROOT			= const_cpu_to_le32(      0x90),
+	AT_INDEX_ALLOCATION		= const_cpu_to_le32(      0xa0),
+	AT_BITMAP			= const_cpu_to_le32(      0xb0),
+	AT_REPARSE_POINT		= const_cpu_to_le32(      0xc0),
+	AT_EA_INFORMATION		= const_cpu_to_le32(      0xd0),
+	AT_EA				= const_cpu_to_le32(      0xe0),
+	AT_PROPERTY_SET			= const_cpu_to_le32(      0xf0),
+	AT_LOGGED_UTILITY_STREAM	= const_cpu_to_le32(     0x100),
+	AT_FIRST_USER_DEFINED_ATTRIBUTE	= const_cpu_to_le32(    0x1000),
+	AT_END				= const_cpu_to_le32(0xffffffff),
+} ATTR_TYPES;
+
+/**
+ * enum COLLATION_RULES - The collation rules for sorting views/indexes/etc
+ * (32-bit).
+ *
+ * COLLATION_UNICODE_STRING - Collate Unicode strings by comparing their binary
+ *	Unicode values, except that when a character can be uppercased, the
+ *	upper case value collates before the lower case one.
+ * COLLATION_FILE_NAME - Collate file names as Unicode strings. The collation
+ *	is done very much like COLLATION_UNICODE_STRING. In fact I have no idea
+ *	what the difference is. Perhaps the difference is that file names
+ *	would treat some special characters in an odd way (see
+ *	unistr.c::ntfs_collate_names() and unistr.c::legal_ansi_char_array[]
+ *	for what I mean but COLLATION_UNICODE_STRING would not give any special
+ *	treatment to any characters at all, but this is speculation.
+ * COLLATION_NTOFS_ULONG - Sorting is done according to ascending u32 key
+ *	values. E.g. used for $SII index in FILE_Secure, which sorts by
+ *	security_id (u32).
+ * COLLATION_NTOFS_SID - Sorting is done according to ascending SID values.
+ *	E.g. used for $O index in FILE_Extend/$Quota.
+ * COLLATION_NTOFS_SECURITY_HASH - Sorting is done first by ascending hash
+ *	values and second by ascending security_id values. E.g. used for $SDH
+ *	index in FILE_Secure.
+ * COLLATION_NTOFS_ULONGS - Sorting is done according to a sequence of ascending
+ *	u32 key values. E.g. used for $O index in FILE_Extend/$ObjId, which
+ *	sorts by object_id (16-byte), by splitting up the object_id in four
+ *	u32 values and using them as individual keys. E.g. take the following
+ *	two security_ids, stored as follows on disk:
+ *		1st: a1 61 65 b7 65 7b d4 11 9e 3d 00 e0 81 10 42 59
+ *		2nd: 38 14 37 d2 d2 f3 d4 11 a5 21 c8 6b 79 b1 97 45
+ *	To compare them, they are split into four u32 values each, like so:
+ *		1st: 0xb76561a1 0x11d47b65 0xe0003d9e 0x59421081
+ *		2nd: 0xd2371438 0x11d4f3d2 0x6bc821a5 0x4597b179
+ *	Now, it is apparent why the 2nd object_id collates after the 1st: the
+ *	first u32 value of the 1st object_id is less than the first u32 of
+ *	the 2nd object_id. If the first u32 values of both object_ids were
+ *	equal then the second u32 values would be compared, etc.
+ */
+typedef enum {
+	COLLATION_BINARY	 = const_cpu_to_le32(0), /* Collate by binary
+					compare where the first byte is most
+					significant. */
+	COLLATION_FILE_NAME	 = const_cpu_to_le32(1), /* Collate file names
+					as Unicode strings. */
+	COLLATION_UNICODE_STRING = const_cpu_to_le32(2), /* Collate Unicode
+					strings by comparing their binary
+					Unicode values, except that when a
+					character can be uppercased, the upper
+					case value collates before the lower
+					case one. */
+	COLLATION_NTOFS_ULONG		= const_cpu_to_le32(16),
+	COLLATION_NTOFS_SID		= const_cpu_to_le32(17),
+	COLLATION_NTOFS_SECURITY_HASH	= const_cpu_to_le32(18),
+	COLLATION_NTOFS_ULONGS		= const_cpu_to_le32(19),
+} COLLATION_RULES;
+
+/**
+ * enum ATTR_DEF_FLAGS -
+ *
+ * The flags (32-bit) describing attribute properties in the attribute
+ * definition structure.  FIXME: This information is based on Regis's
+ * information and, according to him, it is not certain and probably
+ * incomplete.  The INDEXABLE flag is fairly certainly correct as only the file
+ * name attribute has this flag set and this is the only attribute indexed in
+ * NT4.
+ */
+typedef enum {
+	ATTR_DEF_INDEXABLE	= const_cpu_to_le32(0x02), /* Attribute can be
+					indexed. */
+	ATTR_DEF_MULTIPLE	= const_cpu_to_le32(0x04), /* Attribute type
+					can be present multiple times in the
+					mft records of an inode. */
+	ATTR_DEF_NOT_ZERO	= const_cpu_to_le32(0x08), /* Attribute value
+					must contain at least one non-zero
+					byte. */
+	ATTR_DEF_INDEXED_UNIQUE	= const_cpu_to_le32(0x10), /* Attribute must be
+					indexed and the attribute value must be
+					unique for the attribute type in all of
+					the mft records of an inode. */
+	ATTR_DEF_NAMED_UNIQUE	= const_cpu_to_le32(0x20), /* Attribute must be
+					named and the name must be unique for
+					the attribute type in all of the mft
+					records of an inode. */
+	ATTR_DEF_RESIDENT	= const_cpu_to_le32(0x40), /* Attribute must be
+					resident. */
+	ATTR_DEF_ALWAYS_LOG	= const_cpu_to_le32(0x80), /* Always log
+					modifications to this attribute,
+					regardless of whether it is resident or
+					non-resident.  Without this, only log
+					modifications if the attribute is
+					resident. */
+} ATTR_DEF_FLAGS;
+
+/**
+ * struct ATTR_DEF -
+ *
+ * The data attribute of FILE_AttrDef contains a sequence of attribute
+ * definitions for the NTFS volume. With this, it is supposed to be safe for an
+ * older NTFS driver to mount a volume containing a newer NTFS version without
+ * damaging it (that's the theory. In practice it's: not damaging it too much).
+ * Entries are sorted by attribute type. The flags describe whether the
+ * attribute can be resident/non-resident and possibly other things, but the
+ * actual bits are unknown.
+ */
+typedef struct {
+/*hex ofs*/
+/*  0*/	ntfschar name[0x40];		/* Unicode name of the attribute. Zero
+					   terminated. */
+/* 80*/	ATTR_TYPES type;		/* Type of the attribute. */
+/* 84*/	u32 display_rule;		/* Default display rule.
+					   FIXME: What does it mean? (AIA) */
+/* 88*/ COLLATION_RULES collation_rule;	/* Default collation rule. */
+/* 8c*/	ATTR_DEF_FLAGS flags;		/* Flags describing the attribute. */
+/* 90*/	s64 min_size;			/* Optional minimum attribute size. */
+/* 98*/	s64 max_size;			/* Maximum size of attribute. */
+/* sizeof() = 0xa0 or 160 bytes */
+} __attribute__((__packed__)) ATTR_DEF;
+
+/**
+ * enum ATTR_FLAGS - Attribute flags (16-bit).
+ */
+typedef enum {
+	ATTR_IS_COMPRESSED	= const_cpu_to_le16(0x0001),
+	ATTR_COMPRESSION_MASK	= const_cpu_to_le16(0x00ff),  /* Compression
+						method mask. Also, first
+						illegal value. */
+	ATTR_IS_ENCRYPTED	= const_cpu_to_le16(0x4000),
+	ATTR_IS_SPARSE		= const_cpu_to_le16(0x8000),
+} __attribute__((__packed__)) ATTR_FLAGS;
+
+/*
+ * Attribute compression.
+ *
+ * Only the data attribute is ever compressed in the current ntfs driver in
+ * Windows. Further, compression is only applied when the data attribute is
+ * non-resident. Finally, to use compression, the maximum allowed cluster size
+ * on a volume is 4kib.
+ *
+ * The compression method is based on independently compressing blocks of X
+ * clusters, where X is determined from the compression_unit value found in the
+ * non-resident attribute record header (more precisely: X = 2^compression_unit
+ * clusters). On Windows NT/2k, X always is 16 clusters (compression_unit = 4).
+ *
+ * There are three different cases of how a compression block of X clusters
+ * can be stored:
+ *
+ *   1) The data in the block is all zero (a sparse block):
+ *	  This is stored as a sparse block in the runlist, i.e. the runlist
+ *	  entry has length = X and lcn = -1. The mapping pairs array actually
+ *	  uses a delta_lcn value length of 0, i.e. delta_lcn is not present at
+ *	  all, which is then interpreted by the driver as lcn = -1.
+ *	  NOTE: Even uncompressed files can be sparse on NTFS 3.0 volumes, then
+ *	  the same principles apply as above, except that the length is not
+ *	  restricted to being any particular value.
+ *
+ *   2) The data in the block is not compressed:
+ *	  This happens when compression doesn't reduce the size of the block
+ *	  in clusters. I.e. if compression has a small effect so that the
+ *	  compressed data still occupies X clusters, then the uncompressed data
+ *	  is stored in the block.
+ *	  This case is recognised by the fact that the runlist entry has
+ *	  length = X and lcn >= 0. The mapping pairs array stores this as
+ *	  normal with a run length of X and some specific delta_lcn, i.e.
+ *	  delta_lcn has to be present.
+ *
+ *   3) The data in the block is compressed:
+ *	  The common case. This case is recognised by the fact that the run
+ *	  list entry has length L < X and lcn >= 0. The mapping pairs array
+ *	  stores this as normal with a run length of X and some specific
+ *	  delta_lcn, i.e. delta_lcn has to be present. This runlist entry is
+ *	  immediately followed by a sparse entry with length = X - L and
+ *	  lcn = -1. The latter entry is to make up the vcn counting to the
+ *	  full compression block size X.
+ *
+ * In fact, life is more complicated because adjacent entries of the same type
+ * can be coalesced. This means that one has to keep track of the number of
+ * clusters handled and work on a basis of X clusters at a time being one
+ * block. An example: if length L > X this means that this particular runlist
+ * entry contains a block of length X and part of one or more blocks of length
+ * L - X. Another example: if length L < X, this does not necessarily mean that
+ * the block is compressed as it might be that the lcn changes inside the block
+ * and hence the following runlist entry describes the continuation of the
+ * potentially compressed block. The block would be compressed if the
+ * following runlist entry describes at least X - L sparse clusters, thus
+ * making up the compression block length as described in point 3 above. (Of
+ * course, there can be several runlist entries with small lengths so that the
+ * sparse entry does not follow the first data containing entry with
+ * length < X.)
+ *
+ * NOTE: At the end of the compressed attribute value, there most likely is not
+ * just the right amount of data to make up a compression block, thus this data
+ * is not even attempted to be compressed. It is just stored as is, unless
+ * the number of clusters it occupies is reduced when compressed in which case
+ * it is stored as a compressed compression block, complete with sparse
+ * clusters at the end.
+ */
+
+/**
+ * enum RESIDENT_ATTR_FLAGS - Flags of resident attributes (8-bit).
+ */
+typedef enum {
+	RESIDENT_ATTR_IS_INDEXED = 0x01, /* Attribute is referenced in an index
+					    (has implications for deleting and
+					    modifying the attribute). */
+} __attribute__((__packed__)) RESIDENT_ATTR_FLAGS;
+
+/**
+ * struct ATTR_RECORD - Attribute record header.
+ *
+ * Always aligned to 8-byte boundary.
+ */
+typedef struct {
+/*Ofs*/
+/*  0*/	ATTR_TYPES type;	/* The (32-bit) type of the attribute. */
+/*  4*/	u32 length;		/* Byte size of the resident part of the
+				   attribute (aligned to 8-byte boundary).
+				   Used to get to the next attribute. */
+/*  8*/	u8 non_resident;	/* If 0, attribute is resident.
+				   If 1, attribute is non-resident. */
+/*  9*/	u8 name_length;		/* Unicode character size of name of attribute.
+				   0 if unnamed. */
+/* 10*/	u16 name_offset;	/* If name_length != 0, the byte offset to the
+				   beginning of the name from the attribute
+				   record. Note that the name is stored as a
+				   Unicode string. When creating, place offset
+				   just at the end of the record header. Then,
+				   follow with attribute value or mapping pairs
+				   array, resident and non-resident attributes
+				   respectively, aligning to an 8-byte
+				   boundary. */
+/* 12*/	ATTR_FLAGS flags;	/* Flags describing the attribute. */
+/* 14*/	u16 instance;		/* The instance of this attribute record. This
+				   number is unique within this mft record (see
+				   MFT_RECORD/next_attribute_instance notes
+				   above for more details). */
+/* 16*/	union {
+		/* Resident attributes. */
+		struct {
+/* 16 */		u32 value_length; /* Byte size of attribute value. */
+/* 20 */		u16 value_offset; /* Byte offset of the attribute
+					       value from the start of the
+					       attribute record. When creating,
+					       align to 8-byte boundary if we
+					       have a name present as this might
+					       not have a length of a multiple
+					       of 8-bytes. */
+/* 22 */		RESIDENT_ATTR_FLAGS resident_flags; /* See above. */
+/* 23 */		s8 reservedR;	    /* Reserved/alignment to 8-byte
+					       boundary. */
+/* 24 */		void *resident_end[0]; /* Use offsetof(ATTR_RECORD,
+						  resident_end) to get size of
+						  a resident attribute. */
+		} __attribute__((__packed__));
+		/* Non-resident attributes. */
+		struct {
+/* 16*/			VCN lowest_vcn;	/* Lowest valid virtual cluster number
+				for this portion of the attribute value or
+				0 if this is the only extent (usually the
+				case). - Only when an attribute list is used
+				does lowest_vcn != 0 ever occur. */
+/* 24*/			VCN highest_vcn; /* Highest valid vcn of this extent of
+				the attribute value. - Usually there is only one
+				portion, so this usually equals the attribute
+				value size in clusters minus 1. Can be -1 for
+				zero length files. Can be 0 for "single extent"
+				attributes. */
+/* 32*/			u16 mapping_pairs_offset; /* Byte offset from the
+				beginning of the structure to the mapping pairs
+				array which contains the mappings between the
+				vcns and the logical cluster numbers (lcns).
+				When creating, place this at the end of this
+				record header aligned to 8-byte boundary. */
+/* 34*/			u8 compression_unit; /* The compression unit expressed
+				as the log to the base 2 of the number of
+				clusters in a compression unit. 0 means not
+				compressed. (This effectively limits the
+				compression unit size to be a power of two
+				clusters.) WinNT4 only uses a value of 4. */
+/* 35*/			u8 reserved1[5];	/* Align to 8-byte boundary. */
+/* The sizes below are only used when lowest_vcn is zero, as otherwise it would
+   be difficult to keep them up-to-date.*/
+/* 40*/			s64 allocated_size;	/* Byte size of disk space
+				allocated to hold the attribute value. Always
+				is a multiple of the cluster size. When a file
+				is compressed, this field is a multiple of the
+				compression block size (2^compression_unit) and
+				it represents the logically allocated space
+				rather than the actual on disk usage. For this
+				use the compressed_size (see below). */
+/* 48*/			s64 data_size;	/* Byte size of the attribute
+				value. Can be larger than allocated_size if
+				attribute value is compressed or sparse. */
+/* 56*/			s64 initialized_size;	/* Byte size of initialized
+				portion of the attribute value. Usually equals
+				data_size. */
+/* 64 */		void *non_resident_end[0]; /* Use offsetof(ATTR_RECORD,
+						      non_resident_end) to get
+						      size of a non resident
+						      attribute. */
+/* sizeof(uncompressed attr) = 64*/
+/* 64*/			s64 compressed_size;	/* Byte size of the attribute
+				value after compression. Only present when
+				compressed. Always is a multiple of the
+				cluster size. Represents the actual amount of
+				disk space being used on the disk. */
+/* 72 */		void *compressed_end[0];
+				/* Use offsetof(ATTR_RECORD, compressed_end) to
+				   get size of a compressed attribute. */
+/* sizeof(compressed attr) = 72*/
+		} __attribute__((__packed__));
+	} __attribute__((__packed__));
+} __attribute__((__packed__)) ATTR_RECORD;
+
+typedef ATTR_RECORD ATTR_REC;
+
+/**
+ * enum FILE_ATTR_FLAGS - File attribute flags (32-bit).
+ */
+typedef enum {
+	/*
+	 * These flags are only present in the STANDARD_INFORMATION attribute
+	 * (in the field file_attributes).
+	 */
+	FILE_ATTR_READONLY		= const_cpu_to_le32(0x00000001),
+	FILE_ATTR_HIDDEN		= const_cpu_to_le32(0x00000002),
+	FILE_ATTR_SYSTEM		= const_cpu_to_le32(0x00000004),
+	/* Old DOS volid. Unused in NT.	= cpu_to_le32(0x00000008), */
+
+	FILE_ATTR_DIRECTORY		= const_cpu_to_le32(0x00000010),
+	/* FILE_ATTR_DIRECTORY is not considered valid in NT. It is reserved
+	   for the DOS SUBDIRECTORY flag. */
+	FILE_ATTR_ARCHIVE		= const_cpu_to_le32(0x00000020),
+	FILE_ATTR_DEVICE		= const_cpu_to_le32(0x00000040),
+	FILE_ATTR_NORMAL		= const_cpu_to_le32(0x00000080),
+
+	FILE_ATTR_TEMPORARY		= const_cpu_to_le32(0x00000100),
+	FILE_ATTR_SPARSE_FILE		= const_cpu_to_le32(0x00000200),
+	FILE_ATTR_REPARSE_POINT		= const_cpu_to_le32(0x00000400),
+	FILE_ATTR_COMPRESSED		= const_cpu_to_le32(0x00000800),
+
+	FILE_ATTR_OFFLINE		= const_cpu_to_le32(0x00001000),
+	FILE_ATTR_NOT_CONTENT_INDEXED	= const_cpu_to_le32(0x00002000),
+	FILE_ATTR_ENCRYPTED		= const_cpu_to_le32(0x00004000),
+
+	FILE_ATTR_VALID_FLAGS		= const_cpu_to_le32(0x00007fb7),
+	/* FILE_ATTR_VALID_FLAGS masks out the old DOS VolId and the
+	   FILE_ATTR_DEVICE and preserves everything else. This mask
+	   is used to obtain all flags that are valid for reading. */
+	FILE_ATTR_VALID_SET_FLAGS	= const_cpu_to_le32(0x000031a7),
+	/* FILE_ATTR_VALID_SET_FLAGS masks out the old DOS VolId, the
+	   FILE_ATTR_DEVICE, FILE_ATTR_DIRECTORY, FILE_ATTR_SPARSE_FILE,
+	   FILE_ATTR_REPARSE_POINT, FILE_ATRE_COMPRESSED and FILE_ATTR_ENCRYPTED
+	   and preserves the rest. This mask is used to to obtain all flags that
+	   are valid for setting. */
+
+	/**
+	 * FILE_ATTR_I30_INDEX_PRESENT - Is it a directory?
+	 *
+	 * This is a copy of the MFT_RECORD_IS_DIRECTORY bit from the mft
+	 * record, telling us whether this is a directory or not, i.e. whether
+	 * it has an index root attribute named "$I30" or not.
+	 * 
+	 * This flag is only present in the FILE_NAME attribute (in the 
+	 * file_attributes field).
+	 */
+	FILE_ATTR_I30_INDEX_PRESENT	= const_cpu_to_le32(0x10000000),
+	
+	/**
+	 * FILE_ATTR_VIEW_INDEX_PRESENT - Does have a non-directory index?
+	 * 
+	 * This is a copy of the MFT_RECORD_IS_VIEW_INDEX bit from the mft
+	 * record, telling us whether this file has a view index present (eg.
+	 * object id index, quota index, one of the security indexes and the
+	 * reparse points index).
+	 *
+	 * This flag is only present in the $STANDARD_INFORMATION and
+	 * $FILE_NAME attributes.
+	 */
+	FILE_ATTR_VIEW_INDEX_PRESENT	= const_cpu_to_le32(0x20000000),
+} __attribute__((__packed__)) FILE_ATTR_FLAGS;
+
+/*
+ * NOTE on times in NTFS: All times are in MS standard time format, i.e. they
+ * are the number of 100-nanosecond intervals since 1st January 1601, 00:00:00
+ * universal coordinated time (UTC). (In Linux time starts 1st January 1970,
+ * 00:00:00 UTC and is stored as the number of 1-second intervals since then.)
+ */
+
+/**
+ * struct STANDARD_INFORMATION - Attribute: Standard information (0x10).
+ *
+ * NOTE: Always resident.
+ * NOTE: Present in all base file records on a volume.
+ * NOTE: There is conflicting information about the meaning of each of the time
+ *	 fields but the meaning as defined below has been verified to be
+ *	 correct by practical experimentation on Windows NT4 SP6a and is hence
+ *	 assumed to be the one and only correct interpretation.
+ */
+typedef struct {
+/*Ofs*/
+/*  0*/	s64 creation_time;		/* Time file was created. Updated when
+					   a filename is changed(?). */
+/*  8*/	s64 last_data_change_time;	/* Time the data attribute was last
+					   modified. */
+/* 16*/	s64 last_mft_change_time;	/* Time this mft record was last
+					   modified. */
+/* 24*/	s64 last_access_time;		/* Approximate time when the file was
+					   last accessed (obviously this is not
+					   updated on read-only volumes). In
+					   Windows this is only updated when
+					   accessed if some time delta has
+					   passed since the last update. Also,
+					   last access times updates can be
+					   disabled altogether for speed. */
+/* 32*/	FILE_ATTR_FLAGS file_attributes; /* Flags describing the file. */
+/* 36*/	union {
+		/* NTFS 1.2 (and previous, presumably) */
+		struct {
+		/* 36 */ u8 reserved12[12];	/* Reserved/alignment to 8-byte
+						   boundary. */
+		/* 48 */ void *v1_end[0];	/* Marker for offsetof(). */
+		} __attribute__((__packed__));
+/* sizeof() = 48 bytes */
+		/* NTFS 3.0 */
+		struct {
+/*
+ * If a volume has been upgraded from a previous NTFS version, then these
+ * fields are present only if the file has been accessed since the upgrade.
+ * Recognize the difference by comparing the length of the resident attribute
+ * value. If it is 48, then the following fields are missing. If it is 72 then
+ * the fields are present. Maybe just check like this:
+ *	if (resident.ValueLength < sizeof(STANDARD_INFORMATION)) {
+ *		Assume NTFS 1.2- format.
+ *		If (volume version is 3.0+)
+ *			Upgrade attribute to NTFS 3.0 format.
+ *		else
+ *			Use NTFS 1.2- format for access.
+ *	} else
+ *		Use NTFS 3.0 format for access.
+ * Only problem is that it might be legal to set the length of the value to
+ * arbitrarily large values thus spoiling this check. - But chkdsk probably
+ * views that as a corruption, assuming that it behaves like this for all
+ * attributes.
+ */
+		/* 36*/	u32 maximum_versions;	/* Maximum allowed versions for
+				file. Zero if version numbering is disabled. */
+		/* 40*/	u32 version_number;	/* This file's version (if any).
+				Set to zero if maximum_versions is zero. */
+		/* 44*/	u32 class_id;		/* Class id from bidirectional
+				class id index (?). */
+		/* 48*/	u32 owner_id;		/* Owner_id of the user owning
+				the file. Translate via $Q index in FILE_Extend
+				/$Quota to the quota control entry for the user
+				owning the file. Zero if quotas are disabled. */
+		/* 52*/	u32 security_id;	/* Security_id for the file.
+				Translate via $SII index and $SDS data stream
+				in FILE_Secure to the security descriptor. */
+		/* 56*/	u64 quota_charged;	/* Byte size of the charge to
+				the quota for all streams of the file. Note: Is
+				zero if quotas are disabled. */
+		/* 64*/	u64 usn;		/* Last update sequence number
+				of the file. This is a direct index into the
+				change (aka usn) journal file. It is zero if
+				the usn journal is disabled.
+				NOTE: To disable the journal need to delete
+				the journal file itself and to then walk the
+				whole mft and set all Usn entries in all mft
+				records to zero! (This can take a while!)
+				The journal is FILE_Extend/$UsnJrnl. Win2k
+				will recreate the journal and initiate
+				logging if necessary when mounting the
+				partition. This, in contrast to disabling the
+				journal is a very fast process, so the user
+				won't even notice it. */
+		/* 72*/ void *v3_end[0]; /* Marker for offsetof(). */
+		} __attribute__((__packed__));
+	} __attribute__((__packed__));
+/* sizeof() = 72 bytes (NTFS 3.0) */
+} __attribute__((__packed__)) STANDARD_INFORMATION;
+
+/**
+ * struct ATTR_LIST_ENTRY - Attribute: Attribute list (0x20).
+ *
+ * - Can be either resident or non-resident.
+ * - Value consists of a sequence of variable length, 8-byte aligned,
+ * ATTR_LIST_ENTRY records.
+ * - The attribute list attribute contains one entry for each attribute of
+ * the file in which the list is located, except for the list attribute
+ * itself. The list is sorted: first by attribute type, second by attribute
+ * name (if present), third by instance number. The extents of one
+ * non-resident attribute (if present) immediately follow after the initial
+ * extent. They are ordered by lowest_vcn and have their instance set to zero.
+ * It is not allowed to have two attributes with all sorting keys equal.
+ * - Further restrictions:
+ *	- If not resident, the vcn to lcn mapping array has to fit inside the
+ *	  base mft record.
+ *	- The attribute list attribute value has a maximum size of 256kb. This
+ *	  is imposed by the Windows cache manager.
+ * - Attribute lists are only used when the attributes of mft record do not
+ * fit inside the mft record despite all attributes (that can be made
+ * non-resident) having been made non-resident. This can happen e.g. when:
+ *	- File has a large number of hard links (lots of file name
+ *	  attributes present).
+ *	- The mapping pairs array of some non-resident attribute becomes so
+ *	  large due to fragmentation that it overflows the mft record.
+ *	- The security descriptor is very complex (not applicable to
+ *	  NTFS 3.0 volumes).
+ *	- There are many named streams.
+ */
+typedef struct {
+/*Ofs*/
+/*  0*/	ATTR_TYPES type;	/* Type of referenced attribute. */
+/*  4*/	u16 length;		/* Byte size of this entry. */
+/*  6*/	u8 name_length;		/* Size in Unicode chars of the name of the
+				   attribute or 0 if unnamed. */
+/*  7*/	u8 name_offset;		/* Byte offset to beginning of attribute name
+				   (always set this to where the name would
+				   start even if unnamed). */
+/*  8*/	VCN lowest_vcn;		/* Lowest virtual cluster number of this portion
+				   of the attribute value. This is usually 0. It
+				   is non-zero for the case where one attribute
+				   does not fit into one mft record and thus
+				   several mft records are allocated to hold
+				   this attribute. In the latter case, each mft
+				   record holds one extent of the attribute and
+				   there is one attribute list entry for each
+				   extent. NOTE: This is DEFINITELY a signed
+				   value! The windows driver uses cmp, followed
+				   by jg when comparing this, thus it treats it
+				   as signed. */
+/* 16*/	MFT_REF mft_reference;	/* The reference of the mft record holding
+				   the ATTR_RECORD for this portion of the
+				   attribute value. */
+/* 24*/	u16 instance;		/* If lowest_vcn = 0, the instance of the
+				   attribute being referenced; otherwise 0. */
+/* 26*/	ntfschar name[0];	/* Use when creating only. When reading use
+				   name_offset to determine the location of the
+				   name. */
+/* sizeof() = 26 + (attribute_name_length * 2) bytes */
+} __attribute__((__packed__)) ATTR_LIST_ENTRY;
+
+/*
+ * The maximum allowed length for a file name.
+ */
+#define NTFS_MAX_NAME_LEN	255
+
+/**
+ * enum FILE_NAME_TYPE_FLAGS - Possible namespaces for filenames in ntfs.
+ * (8-bit).
+ */
+typedef enum {
+	FILE_NAME_POSIX			= 0x00,
+		/* This is the largest namespace. It is case sensitive and
+		   allows all Unicode characters except for: '\0' and '/'.
+		   Beware that in WinNT/2k files which eg have the same name
+		   except for their case will not be distinguished by the
+		   standard utilities and thus a "del filename" will delete
+		   both "filename" and "fileName" without warning. */
+	FILE_NAME_WIN32			= 0x01,
+		/* The standard WinNT/2k NTFS long filenames. Case insensitive.
+		   All Unicode chars except: '\0', '"', '*', '/', ':', '<',
+		   '>', '?', '\' and '|'. Further, names cannot end with a '.'
+		   or a space. */
+	FILE_NAME_DOS			= 0x02,
+		/* The standard DOS filenames (8.3 format). Uppercase only.
+		   All 8-bit characters greater space, except: '"', '*', '+',
+		   ',', '/', ':', ';', '<', '=', '>', '?' and '\'. */
+	FILE_NAME_WIN32_AND_DOS		= 0x03,
+		/* 3 means that both the Win32 and the DOS filenames are
+		   identical and hence have been saved in this single filename
+		   record. */
+} __attribute__((__packed__)) FILE_NAME_TYPE_FLAGS;
+
+/**
+ * struct FILE_NAME_ATTR - Attribute: Filename (0x30).
+ *
+ * NOTE: Always resident.
+ * NOTE: All fields, except the parent_directory, are only updated when the
+ *	 filename is changed. Until then, they just become out of sync with
+ *	 reality and the more up to date values are present in the standard
+ *	 information attribute.
+ * NOTE: There is conflicting information about the meaning of each of the time
+ *	 fields but the meaning as defined below has been verified to be
+ *	 correct by practical experimentation on Windows NT4 SP6a and is hence
+ *	 assumed to be the one and only correct interpretation.
+ */
+typedef struct {
+/*hex ofs*/
+/*  0*/	MFT_REF parent_directory;	/* Directory this filename is
+					   referenced from. */
+/*  8*/	s64 creation_time;		/* Time file was created. */
+/* 10*/	s64 last_data_change_time;	/* Time the data attribute was last
+					   modified. */
+/* 18*/	s64 last_mft_change_time;	/* Time this mft record was last
+					   modified. */
+/* 20*/	s64 last_access_time;		/* Last time this mft record was
+					   accessed. */
+/* 28*/	s64 allocated_size;		/* Byte size of on-disk allocated space
+					   for the data attribute.  So for
+					   normal $DATA, this is the
+					   allocated_size from the unnamed
+					   $DATA attribute and for compressed
+					   and/or sparse $DATA, this is the
+					   compressed_size from the unnamed
+					   $DATA attribute.  NOTE: This is a
+					   multiple of the cluster size. */
+/* 30*/	s64 data_size;			/* Byte size of actual data in data
+					   attribute. */
+/* 38*/	FILE_ATTR_FLAGS file_attributes;	/* Flags describing the file. */
+/* 3c*/	union {
+	/* 3c*/	struct {
+		/* 3c*/	u16 packed_ea_size;	/* Size of the buffer needed to
+						   pack the extended attributes
+						   (EAs), if such are present.*/
+		/* 3e*/	u16 reserved;		/* Reserved for alignment. */
+		} __attribute__((__packed__));
+	/* 3c*/	u32 reparse_point_tag;		/* Type of reparse point,
+						   present only in reparse
+						   points and only if there are
+						   no EAs. */
+	} __attribute__((__packed__));
+/* 40*/	u8 file_name_length;			/* Length of file name in
+						   (Unicode) characters. */
+/* 41*/	FILE_NAME_TYPE_FLAGS file_name_type;	/* Namespace of the file name.*/
+/* 42*/	ntfschar file_name[0];			/* File name in Unicode. */
+} __attribute__((__packed__)) FILE_NAME_ATTR;
+
+/**
+ * struct GUID - GUID structures store globally unique identifiers (GUID).
+ *
+ * A GUID is a 128-bit value consisting of one group of eight hexadecimal
+ * digits, followed by three groups of four hexadecimal digits each, followed
+ * by one group of twelve hexadecimal digits. GUIDs are Microsoft's
+ * implementation of the distributed computing environment (DCE) universally
+ * unique identifier (UUID).
+ *
+ * Example of a GUID:
+ *	1F010768-5A73-BC91-0010-A52216A7227B
+ */
+typedef struct {
+	u32 data1;	/* The first eight hexadecimal digits of the GUID. */
+	u16 data2;	/* The first group of four hexadecimal digits. */
+	u16 data3;	/* The second group of four hexadecimal digits. */
+	u8 data4[8];	/* The first two bytes are the third group of four
+			   hexadecimal digits. The remaining six bytes are the
+			   final 12 hexadecimal digits. */
+} __attribute__((__packed__)) GUID;
+
+/**
+ * struct OBJ_ID_INDEX_DATA - FILE_Extend/$ObjId contains an index named $O.
+ *
+ * This index contains all object_ids present on the volume as the index keys
+ * and the corresponding mft_record numbers as the index entry data parts.
+ *
+ * The data part (defined below) also contains three other object_ids:
+ *	birth_volume_id - object_id of FILE_Volume on which the file was first
+ *			  created. Optional (i.e. can be zero).
+ *	birth_object_id - object_id of file when it was first created. Usually
+ *			  equals the object_id. Optional (i.e. can be zero).
+ *	domain_id	- Reserved (always zero).
+ */
+typedef struct {
+	MFT_REF mft_reference;	/* Mft record containing the object_id in
+				   the index entry key. */
+	union {
+		struct {
+			GUID birth_volume_id;
+			GUID birth_object_id;
+			GUID domain_id;
+		} __attribute__((__packed__));
+		u8 extended_info[48];
+	} __attribute__((__packed__));
+} __attribute__((__packed__)) OBJ_ID_INDEX_DATA;
+
+/**
+ * struct OBJECT_ID_ATTR - Attribute: Object id (NTFS 3.0+) (0x40).
+ *
+ * NOTE: Always resident.
+ */
+typedef struct {
+	GUID object_id;				/* Unique id assigned to the
+						   file.*/
+	/* The following fields are optional. The attribute value size is 16
+	   bytes, i.e. sizeof(GUID), if these are not present at all. Note,
+	   the entries can be present but one or more (or all) can be zero
+	   meaning that that particular value(s) is(are) not defined. Note,
+	   when the fields are missing here, it is well possible that they are
+	   to be found within the $Extend/$ObjId system file indexed under the
+	   above object_id. */
+	union {
+		struct {
+			GUID birth_volume_id;	/* Unique id of volume on which
+						   the file was first created.*/
+			GUID birth_object_id;	/* Unique id of file when it was
+						   first created. */
+			GUID domain_id;		/* Reserved, zero. */
+		} __attribute__((__packed__));
+		u8 extended_info[48];
+	} __attribute__((__packed__));
+} __attribute__((__packed__)) OBJECT_ID_ATTR;
+
+#if 0
+/**
+ * enum IDENTIFIER_AUTHORITIES -
+ *
+ * The pre-defined IDENTIFIER_AUTHORITIES used as SID_IDENTIFIER_AUTHORITY in
+ * the SID structure (see below).
+ */
+typedef enum {					/* SID string prefix. */
+	SECURITY_NULL_SID_AUTHORITY	= {0, 0, 0, 0, 0, 0},	/* S-1-0 */
+	SECURITY_WORLD_SID_AUTHORITY	= {0, 0, 0, 0, 0, 1},	/* S-1-1 */
+	SECURITY_LOCAL_SID_AUTHORITY	= {0, 0, 0, 0, 0, 2},	/* S-1-2 */
+	SECURITY_CREATOR_SID_AUTHORITY	= {0, 0, 0, 0, 0, 3},	/* S-1-3 */
+	SECURITY_NON_UNIQUE_AUTHORITY	= {0, 0, 0, 0, 0, 4},	/* S-1-4 */
+	SECURITY_NT_SID_AUTHORITY	= {0, 0, 0, 0, 0, 5},	/* S-1-5 */
+} IDENTIFIER_AUTHORITIES;
+#endif
+
+/**
+ * enum RELATIVE_IDENTIFIERS -
+ *
+ * These relative identifiers (RIDs) are used with the above identifier
+ * authorities to make up universal well-known SIDs.
+ *
+ * Note: The relative identifier (RID) refers to the portion of a SID, which
+ * identifies a user or group in relation to the authority that issued the SID.
+ * For example, the universal well-known SID Creator Owner ID (S-1-3-0) is
+ * made up of the identifier authority SECURITY_CREATOR_SID_AUTHORITY (3) and
+ * the relative identifier SECURITY_CREATOR_OWNER_RID (0).
+ */
+typedef enum {					/* Identifier authority. */
+	SECURITY_NULL_RID		  = 0,	/* S-1-0 */
+	SECURITY_WORLD_RID		  = 0,	/* S-1-1 */
+	SECURITY_LOCAL_RID		  = 0,	/* S-1-2 */
+
+	SECURITY_CREATOR_OWNER_RID	  = 0,	/* S-1-3 */
+	SECURITY_CREATOR_GROUP_RID	  = 1,	/* S-1-3 */
+
+	SECURITY_CREATOR_OWNER_SERVER_RID = 2,	/* S-1-3 */
+	SECURITY_CREATOR_GROUP_SERVER_RID = 3,	/* S-1-3 */
+
+	SECURITY_DIALUP_RID		  = 1,
+	SECURITY_NETWORK_RID		  = 2,
+	SECURITY_BATCH_RID		  = 3,
+	SECURITY_INTERACTIVE_RID	  = 4,
+	SECURITY_SERVICE_RID		  = 6,
+	SECURITY_ANONYMOUS_LOGON_RID	  = 7,
+	SECURITY_PROXY_RID		  = 8,
+	SECURITY_ENTERPRISE_CONTROLLERS_RID=9,
+	SECURITY_SERVER_LOGON_RID	  = 9,
+	SECURITY_PRINCIPAL_SELF_RID	  = 0xa,
+	SECURITY_AUTHENTICATED_USER_RID	  = 0xb,
+	SECURITY_RESTRICTED_CODE_RID	  = 0xc,
+	SECURITY_TERMINAL_SERVER_RID	  = 0xd,
+
+	SECURITY_LOGON_IDS_RID		  = 5,
+	SECURITY_LOGON_IDS_RID_COUNT	  = 3,
+
+	SECURITY_LOCAL_SYSTEM_RID	  = 0x12,
+
+	SECURITY_NT_NON_UNIQUE		  = 0x15,
+
+	SECURITY_BUILTIN_DOMAIN_RID	  = 0x20,
+
+	/*
+	 * Well-known domain relative sub-authority values (RIDs).
+	 */
+
+	/* Users. */
+	DOMAIN_USER_RID_ADMIN		  = 0x1f4,
+	DOMAIN_USER_RID_GUEST		  = 0x1f5,
+	DOMAIN_USER_RID_KRBTGT		  = 0x1f6,
+
+	/* Groups. */
+	DOMAIN_GROUP_RID_ADMINS		  = 0x200,
+	DOMAIN_GROUP_RID_USERS		  = 0x201,
+	DOMAIN_GROUP_RID_GUESTS		  = 0x202,
+	DOMAIN_GROUP_RID_COMPUTERS	  = 0x203,
+	DOMAIN_GROUP_RID_CONTROLLERS	  = 0x204,
+	DOMAIN_GROUP_RID_CERT_ADMINS	  = 0x205,
+	DOMAIN_GROUP_RID_SCHEMA_ADMINS	  = 0x206,
+	DOMAIN_GROUP_RID_ENTERPRISE_ADMINS= 0x207,
+	DOMAIN_GROUP_RID_POLICY_ADMINS	  = 0x208,
+
+	/* Aliases. */
+	DOMAIN_ALIAS_RID_ADMINS		  = 0x220,
+	DOMAIN_ALIAS_RID_USERS		  = 0x221,
+	DOMAIN_ALIAS_RID_GUESTS		  = 0x222,
+	DOMAIN_ALIAS_RID_POWER_USERS	  = 0x223,
+
+	DOMAIN_ALIAS_RID_ACCOUNT_OPS	  = 0x224,
+	DOMAIN_ALIAS_RID_SYSTEM_OPS	  = 0x225,
+	DOMAIN_ALIAS_RID_PRINT_OPS	  = 0x226,
+	DOMAIN_ALIAS_RID_BACKUP_OPS	  = 0x227,
+
+	DOMAIN_ALIAS_RID_REPLICATOR	  = 0x228,
+	DOMAIN_ALIAS_RID_RAS_SERVERS	  = 0x229,
+	DOMAIN_ALIAS_RID_PREW2KCOMPACCESS = 0x22a,
+} RELATIVE_IDENTIFIERS;
+
+/*
+ * The universal well-known SIDs:
+ *
+ *	NULL_SID			S-1-0-0
+ *	WORLD_SID			S-1-1-0
+ *	LOCAL_SID			S-1-2-0
+ *	CREATOR_OWNER_SID		S-1-3-0
+ *	CREATOR_GROUP_SID		S-1-3-1
+ *	CREATOR_OWNER_SERVER_SID	S-1-3-2
+ *	CREATOR_GROUP_SERVER_SID	S-1-3-3
+ *
+ *	(Non-unique IDs)		S-1-4
+ *
+ * NT well-known SIDs:
+ *
+ *	NT_AUTHORITY_SID	S-1-5
+ *	DIALUP_SID		S-1-5-1
+ *
+ *	NETWORD_SID		S-1-5-2
+ *	BATCH_SID		S-1-5-3
+ *	INTERACTIVE_SID		S-1-5-4
+ *	SERVICE_SID		S-1-5-6
+ *	ANONYMOUS_LOGON_SID	S-1-5-7		(aka null logon session)
+ *	PROXY_SID		S-1-5-8
+ *	SERVER_LOGON_SID	S-1-5-9		(aka domain controller account)
+ *	SELF_SID		S-1-5-10	(self RID)
+ *	AUTHENTICATED_USER_SID	S-1-5-11
+ *	RESTRICTED_CODE_SID	S-1-5-12	(running restricted code)
+ *	TERMINAL_SERVER_SID	S-1-5-13	(running on terminal server)
+ *
+ *	(Logon IDs)		S-1-5-5-X-Y
+ *
+ *	(NT non-unique IDs)	S-1-5-0x15-...
+ *
+ *	(Built-in domain)	S-1-5-0x20
+ */
+
+/**
+ * union SID_IDENTIFIER_AUTHORITY - A 48-bit value used in the SID structure
+ *
+ * NOTE: This is stored as a big endian number.
+ */
+typedef union {
+	struct {
+		u16 high_part;		/* High 16-bits. */
+		u32 low_part;		/* Low 32-bits. */
+	} __attribute__((__packed__));
+	u8 value[6];			/* Value as individual bytes. */
+} __attribute__((__packed__)) SID_IDENTIFIER_AUTHORITY;
+
+/**
+ * struct SID -
+ *
+ * The SID structure is a variable-length structure used to uniquely identify
+ * users or groups. SID stands for security identifier.
+ *
+ * The standard textual representation of the SID is of the form:
+ *	S-R-I-S-S...
+ * Where:
+ *    - The first "S" is the literal character 'S' identifying the following
+ *	digits as a SID.
+ *    - R is the revision level of the SID expressed as a sequence of digits
+ *	in decimal.
+ *    - I is the 48-bit identifier_authority, expressed as digits in decimal,
+ *	if I < 2^32, or hexadecimal prefixed by "0x", if I >= 2^32.
+ *    - S... is one or more sub_authority values, expressed as digits in
+ *	decimal.
+ *
+ * Example SID; the domain-relative SID of the local Administrators group on
+ * Windows NT/2k:
+ *	S-1-5-32-544
+ * This translates to a SID with:
+ *	revision = 1,
+ *	sub_authority_count = 2,
+ *	identifier_authority = {0,0,0,0,0,5},	// SECURITY_NT_AUTHORITY
+ *	sub_authority[0] = 32,			// SECURITY_BUILTIN_DOMAIN_RID
+ *	sub_authority[1] = 544			// DOMAIN_ALIAS_RID_ADMINS
+ */
+typedef struct {
+	u8 revision;
+	u8 sub_authority_count;
+	SID_IDENTIFIER_AUTHORITY identifier_authority;
+	u32 sub_authority[1];		/* At least one sub_authority. */
+} __attribute__((__packed__)) SID;
+
+/**
+ * enum SID_CONSTANTS - Current constants for SIDs.
+ */
+typedef enum {
+	SID_REVISION			=  1,	/* Current revision level. */
+	SID_MAX_SUB_AUTHORITIES		= 15,	/* Maximum number of those. */
+	SID_RECOMMENDED_SUB_AUTHORITIES	=  1,	/* Will change to around 6 in
+						   a future revision. */
+} SID_CONSTANTS;
+
+/**
+ * enum ACE_TYPES - The predefined ACE types (8-bit, see below).
+ */
+typedef enum {
+	ACCESS_MIN_MS_ACE_TYPE		= 0,
+	ACCESS_ALLOWED_ACE_TYPE		= 0,
+	ACCESS_DENIED_ACE_TYPE		= 1,
+	SYSTEM_AUDIT_ACE_TYPE		= 2,
+	SYSTEM_ALARM_ACE_TYPE		= 3, /* Not implemented as of Win2k. */
+	ACCESS_MAX_MS_V2_ACE_TYPE	= 3,
+
+	ACCESS_ALLOWED_COMPOUND_ACE_TYPE= 4,
+	ACCESS_MAX_MS_V3_ACE_TYPE	= 4,
+
+	/* The following are Win2k only. */
+	ACCESS_MIN_MS_OBJECT_ACE_TYPE	= 5,
+	ACCESS_ALLOWED_OBJECT_ACE_TYPE	= 5,
+	ACCESS_DENIED_OBJECT_ACE_TYPE	= 6,
+	SYSTEM_AUDIT_OBJECT_ACE_TYPE	= 7,
+	SYSTEM_ALARM_OBJECT_ACE_TYPE	= 8,
+	ACCESS_MAX_MS_OBJECT_ACE_TYPE	= 8,
+
+	ACCESS_MAX_MS_V4_ACE_TYPE	= 8,
+
+	/* This one is for WinNT&2k. */
+	ACCESS_MAX_MS_ACE_TYPE		= 8,
+} __attribute__((__packed__)) ACE_TYPES;
+
+/**
+ * enum ACE_FLAGS - The ACE flags (8-bit) for audit and inheritance.
+ *
+ * SUCCESSFUL_ACCESS_ACE_FLAG is only used with system audit and alarm ACE
+ * types to indicate that a message is generated (in Windows!) for successful
+ * accesses.
+ *
+ * FAILED_ACCESS_ACE_FLAG is only used with system audit and alarm ACE types
+ * to indicate that a message is generated (in Windows!) for failed accesses.
+ */
+typedef enum {
+	/* The inheritance flags. */
+	OBJECT_INHERIT_ACE		= 0x01,
+	CONTAINER_INHERIT_ACE		= 0x02,
+	NO_PROPAGATE_INHERIT_ACE	= 0x04,
+	INHERIT_ONLY_ACE		= 0x08,
+	INHERITED_ACE			= 0x10,	/* Win2k only. */
+	VALID_INHERIT_FLAGS		= 0x1f,
+
+	/* The audit flags. */
+	SUCCESSFUL_ACCESS_ACE_FLAG	= 0x40,
+	FAILED_ACCESS_ACE_FLAG		= 0x80,
+} __attribute__((__packed__)) ACE_FLAGS;
+
+/**
+ * struct ACE_HEADER -
+ *
+ * An ACE is an access-control entry in an access-control list (ACL).
+ * An ACE defines access to an object for a specific user or group or defines
+ * the types of access that generate system-administration messages or alarms
+ * for a specific user or group. The user or group is identified by a security
+ * identifier (SID).
+ *
+ * Each ACE starts with an ACE_HEADER structure (aligned on 4-byte boundary),
+ * which specifies the type and size of the ACE. The format of the subsequent
+ * data depends on the ACE type.
+ */
+typedef struct {
+	ACE_TYPES type;		/* Type of the ACE. */
+	ACE_FLAGS flags;	/* Flags describing the ACE. */
+	u16 size;		/* Size in bytes of the ACE. */
+} __attribute__((__packed__)) ACE_HEADER;
+
+/**
+ * enum ACCESS_MASK - The access mask (32-bit).
+ *
+ * Defines the access rights.
+ */
+typedef enum {
+	/*
+	 * The specific rights (bits 0 to 15). Depend on the type of the
+	 * object being secured by the ACE.
+	 */
+
+	/* Specific rights for files and directories are as follows: */
+
+	/* Right to read data from the file. (FILE) */
+	FILE_READ_DATA			= const_cpu_to_le32(0x00000001),
+	/* Right to list contents of a directory. (DIRECTORY) */
+	FILE_LIST_DIRECTORY		= const_cpu_to_le32(0x00000001),
+
+	/* Right to write data to the file. (FILE) */
+	FILE_WRITE_DATA			= const_cpu_to_le32(0x00000002),
+	/* Right to create a file in the directory. (DIRECTORY) */
+	FILE_ADD_FILE			= const_cpu_to_le32(0x00000002),
+
+	/* Right to append data to the file. (FILE) */
+	FILE_APPEND_DATA		= const_cpu_to_le32(0x00000004),
+	/* Right to create a subdirectory. (DIRECTORY) */
+	FILE_ADD_SUBDIRECTORY		= const_cpu_to_le32(0x00000004),
+
+	/* Right to read extended attributes. (FILE/DIRECTORY) */
+	FILE_READ_EA			= const_cpu_to_le32(0x00000008),
+
+	/* Right to write extended attributes. (FILE/DIRECTORY) */
+	FILE_WRITE_EA			= const_cpu_to_le32(0x00000010),
+
+	/* Right to execute a file. (FILE) */
+	FILE_EXECUTE			= const_cpu_to_le32(0x00000020),
+	/* Right to traverse the directory. (DIRECTORY) */
+	FILE_TRAVERSE			= const_cpu_to_le32(0x00000020),
+
+	/*
+	 * Right to delete a directory and all the files it contains (its
+	 * children), even if the files are read-only. (DIRECTORY)
+	 */
+	FILE_DELETE_CHILD		= const_cpu_to_le32(0x00000040),
+
+	/* Right to read file attributes. (FILE/DIRECTORY) */
+	FILE_READ_ATTRIBUTES		= const_cpu_to_le32(0x00000080),
+
+	/* Right to change file attributes. (FILE/DIRECTORY) */
+	FILE_WRITE_ATTRIBUTES		= const_cpu_to_le32(0x00000100),
+
+	/*
+	 * The standard rights (bits 16 to 23). Are independent of the type of
+	 * object being secured.
+	 */
+
+	/* Right to delete the object. */
+	DELETE				= const_cpu_to_le32(0x00010000),
+
+	/*
+	 * Right to read the information in the object's security descriptor,
+	 * not including the information in the SACL. I.e. right to read the
+	 * security descriptor and owner.
+	 */
+	READ_CONTROL			= const_cpu_to_le32(0x00020000),
+
+	/* Right to modify the DACL in the object's security descriptor. */
+	WRITE_DAC			= const_cpu_to_le32(0x00040000),
+
+	/* Right to change the owner in the object's security descriptor. */
+	WRITE_OWNER			= const_cpu_to_le32(0x00080000),
+
+	/*
+	 * Right to use the object for synchronization. Enables a process to
+	 * wait until the object is in the signalled state. Some object types
+	 * do not support this access right.
+	 */
+	SYNCHRONIZE			= const_cpu_to_le32(0x00100000),
+
+	/*
+	 * The following STANDARD_RIGHTS_* are combinations of the above for
+	 * convenience and are defined by the Win32 API.
+	 */
+
+	/* These are currently defined to READ_CONTROL. */
+	STANDARD_RIGHTS_READ		= const_cpu_to_le32(0x00020000),
+	STANDARD_RIGHTS_WRITE		= const_cpu_to_le32(0x00020000),
+	STANDARD_RIGHTS_EXECUTE		= const_cpu_to_le32(0x00020000),
+
+	/* Combines DELETE, READ_CONTROL, WRITE_DAC, and WRITE_OWNER access. */
+	STANDARD_RIGHTS_REQUIRED	= const_cpu_to_le32(0x000f0000),
+
+	/*
+	 * Combines DELETE, READ_CONTROL, WRITE_DAC, WRITE_OWNER, and
+	 * SYNCHRONIZE access.
+	 */
+	STANDARD_RIGHTS_ALL		= const_cpu_to_le32(0x001f0000),
+
+	/*
+	 * The access system ACL and maximum allowed access types (bits 24 to
+	 * 25, bits 26 to 27 are reserved).
+	 */
+	ACCESS_SYSTEM_SECURITY		= const_cpu_to_le32(0x01000000),
+	MAXIMUM_ALLOWED			= const_cpu_to_le32(0x02000000),
+
+	/*
+	 * The generic rights (bits 28 to 31). These map onto the standard and
+	 * specific rights.
+	 */
+
+	/* Read, write, and execute access. */
+	GENERIC_ALL			= const_cpu_to_le32(0x10000000),
+
+	/* Execute access. */
+	GENERIC_EXECUTE			= const_cpu_to_le32(0x20000000),
+
+	/*
+	 * Write access. For files, this maps onto:
+	 *	FILE_APPEND_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_DATA |
+	 *	FILE_WRITE_EA | STANDARD_RIGHTS_WRITE | SYNCHRONIZE
+	 * For directories, the mapping has the same numerical value. See
+	 * above for the descriptions of the rights granted.
+	 */
+	GENERIC_WRITE			= const_cpu_to_le32(0x40000000),
+
+	/*
+	 * Read access. For files, this maps onto:
+	 *	FILE_READ_ATTRIBUTES | FILE_READ_DATA | FILE_READ_EA |
+	 *	STANDARD_RIGHTS_READ | SYNCHRONIZE
+	 * For directories, the mapping has the same numerical value. See
+	 * above for the descriptions of the rights granted.
+	 */
+	GENERIC_READ			= const_cpu_to_le32(0x80000000),
+} ACCESS_MASK;
+
+/**
+ * struct GENERIC_MAPPING -
+ *
+ * The generic mapping array. Used to denote the mapping of each generic
+ * access right to a specific access mask.
+ *
+ * FIXME: What exactly is this and what is it for? (AIA)
+ */
+typedef struct {
+	ACCESS_MASK generic_read;
+	ACCESS_MASK generic_write;
+	ACCESS_MASK generic_execute;
+	ACCESS_MASK generic_all;
+} __attribute__((__packed__)) GENERIC_MAPPING;
+
+/*
+ * The predefined ACE type structures are as defined below.
+ */
+
+/**
+ * struct ACCESS_DENIED_ACE -
+ *
+ * ACCESS_ALLOWED_ACE, ACCESS_DENIED_ACE, SYSTEM_AUDIT_ACE, SYSTEM_ALARM_ACE
+ */
+typedef struct {
+/*  0	ACE_HEADER; -- Unfolded here as gcc doesn't like unnamed structs. */
+	ACE_TYPES type;		/* Type of the ACE. */
+	ACE_FLAGS flags;	/* Flags describing the ACE. */
+	u16 size;		/* Size in bytes of the ACE. */
+
+/*  4*/	ACCESS_MASK mask;	/* Access mask associated with the ACE. */
+/*  8*/	SID sid;		/* The SID associated with the ACE. */
+} __attribute__((__packed__)) ACCESS_ALLOWED_ACE, ACCESS_DENIED_ACE,
+			       SYSTEM_AUDIT_ACE, SYSTEM_ALARM_ACE;
+
+/**
+ * enum OBJECT_ACE_FLAGS - The object ACE flags (32-bit).
+ */
+typedef enum {
+	ACE_OBJECT_TYPE_PRESENT			= const_cpu_to_le32(1),
+	ACE_INHERITED_OBJECT_TYPE_PRESENT	= const_cpu_to_le32(2),
+} OBJECT_ACE_FLAGS;
+
+/**
+ * struct ACCESS_ALLOWED_OBJECT_ACE -
+ */
+typedef struct {
+/*  0	ACE_HEADER; -- Unfolded here as gcc doesn't like unnamed structs. */
+	ACE_TYPES type;		/* Type of the ACE. */
+	ACE_FLAGS flags;	/* Flags describing the ACE. */
+	u16 size;		/* Size in bytes of the ACE. */
+
+/*  4*/	ACCESS_MASK mask;	/* Access mask associated with the ACE. */
+/*  8*/	OBJECT_ACE_FLAGS object_flags;	/* Flags describing the object ACE. */
+/* 12*/	GUID object_type;
+/* 28*/	GUID inherited_object_type;
+/* 44*/	SID sid;		/* The SID associated with the ACE. */
+} __attribute__((__packed__)) ACCESS_ALLOWED_OBJECT_ACE,
+			       ACCESS_DENIED_OBJECT_ACE,
+			       SYSTEM_AUDIT_OBJECT_ACE,
+			       SYSTEM_ALARM_OBJECT_ACE;
+
+/**
+ * struct ACL - An ACL is an access-control list (ACL).
+ *
+ * An ACL starts with an ACL header structure, which specifies the size of
+ * the ACL and the number of ACEs it contains. The ACL header is followed by
+ * zero or more access control entries (ACEs). The ACL as well as each ACE
+ * are aligned on 4-byte boundaries.
+ */
+typedef struct {
+	u8 revision;	/* Revision of this ACL. */
+	u8 alignment1;
+	u16 size;	/* Allocated space in bytes for ACL. Includes this
+			   header, the ACEs and the remaining free space. */
+	u16 ace_count;	/* Number of ACEs in the ACL. */
+	u16 alignment2;
+/* sizeof() = 8 bytes */
+} __attribute__((__packed__)) ACL;
+
+/**
+ * enum ACL_CONSTANTS - Current constants for ACLs.
+ */
+typedef enum {
+	/* Current revision. */
+	ACL_REVISION		= 2,
+	ACL_REVISION_DS		= 4,
+
+	/* History of revisions. */
+	ACL_REVISION1		= 1,
+	MIN_ACL_REVISION	= 2,
+	ACL_REVISION2		= 2,
+	ACL_REVISION3		= 3,
+	ACL_REVISION4		= 4,
+	MAX_ACL_REVISION	= 4,
+} ACL_CONSTANTS;
+
+/**
+ * enum SECURITY_DESCRIPTOR_CONTROL -
+ *
+ * The security descriptor control flags (16-bit).
+ *
+ * SE_OWNER_DEFAULTED - This boolean flag, when set, indicates that the
+ *	SID pointed to by the Owner field was provided by a
+ *	defaulting mechanism rather than explicitly provided by the
+ *	original provider of the security descriptor.  This may
+ *	affect the treatment of the SID with respect to inheritance
+ *	of an owner.
+ *
+ * SE_GROUP_DEFAULTED - This boolean flag, when set, indicates that the
+ *	SID in the Group field was provided by a defaulting mechanism
+ *	rather than explicitly provided by the original provider of
+ *	the security descriptor.  This may affect the treatment of
+ *	the SID with respect to inheritance of a primary group.
+ *
+ * SE_DACL_PRESENT - This boolean flag, when set, indicates that the
+ *	security descriptor contains a discretionary ACL.  If this
+ *	flag is set and the Dacl field of the SECURITY_DESCRIPTOR is
+ *	null, then a null ACL is explicitly being specified.
+ *
+ * SE_DACL_DEFAULTED - This boolean flag, when set, indicates that the
+ *	ACL pointed to by the Dacl field was provided by a defaulting
+ *	mechanism rather than explicitly provided by the original
+ *	provider of the security descriptor.  This may affect the
+ *	treatment of the ACL with respect to inheritance of an ACL.
+ *	This flag is ignored if the DaclPresent flag is not set.
+ *
+ * SE_SACL_PRESENT - This boolean flag, when set,  indicates that the
+ *	security descriptor contains a system ACL pointed to by the
+ *	Sacl field.  If this flag is set and the Sacl field of the
+ *	SECURITY_DESCRIPTOR is null, then an empty (but present)
+ *	ACL is being specified.
+ *
+ * SE_SACL_DEFAULTED - This boolean flag, when set, indicates that the
+ *	ACL pointed to by the Sacl field was provided by a defaulting
+ *	mechanism rather than explicitly provided by the original
+ *	provider of the security descriptor.  This may affect the
+ *	treatment of the ACL with respect to inheritance of an ACL.
+ *	This flag is ignored if the SaclPresent flag is not set.
+ *
+ * SE_SELF_RELATIVE - This boolean flag, when set, indicates that the
+ *	security descriptor is in self-relative form.  In this form,
+ *	all fields of the security descriptor are contiguous in memory
+ *	and all pointer fields are expressed as offsets from the
+ *	beginning of the security descriptor.
+ */
+typedef enum {
+	SE_OWNER_DEFAULTED		= const_cpu_to_le16(0x0001),
+	SE_GROUP_DEFAULTED		= const_cpu_to_le16(0x0002),
+	SE_DACL_PRESENT			= const_cpu_to_le16(0x0004),
+	SE_DACL_DEFAULTED		= const_cpu_to_le16(0x0008),
+	SE_SACL_PRESENT			= const_cpu_to_le16(0x0010),
+	SE_SACL_DEFAULTED		= const_cpu_to_le16(0x0020),
+	SE_DACL_AUTO_INHERIT_REQ	= const_cpu_to_le16(0x0100),
+	SE_SACL_AUTO_INHERIT_REQ	= const_cpu_to_le16(0x0200),
+	SE_DACL_AUTO_INHERITED		= const_cpu_to_le16(0x0400),
+	SE_SACL_AUTO_INHERITED		= const_cpu_to_le16(0x0800),
+	SE_DACL_PROTECTED		= const_cpu_to_le16(0x1000),
+	SE_SACL_PROTECTED		= const_cpu_to_le16(0x2000),
+	SE_RM_CONTROL_VALID		= const_cpu_to_le16(0x4000),
+	SE_SELF_RELATIVE		= const_cpu_to_le16(0x8000),
+} __attribute__((__packed__)) SECURITY_DESCRIPTOR_CONTROL;
+
+/**
+ * struct SECURITY_DESCRIPTOR_RELATIVE -
+ *
+ * Self-relative security descriptor. Contains the owner and group SIDs as well
+ * as the sacl and dacl ACLs inside the security descriptor itself.
+ */
+typedef struct {
+	u8 revision;	/* Revision level of the security descriptor. */
+	u8 alignment;
+	SECURITY_DESCRIPTOR_CONTROL control; /* Flags qualifying the type of
+			   the descriptor as well as the following fields. */
+	u32 owner;	/* Byte offset to a SID representing an object's
+			   owner. If this is NULL, no owner SID is present in
+			   the descriptor. */
+	u32 group;	/* Byte offset to a SID representing an object's
+			   primary group. If this is NULL, no primary group
+			   SID is present in the descriptor. */
+	u32 sacl;	/* Byte offset to a system ACL. Only valid, if
+			   SE_SACL_PRESENT is set in the control field. If
+			   SE_SACL_PRESENT is set but sacl is NULL, a NULL ACL
+			   is specified. */
+	u32 dacl;	/* Byte offset to a discretionary ACL. Only valid, if
+			   SE_DACL_PRESENT is set in the control field. If
+			   SE_DACL_PRESENT is set but dacl is NULL, a NULL ACL
+			   (unconditionally granting access) is specified. */
+/* sizeof() = 0x14 bytes */
+} __attribute__((__packed__)) SECURITY_DESCRIPTOR_RELATIVE;
+
+/**
+ * struct SECURITY_DESCRIPTOR - Absolute security descriptor.
+ *
+ * Does not contain the owner and group SIDs, nor the sacl and dacl ACLs inside
+ * the security descriptor. Instead, it contains pointers to these structures
+ * in memory. Obviously, absolute security descriptors are only useful for in
+ * memory representations of security descriptors.
+ *
+ * On disk, a self-relative security descriptor is used.
+ */
+typedef struct {
+	u8 revision;	/* Revision level of the security descriptor. */
+	u8 alignment;
+	SECURITY_DESCRIPTOR_CONTROL control;	/* Flags qualifying the type of
+			   the descriptor as well as the following fields. */
+	SID *owner;	/* Points to a SID representing an object's owner. If
+			   this is NULL, no owner SID is present in the
+			   descriptor. */
+	SID *group;	/* Points to a SID representing an object's primary
+			   group. If this is NULL, no primary group SID is
+			   present in the descriptor. */
+	ACL *sacl;	/* Points to a system ACL. Only valid, if
+			   SE_SACL_PRESENT is set in the control field. If
+			   SE_SACL_PRESENT is set but sacl is NULL, a NULL ACL
+			   is specified. */
+	ACL *dacl;	/* Points to a discretionary ACL. Only valid, if
+			   SE_DACL_PRESENT is set in the control field. If
+			   SE_DACL_PRESENT is set but dacl is NULL, a NULL ACL
+			   (unconditionally granting access) is specified. */
+} __attribute__((__packed__)) SECURITY_DESCRIPTOR;
+
+/**
+ * enum SECURITY_DESCRIPTOR_CONSTANTS -
+ *
+ * Current constants for security descriptors.
+ */
+typedef enum {
+	/* Current revision. */
+	SECURITY_DESCRIPTOR_REVISION	= 1,
+	SECURITY_DESCRIPTOR_REVISION1	= 1,
+
+	/* The sizes of both the absolute and relative security descriptors is
+	   the same as pointers, at least on ia32 architecture are 32-bit. */
+	SECURITY_DESCRIPTOR_MIN_LENGTH	= sizeof(SECURITY_DESCRIPTOR),
+} SECURITY_DESCRIPTOR_CONSTANTS;
+
+/*
+ * Attribute: Security descriptor (0x50).
+ *
+ * A standard self-relative security descriptor.
+ *
+ * NOTE: Can be resident or non-resident.
+ * NOTE: Not used in NTFS 3.0+, as security descriptors are stored centrally
+ * in FILE_Secure and the correct descriptor is found using the security_id
+ * from the standard information attribute.
+ */
+typedef SECURITY_DESCRIPTOR_RELATIVE SECURITY_DESCRIPTOR_ATTR;
+
+/*
+ * On NTFS 3.0+, all security descriptors are stored in FILE_Secure. Only one
+ * referenced instance of each unique security descriptor is stored.
+ *
+ * FILE_Secure contains no unnamed data attribute, i.e. it has zero length. It
+ * does, however, contain two indexes ($SDH and $SII) as well as a named data
+ * stream ($SDS).
+ *
+ * Every unique security descriptor is assigned a unique security identifier
+ * (security_id, not to be confused with a SID). The security_id is unique for
+ * the NTFS volume and is used as an index into the $SII index, which maps
+ * security_ids to the security descriptor's storage location within the $SDS
+ * data attribute. The $SII index is sorted by ascending security_id.
+ *
+ * A simple hash is computed from each security descriptor. This hash is used
+ * as an index into the $SDH index, which maps security descriptor hashes to
+ * the security descriptor's storage location within the $SDS data attribute.
+ * The $SDH index is sorted by security descriptor hash and is stored in a B+
+ * tree. When searching $SDH (with the intent of determining whether or not a
+ * new security descriptor is already present in the $SDS data stream), if a
+ * matching hash is found, but the security descriptors do not match, the
+ * search in the $SDH index is continued, searching for a next matching hash.
+ *
+ * When a precise match is found, the security_id corresponding to the security
+ * descriptor in the $SDS attribute is read from the found $SDH index entry and
+ * is stored in the $STANDARD_INFORMATION attribute of the file/directory to
+ * which the security descriptor is being applied. The $STANDARD_INFORMATION
+ * attribute is present in all base mft records (i.e. in all files and
+ * directories).
+ *
+ * If a match is not found, the security descriptor is assigned a new unique
+ * security_id and is added to the $SDS data attribute. Then, entries
+ * referencing the this security descriptor in the $SDS data attribute are
+ * added to the $SDH and $SII indexes.
+ *
+ * Note: Entries are never deleted from FILE_Secure, even if nothing
+ * references an entry any more.
+ */
+
+/**
+ * struct SECURITY_DESCRIPTOR_HEADER -
+ *
+ * This header precedes each security descriptor in the $SDS data stream.
+ * This is also the index entry data part of both the $SII and $SDH indexes.
+ */
+typedef struct {
+	u32 hash;	   /* Hash of the security descriptor. */
+	u32 security_id;   /* The security_id assigned to the descriptor. */
+	u64 offset;	   /* Byte offset of this entry in the $SDS stream. */
+	u32 length;	   /* Size in bytes of this entry in $SDS stream. */
+} __attribute__((__packed__)) SECURITY_DESCRIPTOR_HEADER;
+
+/**
+ * struct SDH_INDEX_DATA -
+ */
+typedef struct {
+	u32 hash;          /* Hash of the security descriptor. */
+	u32 security_id;   /* The security_id assigned to the descriptor. */
+	u64 offset;	   /* Byte offset of this entry in the $SDS stream. */
+	u32 length;	   /* Size in bytes of this entry in $SDS stream. */
+	u32 reserved_II;   /* Padding - always unicode "II" or zero. This field
+			      isn't counted in INDEX_ENTRY's data_length. */
+} __attribute__((__packed__)) SDH_INDEX_DATA;
+
+/**
+ * struct SII_INDEX_DATA -
+ */
+typedef SECURITY_DESCRIPTOR_HEADER SII_INDEX_DATA;
+
+/**
+ * struct SDS_ENTRY -
+ *
+ * The $SDS data stream contains the security descriptors, aligned on 16-byte
+ * boundaries, sorted by security_id in a B+ tree. Security descriptors cannot
+ * cross 256kib boundaries (this restriction is imposed by the Windows cache
+ * manager). Each security descriptor is contained in a SDS_ENTRY structure.
+ * Also, each security descriptor is stored twice in the $SDS stream with a
+ * fixed offset of 0x40000 bytes (256kib, the Windows cache manager's max size)
+ * between them; i.e. if a SDS_ENTRY specifies an offset of 0x51d0, then the
+ * the first copy of the security descriptor will be at offset 0x51d0 in the
+ * $SDS data stream and the second copy will be at offset 0x451d0.
+ */
+typedef struct {
+/*  0	SECURITY_DESCRIPTOR_HEADER; -- Unfolded here as gcc doesn't like
+				       unnamed structs. */
+	u32 hash;	   /* Hash of the security descriptor. */
+	u32 security_id;   /* The security_id assigned to the descriptor. */
+	u64 offset;	   /* Byte offset of this entry in the $SDS stream. */
+	u32 length;	   /* Size in bytes of this entry in $SDS stream. */
+/* 20*/	SECURITY_DESCRIPTOR_RELATIVE sid; /* The self-relative security
+					     descriptor. */
+} __attribute__((__packed__)) SDS_ENTRY;
+
+/**
+ * struct SII_INDEX_KEY - The index entry key used in the $SII index.
+ *
+ * The collation type is COLLATION_NTOFS_ULONG.
+ */
+typedef struct {
+	u32 security_id;   /* The security_id assigned to the descriptor. */
+} __attribute__((__packed__)) SII_INDEX_KEY;
+
+/**
+ * struct SDH_INDEX_KEY - The index entry key used in the $SDH index.
+ *
+ * The keys are sorted first by hash and then by security_id.
+ * The collation rule is COLLATION_NTOFS_SECURITY_HASH.
+ */
+typedef struct {
+	u32 hash;	   /* Hash of the security descriptor. */
+	u32 security_id;   /* The security_id assigned to the descriptor. */
+} __attribute__((__packed__)) SDH_INDEX_KEY;
+
+/**
+ * struct VOLUME_NAME - Attribute: Volume name (0x60).
+ *
+ * NOTE: Always resident.
+ * NOTE: Present only in FILE_Volume.
+ */
+typedef struct {
+	ntfschar name[0];	/* The name of the volume in Unicode. */
+} __attribute__((__packed__)) VOLUME_NAME;
+
+/**
+ * enum VOLUME_FLAGS - Possible flags for the volume (16-bit).
+ */
+typedef enum {
+	VOLUME_IS_DIRTY			= const_cpu_to_le16(0x0001),
+	VOLUME_RESIZE_LOG_FILE		= const_cpu_to_le16(0x0002),
+	VOLUME_UPGRADE_ON_MOUNT		= const_cpu_to_le16(0x0004),
+	VOLUME_MOUNTED_ON_NT4		= const_cpu_to_le16(0x0008),
+	VOLUME_DELETE_USN_UNDERWAY	= const_cpu_to_le16(0x0010),
+	VOLUME_REPAIR_OBJECT_ID		= const_cpu_to_le16(0x0020),
+	VOLUME_CHKDSK_UNDERWAY		= const_cpu_to_le16(0x4000),
+	VOLUME_MODIFIED_BY_CHKDSK	= const_cpu_to_le16(0x8000),
+	VOLUME_FLAGS_MASK		= const_cpu_to_le16(0xc03f),
+} __attribute__((__packed__)) VOLUME_FLAGS;
+
+/**
+ * struct VOLUME_INFORMATION - Attribute: Volume information (0x70).
+ *
+ * NOTE: Always resident.
+ * NOTE: Present only in FILE_Volume.
+ * NOTE: Windows 2000 uses NTFS 3.0 while Windows NT4 service pack 6a uses
+ *	 NTFS 1.2. I haven't personally seen other values yet.
+ */
+typedef struct {
+	u64 reserved;		/* Not used (yet?). */
+	u8 major_ver;		/* Major version of the ntfs format. */
+	u8 minor_ver;		/* Minor version of the ntfs format. */
+	VOLUME_FLAGS flags;	/* Bit array of VOLUME_* flags. */
+} __attribute__((__packed__)) VOLUME_INFORMATION;
+
+/**
+ * struct DATA_ATTR - Attribute: Data attribute (0x80).
+ *
+ * NOTE: Can be resident or non-resident.
+ *
+ * Data contents of a file (i.e. the unnamed stream) or of a named stream.
+ */
+typedef struct {
+	u8 data[0];		/* The file's data contents. */
+} __attribute__((__packed__)) DATA_ATTR;
+
+/**
+ * enum INDEX_HEADER_FLAGS - Index header flags (8-bit).
+ */
+typedef enum {
+	/* When index header is in an index root attribute: */
+	SMALL_INDEX	= 0, /* The index is small enough to fit inside the
+				index root attribute and there is no index
+				allocation attribute present. */
+	LARGE_INDEX	= 1, /* The index is too large to fit in the index
+				root attribute and/or an index allocation
+				attribute is present. */
+	/*
+	 * When index header is in an index block, i.e. is part of index
+	 * allocation attribute:
+	 */
+	LEAF_NODE	= 0, /* This is a leaf node, i.e. there are no more
+				nodes branching off it. */
+	INDEX_NODE	= 1, /* This node indexes other nodes, i.e. is not a
+				leaf node. */
+	NODE_MASK	= 1, /* Mask for accessing the *_NODE bits. */
+} __attribute__((__packed__)) INDEX_HEADER_FLAGS;
+
+/**
+ * struct INDEX_HEADER -
+ *
+ * This is the header for indexes, describing the INDEX_ENTRY records, which
+ * follow the INDEX_HEADER. Together the index header and the index entries
+ * make up a complete index.
+ *
+ * IMPORTANT NOTE: The offset, length and size structure members are counted
+ * relative to the start of the index header structure and not relative to the
+ * start of the index root or index allocation structures themselves.
+ */
+typedef struct {
+/*  0*/	u32 entries_offset;	/* Byte offset from the INDEX_HEADER to first
+				   INDEX_ENTRY, aligned to 8-byte boundary.  */
+/*  4*/	u32 index_length;	/* Data size in byte of the INDEX_ENTRY's,
+				   including the INDEX_HEADER, aligned to 8. */
+/*  8*/	u32 allocated_size;	/* Allocated byte size of this index (block),
+				   multiple of 8 bytes. See more below.      */
+	/* 
+	   For the index root attribute, the above two numbers are always
+	   equal, as the attribute is resident and it is resized as needed.
+	   
+	   For the index allocation attribute, the attribute is not resident 
+	   and the allocated_size is equal to the index_block_size specified 
+	   by the corresponding INDEX_ROOT attribute minus the INDEX_BLOCK 
+	   size not counting the INDEX_HEADER part (i.e. minus -24).
+	 */
+/* 12*/	INDEX_HEADER_FLAGS ih_flags;	/* Bit field of INDEX_HEADER_FLAGS.  */
+/* 13*/	u8 reserved[3];			/* Reserved/align to 8-byte boundary.*/
+/* sizeof() == 16 */
+} __attribute__((__packed__)) INDEX_HEADER;
+
+/**
+ * struct INDEX_ROOT - Attribute: Index root (0x90).
+ *
+ * NOTE: Always resident.
+ *
+ * This is followed by a sequence of index entries (INDEX_ENTRY structures)
+ * as described by the index header.
+ *
+ * When a directory is small enough to fit inside the index root then this
+ * is the only attribute describing the directory. When the directory is too
+ * large to fit in the index root, on the other hand, two additional attributes
+ * are present: an index allocation attribute, containing sub-nodes of the B+
+ * directory tree (see below), and a bitmap attribute, describing which virtual
+ * cluster numbers (vcns) in the index allocation attribute are in use by an
+ * index block.
+ *
+ * NOTE: The root directory (FILE_root) contains an entry for itself. Other
+ * directories do not contain entries for themselves, though.
+ */
+typedef struct {
+/*  0*/	ATTR_TYPES type;		/* Type of the indexed attribute. Is
+					   $FILE_NAME for directories, zero
+					   for view indexes. No other values
+					   allowed. */
+/*  4*/	COLLATION_RULES collation_rule;	/* Collation rule used to sort the
+					   index entries. If type is $FILE_NAME,
+					   this must be COLLATION_FILE_NAME. */
+/*  8*/	u32 index_block_size;		/* Size of index block in bytes (in
+					   the index allocation attribute). */
+/* 12*/	s8 clusters_per_index_block;	/* Size of index block in clusters (in
+					   the index allocation attribute), when
+					   an index block is >= than a cluster,
+					   otherwise sectors per index block. */
+/* 13*/	u8 reserved[3];			/* Reserved/align to 8-byte boundary. */
+/* 16*/	INDEX_HEADER index;		/* Index header describing the
+					   following index entries. */
+/* sizeof()= 32 bytes */
+} __attribute__((__packed__)) INDEX_ROOT;
+
+/**
+ * struct INDEX_BLOCK - Attribute: Index allocation (0xa0).
+ *
+ * NOTE: Always non-resident (doesn't make sense to be resident anyway!).
+ *
+ * This is an array of index blocks. Each index block starts with an
+ * INDEX_BLOCK structure containing an index header, followed by a sequence of
+ * index entries (INDEX_ENTRY structures), as described by the INDEX_HEADER.
+ */
+typedef struct {
+/*  0	NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
+	NTFS_RECORD_TYPES magic;/* Magic is "INDX". */
+	u16 usa_ofs;		/* See NTFS_RECORD definition. */
+	u16 usa_count;		/* See NTFS_RECORD definition. */
+
+/*  8*/	LSN lsn;		/* $LogFile sequence number of the last
+				   modification of this index block. */
+/* 16*/	VCN index_block_vcn;	/* Virtual cluster number of the index block. */
+/* 24*/	INDEX_HEADER index;	/* Describes the following index entries. */
+/* sizeof()= 40 (0x28) bytes */
+/*
+ * When creating the index block, we place the update sequence array at this
+ * offset, i.e. before we start with the index entries. This also makes sense,
+ * otherwise we could run into problems with the update sequence array
+ * containing in itself the last two bytes of a sector which would mean that
+ * multi sector transfer protection wouldn't work. As you can't protect data
+ * by overwriting it since you then can't get it back...
+ * When reading use the data from the ntfs record header.
+ */
+} __attribute__((__packed__)) INDEX_BLOCK;
+
+typedef INDEX_BLOCK INDEX_ALLOCATION;
+
+/**
+ * struct REPARSE_INDEX_KEY -
+ *
+ * The system file FILE_Extend/$Reparse contains an index named $R listing
+ * all reparse points on the volume. The index entry keys are as defined
+ * below. Note, that there is no index data associated with the index entries.
+ *
+ * The index entries are sorted by the index key file_id. The collation rule is
+ * COLLATION_NTOFS_ULONGS. FIXME: Verify whether the reparse_tag is not the
+ * primary key / is not a key at all. (AIA)
+ */
+typedef struct {
+	u32 reparse_tag;	/* Reparse point type (inc. flags). */
+	MFT_REF file_id;	/* Mft record of the file containing the
+				   reparse point attribute. */
+} __attribute__((__packed__)) REPARSE_INDEX_KEY;
+
+/**
+ * enum QUOTA_FLAGS - Quota flags (32-bit).
+ */
+typedef enum {
+	/* The user quota flags. Names explain meaning. */
+	QUOTA_FLAG_DEFAULT_LIMITS	= const_cpu_to_le32(0x00000001),
+	QUOTA_FLAG_LIMIT_REACHED	= const_cpu_to_le32(0x00000002),
+	QUOTA_FLAG_ID_DELETED		= const_cpu_to_le32(0x00000004),
+
+	QUOTA_FLAG_USER_MASK		= const_cpu_to_le32(0x00000007),
+		/* Bit mask for user quota flags. */
+
+	/* These flags are only present in the quota defaults index entry,
+	   i.e. in the entry where owner_id = QUOTA_DEFAULTS_ID. */
+	QUOTA_FLAG_TRACKING_ENABLED	= const_cpu_to_le32(0x00000010),
+	QUOTA_FLAG_ENFORCEMENT_ENABLED	= const_cpu_to_le32(0x00000020),
+	QUOTA_FLAG_TRACKING_REQUESTED	= const_cpu_to_le32(0x00000040),
+	QUOTA_FLAG_LOG_THRESHOLD	= const_cpu_to_le32(0x00000080),
+	QUOTA_FLAG_LOG_LIMIT		= const_cpu_to_le32(0x00000100),
+	QUOTA_FLAG_OUT_OF_DATE		= const_cpu_to_le32(0x00000200),
+	QUOTA_FLAG_CORRUPT		= const_cpu_to_le32(0x00000400),
+	QUOTA_FLAG_PENDING_DELETES	= const_cpu_to_le32(0x00000800),
+} QUOTA_FLAGS;
+
+/**
+ * struct QUOTA_CONTROL_ENTRY -
+ *
+ * The system file FILE_Extend/$Quota contains two indexes $O and $Q. Quotas
+ * are on a per volume and per user basis.
+ *
+ * The $Q index contains one entry for each existing user_id on the volume. The
+ * index key is the user_id of the user/group owning this quota control entry,
+ * i.e. the key is the owner_id. The user_id of the owner of a file, i.e. the
+ * owner_id, is found in the standard information attribute. The collation rule
+ * for $Q is COLLATION_NTOFS_ULONG.
+ *
+ * The $O index contains one entry for each user/group who has been assigned
+ * a quota on that volume. The index key holds the SID of the user_id the
+ * entry belongs to, i.e. the owner_id. The collation rule for $O is
+ * COLLATION_NTOFS_SID.
+ *
+ * The $O index entry data is the user_id of the user corresponding to the SID.
+ * This user_id is used as an index into $Q to find the quota control entry
+ * associated with the SID.
+ *
+ * The $Q index entry data is the quota control entry and is defined below.
+ */
+typedef struct {
+	u32 version;		/* Currently equals 2. */
+	QUOTA_FLAGS flags;	/* Flags describing this quota entry. */
+	u64 bytes_used;		/* How many bytes of the quota are in use. */
+	s64 change_time;	/* Last time this quota entry was changed. */
+	s64 threshold;		/* Soft quota (-1 if not limited). */
+	s64 limit;		/* Hard quota (-1 if not limited). */
+	s64 exceeded_time;	/* How long the soft quota has been exceeded. */
+/* The below field is NOT present for the quota defaults entry. */
+	SID sid;		/* The SID of the user/object associated with
+				   this quota entry. If this field is missing
+				   then the INDEX_ENTRY is padded to a multiple
+				   of 8 with zeros which are not counted in
+				   the data_length field. If the sid is present
+				   then this structure is padded with zeros to
+				   a multiple of 8 and the padding is counted in
+				   the INDEX_ENTRY's data_length. */
+} __attribute__((__packed__)) QUOTA_CONTROL_ENTRY;
+
+/**
+ * struct QUOTA_O_INDEX_DATA -
+ */
+typedef struct {
+	u32 owner_id;
+	u32 unknown;		/* Always 32. Seems to be padding and it's not
+				   counted in the INDEX_ENTRY's data_length.
+				   This field shouldn't be really here. */
+} __attribute__((__packed__)) QUOTA_O_INDEX_DATA;
+
+/**
+ * enum PREDEFINED_OWNER_IDS - Predefined owner_id values (32-bit).
+ */
+typedef enum {
+	QUOTA_INVALID_ID	= const_cpu_to_le32(0x00000000),
+	QUOTA_DEFAULTS_ID	= const_cpu_to_le32(0x00000001),
+	QUOTA_FIRST_USER_ID	= const_cpu_to_le32(0x00000100),
+} PREDEFINED_OWNER_IDS;
+
+/**
+ * enum INDEX_ENTRY_FLAGS - Index entry flags (16-bit).
+ */
+typedef enum {
+	INDEX_ENTRY_NODE = const_cpu_to_le16(1), /* This entry contains a
+					sub-node, i.e. a reference to an index
+					block in form of a virtual cluster
+					number (see below). */
+	INDEX_ENTRY_END  = const_cpu_to_le16(2), /* This signifies the last
+					entry in an index block. The index
+					entry does not represent a file but it
+					can point to a sub-node. */
+	INDEX_ENTRY_SPACE_FILLER = 0xffff, /* Just to force 16-bit width. */
+} __attribute__((__packed__)) INDEX_ENTRY_FLAGS;
+
+/**
+ * struct INDEX_ENTRY_HEADER - This the index entry header (see below).
+ * 
+ *         ==========================================================
+ *         !!!!!  SEE DESCRIPTION OF THE FIELDS AT INDEX_ENTRY  !!!!!
+ *         ==========================================================
+ */
+typedef struct {
+/*  0*/	union {
+		MFT_REF indexed_file;
+		struct {
+			u16 data_offset;
+			u16 data_length;
+			u32 reservedV;
+		} __attribute__((__packed__));
+	} __attribute__((__packed__));
+/*  8*/	u16 length;
+/* 10*/	u16 key_length;
+/* 12*/	INDEX_ENTRY_FLAGS flags;
+/* 14*/	u16 reserved;
+/* sizeof() = 16 bytes */
+} __attribute__((__packed__)) INDEX_ENTRY_HEADER;
+
+/**
+ * struct INDEX_ENTRY - This is an index entry.
+ *
+ * A sequence of such entries follows each INDEX_HEADER structure. Together
+ * they make up a complete index. The index follows either an index root
+ * attribute or an index allocation attribute.
+ *
+ * NOTE: Before NTFS 3.0 only filename attributes were indexed.
+ */
+typedef struct {
+/*  0	INDEX_ENTRY_HEADER; -- Unfolded here as gcc dislikes unnamed structs. */
+	union {		/* Only valid when INDEX_ENTRY_END is not set. */
+		MFT_REF indexed_file;		/* The mft reference of the file
+						   described by this index
+						   entry. Used for directory
+						   indexes. */
+		struct { /* Used for views/indexes to find the entry's data. */
+			u16 data_offset;	/* Data byte offset from this
+						   INDEX_ENTRY. Follows the
+						   index key. */
+			u16 data_length;	/* Data length in bytes. */
+			u32 reservedV;		/* Reserved (zero). */
+		} __attribute__((__packed__));
+	} __attribute__((__packed__));
+/*  8*/ u16 length;		 /* Byte size of this index entry, multiple of
+				    8-bytes. Size includes INDEX_ENTRY_HEADER
+				    and the optional subnode VCN. See below. */
+/* 10*/ u16 key_length;		 /* Byte size of the key value, which is in the
+				    index entry. It follows field reserved. Not
+				    multiple of 8-bytes. */
+/* 12*/	INDEX_ENTRY_FLAGS ie_flags; /* Bit field of INDEX_ENTRY_* flags. */
+/* 14*/	u16 reserved;		 /* Reserved/align to 8-byte boundary. */
+/*	End of INDEX_ENTRY_HEADER */
+/* 16*/	union {		/* The key of the indexed attribute. NOTE: Only present
+			   if INDEX_ENTRY_END bit in flags is not set. NOTE: On
+			   NTFS versions before 3.0 the only valid key is the
+			   FILE_NAME_ATTR. On NTFS 3.0+ the following
+			   additional index keys are defined: */
+		FILE_NAME_ATTR file_name;/* $I30 index in directories. */
+		SII_INDEX_KEY sii;	/* $SII index in $Secure. */
+		SDH_INDEX_KEY sdh;	/* $SDH index in $Secure. */
+		GUID object_id;		/* $O index in FILE_Extend/$ObjId: The
+					   object_id of the mft record found in
+					   the data part of the index. */
+		REPARSE_INDEX_KEY reparse;	/* $R index in
+						   FILE_Extend/$Reparse. */
+		SID sid;		/* $O index in FILE_Extend/$Quota:
+					   SID of the owner of the user_id. */
+		u32 owner_id;		/* $Q index in FILE_Extend/$Quota:
+					   user_id of the owner of the quota
+					   control entry in the data part of
+					   the index. */
+	} __attribute__((__packed__)) key;
+	/* The (optional) index data is inserted here when creating.
+	VCN vcn;	   If INDEX_ENTRY_NODE bit in ie_flags is set, the last
+			   eight bytes of this index entry contain the virtual
+			   cluster number of the index block that holds the
+			   entries immediately preceding the current entry. 
+	
+			   If the key_length is zero, then the vcn immediately
+			   follows the INDEX_ENTRY_HEADER. 
+	
+			   The address of the vcn of "ie" INDEX_ENTRY is given by 
+			   (char*)ie + le16_to_cpu(ie->length) - sizeof(VCN)
+	*/
+} __attribute__((__packed__)) INDEX_ENTRY;
+
+/**
+ * struct BITMAP_ATTR - Attribute: Bitmap (0xb0).
+ *
+ * Contains an array of bits (aka a bitfield).
+ *
+ * When used in conjunction with the index allocation attribute, each bit
+ * corresponds to one index block within the index allocation attribute. Thus
+ * the number of bits in the bitmap * index block size / cluster size is the
+ * number of clusters in the index allocation attribute.
+ */
+typedef struct {
+	u8 bitmap[0];			/* Array of bits. */
+} __attribute__((__packed__)) BITMAP_ATTR;
+
+/**
+ * enum PREDEFINED_REPARSE_TAGS -
+ *
+ * The reparse point tag defines the type of the reparse point. It also
+ * includes several flags, which further describe the reparse point.
+ *
+ * The reparse point tag is an unsigned 32-bit value divided in three parts:
+ *
+ * 1. The least significant 16 bits (i.e. bits 0 to 15) specify the type of
+ *    the reparse point.
+ * 2. The 13 bits after this (i.e. bits 16 to 28) are reserved for future use.
+ * 3. The most significant three bits are flags describing the reparse point.
+ *    They are defined as follows:
+ *	bit 29: Name surrogate bit. If set, the filename is an alias for
+ *		another object in the system.
+ *	bit 30: High-latency bit. If set, accessing the first byte of data will
+ *		be slow. (E.g. the data is stored on a tape drive.)
+ *	bit 31: Microsoft bit. If set, the tag is owned by Microsoft. User
+ *		defined tags have to use zero here.
+ */
+typedef enum {
+	IO_REPARSE_TAG_IS_ALIAS		= const_cpu_to_le32(0x20000000),
+	IO_REPARSE_TAG_IS_HIGH_LATENCY	= const_cpu_to_le32(0x40000000),
+	IO_REPARSE_TAG_IS_MICROSOFT	= const_cpu_to_le32(0x80000000),
+
+	IO_REPARSE_TAG_RESERVED_ZERO	= const_cpu_to_le32(0x00000000),
+	IO_REPARSE_TAG_RESERVED_ONE	= const_cpu_to_le32(0x00000001),
+	IO_REPARSE_TAG_RESERVED_RANGE	= const_cpu_to_le32(0x00000001),
+
+	IO_REPARSE_TAG_CSV		= const_cpu_to_le32(0x80000009),
+	IO_REPARSE_TAG_DEDUP		= const_cpu_to_le32(0x80000013),
+	IO_REPARSE_TAG_DFS		= const_cpu_to_le32(0x8000000A),
+	IO_REPARSE_TAG_DFSR		= const_cpu_to_le32(0x80000012),
+	IO_REPARSE_TAG_HSM		= const_cpu_to_le32(0xC0000004),
+	IO_REPARSE_TAG_HSM2		= const_cpu_to_le32(0x80000006),
+	IO_REPARSE_TAG_MOUNT_POINT	= const_cpu_to_le32(0xA0000003),
+	IO_REPARSE_TAG_NFS		= const_cpu_to_le32(0x80000014),
+	IO_REPARSE_TAG_SIS		= const_cpu_to_le32(0x80000007),
+	IO_REPARSE_TAG_SYMLINK		= const_cpu_to_le32(0xA000000C),
+	IO_REPARSE_TAG_WIM		= const_cpu_to_le32(0x80000008),
+
+	IO_REPARSE_TAG_VALID_VALUES	= const_cpu_to_le32(0xf000ffff),
+} PREDEFINED_REPARSE_TAGS;
+
+/**
+ * struct REPARSE_POINT - Attribute: Reparse point (0xc0).
+ *
+ * NOTE: Can be resident or non-resident.
+ */
+typedef struct {
+	u32 reparse_tag;		/* Reparse point type (inc. flags). */
+	u16 reparse_data_length;	/* Byte size of reparse data. */
+	u16 reserved;			/* Align to 8-byte boundary. */
+	u8 reparse_data[0];		/* Meaning depends on reparse_tag. */
+} __attribute__((__packed__)) REPARSE_POINT;
+
+/**
+ * struct EA_INFORMATION - Attribute: Extended attribute information (0xd0).
+ *
+ * NOTE: Always resident.
+ */
+typedef struct {
+	u16 ea_length;		/* Byte size of the packed extended
+				   attributes. */
+	u16 need_ea_count;	/* The number of extended attributes which have
+				   the NEED_EA bit set. */
+	u32 ea_query_length;	/* Byte size of the buffer required to query
+				   the extended attributes when calling
+				   ZwQueryEaFile() in Windows NT/2k. I.e. the
+				   byte size of the unpacked extended
+				   attributes. */
+} __attribute__((__packed__)) EA_INFORMATION;
+
+/**
+ * enum EA_FLAGS - Extended attribute flags (8-bit).
+ */
+typedef enum {
+	NEED_EA	= 0x80,		/* Indicate that the file to which the EA
+				   belongs cannot be interpreted without
+				   understanding the associated extended
+				   attributes. */
+} __attribute__((__packed__)) EA_FLAGS;
+
+/**
+ * struct EA_ATTR - Attribute: Extended attribute (EA) (0xe0).
+ *
+ * Like the attribute list and the index buffer list, the EA attribute value is
+ * a sequence of EA_ATTR variable length records.
+ *
+ * FIXME: It appears weird that the EA name is not Unicode. Is it true?
+ * FIXME: It seems that name is always uppercased. Is it true?
+ */
+typedef struct {
+	u32 next_entry_offset;	/* Offset to the next EA_ATTR. */
+	EA_FLAGS flags;		/* Flags describing the EA. */
+	u8 name_length;		/* Length of the name of the extended
+				   attribute in bytes. */
+	u16 value_length;	/* Byte size of the EA's value. */
+	u8 name[0];		/* Name of the EA. */
+	u8 value[0];		/* The value of the EA. Immediately
+				   follows the name. */
+} __attribute__((__packed__)) EA_ATTR;
+
+/**
+ * struct PROPERTY_SET - Attribute: Property set (0xf0).
+ *
+ * Intended to support Native Structure Storage (NSS) - a feature removed from
+ * NTFS 3.0 during beta testing.
+ */
+typedef struct {
+	/* Irrelevant as feature unused. */
+} __attribute__((__packed__)) PROPERTY_SET;
+
+/**
+ * struct LOGGED_UTILITY_STREAM - Attribute: Logged utility stream (0x100).
+ *
+ * NOTE: Can be resident or non-resident.
+ *
+ * Operations on this attribute are logged to the journal ($LogFile) like
+ * normal metadata changes.
+ *
+ * Used by the Encrypting File System (EFS).  All encrypted files have this
+ * attribute with the name $EFS.  See below for the relevant structures.
+ */
+typedef struct {
+	/* Can be anything the creator chooses. */
+} __attribute__((__packed__)) LOGGED_UTILITY_STREAM;
+
+/*
+ * $EFS Data Structure:
+ *
+ * The following information is about the data structures that are contained
+ * inside a logged utility stream (0x100) with a name of "$EFS".
+ *
+ * The stream starts with an instance of EFS_ATTR_HEADER.
+ *
+ * Next, at offsets offset_to_ddf_array and offset_to_drf_array (unless any of
+ * them is 0) there is a EFS_DF_ARRAY_HEADER immediately followed by a sequence
+ * of multiple data decryption/recovery fields.
+ *
+ * Each data decryption/recovery field starts with a EFS_DF_HEADER and the next
+ * one (if it exists) can be found by adding EFS_DF_HEADER->df_length bytes to
+ * the offset of the beginning of the current EFS_DF_HEADER.
+ *
+ * The data decryption/recovery field contains an EFS_DF_CERTIFICATE_HEADER, a
+ * SID, an optional GUID, an optional container name, a non-optional user name,
+ * and the encrypted FEK.
+ *
+ * Note all the below are best guesses so may have mistakes/inaccuracies.
+ * Corrections/clarifications/additions are always welcome!
+ *
+ * Ntfs.sys takes an EFS value length of <= 0x54 or > 0x40000 to BSOD, i.e. it
+ * is invalid.
+ */
+
+/**
+ * struct EFS_ATTR_HEADER - "$EFS" header.
+ *
+ * The header of the Logged utility stream (0x100) attribute named "$EFS".
+ */
+typedef struct {
+/*  0*/	u32 length;		/* Length of EFS attribute in bytes. */
+	u32 state;		/* Always 0? */
+	u32 version;		/* Efs version.  Always 2? */
+	u32 crypto_api_version;	/* Always 0? */
+/* 16*/	u8 unknown4[16];	/* MD5 hash of decrypted FEK?  This field is
+				   created with a call to UuidCreate() so is
+				   unlikely to be an MD5 hash and is more
+				   likely to be GUID of this encrytped file
+				   or something like that. */
+/* 32*/	u8 unknown5[16];	/* MD5 hash of DDFs? */
+/* 48*/	u8 unknown6[16];	/* MD5 hash of DRFs? */
+/* 64*/	u32 offset_to_ddf_array;/* Offset in bytes to the array of data
+				   decryption fields (DDF), see below.  Zero if
+				   no DDFs are present. */
+	u32 offset_to_drf_array;/* Offset in bytes to the array of data
+				   recovery fields (DRF), see below.  Zero if
+				   no DRFs are present. */
+	u32 reserved;		/* Reserved. */
+} __attribute__((__packed__)) EFS_ATTR_HEADER;
+
+/**
+ * struct EFS_DF_ARRAY_HEADER -
+ */
+typedef struct {
+	u32 df_count;		/* Number of data decryption/recovery fields in
+				   the array. */
+} __attribute__((__packed__)) EFS_DF_ARRAY_HEADER;
+
+/**
+ * struct EFS_DF_HEADER -
+ */
+typedef struct {
+/*  0*/	u32 df_length;		/* Length of this data decryption/recovery
+				   field in bytes. */
+	u32 cred_header_offset;	/* Offset in bytes to the credential header. */
+	u32 fek_size;		/* Size in bytes of the encrypted file
+				   encryption key (FEK). */
+	u32 fek_offset;		/* Offset in bytes to the FEK from the start of
+				   the data decryption/recovery field. */
+/* 16*/	u32 unknown1;		/* always 0?  Might be just padding. */
+} __attribute__((__packed__)) EFS_DF_HEADER;
+
+/**
+ * struct EFS_DF_CREDENTIAL_HEADER -
+ */
+typedef struct {
+/*  0*/	u32 cred_length;	/* Length of this credential in bytes. */
+	u32 sid_offset;		/* Offset in bytes to the user's sid from start
+				   of this structure.  Zero if no sid is
+				   present. */
+/*  8*/	u32 type;		/* Type of this credential:
+					1 = CryptoAPI container.
+					2 = Unexpected type.
+					3 = Certificate thumbprint.
+					other = Unknown type. */
+	union {
+		/* CryptoAPI container. */
+		struct {
+/* 12*/			u32 container_name_offset;	/* Offset in bytes to
+				   the name of the container from start of this
+				   structure (may not be zero). */
+/* 16*/			u32 provider_name_offset;	/* Offset in bytes to
+				   the name of the provider from start of this
+				   structure (may not be zero). */
+			u32 public_key_blob_offset;	/* Offset in bytes to
+				   the public key blob from start of this
+				   structure. */
+/* 24*/			u32 public_key_blob_size;	/* Size in bytes of
+				   public key blob. */
+		} __attribute__((__packed__));
+		/* Certificate thumbprint. */
+		struct {
+/* 12*/			u32 cert_thumbprint_header_size;	/* Size in
+				   bytes of the header of the certificate
+				   thumbprint. */
+/* 16*/			u32 cert_thumbprint_header_offset;	/* Offset in
+				   bytes to the header of the certificate
+				   thumbprint from start of this structure. */
+			u32 unknown1;	/* Always 0?  Might be padding... */
+			u32 unknown2;	/* Always 0?  Might be padding... */
+		} __attribute__((__packed__));
+	} __attribute__((__packed__));
+} __attribute__((__packed__)) EFS_DF_CREDENTIAL_HEADER;
+
+typedef EFS_DF_CREDENTIAL_HEADER EFS_DF_CRED_HEADER;
+
+/**
+ * struct EFS_DF_CERTIFICATE_THUMBPRINT_HEADER -
+ */
+typedef struct {
+/*  0*/	u32 thumbprint_offset;		/* Offset in bytes to the thumbprint. */
+	u32 thumbprint_size;		/* Size of thumbprint in bytes. */
+/*  8*/	u32 container_name_offset;	/* Offset in bytes to the name of the
+					   container from start of this
+					   structure or 0 if no name present. */
+	u32 provider_name_offset;	/* Offset in bytes to the name of the
+					   cryptographic provider from start of
+					   this structure or 0 if no name
+					   present. */
+/* 16*/	u32 user_name_offset;		/* Offset in bytes to the user name
+					   from start of this structure or 0 if
+					   no user name present.  (This is also
+					   known as lpDisplayInformation.) */
+} __attribute__((__packed__)) EFS_DF_CERTIFICATE_THUMBPRINT_HEADER;
+
+typedef EFS_DF_CERTIFICATE_THUMBPRINT_HEADER EFS_DF_CERT_THUMBPRINT_HEADER;
+
+typedef enum {
+	INTX_SYMBOLIC_LINK =
+		const_cpu_to_le64(0x014B4E4C78746E49ULL), /* "IntxLNK\1" */
+	INTX_CHARACTER_DEVICE =
+		const_cpu_to_le64(0x0052484378746E49ULL), /* "IntxCHR\0" */
+	INTX_BLOCK_DEVICE =
+		const_cpu_to_le64(0x004B4C4278746E49ULL), /* "IntxBLK\0" */
+} INTX_FILE_TYPES;
+
+typedef struct {
+	INTX_FILE_TYPES magic;		/* Intx file magic. */
+	union {
+		/* For character and block devices. */
+		struct {
+			u64 major;		/* Major device number. */
+			u64 minor;		/* Minor device number. */
+			void *device_end[0];	/* Marker for offsetof(). */
+		} __attribute__((__packed__));
+		/* For symbolic links. */
+		ntfschar target[0];
+	} __attribute__((__packed__));
+} __attribute__((__packed__)) INTX_FILE;
+
+#endif /* defined _NTFS_LAYOUT_H */
diff --git a/include/ntfs-3g/lcnalloc.h b/include/ntfs-3g/lcnalloc.h
new file mode 100755
index 0000000000000000000000000000000000000000..cbf4c5cd7a06e22022e31cd703e3459b1e787b60
--- /dev/null
+++ b/include/ntfs-3g/lcnalloc.h
@@ -0,0 +1,51 @@
+/*
+ * lcnalloc.h - Exports for cluster (de)allocation. Originated from the Linux-NTFS
+ *		project.
+ *
+ * Copyright (c) 2002 Anton Altaparmakov
+ * Copyright (c) 2004 Yura Pakhuchiy
+ *
+ * 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_LCNALLOC_H
+#define _NTFS_LCNALLOC_H
+
+#include "types.h"
+#include "runlist.h"
+#include "volume.h"
+
+/**
+ * enum NTFS_CLUSTER_ALLOCATION_ZONES -
+ */
+typedef enum {
+	FIRST_ZONE	= 0,	/* For sanity checking. */
+	MFT_ZONE	= 0,	/* Allocate from $MFT zone. */
+	DATA_ZONE	= 1,	/* Allocate from $DATA zone. */
+	LAST_ZONE	= 1,	/* For sanity checking. */
+} NTFS_CLUSTER_ALLOCATION_ZONES;
+
+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);
+
+#endif /* defined _NTFS_LCNALLOC_H */
+
diff --git a/include/ntfs-3g/logfile.h b/include/ntfs-3g/logfile.h
new file mode 100755
index 0000000000000000000000000000000000000000..798d562d17ce720873756a765dbfc514d6b80b8b
--- /dev/null
+++ b/include/ntfs-3g/logfile.h
@@ -0,0 +1,394 @@
+/*
+ * logfile.h - Exports for $LogFile handling.  Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2000-2005 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
+ */
+
+#ifndef _NTFS_LOGFILE_H
+#define _NTFS_LOGFILE_H
+
+#include "types.h"
+#include "endians.h"
+#include "layout.h"
+
+/*
+ * Journal ($LogFile) organization:
+ *
+ * Two restart areas present in the first two pages (restart pages, one restart
+ * area in each page).  When the volume is dismounted they should be identical,
+ * except for the update sequence array which usually has a different update
+ * sequence number.
+ *
+ * These are followed by log records organized in pages headed by a log record
+ * header going up to log file size.  Not all pages contain log records when a
+ * volume is first formatted, but as the volume ages, all records will be used.
+ * When the log file fills up, the records at the beginning are purged (by
+ * modifying the oldest_lsn to a higher value presumably) and writing begins
+ * at the beginning of the file.  Effectively, the log file is viewed as a
+ * circular entity.
+ *
+ * NOTE: Windows NT, 2000, and XP all use log file version 1.1 but they accept
+ * versions <= 1.x, including 0.-1.  (Yes, that is a minus one in there!)  We
+ * probably only want to support 1.1 as this seems to be the current version
+ * and we don't know how that differs from the older versions.  The only
+ * exception is if the journal is clean as marked by the two restart pages
+ * then it doesn't matter whether we are on an earlier version.  We can just
+ * reinitialize the logfile and start again with version 1.1.
+ */
+
+/* Some $LogFile related constants. */
+#define MaxLogFileSize		0x100000000ULL
+#define DefaultLogPageSize	4096
+#define MinLogRecordPages	48
+
+/**
+ * struct RESTART_PAGE_HEADER - Log file restart page header.
+ *
+ * Begins the restart area.
+ */
+typedef struct {
+/*Ofs*/
+/*  0	NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
+/*  0*/	NTFS_RECORD_TYPES magic;/* The magic is "RSTR". */
+/*  4*/	le16 usa_ofs;		/* See NTFS_RECORD definition in layout.h.
+				   When creating, set this to be immediately
+				   after this header structure (without any
+				   alignment). */
+/*  6*/	le16 usa_count;		/* See NTFS_RECORD definition in layout.h. */
+
+/*  8*/	leLSN chkdsk_lsn;	/* The last log file sequence number found by
+				   chkdsk.  Only used when the magic is changed
+				   to "CHKD".  Otherwise this is zero. */
+/* 16*/	le32 system_page_size;	/* Byte size of system pages when the log file
+				   was created, has to be >= 512 and a power of
+				   2.  Use this to calculate the required size
+				   of the usa (usa_count) and add it to usa_ofs.
+				   Then verify that the result is less than the
+				   value of the restart_area_offset. */
+/* 20*/	le32 log_page_size;	/* Byte size of log file pages, has to be >=
+				   512 and a power of 2.  The default is 4096
+				   and is used when the system page size is
+				   between 4096 and 8192.  Otherwise this is
+				   set to the system page size instead. */
+/* 24*/	le16 restart_area_offset;/* Byte offset from the start of this header to
+				   the RESTART_AREA.  Value has to be aligned
+				   to 8-byte boundary.  When creating, set this
+				   to be after the usa. */
+/* 26*/	sle16 minor_ver;	/* Log file minor version.  Only check if major
+				   version is 1. */
+/* 28*/	sle16 major_ver;	/* Log file major version.  We only support
+				   version 1.1. */
+/* sizeof() = 30 (0x1e) bytes */
+} __attribute__((__packed__)) RESTART_PAGE_HEADER;
+
+/*
+ * Constant for the log client indices meaning that there are no client records
+ * 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
+
+/*
+ * These are the so far known RESTART_AREA_* flags (16-bit) which contain
+ * information about the log file in which they are present.
+ */
+enum {
+	RESTART_VOLUME_IS_CLEAN	= const_cpu_to_le16(0x0002),
+	RESTART_SPACE_FILLER	= 0xffff, /* gcc: Force enum bit width to 16. */
+} __attribute__((__packed__));
+
+typedef le16 RESTART_AREA_FLAGS;
+
+/**
+ * struct RESTART_AREA - Log file restart area record.
+ *
+ * The offset of this record is found by adding the offset of the
+ * RESTART_PAGE_HEADER to the restart_area_offset value found in it.
+ * See notes at restart_area_offset above.
+ */
+typedef struct {
+/*Ofs*/
+/*  0*/	leLSN current_lsn;	/* The current, i.e. last LSN inside the log
+				   when the restart area was last written.
+				   This happens often but what is the interval?
+				   Is it just fixed time or is it every time a
+				   check point is written or something else?
+				   On create set to 0. */
+/*  8*/	le16 log_clients;	/* Number of log client records in the array of
+				   log client records which follows this
+				   restart area.  Must be 1.  */
+/* 10*/	le16 client_free_list;	/* The index of the first free log client record
+				   in the array of log client records.
+				   LOGFILE_NO_CLIENT means that there are no
+				   free log client records in the array.
+				   If != LOGFILE_NO_CLIENT, check that
+				   log_clients > client_free_list.  On Win2k
+				   and presumably earlier, on a clean volume
+				   this is != LOGFILE_NO_CLIENT, and it should
+				   be 0, i.e. the first (and only) client
+				   record is free and thus the logfile is
+				   closed and hence clean.  A dirty volume
+				   would have left the logfile open and hence
+				   this would be LOGFILE_NO_CLIENT.  On WinXP
+				   and presumably later, the logfile is always
+				   open, even on clean shutdown so this should
+				   always be LOGFILE_NO_CLIENT. */
+/* 12*/	le16 client_in_use_list;/* The index of the first in-use log client
+				   record in the array of log client records.
+				   LOGFILE_NO_CLIENT means that there are no
+				   in-use log client records in the array.  If
+				   != LOGFILE_NO_CLIENT check that log_clients
+				   > client_in_use_list.  On Win2k and
+				   presumably earlier, on a clean volume this
+				   is LOGFILE_NO_CLIENT, i.e. there are no
+				   client records in use and thus the logfile
+				   is closed and hence clean.  A dirty volume
+				   would have left the logfile open and hence
+				   this would be != LOGFILE_NO_CLIENT, and it
+				   should be 0, i.e. the first (and only)
+				   client record is in use.  On WinXP and
+				   presumably later, the logfile is always
+				   open, even on clean shutdown so this should
+				   always be 0. */
+/* 14*/	RESTART_AREA_FLAGS flags;/* Flags modifying LFS behaviour.  On Win2k
+				   and presumably earlier this is always 0.  On
+				   WinXP and presumably later, if the logfile
+				   was shutdown cleanly, the second bit,
+				   RESTART_VOLUME_IS_CLEAN, is set.  This bit
+				   is cleared when the volume is mounted by
+				   WinXP and set when the volume is dismounted,
+				   thus if the logfile is dirty, this bit is
+				   clear.  Thus we don't need to check the
+				   Windows version to determine if the logfile
+				   is clean.  Instead if the logfile is closed,
+				   we know it must be clean.  If it is open and
+				   this bit is set, we also know it must be
+				   clean.  If on the other hand the logfile is
+				   open and this bit is clear, we can be almost
+				   certain that the logfile is dirty. */
+/* 16*/	le32 seq_number_bits;	/* How many bits to use for the sequence
+				   number.  This is calculated as 67 - the
+				   number of bits required to store the logfile
+				   size in bytes and this can be used in with
+				   the specified file_size as a consistency
+				   check. */
+/* 20*/	le16 restart_area_length;/* Length of the restart area including the
+				   client array.  Following checks required if
+				   version matches.  Otherwise, skip them.
+				   restart_area_offset + restart_area_length
+				   has to be <= system_page_size.  Also,
+				   restart_area_length has to be >=
+				   client_array_offset + (log_clients *
+				   sizeof(log client record)). */
+/* 22*/	le16 client_array_offset;/* Offset from the start of this record to
+				   the first log client record if versions are
+				   matched.  When creating, set this to be
+				   after this restart area structure, aligned
+				   to 8-bytes boundary.  If the versions do not
+				   match, this is ignored and the offset is
+				   assumed to be (sizeof(RESTART_AREA) + 7) &
+				   ~7, i.e. rounded up to first 8-byte
+				   boundary.  Either way, client_array_offset
+				   has to be aligned to an 8-byte boundary.
+				   Also, restart_area_offset +
+				   client_array_offset has to be <= 510.
+				   Finally, client_array_offset + (log_clients
+				   * sizeof(log client record)) has to be <=
+				   system_page_size.  On Win2k and presumably
+				   earlier, this is 0x30, i.e. immediately
+				   following this record.  On WinXP and
+				   presumably later, this is 0x40, i.e. there
+				   are 16 extra bytes between this record and
+				   the client array.  This probably means that
+				   the RESTART_AREA record is actually bigger
+				   in WinXP and later. */
+/* 24*/	sle64 file_size;	/* Usable byte size of the log file.  If the
+				   restart_area_offset + the offset of the
+				   file_size are > 510 then corruption has
+				   occurred.  This is the very first check when
+				   starting with the restart_area as if it
+				   fails it means that some of the above values
+				   will be corrupted by the multi sector
+				   transfer protection.  The file_size has to
+				   be rounded down to be a multiple of the
+				   log_page_size in the RESTART_PAGE_HEADER and
+				   then it has to be at least big enough to
+				   store the two restart pages and 48 (0x30)
+				   log record pages. */
+/* 32*/	le32 last_lsn_data_length;/* Length of data of last LSN, not including
+				   the log record header.  On create set to
+				   0. */
+/* 36*/	le16 log_record_header_length;/* Byte size of the log record header.
+				   If the version matches then check that the
+				   value of log_record_header_length is a
+				   multiple of 8, i.e.
+				   (log_record_header_length + 7) & ~7 ==
+				   log_record_header_length.  When creating set
+				   it to sizeof(LOG_RECORD_HEADER), aligned to
+				   8 bytes. */
+/* 38*/	le16 log_page_data_offset;/* Offset to the start of data in a log record
+				   page.  Must be a multiple of 8.  On create
+				   set it to immediately after the update
+				   sequence array of the log record page. */
+/* 40*/	le32 restart_log_open_count;/* A counter that gets incremented every
+				   time the logfile is restarted which happens
+				   at mount time when the logfile is opened.
+				   When creating set to a random value.  Win2k
+				   sets it to the low 32 bits of the current
+				   system time in NTFS format (see time.h). */
+/* 44*/	le32 reserved;		/* Reserved/alignment to 8-byte boundary. */
+/* sizeof() = 48 (0x30) bytes */
+} __attribute__((__packed__)) RESTART_AREA;
+
+/**
+ * struct LOG_CLIENT_RECORD - Log client record.
+ *
+ * The offset of this record is found by adding the offset of the
+ * RESTART_AREA to the client_array_offset value found in it.
+ */
+typedef struct {
+/*Ofs*/
+/*  0*/	leLSN oldest_lsn;	/* Oldest LSN needed by this client.  On create
+				   set to 0. */
+/*  8*/	leLSN client_restart_lsn;/* LSN at which this client needs to restart
+				   the volume, i.e. the current position within
+				   the log file.  At present, if clean this
+				   should = current_lsn in restart area but it
+				   probably also = current_lsn when dirty most
+				   of the time.  At create set to 0. */
+/* 16*/	le16 prev_client;	/* The offset to the previous log client record
+				   in the array of log client records.
+				   LOGFILE_NO_CLIENT means there is no previous
+				   client record, i.e. this is the first one.
+				   This is always LOGFILE_NO_CLIENT. */
+/* 18*/	le16 next_client;	/* The offset to the next log client record in
+				   the array of log client records.
+				   LOGFILE_NO_CLIENT means there are no next
+				   client records, i.e. this is the last one.
+				   This is always LOGFILE_NO_CLIENT. */
+/* 20*/	le16 seq_number;	/* On Win2k and presumably earlier, this is set
+				   to zero every time the logfile is restarted
+				   and it is incremented when the logfile is
+				   closed at dismount time.  Thus it is 0 when
+				   dirty and 1 when clean.  On WinXP and
+				   presumably later, this is always 0. */
+/* 22*/	u8 reserved[6];		/* Reserved/alignment. */
+/* 28*/	le32 client_name_length;/* Length of client name in bytes.  Should
+				   always be 8. */
+/* 32*/	ntfschar client_name[64];/* Name of the client in Unicode.  Should
+				   always be "NTFS" with the remaining bytes
+				   set to 0. */
+/* sizeof() = 160 (0xa0) bytes */
+} __attribute__((__packed__)) LOG_CLIENT_RECORD;
+
+/**
+ * struct RECORD_PAGE_HEADER - Log page record page header.
+ *
+ * Each log page begins with this header and is followed by several LOG_RECORD
+ * structures, starting at offset 0x40 (the size of this structure and the
+ * following update sequence array and then aligned to 8 byte boundary, but is
+ * this specified anywhere?).
+ */
+typedef struct {
+/*  0	NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
+	NTFS_RECORD_TYPES magic;/* Usually the magic is "RCRD". */
+	u16 usa_ofs;		/* See NTFS_RECORD definition in layout.h.
+				   When creating, set this to be immediately
+				   after this header structure (without any
+				   alignment). */
+	u16 usa_count;		/* See NTFS_RECORD definition in layout.h. */
+
+	union {
+		LSN last_lsn;
+		s64 file_offset;
+	} __attribute__((__packed__)) copy;
+	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.
+ *
+ * (Or is it log record pages?)
+ */
+typedef enum {
+	LOG_RECORD_MULTI_PAGE = const_cpu_to_le16(0x0001),	/* ??? */
+	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. */
+} __attribute__((__packed__)) LOG_RECORD_FLAGS;
+
+/**
+ * struct LOG_CLIENT_ID - The log client id structure identifying a log client.
+ */
+typedef struct {
+	u16 seq_number;
+	u16 client_index;
+} __attribute__((__packed__)) LOG_CLIENT_ID;
+
+/**
+ * struct LOG_RECORD - Log record header.
+ *
+ * Each log record seems to have a constant size of 0x70 bytes.
+ */
+typedef struct {
+	LSN this_lsn;
+	LSN client_previous_lsn;
+	LSN client_undo_next_lsn;
+	u32 client_data_length;
+	LOG_CLIENT_ID client_id;
+	u32 record_type;
+	u32 transaction_id;
+	u16 flags;
+	u16 reserved_or_alignment[3];
+/* Now are at ofs 0x30 into struct. */
+	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. */
+	u16 record_offset;
+	u16 attribute_offset;
+	u32 alignment_or_reserved;
+	VCN target_vcn;
+/* Now at ofs 0x50. */
+	struct {			   /* Only present if lcns_to_follow
+					      is not 0. */
+		LCN lcn;
+	} __attribute__((__packed__)) lcn_list[0];
+} __attribute__((__packed__)) LOG_RECORD;
+
+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);
+
+#endif /* defined _NTFS_LOGFILE_H */
diff --git a/include/ntfs-3g/logging.h b/include/ntfs-3g/logging.h
new file mode 100755
index 0000000000000000000000000000000000000000..82f39fe1661f78469688e7dfd86480ddca1fffaf
--- /dev/null
+++ b/include/ntfs-3g/logging.h
@@ -0,0 +1,121 @@
+/*
+ * logging.h - Centralised logging. Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2005      Richard Russon
+ * Copyright (c) 2007-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
+ * 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 _LOGGING_H_
+#define _LOGGING_H_
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+
+#include "types.h"
+
+/* Function prototype for the logging handlers */
+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))));
+
+/* Logging handlers */
+ntfs_log_handler ntfs_log_handler_syslog  __attribute__((format(printf, 6, 0)));
+ntfs_log_handler ntfs_log_handler_fprintf __attribute__((format(printf, 6, 0)));
+ntfs_log_handler ntfs_log_handler_null    __attribute__((format(printf, 6, 0)));
+ntfs_log_handler ntfs_log_handler_stdout  __attribute__((format(printf, 6, 0)));
+ntfs_log_handler ntfs_log_handler_outerr  __attribute__((format(printf, 6, 0)));
+ntfs_log_handler ntfs_log_handler_stderr  __attribute__((format(printf, 6, 0)));
+
+/* Enable/disable certain log levels */
+u32 ntfs_log_set_levels(u32 levels);
+u32 ntfs_log_clear_levels(u32 levels);
+u32 ntfs_log_get_levels(void);
+
+/* Enable/disable certain log flags */
+u32 ntfs_log_set_flags(u32 flags);
+u32 ntfs_log_clear_flags(u32 flags);
+u32 ntfs_log_get_flags(void);
+
+/* Turn command-line options into logging flags */
+BOOL ntfs_log_parse_option(const char *option);
+
+int ntfs_log_redirect(const char *function, const char *file, int line,
+	u32 level, void *data, const char *format, ...)
+	__attribute__((format(printf, 6, 7)));
+
+/* Logging levels - Determine what gets logged */
+#define NTFS_LOG_LEVEL_DEBUG	(1 <<  0) /* x = 42 */
+#define NTFS_LOG_LEVEL_TRACE	(1 <<  1) /* Entering function x() */
+#define NTFS_LOG_LEVEL_QUIET	(1 <<  2) /* Quietable output */
+#define NTFS_LOG_LEVEL_INFO	(1 <<  3) /* Volume needs defragmenting */
+#define NTFS_LOG_LEVEL_VERBOSE	(1 <<  4) /* Forced to continue */
+#define NTFS_LOG_LEVEL_PROGRESS	(1 <<  5) /* 54% complete */
+#define NTFS_LOG_LEVEL_WARNING	(1 <<  6) /* You should backup before starting */
+#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 */
+#define NTFS_LOG_FLAG_FILENAME	(1 << 1) /* Show the file origin of the message */
+#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 */
+
+/* Macros to simplify logging.  One for each level defined above.
+ * Note, ntfs_log_debug/trace have effect only if DEBUG is defined.
+ */
+#define ntfs_log_critical(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_CRITICAL,NULL,FORMAT,##ARGS)
+#define ntfs_log_error(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_ERROR,NULL,FORMAT,##ARGS)
+#define ntfs_log_info(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_INFO,NULL,FORMAT,##ARGS)
+#define ntfs_log_perror(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_PERROR,NULL,FORMAT,##ARGS)
+#define ntfs_log_progress(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_PROGRESS,NULL,FORMAT,##ARGS)
+#define ntfs_log_quiet(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_QUIET,NULL,FORMAT,##ARGS)
+#define ntfs_log_verbose(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_VERBOSE,NULL,FORMAT,##ARGS)
+#define ntfs_log_warning(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_WARNING,NULL,FORMAT,##ARGS)
+
+/* By default debug and trace messages are compiled into the program,
+ * but not displayed.
+ */
+#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_ */
+
diff --git a/include/ntfs-3g/mft.h b/include/ntfs-3g/mft.h
new file mode 100755
index 0000000000000000000000000000000000000000..b135efce1250c4b553875e3c02b60e1330b75b05
--- /dev/null
+++ b/include/ntfs-3g/mft.h
@@ -0,0 +1,134 @@
+/*
+ * mft.h - Exports for MFT record handling. Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2000-2002 Anton Altaparmakov
+ * Copyright (c) 2004-2005 Richard Russon
+ * Copyright (c) 2006-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
+ * 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_MFT_H
+#define _NTFS_MFT_H
+
+#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);
+
+/**
+ * ntfs_mft_record_read - read a record from the mft
+ * @vol:	volume to read from
+ * @mref:	mft record number to read
+ * @b:		output data buffer
+ *
+ * Read the mft record specified by @mref from volume @vol into buffer @b.
+ * Return 0 on success or -1 on error, with errno set to the error code.
+ *
+ * The read mft record is mst deprotected and is hence ready to use. The caller
+ * should check the record with is_baad_record() in case mst deprotection
+ * failed.
+ *
+ * NOTE: @b has to be at least of size vol->mft_record_size.
+ */
+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;
+}
+
+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);
+
+extern int ntfs_mft_records_write(const ntfs_volume *vol, const MFT_REF mref,
+		const s64 count, MFT_RECORD *b);
+
+/**
+ * ntfs_mft_record_write - write an mft record to disk
+ * @vol:	volume to write to
+ * @mref:	mft record number to write
+ * @b:		data buffer containing the mft record to write
+ *
+ * Write the mft record specified by @mref from buffer @b to volume @vol.
+ * Return 0 on success or -1 on error, with errno set to the error code.
+ *
+ * Before the mft record is written, it is mst protected. After the write, it
+ * is deprotected again, thus resulting in an increase in the update sequence
+ * number inside the buffer @b.
+ *
+ * NOTE: @b has to be at least of size vol->mft_record_size.
+ */
+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;
+}
+
+/**
+ * ntfs_mft_record_get_data_size - return number of bytes used in mft record @b
+ * @m:		mft record to get the data size of
+ *
+ * Takes the mft record @m and returns the number of bytes used in the record
+ * or 0 on error (i.e. @m is not a valid mft record).  Zero is not a valid size
+ * for an mft record as it at least has to have the MFT_RECORD itself and a
+ * zero length attribute of type AT_END, thus making the minimum size 56 bytes.
+ *
+ * Aside:  The size is independent of NTFS versions 1.x/3.x because the 8-byte
+ * alignment of the first attribute mask the difference in MFT_RECORD size
+ * between NTFS 1.x and 3.x.  Also, you would expect every mft record to
+ * contain an update sequence array as well but that could in theory be
+ * non-existent (don't know if Windows' NTFS driver/chkdsk wouldn't view this
+ * as corruption in itself though).
+ */
+static __inline__ u32 ntfs_mft_record_get_data_size(const MFT_RECORD *m)
+{
+	if (!m || !ntfs_is_mft_record(m->magic))
+		return 0;
+	/* Get the number of used bytes and return it. */
+	return le32_to_cpu(m->bytes_in_use);
+}
+
+extern int ntfs_mft_record_layout(const ntfs_volume *vol, const MFT_REF mref,
+		MFT_RECORD *mrec);
+
+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);
+
+#endif /* defined _NTFS_MFT_H */
+
diff --git a/include/ntfs-3g/misc.h b/include/ntfs-3g/misc.h
new file mode 100755
index 0000000000000000000000000000000000000000..a03e964e83ca662d69c2acbc77f8bfdeb694b804
--- /dev/null
+++ b/include/ntfs-3g/misc.h
@@ -0,0 +1,30 @@
+/*
+ * 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);
+
+#endif /* _NTFS_MISC_H_ */
+
diff --git a/include/ntfs-3g/mst.h b/include/ntfs-3g/mst.h
new file mode 100755
index 0000000000000000000000000000000000000000..d6ca6f27015df6a55e09f04787468323abfae9e5
--- /dev/null
+++ b/include/ntfs-3g/mst.h
@@ -0,0 +1,37 @@
+/*
+ * mst.h - Exports for multi sector transfer fixup functions.
+ *         Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2000-2002 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
+ */
+
+#ifndef _NTFS_MST_H
+#define _NTFS_MST_H
+
+#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);
+
+#endif /* defined _NTFS_MST_H */
+
diff --git a/include/ntfs-3g/ntfstime.h b/include/ntfs-3g/ntfstime.h
new file mode 100755
index 0000000000000000000000000000000000000000..d42d0c216cea3dfa9b6112de669f13eae652e49d
--- /dev/null
+++ b/include/ntfs-3g/ntfstime.h
@@ -0,0 +1,133 @@
+/*
+ * ntfstime.h - NTFS time related functions.  Originated from the Linux-NTFS project.
+ *
+ * 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
+ * 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_NTFSTIME_H
+#define _NTFS_NTFSTIME_H
+
+#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)
+#if 0
+struct timespec {
+	time_t tv_sec;
+	long tv_nsec;
+} ;
+#endif
+#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
+ * @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)
+ */
+static __inline__ struct timespec ntfs2timespec(ntfs_time ntfstime)
+{
+	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);
+}
+
+/**
+ * timespec2ntfs - 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
+ *
+ * NTFS uses Microsoft's standard time format which is stored in a sle64 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)
+ */
+static __inline__ ntfs_time timespec2ntfs(struct timespec spec)
+{
+	s64 units;
+
+	units = (s64)spec.tv_sec * 10000000
+				+ NTFS_TIME_OFFSET + spec.tv_nsec/100;
+	return (cpu_to_le64(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));
+}
+
+#endif /* _NTFS_NTFSTIME_H */
diff --git a/include/ntfs-3g/object_id.h b/include/ntfs-3g/object_id.h
new file mode 100755
index 0000000000000000000000000000000000000000..31af9fd8a480428cdd6ed22ec4e0cfbbf6de475d
--- /dev/null
+++ b/include/ntfs-3g/object_id.h
@@ -0,0 +1,35 @@
+/*
+ *
+ * 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 */
diff --git a/include/ntfs-3g/param.h b/include/ntfs-3g/param.h
new file mode 100755
index 0000000000000000000000000000000000000000..da794abba17e2ec60a5519934a61ecf47cf4162b
--- /dev/null
+++ b/include/ntfs-3g/param.h
@@ -0,0 +1,129 @@
+/*
+ * 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 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 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
+ *
+ *	Possible values for high level :
+ *		1 : no cache, kernel control (recommended)
+ *		4 : no cache, file system control
+ *		7 : no cache, kernel control for ACLs
+ *
+ *	Possible values for low level :
+ *		2 : no cache, kernel control
+ *		3 : use kernel/fuse cache, kernel control (external fuse >= 2.8)
+ *		5 : no cache, file system control (recommended)
+ *		8 : no cache, kernel control for ACLs
+ *
+ *	Use of options 7 and 8 requires a patch to fuse
+ *	When Posix ACLs are selected in the configure options, a value
+ *	of 6 is added in the mount report.
+ */
+
+#if defined(__sun) && defined(__SVR4)
+#define HPERMSCONFIG 4 /* access control by kernel is broken on OpenIndiana */
+#else
+#define HPERMSCONFIG 1
+#endif
+#if defined(FUSE_INTERNAL) || !defined(FUSE_VERSION) || (FUSE_VERSION < 28)
+#define LPERMSCONFIG 5
+#else
+#define LPERMSCONFIG 3
+#endif
+
+#endif /* defined _NTFS_PARAM_H */
diff --git a/include/ntfs-3g/realpath.h b/include/ntfs-3g/realpath.h
new file mode 100755
index 0000000000000000000000000000000000000000..970d2af8e8de181c87b31d56e55145cd623f535b
--- /dev/null
+++ b/include/ntfs-3g/realpath.h
@@ -0,0 +1,24 @@
+/*
+ * 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 */
diff --git a/include/ntfs-3g/reparse.h b/include/ntfs-3g/reparse.h
new file mode 100755
index 0000000000000000000000000000000000000000..35f4aa456296b49fb66457ca9aec3535e86ae4d0
--- /dev/null
+++ b/include/ntfs-3g/reparse.h
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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,
+			int *pattr_size);
+BOOL ntfs_possible_symlink(ntfs_inode *ni);
+
+int ntfs_get_ntfs_reparse_data(ntfs_inode *ni, char *value, size_t size);
+
+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 */
diff --git a/include/ntfs-3g/runlist.h b/include/ntfs-3g/runlist.h
new file mode 100755
index 0000000000000000000000000000000000000000..4b73af9f436359c51302c8a0bf4261ad61e4a2df
--- /dev/null
+++ b/include/ntfs-3g/runlist.h
@@ -0,0 +1,90 @@
+/*
+ * runlist.h - Exports for runlist handling. Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2002 Anton Altaparmakov
+ * Copyright (c) 2002 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
+ * 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_RUNLIST_H
+#define _NTFS_RUNLIST_H
+
+#include "types.h"
+
+/* Forward declarations */
+typedef struct _runlist_element runlist_element;
+typedef runlist_element runlist;
+
+#include "attrib.h"
+#include "volume.h"
+
+/**
+ * struct _runlist_element - in memory vcn to lcn mapping array element.
+ * @vcn:	starting vcn of the current array element
+ * @lcn:	starting lcn of the current array element
+ * @length:	length in clusters of the current array element
+ *
+ * The last vcn (in fact the last vcn + 1) is reached when length == 0.
+ *
+ * When lcn == -1 this means that the count vcns starting at vcn are not
+ * physically allocated (i.e. this is a hole / data is sparse).
+ */
+struct _runlist_element {/* In memory vcn to lcn mapping structure element. */
+	VCN vcn;	/* vcn = Starting virtual cluster number. */
+	LCN lcn;	/* lcn = Starting logical cluster number. */
+	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);
+
+extern runlist_element *ntfs_runlists_merge(runlist_element *drl,
+		runlist_element *srl);
+
+extern runlist_element *ntfs_mapping_pairs_decompress(const ntfs_volume *vol,
+		const ATTR_RECORD *attr, runlist_element *old_rl);
+
+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);
+
+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);
+
+extern int ntfs_rl_truncate(runlist **arl, const VCN start_vcn);
+
+extern int ntfs_rl_sparse(runlist *rl);
+extern s64 ntfs_rl_get_compressed_size(ntfs_volume *vol, runlist *rl);
+
+#ifdef NTFS_TEST
+int test_rl_main(int argc, char *argv[]);
+#endif
+
+#endif /* defined _NTFS_RUNLIST_H */
+
diff --git a/include/ntfs-3g/security.h b/include/ntfs-3g/security.h
new file mode 100755
index 0000000000000000000000000000000000000000..8875c9c14f86a9d5f85a0dc125948f6fa430ce42
--- /dev/null
+++ b/include/ntfs-3g/security.h
@@ -0,0 +1,363 @@
+/*
+ * security.h - Exports for handling security/ACLs in NTFS.  
+ *              Originated from the Linux-NTFS project.
+ *
+ * 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
+ * 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_SECURITY_H
+#define _NTFS_SECURITY_H
+
+#include "types.h"
+#include "layout.h"
+#include "inode.h"
+#include "dir.h"
+
+#ifndef POSIXACLS
+#define POSIXACLS 0
+#endif
+
+typedef u16 be16;
+typedef u32 be32;
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define const_cpu_to_be16(x) ((((x) & 255L) << 8) + (((x) >> 8) & 255L))
+#define const_cpu_to_be32(x) ((((x) & 255L) << 24) + (((x) & 0xff00L) << 8) \
+			+ (((x) >> 8) & 0xff00L) + (((x) >> 24) & 255L))
+#else
+#define const_cpu_to_be16(x) (x)
+#define const_cpu_to_be32(x) (x)
+#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;
+	s32 alignment[0];
+	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 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);
+void ntfs_close_secure(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 */
diff --git a/include/ntfs-3g/support.h b/include/ntfs-3g/support.h
new file mode 100755
index 0000000000000000000000000000000000000000..6af4761e22b2e03d36f0b376c9b47746240678c3
--- /dev/null
+++ b/include/ntfs-3g/support.h
@@ -0,0 +1,85 @@
+/*
+ * support.h - Useful definitions and macros. Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2000-2004 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
+ */
+
+#ifndef _NTFS_SUPPORT_H
+#define _NTFS_SUPPORT_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_STDDEF_H
+#include <stddef.h>
+#endif
+
+/*
+ * Our mailing list. Use this define to prevent typos in email address.
+ */
+#define NTFS_DEV_LIST	"ntfs-3g-devel@lists.sf.net"
+
+/*
+ * Generic macro to convert pointers to values for comparison purposes.
+ */
+#ifndef p2n
+#define p2n(p)		((ptrdiff_t)((ptrdiff_t*)(p)))
+#endif
+
+/*
+ * The classic min and max macros.
+ */
+#ifndef min
+#define min(a,b)	((a) <= (b) ? (a) : (b))
+#endif
+
+#ifndef max
+#define max(a,b)	((a) >= (b) ? (a) : (b))
+#endif
+
+/*
+ * Useful macro for determining the offset of a struct member.
+ */
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+/*
+ * Simple bit operation macros. NOTE: These are NOT atomic.
+ */
+#define test_bit(bit, var)	      ((var) & (1 << (bit)))
+#define set_bit(bit, var)	      (var) |= 1 << (bit)
+#define clear_bit(bit, var)	      (var) &= ~(1 << (bit))
+
+#define test_and_set_bit(bit, var)			\
+({							\
+	const BOOL old_state = test_bit(bit, var);	\
+	set_bit(bit, var);				\
+	old_state;					\
+})
+
+#define test_and_clear_bit(bit, var)			\
+({							\
+	const BOOL old_state = test_bit(bit, var);	\
+	clear_bit(bit, var);				\
+	old_state;					\
+})
+
+#endif /* defined _NTFS_SUPPORT_H */
+
diff --git a/include/ntfs-3g/types.h b/include/ntfs-3g/types.h
new file mode 100755
index 0000000000000000000000000000000000000000..a64f12faaea4dd15a40f0b8dcca3671a774fa475
--- /dev/null
+++ b/include/ntfs-3g/types.h
@@ -0,0 +1,132 @@
+/*
+ * types.h - Misc type definitions not related to on-disk structure.  
+ *           Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2000-2004 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
+ */
+
+#ifndef _NTFS_TYPES_H
+#define _NTFS_TYPES_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if HAVE_STDINT_H || !HAVE_CONFIG_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+typedef uint8_t  u8;			/* Unsigned types of an exact size */
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+
+typedef int8_t  s8;			/* Signed types of an exact size */
+typedef int16_t s16;
+typedef int32_t s32;
+typedef int64_t s64;
+
+typedef u16 le16;
+typedef u32 le32;
+typedef u64 le64;
+
+/*
+ * 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 ntfschar;			/* 2-byte Unicode character type. */
+#define UCHAR_T_SIZE_BITS 1
+
+/*
+ * Clusters are signed 64-bit values on NTFS volumes.  We define two types, LCN
+ * and VCN, to allow for type checking and better code readability.
+ */
+typedef s64 VCN;
+typedef sle64 leVCN;
+typedef s64 LCN;
+typedef sle64 leLCN;
+
+/*
+ * The NTFS journal $LogFile uses log sequence numbers which are signed 64-bit
+ * values.  We define our own type LSN, to allow for type checking and better
+ * code readability.
+ */
+typedef s64 LSN;
+typedef sle64 leLSN;
+
+/*
+ * Cygwin has a collision between our BOOL and <windef.h>'s
+ * As long as this file will be included after <windows.h> were fine.
+ */
+#ifndef _WINDEF_H
+/**
+ * enum BOOL - These are just to make the code more readable...
+ */
+typedef enum {
+#ifndef FALSE
+	FALSE = 0,
+#endif
+#ifndef NO
+	NO = 0,
+#endif
+#ifndef ZERO
+	ZERO = 0,
+#endif
+#ifndef TRUE
+	TRUE = 1,
+#endif
+#ifndef YES
+	YES = 1,
+#endif
+#ifndef ONE
+	ONE = 1,
+#endif
+} BOOL;
+#endif /* defined _WINDEF_H */
+
+/**
+ * enum IGNORE_CASE_BOOL -
+ */
+typedef enum {
+	CASE_SENSITIVE = 0,
+	IGNORE_CASE = 1,
+} IGNORE_CASE_BOOL;
+
+#define STATUS_OK				(0)
+#define STATUS_ERROR				(-1)
+#define STATUS_RESIDENT_ATTRIBUTE_FILLED_MFT	(-2)
+#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 */
+
diff --git a/include/ntfs-3g/unistr.h b/include/ntfs-3g/unistr.h
new file mode 100755
index 0000000000000000000000000000000000000000..b6d428e38dcc9fefe7a7cc2211b2f65b87105028
--- /dev/null
+++ b/include/ntfs-3g/unistr.h
@@ -0,0 +1,121 @@
+/*
+ * unistr.h - Exports for Unicode string handling. Originated from the Linux-NTFS
+ *	      project.
+ *
+ * Copyright (c) 2000-2004 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
+ */
+
+#ifndef _NTFS_UNISTR_H
+#define _NTFS_UNISTR_H
+
+#include "types.h"
+#include "layout.h"
+
+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,
+		const ntfschar *name2, const u32 name2_len,
+		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);
+
+extern int ntfs_ucsncasecmp(const ntfschar *s1, const ntfschar *s2, size_t n,
+		const ntfschar *upcase, const u32 upcase_size);
+
+extern u32 ntfs_ucsnlen(const ntfschar *s, u32 maxlen);
+
+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_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 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);
+extern BOOL ntfs_forbidden_names(ntfs_volume *vol,
+				const ntfschar *name, int len);
+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 */
+
diff --git a/include/ntfs-3g/volume.h b/include/ntfs-3g/volume.h
new file mode 100755
index 0000000000000000000000000000000000000000..2720864c286ef320dcb8eab6adaab582807cdd6a
--- /dev/null
+++ b/include/ntfs-3g/volume.h
@@ -0,0 +1,311 @@
+/*
+ * volume.h - Exports for NTFS volume handling. Originated from the Linux-NTFS project.
+ *
+ * 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
+ *
+ * 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_VOLUME_H
+#define _NTFS_VOLUME_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+	/* Do not #include <sys/mount.h> here : conflicts with <linux/fs.h> */
+#ifdef HAVE_MNTENT_H
+#include <mntent.h>
+#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_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;
+
+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;
+
+/**
+ * enum ntfs_volume_state_bits -
+ *
+ * Defined bits for the state field in the ntfs_volume structure.
+ */
+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 */
+} ntfs_volume_state_bits;
+
+#define  test_nvol_flag(nv, flag)	 test_bit(NV_##flag, (nv)->state)
+#define   set_nvol_flag(nv, flag)	  set_bit(NV_##flag, (nv)->state)
+#define clear_nvol_flag(nv, flag)	clear_bit(NV_##flag, (nv)->state)
+
+#define NVolReadOnly(nv)		 test_nvol_flag(nv, ReadOnly)
+#define NVolSetReadOnly(nv)		  set_nvol_flag(nv, ReadOnly)
+#define NVolClearReadOnly(nv)		clear_nvol_flag(nv, ReadOnly)
+
+#define NVolCaseSensitive(nv)		 test_nvol_flag(nv, CaseSensitive)
+#define NVolSetCaseSensitive(nv)	  set_nvol_flag(nv, CaseSensitive)
+#define NVolClearCaseSensitive(nv)	clear_nvol_flag(nv, CaseSensitive)
+
+#define NVolLogFileEmpty(nv)		 test_nvol_flag(nv, LogFileEmpty)
+#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)
+
+/*
+ * NTFS version 1.1 and 1.2 are used by Windows NT4.
+ * NTFS version 2.x is used by Windows 2000 Beta
+ * NTFS version 3.0 is used by Windows 2000.
+ * NTFS version 3.1 is used by Windows XP, 2003 and Vista.
+ */
+
+#define NTFS_V1_1(major, minor) ((major) == 1 && (minor) == 1)
+#define NTFS_V1_2(major, minor) ((major) == 1 && (minor) == 2)
+#define NTFS_V2_X(major, minor) ((major) == 2)
+#define NTFS_V3_0(major, minor) ((major) == 3 && (minor) == 0)
+#define NTFS_V3_1(major, minor) ((major) == 3 && (minor) == 1)
+
+#define NTFS_BUF_SIZE 8192
+
+/**
+ * struct _ntfs_volume - structure describing an open volume in memory.
+ */
+struct _ntfs_volume {
+	union {
+		struct ntfs_device *dev;	/* NTFS device associated with
+						   the volume. */
+		void *sb;	/* For kernel porting compatibility. */
+	};
+	char *vol_name;		/* Name of the volume. */
+	unsigned long state;	/* NTFS specific flags describing this volume.
+				   See ntfs_volume_state_bits above. */
+
+	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 sector_size;	/* Byte size of a sector. */
+	u8 sector_size_bits;	/* Log(2) of the byte size of a sector. */
+	u32 cluster_size;	/* Byte size of a cluster. */
+	u32 mft_record_size;	/* Byte size of a mft record. */
+	u32 indx_record_size;	/* Byte size of a INDX record. */
+	u8 cluster_size_bits;	/* Log(2) of the byte size of a cluster. */
+	u8 mft_record_size_bits;/* Log(2) of the byte size of a mft record. */
+	u8 indx_record_size_bits;/* Log(2) of the byte size of a INDX record. */
+
+	/* 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. */
+	LCN mft_zone_end;	/* First cluster beyond the mft zone. */
+	LCN mft_zone_pos;	/* Current position in the mft zone. */
+	LCN data1_zone_pos;	/* Current position in the first data zone. */
+	LCN data2_zone_pos;	/* Current position in the second data zone. */
+
+	s64 nr_clusters;	/* Volume size in clusters, hence also the
+				   number of bits in lcn_bitmap. */
+	ntfs_inode *lcnbmp_ni;	/* ntfs_inode structure for FILE_Bitmap. */
+	ntfs_attr *lcnbmp_na;	/* ntfs_attr structure for the data attribute
+				   of FILE_Bitmap. Each bit represents a
+				   cluster on the volume, bit 0 representing
+				   lcn 0 and so on. A set bit means that the
+				   cluster and vice versa. */
+
+	LCN mft_lcn;		/* Logical cluster number of the data attribute
+				   for FILE_MFT. */
+	ntfs_inode *mft_ni;	/* ntfs_inode structure for FILE_MFT. */
+	ntfs_attr *mft_na;	/* ntfs_attr structure for the data attribute
+				   of FILE_MFT. */
+	ntfs_attr *mftbmp_na;	/* ntfs_attr structure for the bitmap attribute
+				   of FILE_MFT. Each bit represents an mft
+				   record in the $DATA attribute, bit 0
+				   representing mft record 0 and so on. A set
+				   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. */
+	ntfs_inode *mftmirr_ni;	/* ntfs_inode structure for FILE_MFTMirr. */
+	ntfs_attr *mftmirr_na;	/* ntfs_attr structure for the data attribute
+				   of FILE_MFTMirr. */
+
+	ntfschar *upcase;	/* Upper case equivalents of all 65536 2-byte
+				   Unicode characters. Obtained from
+				   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 */
+#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
+
+};
+
+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);
+
+extern ntfs_volume *ntfs_device_mount(struct ntfs_device *dev,
+		ntfs_mount_flags flags);
+
+extern ntfs_volume *ntfs_mount(const char *name, ntfs_mount_flags 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);
+
+#endif /* defined _NTFS_VOLUME_H */
+
diff --git a/include/ntfs-3g/xattrs.h b/include/ntfs-3g/xattrs.h
new file mode 100755
index 0000000000000000000000000000000000000000..d4e43a3e74b66c77baa334ffa2609631685571f7
--- /dev/null
+++ b/include/ntfs-3g/xattrs.h
@@ -0,0 +1,76 @@
+/*
+ * 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_XATTR_H_
+#define _NTFS_XATTR_H_
+
+/*
+ *		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);
+
+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_XATTR_H_ */
diff --git a/install-sh b/install-sh
new file mode 100755
index 0000000000000000000000000000000000000000..377bb8687ffe16bfc79ea25c8667cabf72aaf2c2
--- /dev/null
+++ b/install-sh
@@ -0,0 +1,527 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2011-11-20.07; # UTC
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# 'make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" ""	$nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+  doit_exec=exec
+else
+  doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+  test "$posix_glob" != "?" || {
+    if (set -f) 2>/dev/null; then
+      posix_glob=
+    else
+      posix_glob=:
+    fi
+  }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+   or: $0 [OPTION]... SRCFILES... DIRECTORY
+   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+   or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+     --help     display this help and exit.
+     --version  display version info and exit.
+
+  -c            (ignored)
+  -C            install only if different (preserve the last data modification time)
+  -d            create directories instead of installing files.
+  -g GROUP      $chgrpprog installed files to GROUP.
+  -m MODE       $chmodprog installed files to MODE.
+  -o USER       $chownprog installed files to USER.
+  -s            $stripprog installed files.
+  -t DIRECTORY  install into DIRECTORY.
+  -T            report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+  RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+  case $1 in
+    -c) ;;
+
+    -C) copy_on_change=true;;
+
+    -d) dir_arg=true;;
+
+    -g) chgrpcmd="$chgrpprog $2"
+	shift;;
+
+    --help) echo "$usage"; exit $?;;
+
+    -m) mode=$2
+	case $mode in
+	  *' '* | *'	'* | *'
+'*	  | *'*'* | *'?'* | *'['*)
+	    echo "$0: invalid mode: $mode" >&2
+	    exit 1;;
+	esac
+	shift;;
+
+    -o) chowncmd="$chownprog $2"
+	shift;;
+
+    -s) stripcmd=$stripprog;;
+
+    -t) dst_arg=$2
+	# Protect names problematic for 'test' and other utilities.
+	case $dst_arg in
+	  -* | [=\(\)!]) dst_arg=./$dst_arg;;
+	esac
+	shift;;
+
+    -T) no_target_directory=true;;
+
+    --version) echo "$0 $scriptversion"; exit $?;;
+
+    --)	shift
+	break;;
+
+    -*)	echo "$0: invalid option: $1" >&2
+	exit 1;;
+
+    *)  break;;
+  esac
+  shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+  # When -d is used, all remaining arguments are directories to create.
+  # When -t is used, the destination is already specified.
+  # Otherwise, the last argument is the destination.  Remove it from $@.
+  for arg
+  do
+    if test -n "$dst_arg"; then
+      # $@ is not empty: it contains at least $arg.
+      set fnord "$@" "$dst_arg"
+      shift # fnord
+    fi
+    shift # arg
+    dst_arg=$arg
+    # Protect names problematic for 'test' and other utilities.
+    case $dst_arg in
+      -* | [=\(\)!]) dst_arg=./$dst_arg;;
+    esac
+  done
+fi
+
+if test $# -eq 0; then
+  if test -z "$dir_arg"; then
+    echo "$0: no input file specified." >&2
+    exit 1
+  fi
+  # It's OK to call 'install-sh -d' without argument.
+  # This can happen when creating conditional directories.
+  exit 0
+fi
+
+if test -z "$dir_arg"; then
+  do_exit='(exit $ret); exit $ret'
+  trap "ret=129; $do_exit" 1
+  trap "ret=130; $do_exit" 2
+  trap "ret=141; $do_exit" 13
+  trap "ret=143; $do_exit" 15
+
+  # Set umask so as not to create temps with too-generous modes.
+  # However, 'strip' requires both read and write access to temps.
+  case $mode in
+    # Optimize common cases.
+    *644) cp_umask=133;;
+    *755) cp_umask=22;;
+
+    *[0-7])
+      if test -z "$stripcmd"; then
+	u_plus_rw=
+      else
+	u_plus_rw='% 200'
+      fi
+      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+    *)
+      if test -z "$stripcmd"; then
+	u_plus_rw=
+      else
+	u_plus_rw=,u+rw
+      fi
+      cp_umask=$mode$u_plus_rw;;
+  esac
+fi
+
+for src
+do
+  # Protect names problematic for 'test' and other utilities.
+  case $src in
+    -* | [=\(\)!]) src=./$src;;
+  esac
+
+  if test -n "$dir_arg"; then
+    dst=$src
+    dstdir=$dst
+    test -d "$dstdir"
+    dstdir_status=$?
+  else
+
+    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+    # might cause directories to be created, which would be especially bad
+    # if $src (and thus $dsttmp) contains '*'.
+    if test ! -f "$src" && test ! -d "$src"; then
+      echo "$0: $src does not exist." >&2
+      exit 1
+    fi
+
+    if test -z "$dst_arg"; then
+      echo "$0: no destination specified." >&2
+      exit 1
+    fi
+    dst=$dst_arg
+
+    # If destination is a directory, append the input filename; won't work
+    # if double slashes aren't ignored.
+    if test -d "$dst"; then
+      if test -n "$no_target_directory"; then
+	echo "$0: $dst_arg: Is a directory" >&2
+	exit 1
+      fi
+      dstdir=$dst
+      dst=$dstdir/`basename "$src"`
+      dstdir_status=0
+    else
+      # Prefer dirname, but fall back on a substitute if dirname fails.
+      dstdir=`
+	(dirname "$dst") 2>/dev/null ||
+	expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	     X"$dst" : 'X\(//\)[^/]' \| \
+	     X"$dst" : 'X\(//\)$' \| \
+	     X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+	echo X"$dst" |
+	    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\/\)[^/].*/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\/\)$/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\).*/{
+		   s//\1/
+		   q
+		 }
+		 s/.*/./; q'
+      `
+
+      test -d "$dstdir"
+      dstdir_status=$?
+    fi
+  fi
+
+  obsolete_mkdir_used=false
+
+  if test $dstdir_status != 0; then
+    case $posix_mkdir in
+      '')
+	# Create intermediate dirs using mode 755 as modified by the umask.
+	# This is like FreeBSD 'install' as of 1997-10-28.
+	umask=`umask`
+	case $stripcmd.$umask in
+	  # Optimize common cases.
+	  *[2367][2367]) mkdir_umask=$umask;;
+	  .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+	  *[0-7])
+	    mkdir_umask=`expr $umask + 22 \
+	      - $umask % 100 % 40 + $umask % 20 \
+	      - $umask % 10 % 4 + $umask % 2
+	    `;;
+	  *) mkdir_umask=$umask,go-w;;
+	esac
+
+	# With -d, create the new directory with the user-specified mode.
+	# Otherwise, rely on $mkdir_umask.
+	if test -n "$dir_arg"; then
+	  mkdir_mode=-m$mode
+	else
+	  mkdir_mode=
+	fi
+
+	posix_mkdir=false
+	case $umask in
+	  *[123567][0-7][0-7])
+	    # POSIX mkdir -p sets u+wx bits regardless of umask, which
+	    # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+	    ;;
+	  *)
+	    tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+	    trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+	    if (umask $mkdir_umask &&
+		exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+	    then
+	      if test -z "$dir_arg" || {
+		   # Check for POSIX incompatibilities with -m.
+		   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+		   # other-writable bit of parent directory when it shouldn't.
+		   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+		   ls_ld_tmpdir=`ls -ld "$tmpdir"`
+		   case $ls_ld_tmpdir in
+		     d????-?r-*) different_mode=700;;
+		     d????-?--*) different_mode=755;;
+		     *) false;;
+		   esac &&
+		   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+		     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+		     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+		   }
+		 }
+	      then posix_mkdir=:
+	      fi
+	      rmdir "$tmpdir/d" "$tmpdir"
+	    else
+	      # Remove any dirs left behind by ancient mkdir implementations.
+	      rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+	    fi
+	    trap '' 0;;
+	esac;;
+    esac
+
+    if
+      $posix_mkdir && (
+	umask $mkdir_umask &&
+	$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+      )
+    then :
+    else
+
+      # The umask is ridiculous, or mkdir does not conform to POSIX,
+      # or it failed possibly due to a race condition.  Create the
+      # directory the slow way, step by step, checking for races as we go.
+
+      case $dstdir in
+	/*) prefix='/';;
+	[-=\(\)!]*) prefix='./';;
+	*)  prefix='';;
+      esac
+
+      eval "$initialize_posix_glob"
+
+      oIFS=$IFS
+      IFS=/
+      $posix_glob set -f
+      set fnord $dstdir
+      shift
+      $posix_glob set +f
+      IFS=$oIFS
+
+      prefixes=
+
+      for d
+      do
+	test X"$d" = X && continue
+
+	prefix=$prefix$d
+	if test -d "$prefix"; then
+	  prefixes=
+	else
+	  if $posix_mkdir; then
+	    (umask=$mkdir_umask &&
+	     $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+	    # Don't fail if two instances are running concurrently.
+	    test -d "$prefix" || exit 1
+	  else
+	    case $prefix in
+	      *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+	      *) qprefix=$prefix;;
+	    esac
+	    prefixes="$prefixes '$qprefix'"
+	  fi
+	fi
+	prefix=$prefix/
+      done
+
+      if test -n "$prefixes"; then
+	# Don't fail if two instances are running concurrently.
+	(umask $mkdir_umask &&
+	 eval "\$doit_exec \$mkdirprog $prefixes") ||
+	  test -d "$dstdir" || exit 1
+	obsolete_mkdir_used=true
+      fi
+    fi
+  fi
+
+  if test -n "$dir_arg"; then
+    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+  else
+
+    # Make a couple of temp file names in the proper directory.
+    dsttmp=$dstdir/_inst.$$_
+    rmtmp=$dstdir/_rm.$$_
+
+    # Trap to clean up those temp files at exit.
+    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+    # Copy the file name to the temp name.
+    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+    # and set any options; do chmod last to preserve setuid bits.
+    #
+    # If any of these fail, we abort the whole thing.  If we want to
+    # ignore errors from any of these, just make sure not to ignore
+    # errors from the above "$doit $cpprog $src $dsttmp" command.
+    #
+    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+    # If -C, don't bother to copy if it wouldn't change the file.
+    if $copy_on_change &&
+       old=`LC_ALL=C ls -dlL "$dst"	2>/dev/null` &&
+       new=`LC_ALL=C ls -dlL "$dsttmp"	2>/dev/null` &&
+
+       eval "$initialize_posix_glob" &&
+       $posix_glob set -f &&
+       set X $old && old=:$2:$4:$5:$6 &&
+       set X $new && new=:$2:$4:$5:$6 &&
+       $posix_glob set +f &&
+
+       test "$old" = "$new" &&
+       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+    then
+      rm -f "$dsttmp"
+    else
+      # Rename the file to the real destination.
+      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+      # The rename failed, perhaps because mv can't rename something else
+      # to itself, or perhaps because mv is so ancient that it does not
+      # support -f.
+      {
+	# Now remove or move aside any old file at destination location.
+	# We try this two ways since rm can't unlink itself on some
+	# systems and the destination file might be busy for other
+	# reasons.  In this case, the final cleanup might fail but the new
+	# file should still install successfully.
+	{
+	  test ! -f "$dst" ||
+	  $doit $rmcmd -f "$dst" 2>/dev/null ||
+	  { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+	    { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+	  } ||
+	  { echo "$0: cannot unlink or rename $dst" >&2
+	    (exit 1); exit 1
+	  }
+	} &&
+
+	# Now rename the file to the real destination.
+	$doit $mvcmd "$dsttmp" "$dst"
+      }
+    fi || exit 1
+
+    trap '' 0
+  fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/libfuse-lite/Android.mk b/libfuse-lite/Android.mk
new file mode 100755
index 0000000000000000000000000000000000000000..1c89247c666790525f4d8627b9fcb5e31db7effc
--- /dev/null
+++ b/libfuse-lite/Android.mk
@@ -0,0 +1,38 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+	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
+
+LOCAL_MODULE := libfuse-lite
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SYSTEM_SHARED_LIBRARIES := \
+	libc
+
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH)/.. \
+	$(LOCAL_PATH)/../include/fuse-lite
+
+LOCAL_CFLAGS := -O2 -g -W -Wall \
+	-D_LARGEFILE_SOURCE \
+	-D_FILE_OFFSET_BITS=64 \
+	-DHAVE_CONFIG_H
+
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_STATIC_LIBRARY)
+
diff --git a/libfuse-lite/Makefile.am b/libfuse-lite/Makefile.am
new file mode 100755
index 0000000000000000000000000000000000000000..d9591ec47fe376649637acb2d24dc238a2f1a17a
--- /dev/null
+++ b/libfuse-lite/Makefile.am
@@ -0,0 +1,31 @@
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+ 
+if FUSE_INTERNAL
+noinst_LTLIBRARIES = libfuse-lite.la
+endif
+
+libfuse_lite_la_CFLAGS=			  \
+	$(AM_CFLAGS) 			  \
+	$(LIBFUSE_LITE_CFLAGS)		  \
+	-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
diff --git a/libfuse-lite/Makefile.in b/libfuse-lite/Makefile.in
new file mode 100755
index 0000000000000000000000000000000000000000..886b46a23513fc827dafe346e01f2f2dc792cfc3
--- /dev/null
+++ b/libfuse-lite/Makefile.in
@@ -0,0 +1,729 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = libfuse-lite
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+	$(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libfuse_lite_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_libfuse_lite_la_OBJECTS = libfuse_lite_la-fuse.lo \
+	libfuse_lite_la-fuse_kern_chan.lo libfuse_lite_la-fuse_loop.lo \
+	libfuse_lite_la-fuse_lowlevel.lo libfuse_lite_la-fuse_opt.lo \
+	libfuse_lite_la-fuse_session.lo \
+	libfuse_lite_la-fuse_signals.lo libfuse_lite_la-fusermount.lo \
+	libfuse_lite_la-helper.lo libfuse_lite_la-mount.lo \
+	libfuse_lite_la-mount_util.lo
+libfuse_lite_la_OBJECTS = $(am_libfuse_lite_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
+libfuse_lite_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(libfuse_lite_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+	-o $@
+@FUSE_INTERNAL_TRUE@am_libfuse_lite_la_rpath =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
+SOURCES = $(libfuse_lite_la_SOURCES)
+DIST_SOURCES = $(libfuse_lite_la_SOURCES)
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FUSE_MODULE_CFLAGS = @FUSE_MODULE_CFLAGS@
+FUSE_MODULE_LIBS = @FUSE_MODULE_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDCONFIG = @LDCONFIG@
+LDFLAGS = @LDFLAGS@
+LIBFUSE_LITE_CFLAGS = @LIBFUSE_LITE_CFLAGS@
+LIBFUSE_LITE_LIBS = @LIBFUSE_LITE_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBNTFS_3G_VERSION = @LIBNTFS_3G_VERSION@
+LIBNTFS_CPPFLAGS = @LIBNTFS_CPPFLAGS@
+LIBNTFS_LIBS = @LIBNTFS_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MKNTFS_CPPFLAGS = @MKNTFS_CPPFLAGS@
+MKNTFS_LIBS = @MKNTFS_LIBS@
+MV = @MV@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NTFSPROGS_STATIC_LIBS = @NTFSPROGS_STATIC_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+OUTPUT_FORMAT = @OUTPUT_FORMAT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+RM = @RM@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+all_includes = @all_includes@
+all_libraries = @all_libraries@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+ntfs3gincludedir = @ntfs3gincludedir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgconfigdir = @pkgconfigdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+rootbindir = @rootbindir@
+rootlibdir = @rootlibdir@
+rootsbindir = @rootsbindir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+@FUSE_INTERNAL_TRUE@noinst_LTLIBRARIES = libfuse-lite.la
+libfuse_lite_la_CFLAGS = \
+	$(AM_CFLAGS) 			  \
+	$(LIBFUSE_LITE_CFLAGS)		  \
+	-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
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libfuse-lite/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu libfuse-lite/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; \
+	locs=`for p in $$list; do echo $$p; done | \
+	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+	      sort -u`; \
+	test -z "$$locs" || { \
+	  echo rm -f $${locs}; \
+	  rm -f $${locs}; \
+	}
+
+libfuse-lite.la: $(libfuse_lite_la_OBJECTS) $(libfuse_lite_la_DEPENDENCIES) $(EXTRA_libfuse_lite_la_DEPENDENCIES) 
+	$(AM_V_CCLD)$(libfuse_lite_la_LINK) $(am_libfuse_lite_la_rpath) $(libfuse_lite_la_OBJECTS) $(libfuse_lite_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfuse_lite_la-fuse.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfuse_lite_la-fuse_kern_chan.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfuse_lite_la-fuse_loop.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfuse_lite_la-fuse_lowlevel.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfuse_lite_la-fuse_opt.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfuse_lite_la-fuse_session.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfuse_lite_la-fuse_signals.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfuse_lite_la-fusermount.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfuse_lite_la-helper.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfuse_lite_la-mount.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfuse_lite_la-mount_util.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+libfuse_lite_la-fuse.lo: fuse.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-fuse.lo -MD -MP -MF $(DEPDIR)/libfuse_lite_la-fuse.Tpo -c -o libfuse_lite_la-fuse.lo `test -f 'fuse.c' || echo '$(srcdir)/'`fuse.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libfuse_lite_la-fuse.Tpo $(DEPDIR)/libfuse_lite_la-fuse.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='fuse.c' object='libfuse_lite_la-fuse.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-fuse.lo `test -f 'fuse.c' || echo '$(srcdir)/'`fuse.c
+
+libfuse_lite_la-fuse_kern_chan.lo: fuse_kern_chan.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-fuse_kern_chan.lo -MD -MP -MF $(DEPDIR)/libfuse_lite_la-fuse_kern_chan.Tpo -c -o libfuse_lite_la-fuse_kern_chan.lo `test -f 'fuse_kern_chan.c' || echo '$(srcdir)/'`fuse_kern_chan.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libfuse_lite_la-fuse_kern_chan.Tpo $(DEPDIR)/libfuse_lite_la-fuse_kern_chan.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='fuse_kern_chan.c' object='libfuse_lite_la-fuse_kern_chan.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-fuse_kern_chan.lo `test -f 'fuse_kern_chan.c' || echo '$(srcdir)/'`fuse_kern_chan.c
+
+libfuse_lite_la-fuse_loop.lo: fuse_loop.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-fuse_loop.lo -MD -MP -MF $(DEPDIR)/libfuse_lite_la-fuse_loop.Tpo -c -o libfuse_lite_la-fuse_loop.lo `test -f 'fuse_loop.c' || echo '$(srcdir)/'`fuse_loop.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libfuse_lite_la-fuse_loop.Tpo $(DEPDIR)/libfuse_lite_la-fuse_loop.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='fuse_loop.c' object='libfuse_lite_la-fuse_loop.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-fuse_loop.lo `test -f 'fuse_loop.c' || echo '$(srcdir)/'`fuse_loop.c
+
+libfuse_lite_la-fuse_lowlevel.lo: fuse_lowlevel.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-fuse_lowlevel.lo -MD -MP -MF $(DEPDIR)/libfuse_lite_la-fuse_lowlevel.Tpo -c -o libfuse_lite_la-fuse_lowlevel.lo `test -f 'fuse_lowlevel.c' || echo '$(srcdir)/'`fuse_lowlevel.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libfuse_lite_la-fuse_lowlevel.Tpo $(DEPDIR)/libfuse_lite_la-fuse_lowlevel.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='fuse_lowlevel.c' object='libfuse_lite_la-fuse_lowlevel.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-fuse_lowlevel.lo `test -f 'fuse_lowlevel.c' || echo '$(srcdir)/'`fuse_lowlevel.c
+
+libfuse_lite_la-fuse_opt.lo: fuse_opt.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-fuse_opt.lo -MD -MP -MF $(DEPDIR)/libfuse_lite_la-fuse_opt.Tpo -c -o libfuse_lite_la-fuse_opt.lo `test -f 'fuse_opt.c' || echo '$(srcdir)/'`fuse_opt.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libfuse_lite_la-fuse_opt.Tpo $(DEPDIR)/libfuse_lite_la-fuse_opt.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='fuse_opt.c' object='libfuse_lite_la-fuse_opt.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-fuse_opt.lo `test -f 'fuse_opt.c' || echo '$(srcdir)/'`fuse_opt.c
+
+libfuse_lite_la-fuse_session.lo: fuse_session.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-fuse_session.lo -MD -MP -MF $(DEPDIR)/libfuse_lite_la-fuse_session.Tpo -c -o libfuse_lite_la-fuse_session.lo `test -f 'fuse_session.c' || echo '$(srcdir)/'`fuse_session.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libfuse_lite_la-fuse_session.Tpo $(DEPDIR)/libfuse_lite_la-fuse_session.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='fuse_session.c' object='libfuse_lite_la-fuse_session.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-fuse_session.lo `test -f 'fuse_session.c' || echo '$(srcdir)/'`fuse_session.c
+
+libfuse_lite_la-fuse_signals.lo: fuse_signals.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-fuse_signals.lo -MD -MP -MF $(DEPDIR)/libfuse_lite_la-fuse_signals.Tpo -c -o libfuse_lite_la-fuse_signals.lo `test -f 'fuse_signals.c' || echo '$(srcdir)/'`fuse_signals.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libfuse_lite_la-fuse_signals.Tpo $(DEPDIR)/libfuse_lite_la-fuse_signals.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='fuse_signals.c' object='libfuse_lite_la-fuse_signals.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-fuse_signals.lo `test -f 'fuse_signals.c' || echo '$(srcdir)/'`fuse_signals.c
+
+libfuse_lite_la-fusermount.lo: fusermount.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-fusermount.lo -MD -MP -MF $(DEPDIR)/libfuse_lite_la-fusermount.Tpo -c -o libfuse_lite_la-fusermount.lo `test -f 'fusermount.c' || echo '$(srcdir)/'`fusermount.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libfuse_lite_la-fusermount.Tpo $(DEPDIR)/libfuse_lite_la-fusermount.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='fusermount.c' object='libfuse_lite_la-fusermount.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-fusermount.lo `test -f 'fusermount.c' || echo '$(srcdir)/'`fusermount.c
+
+libfuse_lite_la-helper.lo: helper.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-helper.lo -MD -MP -MF $(DEPDIR)/libfuse_lite_la-helper.Tpo -c -o libfuse_lite_la-helper.lo `test -f 'helper.c' || echo '$(srcdir)/'`helper.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libfuse_lite_la-helper.Tpo $(DEPDIR)/libfuse_lite_la-helper.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='helper.c' object='libfuse_lite_la-helper.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-helper.lo `test -f 'helper.c' || echo '$(srcdir)/'`helper.c
+
+libfuse_lite_la-mount.lo: mount.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-mount.lo -MD -MP -MF $(DEPDIR)/libfuse_lite_la-mount.Tpo -c -o libfuse_lite_la-mount.lo `test -f 'mount.c' || echo '$(srcdir)/'`mount.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libfuse_lite_la-mount.Tpo $(DEPDIR)/libfuse_lite_la-mount.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='mount.c' object='libfuse_lite_la-mount.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-mount.lo `test -f 'mount.c' || echo '$(srcdir)/'`mount.c
+
+libfuse_lite_la-mount_util.lo: mount_util.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-mount_util.lo -MD -MP -MF $(DEPDIR)/libfuse_lite_la-mount_util.Tpo -c -o libfuse_lite_la-mount_util.lo `test -f 'mount_util.c' || echo '$(srcdir)/'`mount_util.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libfuse_lite_la-mount_util.Tpo $(DEPDIR)/libfuse_lite_la-mount_util.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='mount_util.c' object='libfuse_lite_la-mount_util.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-mount_util.lo `test -f 'mount_util.c' || echo '$(srcdir)/'`mount_util.c
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+	clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \
+	ctags-am distclean distclean-compile distclean-generic \
+	distclean-libtool distclean-tags distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-dvi install-dvi-am install-exec \
+	install-exec-am install-html install-html-am install-info \
+	install-info-am install-man install-pdf install-pdf-am \
+	install-ps install-ps-am install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	tags tags-am uninstall uninstall-am
+
+
+libs:	libfuse-lite.la
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/libfuse-lite/fuse.c b/libfuse-lite/fuse.c
new file mode 100755
index 0000000000000000000000000000000000000000..4c6c7133002dbea3eccdd21870ef2e21e707398b
--- /dev/null
+++ b/libfuse-lite/fuse.c
@@ -0,0 +1,3243 @@
+/*
+    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
+*/
+
+#ifdef __SOLARIS__
+/* For pthread_rwlock_t */
+#define _GNU_SOURCE
+#endif /* __SOLARIS__ */
+
+#include "config.h"
+#include "fuse_i.h"
+#include "fuse_lowlevel.h"
+#include "fuse_opt.h"
+#include "fuse_misc.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <time.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <errno.h>
+#include <signal.h>
+#include <dlfcn.h>
+#include <assert.h>
+#include <sys/param.h>
+#include <sys/uio.h>
+#include <sys/time.h>
+
+#ifdef __SOLARIS__
+#define FUSE_MAX_PATH 4096
+#endif /* __SOLARIS__ */
+
+#define FUSE_DEFAULT_INTR_SIGNAL SIGUSR1
+
+#define FUSE_UNKNOWN_INO 0xffffffff
+#define OFFSET_MAX 0x7fffffffffffffffLL
+
+struct fuse_config {
+    unsigned int uid;
+    unsigned int gid;
+    unsigned int  umask;
+    double entry_timeout;
+    double negative_timeout;
+    double attr_timeout;
+    double ac_attr_timeout;
+    int ac_attr_timeout_set;
+    int debug;
+    int hard_remove;
+    int use_ino;
+    int readdir_ino;
+    int set_mode;
+    int set_uid;
+    int set_gid;
+    int direct_io;
+    int kernel_cache;
+    int intr;
+    int intr_signal;
+    int help;
+#ifdef __SOLARIS__
+    int auto_cache;
+    char *modules;
+#endif /* __SOLARIS__ */
+};
+
+struct fuse_fs {
+    struct fuse_operations op;
+    void *user_data;
+#ifdef __SOLARIS__
+    struct fuse_module *m;
+#endif /* __SOLARIS__ */
+};
+
+#ifdef __SOLARIS__
+struct fusemod_so {
+    void *handle;
+    int ctr;
+};
+#endif /* __SOLARIS__ */
+
+struct fuse {
+    struct fuse_session *se;
+    struct node **name_table;
+    size_t name_table_size;
+    struct node **id_table;
+    size_t id_table_size;
+    fuse_ino_t ctr;
+    unsigned int generation;
+    unsigned int hidectr;
+    pthread_mutex_t lock;
+    pthread_rwlock_t tree_lock;
+    struct fuse_config conf;
+    int intr_installed;
+    struct fuse_fs *fs;
+};
+
+struct lock {
+    int type;
+    off_t start;
+    off_t end;
+    pid_t pid;
+    uint64_t owner;
+    struct lock *next;
+};
+
+struct node {
+    struct node *name_next;
+    struct node *id_next;
+    fuse_ino_t nodeid;
+    unsigned int generation;
+    int refctr;
+    struct node *parent;
+    char *name;
+    uint64_t nlookup;
+    int open_count;
+    int is_hidden;
+#ifdef __SOLARIS__
+    struct timespec stat_updated;
+    struct timespec mtime;
+    off_t size;
+    int cache_valid;
+#endif /* __SOLARIS__ */
+    struct lock *locks;
+};
+
+struct fuse_dh {
+    pthread_mutex_t lock;
+    struct fuse *fuse;
+    fuse_req_t req;
+    char *contents;
+    int allocated;
+    unsigned len;
+    unsigned size;
+    unsigned needlen;
+    int filled;
+    uint64_t fh;
+    int error;
+    fuse_ino_t nodeid;
+};
+
+struct fuse_context_i {
+    struct fuse_context ctx;
+    fuse_req_t req;
+};
+
+static pthread_key_t fuse_context_key;
+static pthread_mutex_t fuse_context_lock = PTHREAD_MUTEX_INITIALIZER;
+static int fuse_context_ref;
+
+#ifdef __SOLARIS__
+
+static struct fusemod_so *fuse_current_so;
+static struct fuse_module *fuse_modules;
+
+static int fuse_load_so_name(const char *soname)
+{
+    struct fusemod_so *so;
+
+    so = calloc(1, sizeof(struct fusemod_so));
+    if (!so) {
+        fprintf(stderr, "fuse: memory allocation failed\n");
+        return -1;
+    }
+
+    fuse_current_so = so;
+    so->handle = dlopen(soname, RTLD_NOW);
+    fuse_current_so = NULL;
+    if (!so->handle) {
+        fprintf(stderr, "fuse: %s\n", dlerror());
+        goto err;
+    }
+    if (!so->ctr) {
+        fprintf(stderr, "fuse: %s did not register any modules", soname);
+        goto err;
+    }
+    return 0;
+
+ err:
+    if (so->handle)
+        dlclose(so->handle);
+    free(so);
+    return -1;
+}
+
+static int fuse_load_so_module(const char *module)
+{
+    int res;
+    char *soname = malloc(strlen(module) + 64);
+    if (!soname) {
+        fprintf(stderr, "fuse: memory allocation failed\n");
+        return -1;
+    }
+    sprintf(soname, "libfusemod_%s.so", module);
+    res = fuse_load_so_name(soname);
+    free(soname);
+    return res;
+}
+
+static struct fuse_module *fuse_find_module(const char *module)
+{
+    struct fuse_module *m;
+    for (m = fuse_modules; m; m = m->next) {
+        if (strcmp(module, m->name) == 0) {
+            m->ctr++;
+            break;
+        }
+    }
+    return m;
+}
+
+static struct fuse_module *fuse_get_module(const char *module)
+{
+    struct fuse_module *m;
+
+    pthread_mutex_lock(&fuse_context_lock);
+    m = fuse_find_module(module);
+    if (!m) {
+        int err = fuse_load_so_module(module);
+        if (!err)
+            m = fuse_find_module(module);
+    }
+    pthread_mutex_unlock(&fuse_context_lock);
+    return m;
+}
+
+static void fuse_put_module(struct fuse_module *m)
+{
+    pthread_mutex_lock(&fuse_context_lock);
+    assert(m->ctr > 0);
+    m->ctr--;
+    if (!m->ctr && m->so) {
+        struct fusemod_so *so = m->so;
+        assert(so->ctr > 0);
+        so->ctr--;
+        if (!so->ctr) {
+            struct fuse_module **mp;
+            for (mp = &fuse_modules; *mp;) {
+                if ((*mp)->so == so)
+                    *mp = (*mp)->next;
+                else
+                    mp = &(*mp)->next;
+            }
+            dlclose(so->handle);
+            free(so);
+        }
+    }
+    pthread_mutex_unlock(&fuse_context_lock);
+}
+#endif /* __SOLARIS__ */
+
+static struct node *get_node_nocheck(struct fuse *f, fuse_ino_t nodeid)
+{
+    size_t hash = nodeid % f->id_table_size;
+    struct node *node;
+
+    for (node = f->id_table[hash]; node != NULL; node = node->id_next)
+        if (node->nodeid == nodeid)
+            return node;
+
+    return NULL;
+}
+
+static struct node *get_node(struct fuse *f, fuse_ino_t nodeid)
+{
+    struct node *node = get_node_nocheck(f, nodeid);
+    if (!node) {
+        fprintf(stderr, "fuse internal error: node %llu not found\n",
+                (unsigned long long) nodeid);
+        abort();
+    }
+    return node;
+}
+
+static void free_node(struct node *node)
+{
+    free(node->name);
+    free(node);
+}
+
+static void unhash_id(struct fuse *f, struct node *node)
+{
+    size_t hash = node->nodeid % f->id_table_size;
+    struct node **nodep = &f->id_table[hash];
+
+    for (; *nodep != NULL; nodep = &(*nodep)->id_next)
+        if (*nodep == node) {
+            *nodep = node->id_next;
+            return;
+        }
+}
+
+static void hash_id(struct fuse *f, struct node *node)
+{
+    size_t hash = node->nodeid % f->id_table_size;
+    node->id_next = f->id_table[hash];
+    f->id_table[hash] = node;
+}
+
+static unsigned int name_hash(struct fuse *f, fuse_ino_t parent,
+                              const char *name)
+{
+    unsigned int hash = *name;
+
+    if (hash)
+        for (name += 1; *name != '\0'; name++)
+            hash = (hash << 5) - hash + *name;
+
+    return (hash + parent) % f->name_table_size;
+}
+
+static void unref_node(struct fuse *f, struct node *node);
+
+static void unhash_name(struct fuse *f, struct node *node)
+{
+    if (node->name) {
+        size_t hash = name_hash(f, node->parent->nodeid, node->name);
+        struct node **nodep = &f->name_table[hash];
+
+        for (; *nodep != NULL; nodep = &(*nodep)->name_next)
+            if (*nodep == node) {
+                *nodep = node->name_next;
+                node->name_next = NULL;
+                unref_node(f, node->parent);
+                free(node->name);
+                node->name = NULL;
+                node->parent = NULL;
+                return;
+            }
+        fprintf(stderr, "fuse internal error: unable to unhash node: %llu\n",
+                (unsigned long long) node->nodeid);
+        abort();
+    }
+}
+
+static int hash_name(struct fuse *f, struct node *node, fuse_ino_t parentid,
+                     const char *name)
+{
+    size_t hash = name_hash(f, parentid, name);
+    struct node *parent = get_node(f, parentid);
+    node->name = strdup(name);
+    if (node->name == NULL)
+        return -1;
+
+    parent->refctr ++;
+    node->parent = parent;
+    node->name_next = f->name_table[hash];
+    f->name_table[hash] = node;
+    return 0;
+}
+
+static void delete_node(struct fuse *f, struct node *node)
+{
+    if (f->conf.debug)
+        fprintf(stderr, "delete: %llu\n", (unsigned long long) node->nodeid);
+
+    assert(!node->name);
+    unhash_id(f, node);
+    free_node(node);
+}
+
+static void unref_node(struct fuse *f, struct node *node)
+{
+    assert(node->refctr > 0);
+    node->refctr --;
+    if (!node->refctr)
+        delete_node(f, node);
+}
+
+static fuse_ino_t next_id(struct fuse *f)
+{
+    do {
+        f->ctr = (f->ctr + 1) & 0xffffffff;
+        if (!f->ctr)
+            f->generation ++;
+    } while (f->ctr == 0 || f->ctr == FUSE_UNKNOWN_INO ||
+             get_node_nocheck(f, f->ctr) != NULL);
+    return f->ctr;
+}
+
+static struct node *lookup_node(struct fuse *f, fuse_ino_t parent,
+                                const char *name)
+{
+    size_t hash = name_hash(f, parent, name);
+    struct node *node;
+
+    for (node = f->name_table[hash]; node != NULL; node = node->name_next)
+        if (node->parent->nodeid == parent && strcmp(node->name, name) == 0)
+            return node;
+
+    return NULL;
+}
+
+static struct node *find_node(struct fuse *f, fuse_ino_t parent,
+                              const char *name)
+{
+    struct node *node;
+
+    pthread_mutex_lock(&f->lock);
+    node = lookup_node(f, parent, name);
+    if (node == NULL) {
+        node = (struct node *) calloc(1, sizeof(struct node));
+        if (node == NULL)
+            goto out_err;
+
+        node->refctr = 1;
+        node->nodeid = next_id(f);
+        node->open_count = 0;
+        node->is_hidden = 0;
+        node->generation = f->generation;
+        if (hash_name(f, node, parent, name) == -1) {
+            free(node);
+            node = NULL;
+            goto out_err;
+        }
+        hash_id(f, node);
+    }
+    node->nlookup ++;
+ out_err:
+    pthread_mutex_unlock(&f->lock);
+    return node;
+}
+
+#ifndef __SOLARIS__
+static char *add_name(char **buf, unsigned *bufsize, char *s, const char *name)
+#else /* __SOLARIS__ */
+static char *add_name(char *buf, char *s, const char *name)
+#endif /* __SOLARIS__ */
+{
+    size_t len = strlen(name);
+
+#ifndef __SOLARIS__
+    if (s - len <= *buf) {
+	unsigned pathlen = *bufsize - (s - *buf);
+	unsigned newbufsize = *bufsize;
+	char *newbuf;
+
+	while (newbufsize < pathlen + len + 1) {
+	    if (newbufsize >= 0x80000000)
+	    	newbufsize = 0xffffffff;
+	    else
+	    	newbufsize *= 2;
+	}
+
+	newbuf = realloc(*buf, newbufsize);
+	if (newbuf == NULL)
+		return NULL;
+
+	*buf = newbuf;
+	s = newbuf + newbufsize - pathlen;
+	memmove(s, newbuf + *bufsize - pathlen, pathlen);
+	*bufsize = newbufsize;
+    }
+    s -= len;
+#else /* ! __SOLARIS__ */
+    s -= len;
+    if (s <= buf) {
+        fprintf(stderr, "fuse: path too long: ...%s\n", s + len);
+        return NULL;
+    }
+#endif /* __SOLARIS__ */
+    strncpy(s, name, len);
+    s--;
+    *s = '/';
+
+    return s;
+}
+
+static char *get_path_name(struct fuse *f, fuse_ino_t nodeid, const char *name)
+{
+#ifdef __SOLARIS__
+    char buf[FUSE_MAX_PATH];
+    char *s = buf + FUSE_MAX_PATH - 1;
+    struct node *node;
+
+    *s = '\0';
+
+    if (name != NULL) {
+        s = add_name(buf, s, name);
+        if (s == NULL)
+            return NULL;
+    }
+
+    pthread_mutex_lock(&f->lock);
+    for (node = get_node(f, nodeid); node && node->nodeid != FUSE_ROOT_ID;
+         node = node->parent) {
+        if (node->name == NULL) {
+            s = NULL;
+            break;
+        }
+
+        s = add_name(buf, s, node->name);
+        if (s == NULL)
+            break;
+    }
+    pthread_mutex_unlock(&f->lock);
+
+    if (node == NULL || s == NULL)
+        return NULL;
+    else if (*s == '\0')
+        return strdup("/");
+    else
+        return strdup(s);
+
+#else /* __SOLARIS__ */
+
+    unsigned bufsize = 256;
+    char *buf;
+    char *s;
+    struct node *node;
+
+    buf = malloc(bufsize);
+    if (buf == NULL)
+            return NULL;
+
+    s = buf + bufsize - 1;
+    *s = '\0';
+
+    if (name != NULL) {
+        s = add_name(&buf, &bufsize, s, name);
+        if (s == NULL)
+            goto out_free;
+    }
+
+    pthread_mutex_lock(&f->lock);
+    for (node = get_node(f, nodeid); node && node->nodeid != FUSE_ROOT_ID;
+         node = node->parent) {
+        if (node->name == NULL) {
+            s = NULL;
+            break;
+        }
+
+        s = add_name(&buf, &bufsize, s, node->name);
+        if (s == NULL)
+            break;
+    }
+    pthread_mutex_unlock(&f->lock);
+
+    if (node == NULL || s == NULL)
+        goto out_free;
+    
+    if (s[0])
+            memmove(buf, s, bufsize - (s - buf));
+    else
+            strcpy(buf, "/");
+    return buf;
+    
+out_free:
+    free(buf);
+    return NULL;
+#endif /* __SOLARIS__ */
+}
+
+static char *get_path(struct fuse *f, fuse_ino_t nodeid)
+{
+    return get_path_name(f, nodeid, NULL);
+}
+
+static void forget_node(struct fuse *f, fuse_ino_t nodeid, uint64_t nlookup)
+{
+    struct node *node;
+    if (nodeid == FUSE_ROOT_ID)
+        return;
+    pthread_mutex_lock(&f->lock);
+    node = get_node(f, nodeid);
+    assert(node->nlookup >= nlookup);
+    node->nlookup -= nlookup;
+    if (!node->nlookup) {
+        unhash_name(f, node);
+        unref_node(f, node);
+    }
+    pthread_mutex_unlock(&f->lock);
+}
+
+static void remove_node(struct fuse *f, fuse_ino_t dir, const char *name)
+{
+    struct node *node;
+
+    pthread_mutex_lock(&f->lock);
+    node = lookup_node(f, dir, name);
+    if (node != NULL)
+        unhash_name(f, node);
+    pthread_mutex_unlock(&f->lock);
+}
+
+static int rename_node(struct fuse *f, fuse_ino_t olddir, const char *oldname,
+                        fuse_ino_t newdir, const char *newname, int hide)
+{
+    struct node *node;
+    struct node *newnode;
+    int err = 0;
+
+    pthread_mutex_lock(&f->lock);
+    node  = lookup_node(f, olddir, oldname);
+    newnode  = lookup_node(f, newdir, newname);
+    if (node == NULL)
+        goto out;
+
+    if (newnode != NULL) {
+        if (hide) {
+            fprintf(stderr, "fuse: hidden file got created during hiding\n");
+            err = -EBUSY;
+            goto out;
+        }
+        unhash_name(f, newnode);
+    }
+
+    unhash_name(f, node);
+    if (hash_name(f, node, newdir, newname) == -1) {
+        err = -ENOMEM;
+        goto out;
+    }
+
+    if (hide)
+        node->is_hidden = 1;
+
+ out:
+    pthread_mutex_unlock(&f->lock);
+    return err;
+}
+
+static void set_stat(struct fuse *f, fuse_ino_t nodeid, struct stat *stbuf)
+{
+    if (!f->conf.use_ino)
+        stbuf->st_ino = nodeid;
+    if (f->conf.set_mode)
+        stbuf->st_mode = (stbuf->st_mode & S_IFMT) | (0777 & ~f->conf.umask);
+    if (f->conf.set_uid)
+        stbuf->st_uid = f->conf.uid;
+    if (f->conf.set_gid)
+        stbuf->st_gid = f->conf.gid;
+}
+
+static struct fuse *req_fuse(fuse_req_t req)
+{
+    return (struct fuse *) fuse_req_userdata(req);
+}
+
+static void fuse_intr_sighandler(int sig)
+{
+    (void) sig;
+    /* Nothing to do */
+}
+
+struct fuse_intr_data {
+    pthread_t id;
+    pthread_cond_t cond;
+    int finished;
+};
+
+static void fuse_interrupt(fuse_req_t req, void *d_)
+{
+    struct fuse_intr_data *d = d_;
+    struct fuse *f = req_fuse(req);
+
+    if (d->id == pthread_self())
+        return;
+
+    pthread_mutex_lock(&f->lock);
+    while (!d->finished) {
+        struct timeval now;
+        struct timespec timeout;
+
+        pthread_kill(d->id, f->conf.intr_signal);
+        gettimeofday(&now, NULL);
+        timeout.tv_sec = now.tv_sec + 1;
+        timeout.tv_nsec = now.tv_usec * 1000;
+        pthread_cond_timedwait(&d->cond, &f->lock, &timeout);
+    }
+    pthread_mutex_unlock(&f->lock);
+}
+
+static void fuse_do_finish_interrupt(struct fuse *f, fuse_req_t req,
+                                     struct fuse_intr_data *d)
+{
+    pthread_mutex_lock(&f->lock);
+    d->finished = 1;
+    pthread_cond_broadcast(&d->cond);
+    pthread_mutex_unlock(&f->lock);
+    fuse_req_interrupt_func(req, NULL, NULL);
+    pthread_cond_destroy(&d->cond);
+}
+
+static void fuse_do_prepare_interrupt(fuse_req_t req, struct fuse_intr_data *d)
+{
+    d->id = pthread_self();
+    pthread_cond_init(&d->cond, NULL);
+    d->finished = 0;
+    fuse_req_interrupt_func(req, fuse_interrupt, d);
+}
+
+static void fuse_finish_interrupt(struct fuse *f, fuse_req_t req,
+                                         struct fuse_intr_data *d)
+{
+    if (f->conf.intr)
+        fuse_do_finish_interrupt(f, req, d);
+}
+
+static void fuse_prepare_interrupt(struct fuse *f, fuse_req_t req,
+                                          struct fuse_intr_data *d)
+{
+    if (f->conf.intr)
+        fuse_do_prepare_interrupt(req, d);
+}
+
+int fuse_fs_getattr(struct fuse_fs *fs, const char *path, struct stat *buf)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.getattr)
+        return fs->op.getattr(path, buf);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_fgetattr(struct fuse_fs *fs, const char *path, struct stat *buf,
+                     struct fuse_file_info *fi)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.fgetattr)
+        return fs->op.fgetattr(path, buf, fi);
+    else if (fs->op.getattr)
+        return fs->op.getattr(path, buf);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_rename(struct fuse_fs *fs, const char *oldpath,
+                   const char *newpath)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.rename)
+        return fs->op.rename(oldpath, newpath);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_unlink(struct fuse_fs *fs, const char *path)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.unlink)
+        return fs->op.unlink(path);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_rmdir(struct fuse_fs *fs, const char *path)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.rmdir)
+        return fs->op.rmdir(path);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_symlink(struct fuse_fs *fs, const char *linkname, const char *path)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.symlink)
+        return fs->op.symlink(linkname, path);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_link(struct fuse_fs *fs, const char *oldpath, const char *newpath)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.link)
+        return fs->op.link(oldpath, newpath);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_release(struct fuse_fs *fs,  const char *path,
+                    struct fuse_file_info *fi)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.release)
+        return fs->op.release(path, fi);
+    else
+        return 0;
+}
+
+int fuse_fs_opendir(struct fuse_fs *fs, const char *path,
+                    struct fuse_file_info *fi)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.opendir)
+        return fs->op.opendir(path, fi);
+    else
+        return 0;
+}
+
+int fuse_fs_open(struct fuse_fs *fs, const char *path,
+                 struct fuse_file_info *fi)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.open)
+        return fs->op.open(path, fi);
+    else
+        return 0;
+}
+
+int fuse_fs_read(struct fuse_fs *fs, const char *path, char *buf, size_t size,
+                 off_t off, struct fuse_file_info *fi)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.read)
+        return fs->op.read(path, buf, size, off, fi);
+    else
+        return -ENOSYS;
+}
+
+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)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.write)
+        return fs->op.write(path, buf, size, off, fi);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_fsync(struct fuse_fs *fs, const char *path, int datasync,
+                  struct fuse_file_info *fi)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.fsync)
+        return fs->op.fsync(path, datasync, fi);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_fsyncdir(struct fuse_fs *fs, const char *path, int datasync,
+                     struct fuse_file_info *fi)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.fsyncdir)
+        return fs->op.fsyncdir(path, datasync, fi);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_flush(struct fuse_fs *fs, const char *path,
+                  struct fuse_file_info *fi)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.flush)
+        return fs->op.flush(path, fi);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_statfs(struct fuse_fs *fs, const char *path, struct statvfs *buf)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.statfs)
+        return fs->op.statfs(path, buf);
+    else {
+        buf->f_namemax = 255;
+        buf->f_bsize = 512;
+        return 0;
+    }
+}
+
+int fuse_fs_releasedir(struct fuse_fs *fs, const char *path,
+                       struct fuse_file_info *fi)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.releasedir)
+        return fs->op.releasedir(path, fi);
+    else
+        return 0;
+}
+
+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)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.readdir)
+        return fs->op.readdir(path, buf, filler, off, fi);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_create(struct fuse_fs *fs, const char *path, mode_t mode,
+                   struct fuse_file_info *fi)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.create)
+        return fs->op.create(path, mode, fi);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_lock(struct fuse_fs *fs, const char *path,
+                 struct fuse_file_info *fi, int cmd, struct flock *lock)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.lock)
+        return fs->op.lock(path, fi, cmd, lock);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid, gid_t gid)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.chown)
+        return fs->op.chown(path, uid, gid);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_truncate(struct fuse_fs *fs, const char *path, off_t size)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.truncate)
+        return fs->op.truncate(path, size);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_ftruncate(struct fuse_fs *fs, const char *path, off_t size,
+                      struct fuse_file_info *fi)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.ftruncate)
+        return fs->op.ftruncate(path, size, fi);
+    else if (fs->op.truncate)
+        return fs->op.truncate(path, size);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_utimens(struct fuse_fs *fs, const char *path,
+                    const struct timespec tv[2])
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.utimens)
+        return fs->op.utimens(path, tv);
+    else if(fs->op.utime) {
+        struct utimbuf buf;
+        buf.actime = tv[0].tv_sec;
+        buf.modtime = tv[1].tv_sec;
+        return fs->op.utime(path, &buf);
+    } else
+        return -ENOSYS;
+}
+
+int fuse_fs_access(struct fuse_fs *fs, const char *path, int mask)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.access)
+        return fs->op.access(path, mask);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_readlink(struct fuse_fs *fs, const char *path, char *buf,
+                     size_t len)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.readlink)
+        return fs->op.readlink(path, buf, len);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_mknod(struct fuse_fs *fs, const char *path, mode_t mode,
+                  dev_t rdev)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.mknod)
+        return fs->op.mknod(path, mode, rdev);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_mkdir(struct fuse_fs *fs, const char *path, mode_t mode)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.mkdir)
+        return fs->op.mkdir(path, mode);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_setxattr(struct fuse_fs *fs, const char *path, const char *name,
+                     const char *value, size_t size, int flags)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.setxattr)
+        return fs->op.setxattr(path, name, value, size, flags);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_getxattr(struct fuse_fs *fs, const char *path, const char *name,
+                     char *value, size_t size)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.getxattr)
+        return fs->op.getxattr(path, name, value, size);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_listxattr(struct fuse_fs *fs, const char *path, char *list,
+                      size_t size)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.listxattr)
+        return fs->op.listxattr(path, list, size);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize,
+                 uint64_t *idx)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.bmap)
+        return fs->op.bmap(path, blocksize, idx);
+    else
+        return -ENOSYS;
+}
+
+int fuse_fs_removexattr(struct fuse_fs *fs, const char *path, const char *name)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.removexattr)
+        return fs->op.removexattr(path, name);
+    else
+        return -ENOSYS;
+}
+
+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)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.ioctl) {
+/*
+	if (fs->debug)
+	    fprintf(stderr, "ioctl[%llu] 0x%x flags: 0x%x\n",
+		    (unsigned long long) fi->fh, cmd, flags);
+*/
+	return fs->op.ioctl(path, cmd, arg, fi, flags, data);
+    } else
+	return -ENOSYS;
+}
+
+static int is_open(struct fuse *f, fuse_ino_t dir, const char *name)
+{
+    struct node *node;
+    int isopen = 0;
+    pthread_mutex_lock(&f->lock);
+    node = lookup_node(f, dir, name);
+    if (node && node->open_count > 0)
+        isopen = 1;
+    pthread_mutex_unlock(&f->lock);
+    return isopen;
+}
+
+static char *hidden_name(struct fuse *f, fuse_ino_t dir, const char *oldname,
+                         char *newname, size_t bufsize)
+{
+    struct stat buf;
+    struct node *node;
+    struct node *newnode;
+    char *newpath;
+    int res;
+    int failctr = 10;
+
+    do {
+        pthread_mutex_lock(&f->lock);
+        node = lookup_node(f, dir, oldname);
+        if (node == NULL) {
+            pthread_mutex_unlock(&f->lock);
+            return NULL;
+        }
+        do {
+            f->hidectr ++;
+            snprintf(newname, bufsize, ".fuse_hidden%08x%08x",
+                     (unsigned int) node->nodeid, f->hidectr);
+            newnode = lookup_node(f, dir, newname);
+        } while(newnode);
+        pthread_mutex_unlock(&f->lock);
+
+        newpath = get_path_name(f, dir, newname);
+        if (!newpath)
+            break;
+
+        res = fuse_fs_getattr(f->fs, newpath, &buf);
+        if (res == -ENOENT)
+            break;
+        free(newpath);
+        newpath = NULL;
+    } while(res == 0 && --failctr);
+
+    return newpath;
+}
+
+static int hide_node(struct fuse *f, const char *oldpath,
+                     fuse_ino_t dir, const char *oldname)
+{
+    char newname[64];
+    char *newpath;
+    int err = -EBUSY;
+
+    newpath = hidden_name(f, dir, oldname, newname, sizeof(newname));
+    if (newpath) {
+        err = fuse_fs_rename(f->fs, oldpath, newpath);
+        if (!err)
+            err = rename_node(f, dir, oldname, dir, newname, 1);
+        free(newpath);
+    }
+    return err;
+}
+
+#ifdef __SOLARIS__
+
+static int mtime_eq(const struct stat *stbuf, const struct timespec *ts)
+{
+    return stbuf->st_mtime == ts->tv_sec && ST_MTIM_NSEC(stbuf) == ts->tv_nsec;
+}
+
+#ifndef CLOCK_MONOTONIC
+#define CLOCK_MONOTONIC CLOCK_REALTIME
+#endif
+
+static void curr_time(struct timespec *now)
+{
+    static clockid_t clockid = CLOCK_MONOTONIC;
+    int res = clock_gettime(clockid, now);
+    if (res == -1 && errno == EINVAL) {
+        clockid = CLOCK_REALTIME;
+        res = clock_gettime(clockid, now);
+    }
+    if (res == -1) {
+        perror("fuse: clock_gettime");
+        abort();
+    }
+}
+
+static void update_stat(struct node *node, const struct stat *stbuf)
+{
+    if (node->cache_valid && (!mtime_eq(stbuf, &node->mtime) ||
+                              stbuf->st_size != node->size))
+        node->cache_valid = 0;
+    node->mtime.tv_sec = stbuf->st_mtime;
+    node->mtime.tv_nsec = ST_MTIM_NSEC(stbuf);
+    node->size = stbuf->st_size;
+    curr_time(&node->stat_updated);
+}
+
+#endif /* __SOLARIS__ */
+
+static int lookup_path(struct fuse *f, fuse_ino_t nodeid,
+                       const char *name, const char *path,
+                       struct fuse_entry_param *e, struct fuse_file_info *fi)
+{
+    int res;
+
+    memset(e, 0, sizeof(struct fuse_entry_param));
+    if (fi)
+        res = fuse_fs_fgetattr(f->fs, path, &e->attr, fi);
+    else
+        res = fuse_fs_getattr(f->fs, path, &e->attr);
+    if (res == 0) {
+        struct node *node;
+
+        node = find_node(f, nodeid, name);
+        if (node == NULL)
+            res = -ENOMEM;
+        else {
+            e->ino = node->nodeid;
+            e->generation = node->generation;
+            e->entry_timeout = f->conf.entry_timeout;
+            e->attr_timeout = f->conf.attr_timeout;
+#ifdef __SOLARIS__
+            if (f->conf.auto_cache) {
+                pthread_mutex_lock(&f->lock);
+                update_stat(node, &e->attr);
+                pthread_mutex_unlock(&f->lock);
+            }
+#endif /* __SOLARIS__ */
+            set_stat(f, e->ino, &e->attr);
+            if (f->conf.debug)
+                fprintf(stderr, "   NODEID: %lu\n", (unsigned long) e->ino);
+        }
+    }
+    return res;
+}
+
+static struct fuse_context_i *fuse_get_context_internal(void)
+{
+    struct fuse_context_i *c;
+
+    c = (struct fuse_context_i *) pthread_getspecific(fuse_context_key);
+    if (c == NULL) {
+        c = (struct fuse_context_i *) malloc(sizeof(struct fuse_context_i));
+        if (c == NULL) {
+            /* This is hard to deal with properly, so just abort.  If
+               memory is so low that the context cannot be allocated,
+               there's not much hope for the filesystem anyway */ 
+            fprintf(stderr, "fuse: failed to allocate thread specific data\n");
+            abort();
+        }
+        pthread_setspecific(fuse_context_key, c);
+    }
+    return c;
+}
+
+static void fuse_freecontext(void *data)
+{
+    free(data);
+}
+
+static int fuse_create_context_key(void)
+{
+    int err = 0;
+    pthread_mutex_lock(&fuse_context_lock);
+    if (!fuse_context_ref) {
+        err = pthread_key_create(&fuse_context_key, fuse_freecontext);
+        if (err) {
+            fprintf(stderr, "fuse: failed to create thread specific key: %s\n",
+                    strerror(err));
+            pthread_mutex_unlock(&fuse_context_lock);
+            return -1;
+        }
+    }
+    fuse_context_ref++;
+    pthread_mutex_unlock(&fuse_context_lock);
+    return 0;
+}
+
+static void fuse_delete_context_key(void)
+{
+    pthread_mutex_lock(&fuse_context_lock);
+    fuse_context_ref--;
+    if (!fuse_context_ref) {
+        free(pthread_getspecific(fuse_context_key));
+        pthread_key_delete(fuse_context_key);
+    }
+    pthread_mutex_unlock(&fuse_context_lock);
+}
+
+static struct fuse *req_fuse_prepare(fuse_req_t req)
+{
+    struct fuse_context_i *c = fuse_get_context_internal();
+    const struct fuse_ctx *ctx = fuse_req_ctx(req);
+    c->req = req;
+    c->ctx.fuse = req_fuse(req);
+    c->ctx.uid = ctx->uid;
+    c->ctx.gid = ctx->gid;
+    c->ctx.pid = ctx->pid;
+#ifdef POSIXACLS
+    c->ctx.umask = ctx->umask;
+#endif
+    return c->ctx.fuse;
+}
+
+#ifndef __SOLARIS__
+static void reply_err(fuse_req_t req, int err)
+#else /* __SOLARIS__ */
+static inline void reply_err(fuse_req_t req, int err)
+#endif /* __SOLARIS__ */
+{
+    /* fuse_reply_err() uses non-negated errno values */
+    fuse_reply_err(req, -err);
+}
+
+static void reply_entry(fuse_req_t req, const struct fuse_entry_param *e,
+                        int err)
+{
+    if (!err) {
+        struct fuse *f = req_fuse(req);
+        if (fuse_reply_entry(req, e) == -ENOENT)
+            forget_node(f, e->ino, 1);
+    } else
+        reply_err(req, err);
+}
+
+void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.init)
+        fs->user_data = fs->op.init(conn);
+}
+
+static void fuse_lib_init(void *data, struct fuse_conn_info *conn)
+{
+    struct fuse *f = (struct fuse *) data;
+    struct fuse_context_i *c = fuse_get_context_internal();
+
+    memset(c, 0, sizeof(*c));
+    c->ctx.fuse = f;
+    fuse_fs_init(f->fs, conn);
+}
+
+void fuse_fs_destroy(struct fuse_fs *fs)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.destroy)
+        fs->op.destroy(fs->user_data);
+#ifdef __SOLARIS__
+    if (fs->m)
+        fuse_put_module(fs->m);
+#endif /* __SOLARIS__ */
+    free(fs);
+}
+
+static void fuse_lib_destroy(void *data)
+{
+    struct fuse *f = (struct fuse *) data;
+    struct fuse_context_i *c = fuse_get_context_internal();
+
+    memset(c, 0, sizeof(*c));
+    c->ctx.fuse = f;
+    fuse_fs_destroy(f->fs);
+    f->fs = NULL;
+}
+
+static void fuse_lib_lookup(fuse_req_t req, fuse_ino_t parent,
+                            const char *name)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    struct fuse_entry_param e;
+    char *path;
+    int err;
+
+    err = -ENOENT;
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path_name(f, parent, name);
+    if (path != NULL) {
+        struct fuse_intr_data d;
+        if (f->conf.debug)
+            fprintf(stderr, "LOOKUP %s\n", path);
+        fuse_prepare_interrupt(f, req, &d); 
+        err = lookup_path(f, parent, name, path, &e, NULL);
+        if (err == -ENOENT && f->conf.negative_timeout != 0.0) {
+            e.ino = 0;
+            e.entry_timeout = f->conf.negative_timeout;
+            err = 0;
+        }
+        fuse_finish_interrupt(f, req, &d);
+        free(path);
+    }
+    pthread_rwlock_unlock(&f->tree_lock);
+    reply_entry(req, &e, err);
+}
+
+static void fuse_lib_forget(fuse_req_t req, fuse_ino_t ino,
+                            unsigned long nlookup)
+{
+    struct fuse *f = req_fuse(req);
+    if (f->conf.debug)
+        fprintf(stderr, "FORGET %llu/%lu\n", (unsigned long long)ino, nlookup);
+    forget_node(f, ino, nlookup);
+    fuse_reply_none(req);
+}
+
+static void fuse_lib_getattr(fuse_req_t req, fuse_ino_t ino,
+                             struct fuse_file_info *fi)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    struct stat buf;
+    char *path;
+    int err;
+
+    (void) fi;
+    memset(&buf, 0, sizeof(buf));
+
+    err = -ENOENT;
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path(f, ino);
+    if (path != NULL) {
+        struct fuse_intr_data d;
+        fuse_prepare_interrupt(f, req, &d);
+        err = fuse_fs_getattr(f->fs, path, &buf);
+        fuse_finish_interrupt(f, req, &d);
+        free(path);
+    }
+    pthread_rwlock_unlock(&f->tree_lock);
+    if (!err) {
+#ifdef __SOLARIS__
+        if (f->conf.auto_cache) {
+            pthread_mutex_lock(&f->lock);
+            update_stat(get_node(f, ino), &buf);
+            pthread_mutex_unlock(&f->lock);
+        }
+#endif /* __SOLARIS__ */
+        set_stat(f, ino, &buf);
+        fuse_reply_attr(req, &buf, f->conf.attr_timeout);
+    } else
+        reply_err(req, err);
+}
+
+int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode)
+{
+    fuse_get_context()->private_data = fs->user_data;
+    if (fs->op.chmod)
+        return fs->op.chmod(path, mode);
+    else
+        return -ENOSYS;
+}
+
+static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
+                             int valid, struct fuse_file_info *fi)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    struct stat buf;
+    char *path;
+    int err;
+
+    err = -ENOENT;
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path(f, ino);
+    if (path != NULL) {
+        struct fuse_intr_data d;
+        fuse_prepare_interrupt(f, req, &d);
+        err = 0;
+        if (!err && (valid & FUSE_SET_ATTR_MODE))
+            err = fuse_fs_chmod(f->fs, path, attr->st_mode);
+        if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) {
+            uid_t uid = 
+                (valid & FUSE_SET_ATTR_UID) ? attr->st_uid : (uid_t) -1;
+            gid_t gid = 
+                (valid & FUSE_SET_ATTR_GID) ? attr->st_gid : (gid_t) -1;
+            err = fuse_fs_chown(f->fs, path, uid, gid);
+        }
+        if (!err && (valid & FUSE_SET_ATTR_SIZE)) {
+            if (fi)
+                err = fuse_fs_ftruncate(f->fs, path, attr->st_size, fi);
+            else
+                err = fuse_fs_truncate(f->fs, path, attr->st_size);
+        }
+#ifdef HAVE_UTIMENSAT
+        if (!err &&
+            (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))) {
+            struct timespec tv[2];
+
+            tv[0].tv_sec = 0;
+            tv[1].tv_sec = 0;
+            tv[0].tv_nsec = UTIME_OMIT;
+            tv[1].tv_nsec = UTIME_OMIT;
+
+            if (valid & FUSE_SET_ATTR_ATIME_NOW)
+                tv[0].tv_nsec = UTIME_NOW;
+            else if (valid & FUSE_SET_ATTR_ATIME)
+                tv[0] = attr->st_atim;
+
+            if (valid & FUSE_SET_ATTR_MTIME_NOW)
+                tv[1].tv_nsec = UTIME_NOW;
+            else if (valid & FUSE_SET_ATTR_MTIME)
+                tv[1] = attr->st_mtim;
+
+            err = fuse_fs_utimens(f->fs, path, tv);
+        } else
+#endif
+        if (!err && (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) ==
+            (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {
+            struct timespec tv[2];
+            tv[0].tv_sec = attr->st_atime;
+            tv[0].tv_nsec = ST_ATIM_NSEC(attr);
+            tv[1].tv_sec = attr->st_mtime;
+            tv[1].tv_nsec = ST_MTIM_NSEC(attr);
+            err = fuse_fs_utimens(f->fs, path, tv);
+        }
+        if (!err)
+            err = fuse_fs_getattr(f->fs,  path, &buf);
+        fuse_finish_interrupt(f, req, &d);
+        free(path);
+    }
+    pthread_rwlock_unlock(&f->tree_lock);
+    if (!err) {
+#ifdef __SOLARIS__
+        if (f->conf.auto_cache) {
+            pthread_mutex_lock(&f->lock);
+            update_stat(get_node(f, ino), &buf);
+            pthread_mutex_unlock(&f->lock);
+        }
+#endif /* __SOLARIS__ */
+        set_stat(f, ino, &buf);
+        fuse_reply_attr(req, &buf, f->conf.attr_timeout);
+    } else
+        reply_err(req, err);
+}
+
+static void fuse_lib_access(fuse_req_t req, fuse_ino_t ino, int mask)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    char *path;
+    int err;
+
+    err = -ENOENT;
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path(f, ino);
+    if (path != NULL) {
+        struct fuse_intr_data d;
+        if (f->conf.debug)
+            fprintf(stderr, "ACCESS %s 0%o\n", path, mask);
+        fuse_prepare_interrupt(f, req, &d);
+        err = fuse_fs_access(f->fs, path, mask);
+        fuse_finish_interrupt(f, req, &d);
+        free(path);
+    }
+    pthread_rwlock_unlock(&f->tree_lock);
+    reply_err(req, err);
+}
+
+static void fuse_lib_readlink(fuse_req_t req, fuse_ino_t ino)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    char linkname[PATH_MAX + 1];
+    char *path;
+    int err;
+
+    err = -ENOENT;
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path(f, ino);
+    if (path != NULL) {
+        struct fuse_intr_data d;
+        fuse_prepare_interrupt(f, req, &d);
+        err = fuse_fs_readlink(f->fs, path, linkname, sizeof(linkname));
+        fuse_finish_interrupt(f, req, &d);
+        free(path);
+    }
+    pthread_rwlock_unlock(&f->tree_lock);
+    if (!err) {
+        linkname[PATH_MAX] = '\0';
+        fuse_reply_readlink(req, linkname);
+    } else
+        reply_err(req, err);
+}
+
+static void fuse_lib_mknod(fuse_req_t req, fuse_ino_t parent, const char *name,
+                           mode_t mode, dev_t rdev)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    struct fuse_entry_param e;
+    char *path;
+    int err;
+
+    err = -ENOENT;
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path_name(f, parent, name);
+    if (path) {
+        struct fuse_intr_data d;
+        if (f->conf.debug)
+            fprintf(stderr, "MKNOD %s\n", path);
+        fuse_prepare_interrupt(f, req, &d);
+        err = -ENOSYS;
+        if (S_ISREG(mode)) {
+            struct fuse_file_info fi;
+
+            memset(&fi, 0, sizeof(fi));
+            fi.flags = O_CREAT | O_EXCL | O_WRONLY;
+            err = fuse_fs_create(f->fs, path, mode, &fi);
+            if (!err) {
+                err = lookup_path(f, parent, name, path, &e, &fi);
+                fuse_fs_release(f->fs, path, &fi);
+            }
+        }
+        if (err == -ENOSYS) {
+            err = fuse_fs_mknod(f->fs, path, mode, rdev);
+            if (!err)
+                err = lookup_path(f, parent, name, path, &e, NULL);
+        }
+        fuse_finish_interrupt(f, req, &d);
+        free(path);
+    }
+    pthread_rwlock_unlock(&f->tree_lock);
+    reply_entry(req, &e, err);
+}
+
+static void fuse_lib_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,
+                           mode_t mode)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    struct fuse_entry_param e;
+    char *path;
+    int err;
+
+    err = -ENOENT;
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path_name(f, parent, name);
+    if (path != NULL) {
+        struct fuse_intr_data d;
+        if (f->conf.debug)
+            fprintf(stderr, "MKDIR %s\n", path);
+        fuse_prepare_interrupt(f, req, &d);
+        err = fuse_fs_mkdir(f->fs, path, mode);
+        if (!err)
+            err = lookup_path(f, parent, name, path, &e, NULL);
+        fuse_finish_interrupt(f, req, &d);
+        free(path);
+    }
+    pthread_rwlock_unlock(&f->tree_lock);
+    reply_entry(req, &e, err);
+}
+
+static void fuse_lib_unlink(fuse_req_t req, fuse_ino_t parent,
+                            const char *name)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    char *path;
+    int err;
+
+    err = -ENOENT;
+    pthread_rwlock_wrlock(&f->tree_lock);
+    path = get_path_name(f, parent, name);
+    if (path != NULL) {
+        struct fuse_intr_data d;
+        if (f->conf.debug)
+            fprintf(stderr, "UNLINK %s\n", path);
+        fuse_prepare_interrupt(f, req, &d);
+        if (!f->conf.hard_remove && is_open(f, parent, name))
+            err = hide_node(f, path, parent, name);
+        else {
+            err = fuse_fs_unlink(f->fs, path);
+            if (!err)
+                remove_node(f, parent, name);
+        }
+        fuse_finish_interrupt(f, req, &d);
+        free(path);
+    }
+    pthread_rwlock_unlock(&f->tree_lock);
+    reply_err(req, err);
+}
+
+static void fuse_lib_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    char *path;
+    int err;
+
+    err = -ENOENT;
+    pthread_rwlock_wrlock(&f->tree_lock);
+    path = get_path_name(f, parent, name);
+    if (path != NULL) {
+        struct fuse_intr_data d;
+        if (f->conf.debug)
+            fprintf(stderr, "RMDIR %s\n", path);
+        fuse_prepare_interrupt(f, req, &d);
+        err = fuse_fs_rmdir(f->fs, path);
+        fuse_finish_interrupt(f, req, &d);
+        if (!err)
+            remove_node(f, parent, name);
+        free(path);
+    }
+    pthread_rwlock_unlock(&f->tree_lock);
+    reply_err(req, err);
+}
+
+static void fuse_lib_symlink(fuse_req_t req, const char *linkname,
+                             fuse_ino_t parent, const char *name)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    struct fuse_entry_param e;
+    char *path;
+    int err;
+
+    err = -ENOENT;
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path_name(f, parent, name);
+    if (path != NULL) {
+        struct fuse_intr_data d;
+        if (f->conf.debug)
+            fprintf(stderr, "SYMLINK %s\n", path);
+        fuse_prepare_interrupt(f, req, &d);
+        err = fuse_fs_symlink(f->fs, linkname, path);
+        if (!err)
+            err = lookup_path(f, parent, name, path, &e, NULL);
+        fuse_finish_interrupt(f, req, &d);
+        free(path);
+    }
+    pthread_rwlock_unlock(&f->tree_lock);
+    reply_entry(req, &e, err);
+}
+
+static void fuse_lib_rename(fuse_req_t req, fuse_ino_t olddir,
+                            const char *oldname, fuse_ino_t newdir,
+                            const char *newname)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    char *oldpath;
+    char *newpath;
+    int err;
+
+    err = -ENOENT;
+    pthread_rwlock_wrlock(&f->tree_lock);
+    oldpath = get_path_name(f, olddir, oldname);
+    if (oldpath != NULL) {
+        newpath = get_path_name(f, newdir, newname);
+        if (newpath != NULL) {
+            struct fuse_intr_data d;
+            if (f->conf.debug)
+                fprintf(stderr, "RENAME %s -> %s\n", oldpath, newpath);
+            err = 0;
+            fuse_prepare_interrupt(f, req, &d);
+            if (!f->conf.hard_remove && is_open(f, newdir, newname))
+                err = hide_node(f, newpath, newdir, newname);
+            if (!err) {
+                err = fuse_fs_rename(f->fs, oldpath, newpath);
+                if (!err)
+                    err = rename_node(f, olddir, oldname, newdir, newname, 0);
+            }
+            fuse_finish_interrupt(f, req, &d);
+            free(newpath);
+        }
+        free(oldpath);
+    }
+    pthread_rwlock_unlock(&f->tree_lock);
+    reply_err(req, err);
+}
+
+static void fuse_lib_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,
+                          const char *newname)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    struct fuse_entry_param e;
+    char *oldpath;
+    char *newpath;
+    int err;
+
+    err = -ENOENT;
+    pthread_rwlock_rdlock(&f->tree_lock);
+    oldpath = get_path(f, ino);
+    if (oldpath != NULL) {
+        newpath =  get_path_name(f, newparent, newname);
+        if (newpath != NULL) {
+            struct fuse_intr_data d;
+            if (f->conf.debug)
+                fprintf(stderr, "LINK %s\n", newpath);
+            fuse_prepare_interrupt(f, req, &d);
+            err = fuse_fs_link(f->fs, oldpath, newpath);
+            if (!err)
+                err = lookup_path(f, newparent, newname, newpath, &e, NULL);
+            fuse_finish_interrupt(f, req, &d);
+            free(newpath);
+        }
+        free(oldpath);
+    }
+    pthread_rwlock_unlock(&f->tree_lock);
+    reply_entry(req, &e, err);
+}
+
+static void fuse_do_release(struct fuse *f, fuse_ino_t ino, const char *path,
+                            struct fuse_file_info *fi)
+{
+    struct node *node;
+    int unlink_hidden = 0;
+
+    fuse_fs_release(f->fs, path ? path : "-", fi);
+
+    pthread_mutex_lock(&f->lock);
+    node = get_node(f, ino);
+    assert(node->open_count > 0);
+    --node->open_count;
+    if (node->is_hidden && !node->open_count) {
+        unlink_hidden = 1;
+        node->is_hidden = 0;
+    }
+    pthread_mutex_unlock(&f->lock);
+
+    if(unlink_hidden && path)
+        fuse_fs_unlink(f->fs, path);
+}
+
+static void fuse_lib_create(fuse_req_t req, fuse_ino_t parent,
+                            const char *name, mode_t mode,
+                            struct fuse_file_info *fi)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    struct fuse_intr_data d;
+    struct fuse_entry_param e;
+    char *path;
+    int err;
+
+    err = -ENOENT;
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path_name(f, parent, name);
+    if (path) {
+        fuse_prepare_interrupt(f, req, &d);
+        err = fuse_fs_create(f->fs, path, mode, fi);
+        if (!err) {
+            err = lookup_path(f, parent, name, path, &e, fi);
+            if (err)
+                fuse_fs_release(f->fs, path, fi);
+            else if (!S_ISREG(e.attr.st_mode)) {
+                err = -EIO;
+                fuse_fs_release(f->fs, path, fi);
+                forget_node(f, e.ino, 1);
+            } else {
+                if (f->conf.direct_io)
+                    fi->direct_io = 1;
+                if (f->conf.kernel_cache)
+                    fi->keep_cache = 1;
+
+            }
+        }
+        fuse_finish_interrupt(f, req, &d);
+    }
+    if (!err) {
+        pthread_mutex_lock(&f->lock);
+        get_node(f, e.ino)->open_count++;
+        pthread_mutex_unlock(&f->lock);
+        if (fuse_reply_create(req, &e, fi) == -ENOENT) {
+            /* The open syscall was interrupted, so it must be cancelled */
+            fuse_prepare_interrupt(f, req, &d);
+            fuse_do_release(f, e.ino, path, fi);
+            fuse_finish_interrupt(f, req, &d);
+            forget_node(f, e.ino, 1);
+        } else if (f->conf.debug) {
+            fprintf(stderr, "  CREATE[%llu] flags: 0x%x %s\n",
+                    (unsigned long long) fi->fh, fi->flags, path);
+        }
+    } else
+        reply_err(req, err);
+
+    if (path)
+        free(path);
+
+    pthread_rwlock_unlock(&f->tree_lock);
+}
+
+#ifdef __SOLARIS__
+
+static double diff_timespec(const struct timespec *t1,
+                            const struct timespec *t2)
+{
+    return (t1->tv_sec - t2->tv_sec) + 
+        ((double) t1->tv_nsec - (double) t2->tv_nsec) / 1000000000.0;
+}
+
+static void open_auto_cache(struct fuse *f, fuse_ino_t ino, const char *path,
+                            struct fuse_file_info *fi)
+{
+    struct node *node;
+
+    pthread_mutex_lock(&f->lock);
+    node = get_node(f, ino);
+    if (node->cache_valid) {
+        struct timespec now;
+
+        curr_time(&now);
+        if (diff_timespec(&now, &node->stat_updated) > f->conf.ac_attr_timeout) {
+            struct stat stbuf;
+            int err;
+            pthread_mutex_unlock(&f->lock);
+            err = fuse_fs_fgetattr(f->fs, path, &stbuf, fi);
+            pthread_mutex_lock(&f->lock);
+            if (!err)
+                update_stat(node, &stbuf);
+            else
+                node->cache_valid = 0;
+        }
+    }
+    if (node->cache_valid)
+        fi->keep_cache = 1;
+
+    node->cache_valid = 1;
+    pthread_mutex_unlock(&f->lock);
+}
+
+#endif /* __SOLARIS__ */
+
+static void fuse_lib_open(fuse_req_t req, fuse_ino_t ino,
+                          struct fuse_file_info *fi)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    struct fuse_intr_data d;
+    char *path = NULL;
+    int err = 0;
+
+    err = -ENOENT;
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path(f, ino);
+    if (path) {
+        fuse_prepare_interrupt(f, req, &d);
+        err = fuse_fs_open(f->fs, path, fi);
+        if (!err) {
+            if (f->conf.direct_io)
+                fi->direct_io = 1;
+            if (f->conf.kernel_cache)
+                fi->keep_cache = 1;
+#ifdef __SOLARIS__
+
+            if (f->conf.auto_cache)
+                open_auto_cache(f, ino, path, fi);
+#endif /* __SOLARIS__ */
+        }
+        fuse_finish_interrupt(f, req, &d);
+    }
+    if (!err) {
+        pthread_mutex_lock(&f->lock);
+        get_node(f, ino)->open_count++;
+        pthread_mutex_unlock(&f->lock);
+        if (fuse_reply_open(req, fi) == -ENOENT) {
+            /* The open syscall was interrupted, so it must be cancelled */
+            fuse_prepare_interrupt(f, req, &d);
+            fuse_do_release(f, ino, path, fi);
+            fuse_finish_interrupt(f, req, &d);
+        } else if (f->conf.debug) {
+            fprintf(stderr, "OPEN[%llu] flags: 0x%x %s\n",
+                    (unsigned long long) fi->fh, fi->flags, path);
+        }
+    } else
+        reply_err(req, err);
+
+    if (path)
+        free(path);
+    pthread_rwlock_unlock(&f->tree_lock);
+}
+
+static void fuse_lib_read(fuse_req_t req, fuse_ino_t ino, size_t size,
+                          off_t off, struct fuse_file_info *fi)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    char *path;
+    char *buf;
+    int res;
+
+    buf = (char *) malloc(size);
+    if (buf == NULL) {
+        reply_err(req, -ENOMEM);
+        return;
+    }
+
+    res = -ENOENT;
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path(f, ino);
+    if (path != NULL) {
+        struct fuse_intr_data d;
+        if (f->conf.debug)
+            fprintf(stderr, "READ[%llu] %lu bytes from %llu\n",
+                    (unsigned long long) fi->fh, (unsigned long) size,
+                    (unsigned long long) off);
+
+        fuse_prepare_interrupt(f, req, &d);
+        res = fuse_fs_read(f->fs, path, buf, size, off, fi);
+        fuse_finish_interrupt(f, req, &d);
+        free(path);
+    }
+    pthread_rwlock_unlock(&f->tree_lock);
+
+    if (res >= 0) {
+        if (f->conf.debug)
+            fprintf(stderr, "   READ[%llu] %u bytes\n",
+                    (unsigned long long)fi->fh, res);
+        if ((size_t) res > size)
+            fprintf(stderr, "fuse: read too many bytes");
+        fuse_reply_buf(req, buf, res);
+    } else
+        reply_err(req, res);
+
+    free(buf);
+}
+
+static void fuse_lib_write(fuse_req_t req, fuse_ino_t ino, const char *buf,
+                       size_t size, off_t off, struct fuse_file_info *fi)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    char *path;
+    int res;
+
+    res = -ENOENT;
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path(f, ino);
+    if (path != NULL) {
+        struct fuse_intr_data d;
+        if (f->conf.debug)
+            fprintf(stderr, "WRITE%s[%llu] %lu bytes to %llu\n",
+                    fi->writepage ? "PAGE" : "", (unsigned long long) fi->fh,
+                    (unsigned long) size, (unsigned long long) off);
+
+        fuse_prepare_interrupt(f, req, &d);
+        res = fuse_fs_write(f->fs, path, buf, size, off, fi);
+        fuse_finish_interrupt(f, req, &d);
+        free(path);
+    }
+    pthread_rwlock_unlock(&f->tree_lock);
+
+    if (res >= 0) {
+        if (f->conf.debug)
+            fprintf(stderr, "   WRITE%s[%llu] %u bytes\n",
+                    fi->writepage ? "PAGE" : "", (unsigned long long) fi->fh,
+                    res);
+        if ((size_t) res > size)
+            fprintf(stderr, "fuse: wrote too many bytes");
+        fuse_reply_write(req, res);
+    } else
+        reply_err(req, res);
+}
+
+static void fuse_lib_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,
+                       struct fuse_file_info *fi)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    char *path;
+    int err;
+
+    err = -ENOENT;
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path(f, ino);
+    if (path != NULL) {
+        struct fuse_intr_data d;
+        if (f->conf.debug)
+            fprintf(stderr, "FSYNC[%llu]\n", (unsigned long long) fi->fh);
+        fuse_prepare_interrupt(f, req, &d);
+        err = fuse_fs_fsync(f->fs, path, datasync, fi);
+        fuse_finish_interrupt(f, req, &d);
+        free(path);
+    }
+    pthread_rwlock_unlock(&f->tree_lock);
+    reply_err(req, err);
+}
+
+static struct fuse_dh *get_dirhandle(const struct fuse_file_info *llfi,
+                                     struct fuse_file_info *fi)
+{
+    struct fuse_dh *dh = (struct fuse_dh *) (uintptr_t) llfi->fh;
+    memset(fi, 0, sizeof(struct fuse_file_info));
+    fi->fh = dh->fh;
+    fi->fh_old = dh->fh;
+    return dh;
+}
+
+static void fuse_lib_opendir(fuse_req_t req, fuse_ino_t ino,
+                       struct fuse_file_info *llfi)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    struct fuse_intr_data d;
+    struct fuse_dh *dh;
+    struct fuse_file_info fi;
+    char *path;
+    int err;
+
+    dh = (struct fuse_dh *) malloc(sizeof(struct fuse_dh));
+    if (dh == NULL) {
+        reply_err(req, -ENOMEM);
+        return;
+    }
+    memset(dh, 0, sizeof(struct fuse_dh));
+    dh->fuse = f;
+    dh->contents = NULL;
+    dh->len = 0;
+    dh->filled = 0;
+    dh->nodeid = ino;
+    fuse_mutex_init(&dh->lock);
+
+    llfi->fh = (uintptr_t) dh;
+
+    memset(&fi, 0, sizeof(fi));
+    fi.flags = llfi->flags;
+
+    err = -ENOENT;
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path(f, ino);
+    if (path != NULL) {
+        fuse_prepare_interrupt(f, req, &d);
+        err = fuse_fs_opendir(f->fs, path, &fi);
+        fuse_finish_interrupt(f, req, &d);
+        dh->fh = fi.fh;
+    }
+    if (!err) {
+        if (fuse_reply_open(req, llfi) == -ENOENT) {
+            /* The opendir syscall was interrupted, so it must be cancelled */
+            fuse_prepare_interrupt(f, req, &d);
+            fuse_fs_releasedir(f->fs, path, &fi);
+            fuse_finish_interrupt(f, req, &d);
+            pthread_mutex_destroy(&dh->lock);
+            free(dh);
+        }
+    } else {
+        reply_err(req, err);
+#ifndef __SOLARIS__
+        pthread_mutex_destroy(&dh->lock);
+#endif /* ! __SOLARIS__ */
+        free(dh);
+    }
+    free(path);
+    pthread_rwlock_unlock(&f->tree_lock);
+}
+
+static int extend_contents(struct fuse_dh *dh, unsigned minsize)
+{
+    if (minsize > dh->size) {
+        char *newptr;
+        unsigned newsize = dh->size;
+        if (!newsize)
+            newsize = 1024;
+#ifndef __SOLARIS__
+        while (newsize < minsize) {
+	    if (newsize >= 0x80000000)
+	       	newsize = 0xffffffff;
+	    else
+	       	newsize *= 2;
+        }
+#else /* __SOLARIS__ */
+        while (newsize < minsize)
+            newsize *= 2;
+#endif /* __SOLARIS__ */
+
+        newptr = (char *) realloc(dh->contents, newsize);
+        if (!newptr) {
+            dh->error = -ENOMEM;
+            return -1;
+        }
+        dh->contents = newptr;
+        dh->size = newsize;
+    }
+    return 0;
+}
+
+static int fill_dir(void *dh_, const char *name, const struct stat *statp,
+                    off_t off)
+{
+    struct fuse_dh *dh = (struct fuse_dh *) dh_;
+    struct stat stbuf;
+    size_t newlen;
+
+    if (statp)
+        stbuf = *statp;
+    else {
+        memset(&stbuf, 0, sizeof(stbuf));
+        stbuf.st_ino = FUSE_UNKNOWN_INO;
+    }
+
+    if (!dh->fuse->conf.use_ino) {
+        stbuf.st_ino = FUSE_UNKNOWN_INO;
+        if (dh->fuse->conf.readdir_ino) {
+            struct node *node;
+            pthread_mutex_lock(&dh->fuse->lock);
+            node = lookup_node(dh->fuse, dh->nodeid, name);
+            if (node)
+                stbuf.st_ino  = (ino_t) node->nodeid;
+            pthread_mutex_unlock(&dh->fuse->lock);
+        }
+    }
+
+    if (off) {
+        if (extend_contents(dh, dh->needlen) == -1)
+            return 1;
+
+        dh->filled = 0;
+        newlen = dh->len + fuse_add_direntry(dh->req, dh->contents + dh->len,
+                                             dh->needlen - dh->len, name,
+                                             &stbuf, off);
+        if (newlen > dh->needlen)
+            return 1;
+    } else {
+        newlen = dh->len + fuse_add_direntry(dh->req, NULL, 0, name, NULL, 0);
+        if (extend_contents(dh, newlen) == -1)
+            return 1;
+
+        fuse_add_direntry(dh->req, dh->contents + dh->len, dh->size - dh->len,
+                          name, &stbuf, newlen);
+    }
+    dh->len = newlen;
+    return 0;
+}
+
+static int readdir_fill(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
+                        size_t size, off_t off, struct fuse_dh *dh,
+                        struct fuse_file_info *fi)
+{
+    int err = -ENOENT;
+    char *path;
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path(f, ino);
+    if (path != NULL) {
+        struct fuse_intr_data d;
+
+        dh->len = 0;
+        dh->error = 0;
+        dh->needlen = size;
+        dh->filled = 1;
+        dh->req = req;
+        fuse_prepare_interrupt(f, req, &d);
+        err = fuse_fs_readdir(f->fs, path, dh, fill_dir, off, fi);
+        fuse_finish_interrupt(f, req, &d);
+        dh->req = NULL;
+        if (!err)
+            err = dh->error;
+        if (err)
+            dh->filled = 0;
+        free(path);
+    }
+    pthread_rwlock_unlock(&f->tree_lock);
+    return err;
+}
+
+static void fuse_lib_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
+                             off_t off, struct fuse_file_info *llfi)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    struct fuse_file_info fi;
+    struct fuse_dh *dh = get_dirhandle(llfi, &fi);
+
+    pthread_mutex_lock(&dh->lock);
+    /* According to SUS, directory contents need to be refreshed on
+       rewinddir() */
+    if (!off)
+        dh->filled = 0;
+
+    if (!dh->filled) {
+        int err = readdir_fill(f, req, ino, size, off, dh, &fi);
+        if (err) {
+            reply_err(req, err);
+            goto out;
+        }
+    }
+    if (dh->filled) {
+        if (off < dh->len) {
+            if (off + size > dh->len)
+                size = dh->len - off;
+        } else
+            size = 0;
+    } else {
+        size = dh->len;
+        off = 0;
+    }
+    fuse_reply_buf(req, dh->contents + off, size);
+ out:
+    pthread_mutex_unlock(&dh->lock);
+}
+
+static void fuse_lib_releasedir(fuse_req_t req, fuse_ino_t ino,
+                            struct fuse_file_info *llfi)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    struct fuse_intr_data d;
+    struct fuse_file_info fi;
+    struct fuse_dh *dh = get_dirhandle(llfi, &fi);
+    char *path;
+
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path(f, ino);
+    fuse_prepare_interrupt(f, req, &d);
+    fuse_fs_releasedir(f->fs, path ? path : "-", &fi);
+    fuse_finish_interrupt(f, req, &d);
+    if (path)
+        free(path);
+    pthread_rwlock_unlock(&f->tree_lock);
+    pthread_mutex_lock(&dh->lock);
+    pthread_mutex_unlock(&dh->lock);
+    pthread_mutex_destroy(&dh->lock);
+    free(dh->contents);
+    free(dh);
+    reply_err(req, 0);
+}
+
+static void fuse_lib_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync,
+                          struct fuse_file_info *llfi)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    struct fuse_file_info fi;
+    char *path;
+    int err;
+
+    get_dirhandle(llfi, &fi);
+
+    err = -ENOENT;
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path(f, ino);
+    if (path != NULL) {
+        struct fuse_intr_data d;
+        fuse_prepare_interrupt(f, req, &d);
+        err = fuse_fs_fsyncdir(f->fs, path, datasync, &fi);
+        fuse_finish_interrupt(f, req, &d);
+        free(path);
+    }
+    pthread_rwlock_unlock(&f->tree_lock);
+    reply_err(req, err);
+}
+
+static void fuse_lib_statfs(fuse_req_t req, fuse_ino_t ino)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    struct statvfs buf;
+    char *path;
+    int err;
+
+    memset(&buf, 0, sizeof(buf));
+    pthread_rwlock_rdlock(&f->tree_lock);
+    if (!ino) {
+        err = -ENOMEM;
+        path = strdup("/");
+    } else {
+        err = -ENOENT;
+        path = get_path(f, ino);
+    }
+    if (path) {
+        struct fuse_intr_data d;
+        fuse_prepare_interrupt(f, req, &d);
+        err = fuse_fs_statfs(f->fs, path, &buf);
+        fuse_finish_interrupt(f, req, &d);
+        free(path);
+    }
+    pthread_rwlock_unlock(&f->tree_lock);
+
+    if (!err)
+        fuse_reply_statfs(req, &buf);
+    else
+        reply_err(req, err);
+}
+
+static void fuse_lib_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
+                              const char *value, size_t size, int flags)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    char *path;
+    int err;
+
+    err = -ENOENT;
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path(f, ino);
+    if (path != NULL) {
+        struct fuse_intr_data d;
+        fuse_prepare_interrupt(f, req, &d);
+        err = fuse_fs_setxattr(f->fs, path, name, value, size, flags);
+        fuse_finish_interrupt(f, req, &d);
+        free(path);
+    }
+    pthread_rwlock_unlock(&f->tree_lock);
+    reply_err(req, err);
+}
+
+static int common_getxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
+                           const char *name, char *value, size_t size)
+{
+    int err;
+    char *path;
+
+    err = -ENOENT;
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path(f, ino);
+    if (path != NULL) {
+        struct fuse_intr_data d;
+        fuse_prepare_interrupt(f, req, &d);
+        err = fuse_fs_getxattr(f->fs, path, name, value, size);
+        fuse_finish_interrupt(f, req, &d);
+        free(path);
+    }
+    pthread_rwlock_unlock(&f->tree_lock);
+    return err;
+}
+
+static void fuse_lib_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
+                              size_t size)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    int res;
+
+    if (size) {
+        char *value = (char *) malloc(size);
+        if (value == NULL) {
+            reply_err(req, -ENOMEM);
+            return;
+        }
+        res = common_getxattr(f, req, ino, name, value, size);
+        if (res > 0)
+            fuse_reply_buf(req, value, res);
+        else
+            reply_err(req, res);
+        free(value);
+    } else {
+        res = common_getxattr(f, req, ino, name, NULL, 0);
+        if (res >= 0)
+            fuse_reply_xattr(req, res);
+        else
+            reply_err(req, res);
+    }
+}
+
+static int common_listxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
+                            char *list, size_t size)
+{
+    char *path;
+    int err;
+
+    err = -ENOENT;
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path(f, ino);
+    if (path != NULL) {
+        struct fuse_intr_data d;
+        fuse_prepare_interrupt(f, req, &d);
+        err = fuse_fs_listxattr(f->fs, path, list, size);
+        fuse_finish_interrupt(f, req, &d);
+        free(path);
+    }
+    pthread_rwlock_unlock(&f->tree_lock);
+    return err;
+}
+
+static void fuse_lib_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    int res;
+
+    if (size) {
+        char *list = (char *) malloc(size);
+        if (list == NULL) {
+            reply_err(req, -ENOMEM);
+            return;
+        }
+        res = common_listxattr(f, req, ino, list, size);
+        if (res > 0)
+            fuse_reply_buf(req, list, res);
+        else
+            reply_err(req, res);
+        free(list);
+    } else {
+        res = common_listxattr(f, req, ino, NULL, 0);
+        if (res >= 0)
+            fuse_reply_xattr(req, res);
+        else
+            reply_err(req, res);
+    }
+}
+
+static void fuse_lib_removexattr(fuse_req_t req, fuse_ino_t ino,
+                                 const char *name)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    char *path;
+    int err;
+
+    err = -ENOENT;
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path(f, ino);
+    if (path != NULL) {
+        struct fuse_intr_data d;
+        fuse_prepare_interrupt(f, req, &d);
+        err = fuse_fs_removexattr(f->fs, path, name);
+        fuse_finish_interrupt(f, req, &d);
+        free(path);
+    }
+    pthread_rwlock_unlock(&f->tree_lock);
+    reply_err(req, err);
+}
+
+static struct lock *locks_conflict(struct node *node, const struct lock *lock)
+{
+    struct lock *l;
+
+    for (l = node->locks; l; l = l->next)
+        if (l->owner != lock->owner &&
+            lock->start <= l->end && l->start <= lock->end &&
+            (l->type == F_WRLCK || lock->type == F_WRLCK))
+            break;
+
+    return l;
+}
+
+static void delete_lock(struct lock **lockp)
+{
+    struct lock *l = *lockp;
+    *lockp = l->next;
+    free(l);
+}
+
+static void insert_lock(struct lock **pos, struct lock *lock)
+{
+    lock->next = *pos;
+    *pos = lock;
+}
+
+static int locks_insert(struct node *node, struct lock *lock)
+{
+    struct lock **lp;
+    struct lock *newl1 = NULL;
+    struct lock *newl2 = NULL;
+
+    if (lock->type != F_UNLCK || lock->start != 0 || lock->end != OFFSET_MAX) {
+        newl1 = malloc(sizeof(struct lock));
+        newl2 = malloc(sizeof(struct lock));
+
+        if (!newl1 || !newl2) {
+            free(newl1);
+            free(newl2);
+            return -ENOLCK;
+        }
+    }
+
+    for (lp = &node->locks; *lp;) {
+        struct lock *l = *lp;
+        if (l->owner != lock->owner)
+            goto skip;
+
+        if (lock->type == l->type) {
+            if (l->end < lock->start - 1)
+                goto skip;
+            if (lock->end < l->start - 1)
+                break;
+            if (l->start <= lock->start && lock->end <= l->end)
+                goto out;
+            if (l->start < lock->start)
+                lock->start = l->start;
+            if (lock->end < l->end)
+                lock->end = l->end;
+            goto delete;
+        } else {
+            if (l->end < lock->start)
+                goto skip;
+            if (lock->end < l->start)
+                break;
+            if (lock->start <= l->start && l->end <= lock->end)
+                goto delete;
+            if (l->end <= lock->end) {
+                l->end = lock->start - 1;
+                goto skip;
+            }
+            if (lock->start <= l->start) {
+                l->start = lock->end + 1;
+                break;
+            }
+            *newl2 = *l;
+            newl2->start = lock->end + 1;
+            l->end = lock->start - 1;
+            insert_lock(&l->next, newl2);
+            newl2 = NULL;
+        }
+    skip:
+        lp = &l->next;
+        continue;
+
+    delete:
+        delete_lock(lp);
+    }
+    if (lock->type != F_UNLCK) {
+        *newl1 = *lock;
+        insert_lock(lp, newl1);
+        newl1 = NULL;
+    }
+out:
+    free(newl1);
+    free(newl2);
+    return 0;
+}
+
+static void flock_to_lock(struct flock *flock, struct lock *lock)
+{
+    memset(lock, 0, sizeof(struct lock));
+    lock->type = flock->l_type;
+    lock->start = flock->l_start;
+    lock->end = flock->l_len ? flock->l_start + flock->l_len - 1 : OFFSET_MAX;
+    lock->pid = flock->l_pid;
+}
+
+static void lock_to_flock(struct lock *lock, struct flock *flock)
+{
+    flock->l_type = lock->type;
+    flock->l_start = lock->start;
+    flock->l_len = (lock->end == OFFSET_MAX) ? 0 : lock->end - lock->start + 1;
+    flock->l_pid = lock->pid;
+}
+
+static int fuse_flush_common(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
+                             const char *path, struct fuse_file_info *fi)
+{
+    struct fuse_intr_data d;
+    struct flock lock;
+    struct lock l;
+    int err;
+    int errlock;
+
+    fuse_prepare_interrupt(f, req, &d);
+    memset(&lock, 0, sizeof(lock));
+    lock.l_type = F_UNLCK;
+    lock.l_whence = SEEK_SET;
+    err = fuse_fs_flush(f->fs, path, fi);
+    errlock = fuse_fs_lock(f->fs, path, fi, F_SETLK, &lock);
+    fuse_finish_interrupt(f, req, &d);
+
+    if (errlock != -ENOSYS) {
+        flock_to_lock(&lock, &l);
+        l.owner = fi->lock_owner;
+        pthread_mutex_lock(&f->lock);
+        locks_insert(get_node(f, ino), &l);
+        pthread_mutex_unlock(&f->lock);
+
+        /* if op.lock() is defined FLUSH is needed regardless of op.flush() */
+        if (err == -ENOSYS)
+            err = 0;
+    }
+    return err;
+}
+
+static void fuse_lib_release(fuse_req_t req, fuse_ino_t ino,
+                             struct fuse_file_info *fi)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    struct fuse_intr_data d;
+    char *path;
+    int err = 0;
+
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path(f, ino);
+    if (f->conf.debug)
+        fprintf(stderr, "RELEASE%s[%llu] flags: 0x%x\n",
+                fi->flush ? "+FLUSH" : "",
+                (unsigned long long) fi->fh, fi->flags);
+
+    if (fi->flush) {
+        err = fuse_flush_common(f, req, ino, path, fi);
+        if (err == -ENOSYS)
+            err = 0;
+    }
+
+    fuse_prepare_interrupt(f, req, &d);
+    fuse_do_release(f, ino, path, fi);
+    fuse_finish_interrupt(f, req, &d);
+    free(path);
+    pthread_rwlock_unlock(&f->tree_lock);
+
+    reply_err(req, err);
+}
+
+static void fuse_lib_flush(fuse_req_t req, fuse_ino_t ino,
+                       struct fuse_file_info *fi)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    char *path;
+    int err;
+
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path(f, ino);
+    if (path && f->conf.debug)
+        fprintf(stderr, "FLUSH[%llu]\n", (unsigned long long) fi->fh);
+    err = fuse_flush_common(f, req, ino, path, fi);
+    free(path);
+    pthread_rwlock_unlock(&f->tree_lock);
+    reply_err(req, err);
+}
+
+static int fuse_lock_common(fuse_req_t req, fuse_ino_t ino,
+                            struct fuse_file_info *fi, struct flock *lock,
+                            int cmd)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    char *path;
+    int err;
+
+    err = -ENOENT;
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path(f, ino);
+    if (path != NULL) {
+        struct fuse_intr_data d;
+        fuse_prepare_interrupt(f, req, &d);
+        err = fuse_fs_lock(f->fs, path, fi, cmd, lock);
+        fuse_finish_interrupt(f, req, &d);
+        free(path);
+    }
+    pthread_rwlock_unlock(&f->tree_lock);
+    return err;
+}
+
+static void fuse_lib_getlk(fuse_req_t req, fuse_ino_t ino,
+                           struct fuse_file_info *fi, struct flock *lock)
+{
+    int err;
+    struct lock l;
+    struct lock *conflict;
+    struct fuse *f = req_fuse(req);
+
+    flock_to_lock(lock, &l);
+    l.owner = fi->lock_owner;
+    pthread_mutex_lock(&f->lock);
+    conflict = locks_conflict(get_node(f, ino), &l);
+    if (conflict)
+        lock_to_flock(conflict, lock);
+    pthread_mutex_unlock(&f->lock);
+    if (!conflict)
+        err = fuse_lock_common(req, ino, fi, lock, F_GETLK);
+    else
+        err = 0;
+
+    if (!err)
+        fuse_reply_lock(req, lock);
+    else
+        reply_err(req, err);
+}
+
+static void fuse_lib_setlk(fuse_req_t req, fuse_ino_t ino,
+                           struct fuse_file_info *fi, struct flock *lock,
+                           int should_sleep)
+{
+    int err = fuse_lock_common(req, ino, fi, lock, should_sleep ? F_SETLKW : F_SETLK);
+    if (!err) {
+        struct fuse *f = req_fuse(req);
+        struct lock l;
+        flock_to_lock(lock, &l);
+        l.owner = fi->lock_owner;
+        pthread_mutex_lock(&f->lock);
+        locks_insert(get_node(f, ino), &l);
+        pthread_mutex_unlock(&f->lock);
+    }
+    reply_err(req, err);
+}
+
+static void fuse_lib_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize,
+                          uint64_t idx)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    struct fuse_intr_data d;
+    char *path;
+    int err;
+
+    err = -ENOENT;
+    pthread_rwlock_rdlock(&f->tree_lock);
+    path = get_path(f, ino);
+    if (path != NULL) {
+        fuse_prepare_interrupt(f, req, &d);
+        err = fuse_fs_bmap(f->fs, path, blocksize, &idx);
+        fuse_finish_interrupt(f, req, &d);
+        free(path);
+    }
+    pthread_rwlock_unlock(&f->tree_lock);
+    if (!err)
+        fuse_reply_bmap(req, idx);
+    else
+        reply_err(req, err);
+}
+
+static void fuse_lib_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
+			   struct fuse_file_info *llfi, unsigned int flags,
+			   const void *in_buf, size_t in_bufsz,
+			   size_t out_bufsz)
+{
+    struct fuse *f = req_fuse_prepare(req);
+    struct fuse_intr_data d;
+    struct fuse_file_info fi;
+    char *path, *out_buf = NULL;
+    int err;
+
+    err = -EPERM;
+    if (flags & FUSE_IOCTL_UNRESTRICTED)
+	goto err;
+
+    if (flags & FUSE_IOCTL_DIR)
+	get_dirhandle(llfi, &fi);
+    else
+	fi = *llfi;
+
+    if (out_bufsz) {
+	err = -ENOMEM;
+	out_buf = malloc(out_bufsz);
+	if (!out_buf)
+	    goto err;
+    }
+
+    assert(!in_bufsz || !out_bufsz || in_bufsz == out_bufsz);
+    if (out_buf)
+	memcpy(out_buf, in_buf, in_bufsz);
+
+    path = get_path(f, ino); /* Should be get_path_nullok() */
+    if (!path) {
+	err = ENOENT;
+	goto err;
+    }
+
+    fuse_prepare_interrupt(f, req, &d);
+
+	/* Note : const qualifier dropped */
+    err = fuse_fs_ioctl(f->fs, path, cmd, arg, &fi, flags,
+			out_buf ? (void*)out_buf : (void*)(uintptr_t)in_buf);
+
+    fuse_finish_interrupt(f, req, &d);
+    free(path);
+
+    fuse_reply_ioctl(req, err, out_buf, out_bufsz);
+	goto out;
+err:
+    reply_err(req, err);
+out:
+    free(out_buf);
+}
+
+static struct fuse_lowlevel_ops fuse_path_ops = {
+    .init = fuse_lib_init,
+    .destroy = fuse_lib_destroy,
+    .lookup = fuse_lib_lookup,
+    .forget = fuse_lib_forget,
+    .getattr = fuse_lib_getattr,
+    .setattr = fuse_lib_setattr,
+    .access = fuse_lib_access,
+    .readlink = fuse_lib_readlink,
+    .mknod = fuse_lib_mknod,
+    .mkdir = fuse_lib_mkdir,
+    .unlink = fuse_lib_unlink,
+    .rmdir = fuse_lib_rmdir,
+    .symlink = fuse_lib_symlink,
+    .rename = fuse_lib_rename,
+    .link = fuse_lib_link,
+    .create = fuse_lib_create,
+    .open = fuse_lib_open,
+    .read = fuse_lib_read,
+    .write = fuse_lib_write,
+    .flush = fuse_lib_flush,
+    .release = fuse_lib_release,
+    .fsync = fuse_lib_fsync,
+    .opendir = fuse_lib_opendir,
+    .readdir = fuse_lib_readdir,
+    .releasedir = fuse_lib_releasedir,
+    .fsyncdir = fuse_lib_fsyncdir,
+    .statfs = fuse_lib_statfs,
+    .setxattr = fuse_lib_setxattr,
+    .getxattr = fuse_lib_getxattr,
+    .listxattr = fuse_lib_listxattr,
+    .removexattr = fuse_lib_removexattr,
+    .getlk = fuse_lib_getlk,
+    .setlk = fuse_lib_setlk,
+    .bmap = fuse_lib_bmap,
+    .ioctl = fuse_lib_ioctl,
+};
+
+struct fuse_session *fuse_get_session(struct fuse *f)
+{
+    return f->se;
+}
+
+int fuse_loop(struct fuse *f)
+{
+    if (f)
+        return fuse_session_loop(f->se);
+    else
+        return -1;
+}
+
+void fuse_exit(struct fuse *f)
+{
+    fuse_session_exit(f->se);
+}
+
+struct fuse_context *fuse_get_context(void)
+{
+    return &fuse_get_context_internal()->ctx;
+}
+
+int fuse_interrupted(void)
+{
+    return fuse_req_interrupted(fuse_get_context_internal()->req);
+}
+
+enum {
+    KEY_HELP,
+};
+
+#define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v }
+
+static const struct fuse_opt fuse_lib_opts[] = {
+    FUSE_OPT_KEY("-h",                    KEY_HELP),
+    FUSE_OPT_KEY("--help",                KEY_HELP),
+    FUSE_OPT_KEY("debug",                 FUSE_OPT_KEY_KEEP),
+    FUSE_OPT_KEY("-d",                    FUSE_OPT_KEY_KEEP),
+    FUSE_LIB_OPT("debug",                 debug, 1),
+    FUSE_LIB_OPT("-d",                    debug, 1),
+    FUSE_LIB_OPT("hard_remove",           hard_remove, 1),
+    FUSE_LIB_OPT("use_ino",               use_ino, 1),
+    FUSE_LIB_OPT("readdir_ino",           readdir_ino, 1),
+    FUSE_LIB_OPT("direct_io",             direct_io, 1),
+    FUSE_LIB_OPT("kernel_cache",          kernel_cache, 1),
+#ifdef __SOLARIS__
+    FUSE_LIB_OPT("auto_cache",            auto_cache, 1),
+    FUSE_LIB_OPT("noauto_cache",          auto_cache, 0),
+#endif /* __SOLARIS__ */
+    FUSE_LIB_OPT("umask=",                set_mode, 1),
+    FUSE_LIB_OPT("umask=%o",              umask, 0),
+    FUSE_LIB_OPT("uid=",                  set_uid, 1),
+    FUSE_LIB_OPT("uid=%d",                uid, 0),
+    FUSE_LIB_OPT("gid=",                  set_gid, 1),
+    FUSE_LIB_OPT("gid=%d",                gid, 0),
+    FUSE_LIB_OPT("entry_timeout=%lf",     entry_timeout, 0),
+    FUSE_LIB_OPT("attr_timeout=%lf",      attr_timeout, 0),
+    FUSE_LIB_OPT("ac_attr_timeout=%lf",   ac_attr_timeout, 0),
+    FUSE_LIB_OPT("ac_attr_timeout=",      ac_attr_timeout_set, 1),
+    FUSE_LIB_OPT("negative_timeout=%lf",  negative_timeout, 0),
+    FUSE_LIB_OPT("intr",                  intr, 1),
+    FUSE_LIB_OPT("intr_signal=%d",        intr_signal, 0),
+#ifdef __SOLARIS__
+    FUSE_LIB_OPT("modules=%s",            modules, 0),
+#endif /* __SOLARIS__ */
+    FUSE_OPT_END
+};
+
+static void fuse_lib_help(void)
+{
+    fprintf(stderr,
+"    -o hard_remove         immediate removal (don't hide files)\n"
+"    -o use_ino             let filesystem set inode numbers\n"
+"    -o readdir_ino         try to fill in d_ino in readdir\n"
+"    -o direct_io           use direct I/O\n"
+"    -o kernel_cache        cache files in kernel\n"
+#ifdef __SOLARIS__
+"    -o [no]auto_cache      enable caching based on modification times\n"
+#endif /* __SOLARIS__ */
+"    -o umask=M             set file permissions (octal)\n"
+"    -o uid=N               set file owner\n"
+"    -o gid=N               set file group\n"
+"    -o entry_timeout=T     cache timeout for names (1.0s)\n"
+"    -o negative_timeout=T  cache timeout for deleted names (0.0s)\n"
+"    -o attr_timeout=T      cache timeout for attributes (1.0s)\n"
+"    -o ac_attr_timeout=T   auto cache timeout for attributes (attr_timeout)\n"
+"    -o intr                allow requests to be interrupted\n"
+"    -o intr_signal=NUM     signal to send on interrupt (%i)\n"
+#ifdef __SOLARIS__
+"    -o modules=M1[:M2...]  names of modules to push onto filesystem stack\n"
+#endif /* __SOLARIS__ */
+"\n", FUSE_DEFAULT_INTR_SIGNAL);
+}
+
+#ifdef __SOLARIS__
+
+static void fuse_lib_help_modules(void)
+{
+    struct fuse_module *m;
+    fprintf(stderr, "\nModule options:\n");
+    pthread_mutex_lock(&fuse_context_lock);
+    for (m = fuse_modules; m; m = m->next) {
+        struct fuse_fs *fs = NULL;
+        struct fuse_fs *newfs;
+        struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
+        if (fuse_opt_add_arg(&args, "") != -1 &&
+            fuse_opt_add_arg(&args, "-h") != -1) {
+            fprintf(stderr, "\n[%s]\n", m->name);
+            newfs = m->factory(&args, &fs);
+            assert(newfs == NULL);
+        }
+        fuse_opt_free_args(&args);
+    }
+    pthread_mutex_unlock(&fuse_context_lock);
+}
+
+int fuse_is_lib_option(const char *opt)
+{
+    return fuse_lowlevel_is_lib_option(opt) ||
+        fuse_opt_match(fuse_lib_opts, opt);
+}
+
+#endif /* __SOLARIS__ */
+
+static int fuse_lib_opt_proc(void *data, const char *arg, int key,
+                             struct fuse_args *outargs)
+{
+    (void) arg; (void) outargs;
+
+    if (key == KEY_HELP) {
+        struct fuse_config *conf = (struct fuse_config *) data;
+        fuse_lib_help();
+        conf->help = 1;
+    }
+
+    return 1;
+}
+
+static int fuse_init_intr_signal(int signum, int *installed)
+{
+    struct sigaction old_sa;
+
+    if (sigaction(signum, NULL, &old_sa) == -1) {
+        perror("fuse: cannot get old signal handler");
+        return -1;
+    }
+
+    if (old_sa.sa_handler == SIG_DFL) {
+        struct sigaction sa;
+
+        memset(&sa, 0, sizeof(struct sigaction));
+        sa.sa_handler = fuse_intr_sighandler;
+        sigemptyset(&sa.sa_mask);
+
+        if (sigaction(signum, &sa, NULL) == -1) {
+            perror("fuse: cannot set interrupt signal handler");
+            return -1;
+        }
+        *installed = 1;
+    }
+    return 0;
+}
+
+static void fuse_restore_intr_signal(int signum)
+{
+    struct sigaction sa;
+
+    memset(&sa, 0, sizeof(struct sigaction));
+    sa.sa_handler = SIG_DFL;
+    sigaction(signum, &sa, NULL);
+}
+
+#ifdef __SOLARIS__
+
+static int fuse_push_module(struct fuse *f, const char *module,
+                            struct fuse_args *args)
+{
+    struct fuse_fs *newfs;
+    struct fuse_module *m = fuse_get_module(module);
+    struct fuse_fs *fs[2];
+
+    fs[0] = f->fs;
+    fs[1] = NULL;
+    if (!m)
+        return -1;
+
+    newfs = m->factory(args, fs);
+    if (!newfs) {
+        fuse_put_module(m);
+        return -1;
+    }
+    newfs->m = m;
+    f->fs = newfs;
+    return 0;
+}
+
+#endif /* __SOLARIS__ */
+
+struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size,
+                            void *user_data)
+{
+    struct fuse_fs *fs;
+
+    if (sizeof(struct fuse_operations) < op_size) {
+        fprintf(stderr, "fuse: warning: library too old, some operations may not not work\n");
+        op_size = sizeof(struct fuse_operations);
+    }
+
+    fs = (struct fuse_fs *) calloc(1, sizeof(struct fuse_fs));
+    if (!fs) {
+        fprintf(stderr, "fuse: failed to allocate fuse_fs object\n");
+        return NULL;
+    }
+
+    fs->user_data = user_data;
+    if (op)
+        memcpy(&fs->op, op, op_size);
+    return fs;
+}
+
+struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args,
+		      const struct fuse_operations *op, size_t op_size,
+		      void *user_data)
+{
+    struct fuse *f;
+    struct node *root;
+    struct fuse_fs *fs;
+    struct fuse_lowlevel_ops llop = fuse_path_ops;
+
+    if (fuse_create_context_key() == -1)
+        goto out;
+
+    f = (struct fuse *) calloc(1, sizeof(struct fuse));
+    if (f == NULL) {
+        fprintf(stderr, "fuse: failed to allocate fuse object\n");
+        goto out_delete_context_key;
+    }
+
+    fs = fuse_fs_new(op, op_size, user_data);
+    if (!fs)
+        goto out_free;
+
+    f->fs = fs;
+
+    /* Oh f**k, this is ugly! */
+    if (!fs->op.lock) {
+        llop.getlk = NULL;
+        llop.setlk = NULL;
+    }
+
+    f->conf.entry_timeout = 1.0;
+    f->conf.attr_timeout = 1.0;
+    f->conf.negative_timeout = 0.0;
+    f->conf.intr_signal = FUSE_DEFAULT_INTR_SIGNAL;
+
+    if (fuse_opt_parse(args, &f->conf, fuse_lib_opts, fuse_lib_opt_proc) == -1)
+        goto out_free_fs;
+
+#ifdef __SOLARIS__
+    if (f->conf.modules) {
+        char *module;
+        char *next;
+
+        for (module = f->conf.modules; module; module = next) {
+            char *p;
+            for (p = module; *p && *p != ':'; p++);
+            next = *p ? p + 1 : NULL;
+            *p = '\0';
+            if (module[0] && fuse_push_module(f, module, args) == -1)
+                goto out_free_fs;
+        }
+    }
+#endif /* __SOLARIS__ */
+
+    if (!f->conf.ac_attr_timeout_set)
+        f->conf.ac_attr_timeout = f->conf.attr_timeout;
+
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+    /*
+     * In FreeBSD, we always use these settings as inode numbers are needed to
+     * make getcwd(3) work.
+     */
+    f->conf.readdir_ino = 1;
+#endif
+
+    f->se = fuse_lowlevel_new(args, &llop, sizeof(llop), f);
+
+    if (f->se == NULL) {
+#ifdef __SOLARIS__
+        if (f->conf.help)
+            fuse_lib_help_modules();
+#endif /* __SOLARIS__ */
+        goto out_free_fs;
+    }
+
+    fuse_session_add_chan(f->se, ch);
+
+    f->ctr = 0;
+    f->generation = 0;
+    /* FIXME: Dynamic hash table */
+    f->name_table_size = 14057;
+    f->name_table = (struct node **)
+        calloc(1, sizeof(struct node *) * f->name_table_size);
+    if (f->name_table == NULL) {
+        fprintf(stderr, "fuse: memory allocation failed\n");
+        goto out_free_session;
+    }
+
+    f->id_table_size = 14057;
+    f->id_table = (struct node **)
+        calloc(1, sizeof(struct node *) * f->id_table_size);
+    if (f->id_table == NULL) {
+        fprintf(stderr, "fuse: memory allocation failed\n");
+        goto out_free_name_table;
+    }
+
+    fuse_mutex_init(&f->lock);
+    pthread_rwlock_init(&f->tree_lock, NULL);
+
+    root = (struct node *) calloc(1, sizeof(struct node));
+    if (root == NULL) {
+        fprintf(stderr, "fuse: memory allocation failed\n");
+        goto out_free_id_table;
+    }
+
+    root->name = strdup("/");
+    if (root->name == NULL) {
+        fprintf(stderr, "fuse: memory allocation failed\n");
+        goto out_free_root;
+    }
+
+    if (f->conf.intr &&
+        fuse_init_intr_signal(f->conf.intr_signal, &f->intr_installed) == -1)
+        goto out_free_root_name;
+
+    root->parent = NULL;
+    root->nodeid = FUSE_ROOT_ID;
+    root->generation = 0;
+    root->refctr = 1;
+    root->nlookup = 1;
+    hash_id(f, root);
+
+    return f;
+
+ out_free_root_name:
+    free(root->name);
+ out_free_root:
+    free(root);
+ out_free_id_table:
+    free(f->id_table);
+ out_free_name_table:
+    free(f->name_table);
+ out_free_session:
+    fuse_session_destroy(f->se);
+ out_free_fs:
+    /* Horrible compatibility hack to stop the destructor from being
+       called on the filesystem without init being called first */
+    fs->op.destroy = NULL;
+    fuse_fs_destroy(f->fs);
+#ifdef __SOLARIS__
+    free(f->conf.modules);
+#endif /* __SOLARIS__ */
+ out_free:
+    free(f);
+ out_delete_context_key:
+    fuse_delete_context_key();
+ out:
+    return NULL;
+}
+
+void fuse_destroy(struct fuse *f)
+{
+    size_t i;
+
+    if (f->conf.intr && f->intr_installed)
+        fuse_restore_intr_signal(f->conf.intr_signal);
+
+    if (f->fs) {
+        struct fuse_context_i *c = fuse_get_context_internal();
+
+        memset(c, 0, sizeof(*c));
+        c->ctx.fuse = f;
+
+        for (i = 0; i < f->id_table_size; i++) {
+            struct node *node;
+
+            for (node = f->id_table[i]; node != NULL; node = node->id_next) {
+                if (node->is_hidden) {
+                    char *path = get_path(f, node->nodeid);
+                    if (path) {
+                        fuse_fs_unlink(f->fs, path);
+                        free(path);
+                    }
+                }
+            }
+        }
+    }
+    for (i = 0; i < f->id_table_size; i++) {
+        struct node *node;
+        struct node *next;
+
+        for (node = f->id_table[i]; node != NULL; node = next) {
+            next = node->id_next;
+            free_node(node);
+        }
+    }
+    free(f->id_table);
+    free(f->name_table);
+    pthread_mutex_destroy(&f->lock);
+    pthread_rwlock_destroy(&f->tree_lock);
+    fuse_session_destroy(f->se);
+#ifdef __SOLARIS__
+    free(f->conf.modules);
+#endif /* __SOLARIS__ */
+    free(f);
+    fuse_delete_context_key();
+}
diff --git a/libfuse-lite/fuse_i.h b/libfuse-lite/fuse_i.h
new file mode 100755
index 0000000000000000000000000000000000000000..38c45c72bec23db15c1e280abd7f94b7da90cbc9
--- /dev/null
+++ b/libfuse-lite/fuse_i.h
@@ -0,0 +1,25 @@
+/*
+    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);
diff --git a/libfuse-lite/fuse_kern_chan.c b/libfuse-lite/fuse_kern_chan.c
new file mode 100755
index 0000000000000000000000000000000000000000..e9963b5d9ca5dbaeffc6b33c4afe2dbc15219fe8
--- /dev/null
+++ b/libfuse-lite/fuse_kern_chan.c
@@ -0,0 +1,96 @@
+/*
+    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);
+}
diff --git a/libfuse-lite/fuse_loop.c b/libfuse-lite/fuse_loop.c
new file mode 100755
index 0000000000000000000000000000000000000000..0b592e5316885cfffb5558dcdeee3d888222e7da
--- /dev/null
+++ b/libfuse-lite/fuse_loop.c
@@ -0,0 +1,40 @@
+/*
+    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;
+}
diff --git a/libfuse-lite/fuse_lowlevel.c b/libfuse-lite/fuse_lowlevel.c
new file mode 100755
index 0000000000000000000000000000000000000000..ee01c7c108af6600bd8de6a69f2cd9d83e71ce27
--- /dev/null
+++ b/libfuse-lite/fuse_lowlevel.c
@@ -0,0 +1,1434 @@
+/*
+    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_opt.h"
+#include "fuse_i.h"
+#include "fuse_misc.h"
+#include "fuse_lowlevel_compat.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+
+#define PARAM(inarg) (((const char *)(inarg)) + sizeof(*(inarg)))
+#define OFFSET_MAX 0x7fffffffffffffffLL
+
+struct fuse_ll;
+
+struct fuse_req {
+    struct fuse_ll *f;
+    uint64_t unique;
+    int ctr;
+    pthread_mutex_t lock;
+    struct fuse_ctx ctx;
+    struct fuse_chan *ch;
+    int interrupted;
+    union {
+        struct {
+            uint64_t unique;
+        } i;
+        struct {
+            fuse_interrupt_func_t func;
+            void *data;
+        } ni;
+    } u;
+    struct fuse_req *next;
+    struct fuse_req *prev;
+};
+
+struct fuse_ll {
+    int debug;
+    int allow_root;
+    struct fuse_lowlevel_ops op;
+    int got_init;
+    void *userdata;
+    uid_t owner;
+    struct fuse_conn_info conn;
+    struct fuse_req list;
+    struct fuse_req interrupts;
+    pthread_mutex_t lock;
+    int got_destroy;
+};
+
+static void convert_stat(const struct stat *stbuf, struct fuse_attr *attr)
+{
+    attr->ino       = stbuf->st_ino;
+    attr->mode      = stbuf->st_mode;
+    attr->nlink     = stbuf->st_nlink;
+    attr->uid       = stbuf->st_uid;
+    attr->gid       = stbuf->st_gid;
+    attr->rdev      = stbuf->st_rdev;
+    attr->size      = stbuf->st_size;
+    attr->blocks    = stbuf->st_blocks;
+    attr->atime     = stbuf->st_atime;
+    attr->mtime     = stbuf->st_mtime;
+    attr->ctime     = stbuf->st_ctime;
+    attr->atimensec = ST_ATIM_NSEC(stbuf);
+    attr->mtimensec = ST_MTIM_NSEC(stbuf);
+    attr->ctimensec = ST_CTIM_NSEC(stbuf);
+#ifdef POSIXACLS
+    attr->filling = 0; /* JPA trying to be safe */
+#endif
+}
+
+static void convert_attr(const struct fuse_setattr_in *attr, struct stat *stbuf)
+{
+    stbuf->st_mode         = attr->mode;
+    stbuf->st_uid          = attr->uid;
+    stbuf->st_gid          = attr->gid;
+    stbuf->st_size         = attr->size;
+    stbuf->st_atime        = attr->atime;
+    stbuf->st_mtime        = attr->mtime;
+    ST_ATIM_NSEC_SET(stbuf, attr->atimensec);
+    ST_MTIM_NSEC_SET(stbuf, attr->mtimensec);
+}
+
+static  size_t iov_length(const struct iovec *iov, size_t count)
+{
+    size_t seg;
+    size_t ret = 0;
+
+    for (seg = 0; seg < count; seg++)
+        ret += iov[seg].iov_len;
+    return ret;
+}
+
+static void list_init_req(struct fuse_req *req)
+{
+    req->next = req;
+    req->prev = req;
+}
+
+static void list_del_req(struct fuse_req *req)
+{
+    struct fuse_req *prev = req->prev;
+    struct fuse_req *next = req->next;
+    prev->next = next;
+    next->prev = prev;
+}
+
+static void list_add_req(struct fuse_req *req, struct fuse_req *next)
+{
+    struct fuse_req *prev = next->prev;
+    req->next = next;
+    req->prev = prev;
+    prev->next = req;
+    next->prev = req;
+}
+
+static void destroy_req(fuse_req_t req)
+{
+    pthread_mutex_destroy(&req->lock);
+    free(req);
+}
+
+static void free_req(fuse_req_t req)
+{
+    int ctr;
+    struct fuse_ll *f = req->f;
+
+    pthread_mutex_lock(&req->lock);
+    req->u.ni.func = NULL;
+    req->u.ni.data = NULL;
+    pthread_mutex_unlock(&req->lock);
+
+    pthread_mutex_lock(&f->lock);
+    list_del_req(req);
+    ctr = --req->ctr;
+    pthread_mutex_unlock(&f->lock);
+    if (!ctr)
+        destroy_req(req);
+}
+
+static int send_reply_iov(fuse_req_t req, int error, struct iovec *iov,
+                          int count)
+{
+    struct fuse_out_header out;
+    int res;
+
+    if (error <= -1000 || error > 0) {
+        fprintf(stderr, "fuse: bad error value: %i\n",  error);
+        error = -ERANGE;
+    }
+
+    out.unique = req->unique;
+    out.error = error;
+    iov[0].iov_base = &out;
+    iov[0].iov_len = sizeof(struct fuse_out_header);
+    out.len = iov_length(iov, count);
+
+    if (req->f->debug)
+        fprintf(stderr, "   unique: %llu, error: %i (%s), outsize: %i\n",
+                (unsigned long long) out.unique, out.error,
+                strerror(-out.error), out.len);
+    res = fuse_chan_send(req->ch, iov, count);
+    free_req(req);
+
+    return res;
+}
+
+static int send_reply(fuse_req_t req, int error, const void *arg,
+                      size_t argsize)
+{
+    struct iovec iov[2];
+    int count = 1;
+    if (argsize) {
+		/* Note : const qualifier dropped */
+        iov[1].iov_base = (void *)(uintptr_t) arg;
+        iov[1].iov_len = argsize;
+        count++;
+    }
+    return send_reply_iov(req, error, iov, count);
+}
+
+#if 0 /* not used */
+int fuse_reply_iov(fuse_req_t req, const struct iovec *iov, int count)
+{
+    int res;
+    struct iovec *padded_iov;
+
+    padded_iov = malloc((count + 1) * sizeof(struct iovec));
+    if (padded_iov == NULL)
+        return fuse_reply_err(req, -ENOMEM);
+
+    memcpy(padded_iov + 1, iov, count * sizeof(struct iovec));
+    count++;
+
+    res = send_reply_iov(req, 0, padded_iov, count);
+    free(padded_iov);
+
+    return res;
+}
+#endif
+
+size_t fuse_dirent_size(size_t namelen)
+{
+    return FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + namelen);
+}
+
+char *fuse_add_dirent(char *buf, const char *name, const struct stat *stbuf,
+                      off_t off)
+{
+    unsigned namelen = strlen(name);
+    unsigned entlen = FUSE_NAME_OFFSET + namelen;
+    unsigned entsize = fuse_dirent_size(namelen);
+    unsigned padlen = entsize - entlen;
+    struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
+
+    dirent->ino = stbuf->st_ino;
+    dirent->off = off;
+    dirent->namelen = namelen;
+    dirent->type = (stbuf->st_mode & 0170000) >> 12;
+    strncpy(dirent->name, name, namelen);
+    if (padlen)
+        memset(buf + entlen, 0, padlen);
+
+    return buf + entsize;
+}
+
+size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize,
+                         const char *name, const struct stat *stbuf, off_t off)
+{
+    size_t entsize;
+
+    (void) req;
+    entsize = fuse_dirent_size(strlen(name));
+    if (entsize <= bufsize && buf)
+        fuse_add_dirent(buf, name, stbuf, off);
+    return entsize;
+}
+
+static void convert_statfs(const struct statvfs *stbuf,
+                           struct fuse_kstatfs *kstatfs)
+{
+    kstatfs->bsize	= stbuf->f_bsize;
+    kstatfs->frsize	= stbuf->f_frsize;
+    kstatfs->blocks	= stbuf->f_blocks;
+    kstatfs->bfree	= stbuf->f_bfree;
+    kstatfs->bavail	= stbuf->f_bavail;
+    kstatfs->files	= stbuf->f_files;
+    kstatfs->ffree	= stbuf->f_ffree;
+    kstatfs->namelen	= stbuf->f_namemax;
+}
+
+static int send_reply_ok(fuse_req_t req, const void *arg, size_t argsize)
+{
+    return send_reply(req, 0, arg, argsize);
+}
+
+int fuse_reply_err(fuse_req_t req, int err)
+{
+    return send_reply(req, -err, NULL, 0);
+}
+
+void fuse_reply_none(fuse_req_t req)
+{
+    fuse_chan_send(req->ch, NULL, 0);
+    free_req(req);
+}
+
+static unsigned long calc_timeout_sec(double t)
+{
+    if (t > (double) ULONG_MAX)
+        return ULONG_MAX;
+    else if (t < 0.0)
+        return 0;
+    else
+        return (unsigned long) t;
+}
+
+static unsigned int calc_timeout_nsec(double t)
+{
+    unsigned long secs = calc_timeout_sec(t);
+    double f = t - (double)secs;
+    if (f < 0.0)
+        return 0;
+    else if (f >= 0.999999999)
+        return 999999999;
+    else
+        return (unsigned int) (f * 1.0e9);
+}
+
+static void fill_entry(struct fuse_entry_out *arg,
+                       const struct fuse_entry_param *e)
+{
+    arg->nodeid = e->ino;
+    arg->generation = e->generation;
+    arg->entry_valid = calc_timeout_sec(e->entry_timeout);
+    arg->entry_valid_nsec = calc_timeout_nsec(e->entry_timeout);
+    arg->attr_valid = calc_timeout_sec(e->attr_timeout);
+    arg->attr_valid_nsec = calc_timeout_nsec(e->attr_timeout);
+    convert_stat(&e->attr, &arg->attr);
+}
+
+static void fill_open(struct fuse_open_out *arg,
+                      const struct fuse_file_info *f)
+{
+    arg->fh = f->fh;
+    if (f->direct_io)
+        arg->open_flags |= FOPEN_DIRECT_IO;
+    if (f->keep_cache)
+        arg->open_flags |= FOPEN_KEEP_CACHE;
+}
+
+int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e)
+{
+    struct fuse_entry_out arg;
+
+    /* before ABI 7.4 e->ino == 0 was invalid, only ENOENT meant
+       negative entry */
+    if (!e->ino && req->f->conn.proto_minor < 4)
+        return fuse_reply_err(req, ENOENT);
+
+    memset(&arg, 0, sizeof(arg));
+    fill_entry(&arg, e);
+    return send_reply_ok(req, &arg, (req->f->conn.proto_minor >= 12 
+			? sizeof(arg) : FUSE_COMPAT_ENTRY_OUT_SIZE));
+}
+
+int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e,
+                      const struct fuse_file_info *f)
+{
+    struct {
+        struct fuse_entry_out e;
+        struct fuse_open_out o;
+    } arg;
+
+    memset(&arg, 0, sizeof(arg));
+    fill_entry(&arg.e, e);
+    if (req->f->conn.proto_minor < 12) {
+	fill_open((struct fuse_open_out*)
+		((char*)&arg + FUSE_COMPAT_ENTRY_OUT_SIZE), f);
+	return send_reply_ok(req, &arg,
+		FUSE_COMPAT_ENTRY_OUT_SIZE + sizeof(struct fuse_open_out));
+    } else {
+    	fill_open(&arg.o, f);
+    	return send_reply_ok(req, &arg, sizeof(arg));
+    }
+}
+
+int fuse_reply_attr(fuse_req_t req, const struct stat *attr,
+                    double attr_timeout)
+{
+    struct fuse_attr_out arg;
+
+    memset(&arg, 0, sizeof(arg));
+    arg.attr_valid = calc_timeout_sec(attr_timeout);
+    arg.attr_valid_nsec = calc_timeout_nsec(attr_timeout);
+    convert_stat(attr, &arg.attr);
+
+    return send_reply_ok(req, &arg, (req->f->conn.proto_minor >= 12
+			? sizeof(arg) : FUSE_COMPAT_FUSE_ATTR_OUT_SIZE));
+}
+
+int fuse_reply_readlink(fuse_req_t req, const char *linkname)
+{
+    return send_reply_ok(req, linkname, strlen(linkname));
+}
+
+int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *f)
+{
+    struct fuse_open_out arg;
+
+    memset(&arg, 0, sizeof(arg));
+    fill_open(&arg, f);
+    return send_reply_ok(req, &arg, sizeof(arg));
+}
+
+int fuse_reply_write(fuse_req_t req, size_t count)
+{
+    struct fuse_write_out arg;
+
+    memset(&arg, 0, sizeof(arg));
+    arg.size = count;
+
+    return send_reply_ok(req, &arg, sizeof(arg));
+}
+
+int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size)
+{
+    return send_reply_ok(req, buf, size);
+}
+
+int fuse_reply_statfs(fuse_req_t req, const struct statvfs *stbuf)
+{
+    struct fuse_statfs_out arg;
+    size_t size = req->f->conn.proto_minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(arg);
+
+    memset(&arg, 0, sizeof(arg));
+    convert_statfs(stbuf, &arg.st);
+
+    return send_reply_ok(req, &arg, size);
+}
+
+int fuse_reply_xattr(fuse_req_t req, size_t count)
+{
+    struct fuse_getxattr_out arg;
+
+    memset(&arg, 0, sizeof(arg));
+    arg.size = count;
+
+    return send_reply_ok(req, &arg, sizeof(arg));
+}
+
+int fuse_reply_lock(fuse_req_t req, struct flock *lock)
+{
+    struct fuse_lk_out arg;
+
+    memset(&arg, 0, sizeof(arg));
+    arg.lk.type = lock->l_type;
+    if (lock->l_type != F_UNLCK) {
+        arg.lk.start = lock->l_start;
+        if (lock->l_len == 0)
+            arg.lk.end = OFFSET_MAX;
+        else
+            arg.lk.end = lock->l_start + lock->l_len - 1;
+    }
+    arg.lk.pid = lock->l_pid;
+    return send_reply_ok(req, &arg, sizeof(arg));
+}
+
+int fuse_reply_bmap(fuse_req_t req, uint64_t idx)
+{
+    struct fuse_bmap_out arg;
+
+    memset(&arg, 0, sizeof(arg));
+    arg.block = idx;
+
+    return send_reply_ok(req, &arg, sizeof(arg));
+}
+
+int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size)
+{
+    struct fuse_ioctl_out arg;
+    struct iovec iov[3];
+    size_t count = 1;
+
+    memset(&arg, 0, sizeof(arg));
+    arg.result = result;
+    iov[count].iov_base = &arg;
+    iov[count].iov_len = sizeof(arg);
+    count++;
+
+    if (size) {
+		/* Note : const qualifier dropped */
+	iov[count].iov_base = (char *)(uintptr_t) buf;
+	iov[count].iov_len = size;
+	count++;
+    }
+
+    return send_reply_iov(req, 0, iov, count);
+}
+
+static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const char *name = (const char *) inarg;
+
+    if (req->f->op.lookup)
+        req->f->op.lookup(req, nodeid, name);
+    else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_forget(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_forget_in *arg = (const struct fuse_forget_in *) inarg;
+
+    if (req->f->op.forget)
+        req->f->op.forget(req, nodeid, arg->nlookup);
+    else
+        fuse_reply_none(req);
+}
+
+static void do_getattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    (void) inarg;
+
+    if (req->f->op.getattr)
+        req->f->op.getattr(req, nodeid, NULL);
+    else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_setattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_setattr_in *arg = (const struct fuse_setattr_in *) inarg;
+
+    if (req->f->op.setattr) {
+        struct fuse_file_info *fi = NULL;
+        struct fuse_file_info fi_store;
+        struct stat stbuf;
+        memset(&stbuf, 0, sizeof(stbuf));
+        convert_attr(arg, &stbuf);
+        if (arg->valid & FATTR_FH) {
+            memset(&fi_store, 0, sizeof(fi_store));
+            fi = &fi_store;
+            fi->fh = arg->fh;
+            fi->fh_old = fi->fh;
+        }
+        req->f->op.setattr(req, nodeid, &stbuf, arg->valid & ~FATTR_FH, fi);
+    } else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_access(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_access_in *arg = (const struct fuse_access_in *) inarg;
+
+    if (req->f->op.access)
+        req->f->op.access(req, nodeid, arg->mask);
+    else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_readlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    (void) inarg;
+
+    if (req->f->op.readlink)
+        req->f->op.readlink(req, nodeid);
+    else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_mknod(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_mknod_in *arg = (const struct fuse_mknod_in *) inarg;
+    const char *name = PARAM(arg);
+
+    if (req->f->conn.proto_minor >= 12)
+	req->ctx.umask = arg->umask;
+    else
+	name = (const char *) inarg + FUSE_COMPAT_MKNOD_IN_SIZE;
+
+    if (req->f->op.mknod)
+	req->f->op.mknod(req, nodeid, name, arg->mode, arg->rdev);
+    else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_mkdir_in *arg = (const struct fuse_mkdir_in *) inarg;
+
+    if (req->f->conn.proto_minor >= 12)
+	req->ctx.umask = arg->umask;
+
+    if (req->f->op.mkdir)
+        req->f->op.mkdir(req, nodeid, PARAM(arg), arg->mode);
+    else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_unlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const char *name = (const char *) inarg;
+
+    if (req->f->op.unlink)
+        req->f->op.unlink(req, nodeid, name);
+    else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_rmdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const char *name = (const char *) inarg;
+
+    if (req->f->op.rmdir)
+        req->f->op.rmdir(req, nodeid, name);
+    else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_symlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const char *name = (const char *) inarg;
+    const char *linkname = ((const char *) inarg) + strlen((const char *) inarg) + 1;
+
+    if (req->f->op.symlink)
+        req->f->op.symlink(req, linkname, nodeid, name);
+    else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_rename(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_rename_in *arg = (const struct fuse_rename_in *) inarg;
+    const char *oldname = PARAM(arg);
+    const char *newname = oldname + strlen(oldname) + 1;
+
+    if (req->f->op.rename)
+        req->f->op.rename(req, nodeid, oldname, arg->newdir, newname);
+    else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_link(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_link_in *arg = (const struct fuse_link_in *) inarg;
+
+    if (req->f->op.link)
+        req->f->op.link(req, arg->oldnodeid, nodeid, PARAM(arg));
+    else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_create(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_create_in *arg = (const struct fuse_create_in *) inarg;
+
+    if (req->f->op.create) {
+        struct fuse_file_info fi;
+	const char *name = PARAM(arg);
+
+        memset(&fi, 0, sizeof(fi));
+        fi.flags = arg->flags;
+
+	if (req->f->conn.proto_minor >= 12)
+		req->ctx.umask = arg->umask;
+	else
+		name = (const char *) inarg + sizeof(struct fuse_open_in);
+
+	req->f->op.create(req, nodeid, name, arg->mode, &fi);
+    } else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_open(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_open_in *arg = (const struct fuse_open_in *) inarg;
+    struct fuse_file_info fi;
+
+    memset(&fi, 0, sizeof(fi));
+    fi.flags = arg->flags;
+
+    if (req->f->op.open)
+        req->f->op.open(req, nodeid, &fi);
+    else
+        fuse_reply_open(req, &fi);
+}
+
+static void do_read(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_read_in *arg = (const struct fuse_read_in *) inarg;
+
+    if (req->f->op.read) {
+        struct fuse_file_info fi;
+
+        memset(&fi, 0, sizeof(fi));
+        fi.fh = arg->fh;
+        fi.fh_old = fi.fh;
+        req->f->op.read(req, nodeid, arg->size, arg->offset, &fi);
+    } else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_write(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_write_in *arg = (const struct fuse_write_in *) inarg;
+    struct fuse_file_info fi;
+
+    memset(&fi, 0, sizeof(fi));
+    fi.fh = arg->fh;
+    fi.fh_old = fi.fh;
+    fi.writepage = arg->write_flags & 1;
+
+    if (req->f->op.write) {
+	const char *buf;
+
+	if (req->f->conn.proto_minor >= 12)
+		buf = PARAM(arg);
+	else
+		buf = ((const char*)arg) + FUSE_COMPAT_WRITE_IN_SIZE;
+        req->f->op.write(req, nodeid, buf, arg->size, arg->offset, &fi);
+    } else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_flush(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_flush_in *arg = (const struct fuse_flush_in *) inarg;
+    struct fuse_file_info fi;
+
+    memset(&fi, 0, sizeof(fi));
+    fi.fh = arg->fh;
+    fi.fh_old = fi.fh;
+    fi.flush = 1;
+    if (req->f->conn.proto_minor >= 7)
+        fi.lock_owner = arg->lock_owner;
+
+    if (req->f->op.flush)
+        req->f->op.flush(req, nodeid, &fi);
+    else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_release(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_release_in *arg = (const struct fuse_release_in *) inarg;
+    struct fuse_file_info fi;
+
+    memset(&fi, 0, sizeof(fi));
+    fi.flags = arg->flags;
+    fi.fh = arg->fh;
+    fi.fh_old = fi.fh;
+    if (req->f->conn.proto_minor >= 8) {
+        fi.flush = (arg->release_flags & FUSE_RELEASE_FLUSH) ? 1 : 0;
+        fi.lock_owner = arg->lock_owner;
+    }
+
+    if (req->f->op.release)
+        req->f->op.release(req, nodeid, &fi);
+    else
+        fuse_reply_err(req, 0);
+}
+
+static void do_fsync(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_fsync_in *arg = (const struct fuse_fsync_in *) inarg;
+    struct fuse_file_info fi;
+
+    memset(&fi, 0, sizeof(fi));
+    fi.fh = arg->fh;
+    fi.fh_old = fi.fh;
+
+    if (req->f->op.fsync)
+        req->f->op.fsync(req, nodeid, arg->fsync_flags & 1, &fi);
+    else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_opendir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_open_in *arg = (const struct fuse_open_in *) inarg;
+    struct fuse_file_info fi;
+
+    memset(&fi, 0, sizeof(fi));
+    fi.flags = arg->flags;
+
+    if (req->f->op.opendir)
+        req->f->op.opendir(req, nodeid, &fi);
+    else
+        fuse_reply_open(req, &fi);
+}
+
+static void do_readdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_read_in *arg = (const struct fuse_read_in *) inarg;
+    struct fuse_file_info fi;
+
+    memset(&fi, 0, sizeof(fi));
+    fi.fh = arg->fh;
+    fi.fh_old = fi.fh;
+
+    if (req->f->op.readdir)
+        req->f->op.readdir(req, nodeid, arg->size, arg->offset, &fi);
+    else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_release_in *arg = (const struct fuse_release_in *) inarg;
+    struct fuse_file_info fi;
+
+    memset(&fi, 0, sizeof(fi));
+    fi.flags = arg->flags;
+    fi.fh = arg->fh;
+    fi.fh_old = fi.fh;
+
+    if (req->f->op.releasedir)
+        req->f->op.releasedir(req, nodeid, &fi);
+    else
+        fuse_reply_err(req, 0);
+}
+
+static void do_fsyncdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_fsync_in *arg = (const struct fuse_fsync_in *) inarg;
+    struct fuse_file_info fi;
+
+    memset(&fi, 0, sizeof(fi));
+    fi.fh = arg->fh;
+    fi.fh_old = fi.fh;
+
+    if (req->f->op.fsyncdir)
+        req->f->op.fsyncdir(req, nodeid, arg->fsync_flags & 1, &fi);
+    else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_statfs(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    (void) nodeid;
+    (void) inarg;
+
+    if (req->f->op.statfs)
+        req->f->op.statfs(req, nodeid);
+    else {
+        struct statvfs buf = {
+            .f_namemax = 255,
+            .f_bsize = 512,
+        };
+        fuse_reply_statfs(req, &buf);
+    }
+}
+
+static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_setxattr_in *arg = (const struct fuse_setxattr_in *) inarg;
+    const char *name = PARAM(arg);
+    const char *value = name + strlen(name) + 1;
+
+    if (req->f->op.setxattr)
+        req->f->op.setxattr(req, nodeid, name, value, arg->size, arg->flags);
+    else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_getxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_getxattr_in *arg = (const struct fuse_getxattr_in *) inarg;
+
+    if (req->f->op.getxattr)
+        req->f->op.getxattr(req, nodeid, PARAM(arg), arg->size);
+    else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_listxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_getxattr_in *arg = (const struct fuse_getxattr_in *) inarg;
+
+    if (req->f->op.listxattr)
+        req->f->op.listxattr(req, nodeid, arg->size);
+    else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_removexattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const char *name = (const char *) inarg;
+
+    if (req->f->op.removexattr)
+        req->f->op.removexattr(req, nodeid, name);
+    else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void convert_fuse_file_lock(const struct fuse_file_lock *fl,
+                                   struct flock *flock)
+{
+    memset(flock, 0, sizeof(struct flock));
+    flock->l_type = fl->type;
+    flock->l_whence = SEEK_SET;
+    flock->l_start = fl->start;
+    if (fl->end == OFFSET_MAX)
+        flock->l_len = 0;
+    else
+        flock->l_len = fl->end - fl->start + 1;
+    flock->l_pid = fl->pid;
+}
+
+static void do_getlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_lk_in *arg = (const struct fuse_lk_in *) inarg;
+    struct fuse_file_info fi;
+    struct flock flock;
+
+    memset(&fi, 0, sizeof(fi));
+    fi.fh = arg->fh;
+    fi.lock_owner = arg->owner;
+
+    convert_fuse_file_lock(&arg->lk, &flock);
+    if (req->f->op.getlk)
+        req->f->op.getlk(req, nodeid, &fi, &flock);
+    else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_setlk_common(fuse_req_t req, fuse_ino_t nodeid,
+                            const void *inarg, int should_sleep)
+{
+    const struct fuse_lk_in *arg = (const struct fuse_lk_in *) inarg;
+    struct fuse_file_info fi;
+    struct flock flock;
+
+    memset(&fi, 0, sizeof(fi));
+    fi.fh = arg->fh;
+    fi.lock_owner = arg->owner;
+
+    convert_fuse_file_lock(&arg->lk, &flock);
+    if (req->f->op.setlk)
+        req->f->op.setlk(req, nodeid, &fi, &flock, should_sleep);
+    else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_setlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    do_setlk_common(req, nodeid, inarg, 0);
+}
+
+static void do_setlkw(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    do_setlk_common(req, nodeid, inarg, 1);
+}
+
+static int find_interrupted(struct fuse_ll *f, struct fuse_req *req)
+{
+    struct fuse_req *curr;
+
+    for (curr = f->list.next; curr != &f->list; curr = curr->next) {
+        if (curr->unique == req->u.i.unique) {
+            curr->ctr++;
+            pthread_mutex_unlock(&f->lock);
+
+            /* Ugh, ugly locking */
+            pthread_mutex_lock(&curr->lock);
+            pthread_mutex_lock(&f->lock);
+            curr->interrupted = 1;
+            pthread_mutex_unlock(&f->lock);
+            if (curr->u.ni.func)
+                curr->u.ni.func(curr, curr->u.ni.data);
+            pthread_mutex_unlock(&curr->lock);
+
+            pthread_mutex_lock(&f->lock);
+            curr->ctr--;
+            if (!curr->ctr)
+                destroy_req(curr);
+
+            return 1;
+        }
+    }
+    for (curr = f->interrupts.next; curr != &f->interrupts;
+         curr = curr->next) {
+        if (curr->u.i.unique == req->u.i.unique)
+            return 1;
+    }
+    return 0;
+}
+
+static void do_interrupt(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_interrupt_in *arg = (const struct fuse_interrupt_in *) inarg;
+    struct fuse_ll *f = req->f;
+
+    (void) nodeid;
+    if (f->debug)
+        fprintf(stderr, "INTERRUPT: %llu\n", (unsigned long long) arg->unique);
+
+    req->u.i.unique = arg->unique;
+
+    pthread_mutex_lock(&f->lock);
+    if (find_interrupted(f, req))
+        destroy_req(req);
+    else
+        list_add_req(req, &f->interrupts);
+    pthread_mutex_unlock(&f->lock);
+}
+
+static struct fuse_req *check_interrupt(struct fuse_ll *f, struct fuse_req *req)
+{
+    struct fuse_req *curr;
+
+    for (curr = f->interrupts.next; curr != &f->interrupts; curr = curr->next) {
+        if (curr->u.i.unique == req->unique) {
+            req->interrupted = 1;
+            list_del_req(curr);
+            free(curr);
+            return NULL;
+        }
+    }
+    curr = f->interrupts.next;
+    if (curr != &f->interrupts) {
+        list_del_req(curr);
+        list_init_req(curr);
+        return curr;
+    } else
+        return NULL;
+}
+
+static void do_bmap(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_bmap_in *arg = (const struct fuse_bmap_in *) inarg;
+
+    if (req->f->op.bmap)
+        req->f->op.bmap(req, nodeid, arg->blocksize, arg->block);
+    else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_ioctl(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_ioctl_in *arg = (const struct fuse_ioctl_in *) inarg;
+    unsigned int flags = arg->flags;
+    const void *in_buf = arg->in_size ? PARAM(arg) : NULL;
+    struct fuse_file_info fi;
+
+    if (flags & FUSE_IOCTL_DIR &&
+        !(req->f->conn.want & FUSE_CAP_IOCTL_DIR)) {
+    	fuse_reply_err(req, ENOTTY);
+    	return;
+    }
+
+    memset(&fi, 0, sizeof(fi));
+    fi.fh = arg->fh;
+
+/* TODO JPA (need req->ioctl_64bit in obscure fuse_req_t)
+// probably a 64 bit ioctl on a 32-bit cpu
+// this is to forward a request from the kernel
+    if (sizeof(void *) == 4 && req->f->conn.proto_minor >= 16 &&
+		!(flags & FUSE_IOCTL_32BIT)) {
+    	req->ioctl_64bit = 1;
+    }
+*/
+
+    if (req->f->op.ioctl)
+    	req->f->op.ioctl(req, nodeid, arg->cmd,
+    			 (void *)(uintptr_t)arg->arg, &fi, flags,
+    			 in_buf, arg->in_size, arg->out_size);
+    else
+    	fuse_reply_err(req, ENOSYS);
+}
+
+static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    const struct fuse_init_in *arg = (const struct fuse_init_in *) inarg;
+    struct fuse_init_out outarg;
+    struct fuse_ll *f = req->f;
+    size_t bufsize = fuse_chan_bufsize(req->ch);
+
+    (void) nodeid;
+    if (f->debug) {
+        fprintf(stderr, "INIT: %u.%u\n", arg->major, arg->minor);
+        if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {
+            fprintf(stderr, "flags=0x%08x\n", arg->flags);
+            fprintf(stderr, "max_readahead=0x%08x\n", arg->max_readahead);
+        }
+    }
+    f->conn.proto_major = arg->major;
+    f->conn.proto_minor = arg->minor;
+
+    if (arg->major < 7) {
+        fprintf(stderr, "fuse: unsupported protocol version: %u.%u\n",
+                arg->major, arg->minor);
+        fuse_reply_err(req, EPROTO);
+        return;
+    }
+
+    if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {
+        if (f->conn.async_read)
+            f->conn.async_read = arg->flags & FUSE_ASYNC_READ;
+        if (arg->max_readahead < f->conn.max_readahead)
+            f->conn.max_readahead = arg->max_readahead;
+#ifdef POSIXACLS
+	if (arg->flags & FUSE_DONT_MASK)
+	    f->conn.capable |= FUSE_CAP_DONT_MASK;
+#endif
+	if (arg->flags & FUSE_BIG_WRITES)
+	    f->conn.capable |= FUSE_CAP_BIG_WRITES;
+	if (arg->flags & FUSE_HAS_IOCTL_DIR)
+	    f->conn.capable |= FUSE_CAP_IOCTL_DIR;
+    } else {
+        f->conn.async_read = 0;
+        f->conn.max_readahead = 0;
+    }
+
+    if (bufsize < FUSE_MIN_READ_BUFFER) {
+        fprintf(stderr, "fuse: warning: buffer size too small: %zu\n",
+                bufsize);
+        bufsize = FUSE_MIN_READ_BUFFER;
+    }
+
+    bufsize -= 4096;
+    if (bufsize < f->conn.max_write)
+        f->conn.max_write = bufsize;
+
+    f->got_init = 1;
+    if (f->op.init)
+        f->op.init(f->userdata, &f->conn);
+
+    memset(&outarg, 0, sizeof(outarg));
+    outarg.major = FUSE_KERNEL_VERSION;
+	/*
+	 * Suggest using protocol 7.18 when available, and fallback
+	 * to 7.12 or even earlier when running on an old kernel.
+	 * Protocol 7.12 has the ability to process the umask
+	 * conditionnally (as needed if POSIXACLS is set)
+	 * Protocol 7.18 has the ability to process the ioctls
+	 */
+    if (arg->major > 7 || (arg->major == 7 && arg->minor >= 18)) {
+	    outarg.minor = FUSE_KERNEL_MINOR_VERSION;
+	    if (f->conn.want & FUSE_CAP_IOCTL_DIR)
+		outarg.flags |= FUSE_HAS_IOCTL_DIR;
+#ifdef POSIXACLS
+	    if (f->conn.want & FUSE_CAP_DONT_MASK)
+		outarg.flags |= FUSE_DONT_MASK;
+#endif
+    } else {
+	/* Never use a version more recent than supported by the kernel */
+	if ((arg->major < FUSE_KERNEL_MAJOR_FALLBACK)
+	    || ((arg->major == FUSE_KERNEL_MAJOR_FALLBACK)
+		&& (arg->minor < FUSE_KERNEL_MINOR_FALLBACK))) {
+	    outarg.major = arg->major;
+	    outarg.minor = arg->minor;
+	} else {
+	    outarg.major = FUSE_KERNEL_MAJOR_FALLBACK;
+	    outarg.minor = FUSE_KERNEL_MINOR_FALLBACK;
+#ifdef POSIXACLS
+	    if (f->conn.want & FUSE_CAP_DONT_MASK)
+		outarg.flags |= FUSE_DONT_MASK;
+#endif
+    	}
+    }
+    if (f->conn.async_read)
+        outarg.flags |= FUSE_ASYNC_READ;
+    if (f->op.getlk && f->op.setlk)
+        outarg.flags |= FUSE_POSIX_LOCKS;
+    if (f->conn.want & FUSE_CAP_BIG_WRITES)
+	outarg.flags |= FUSE_BIG_WRITES;
+    outarg.max_readahead = f->conn.max_readahead;
+    outarg.max_write = f->conn.max_write;
+
+    if (f->debug) {
+        fprintf(stderr, "   INIT: %u.%u\n", outarg.major, outarg.minor);
+        fprintf(stderr, "   flags=0x%08x\n", outarg.flags);
+        fprintf(stderr, "   max_readahead=0x%08x\n", outarg.max_readahead);
+        fprintf(stderr, "   max_write=0x%08x\n", outarg.max_write);
+    }
+
+    send_reply_ok(req, &outarg, arg->minor < 5 ? 8 : sizeof(outarg));
+}
+
+static void do_destroy(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+    struct fuse_ll *f = req->f;
+
+    (void) nodeid;
+    (void) inarg;
+
+    f->got_destroy = 1;
+    if (f->op.destroy)
+        f->op.destroy(f->userdata);
+
+    send_reply_ok(req, NULL, 0);
+}
+
+void *fuse_req_userdata(fuse_req_t req)
+{
+    return req->f->userdata;
+}
+
+const struct fuse_ctx *fuse_req_ctx(fuse_req_t req)
+{
+    return &req->ctx;
+}
+
+void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func,
+                             void *data)
+{
+    pthread_mutex_lock(&req->lock);
+    req->u.ni.func = func;
+    req->u.ni.data = data;
+    if (req->interrupted && func)
+        func(req, data);
+    pthread_mutex_unlock(&req->lock);
+}
+
+int fuse_req_interrupted(fuse_req_t req)
+{
+    int interrupted;
+
+    pthread_mutex_lock(&req->f->lock);
+    interrupted = req->interrupted;
+    pthread_mutex_unlock(&req->f->lock);
+
+    return interrupted;
+}
+
+static struct {
+    void (*func)(fuse_req_t, fuse_ino_t, const void *);
+    const char *name;
+} fuse_ll_ops[] = {
+    [FUSE_LOOKUP]      = { do_lookup,      "LOOKUP"      },
+    [FUSE_FORGET]      = { do_forget,      "FORGET"      },
+    [FUSE_GETATTR]     = { do_getattr,     "GETATTR"     },
+    [FUSE_SETATTR]     = { do_setattr,     "SETATTR"     },
+    [FUSE_READLINK]    = { do_readlink,    "READLINK"    },
+    [FUSE_SYMLINK]     = { do_symlink,     "SYMLINK"     },
+    [FUSE_MKNOD]       = { do_mknod,       "MKNOD"       },
+    [FUSE_MKDIR]       = { do_mkdir,       "MKDIR"       },
+    [FUSE_UNLINK]      = { do_unlink,      "UNLINK"      },
+    [FUSE_RMDIR]       = { do_rmdir,       "RMDIR"       },
+    [FUSE_RENAME]      = { do_rename,      "RENAME"      },
+    [FUSE_LINK]        = { do_link,        "LINK"        },
+    [FUSE_OPEN]        = { do_open,        "OPEN"        },
+    [FUSE_READ]        = { do_read,        "READ"        },
+    [FUSE_WRITE]       = { do_write,       "WRITE"       },
+    [FUSE_STATFS]      = { do_statfs,      "STATFS"      },
+    [FUSE_RELEASE]     = { do_release,     "RELEASE"     },
+    [FUSE_FSYNC]       = { do_fsync,       "FSYNC"       },
+    [FUSE_SETXATTR]    = { do_setxattr,    "SETXATTR"    },
+    [FUSE_GETXATTR]    = { do_getxattr,    "GETXATTR"    },
+    [FUSE_LISTXATTR]   = { do_listxattr,   "LISTXATTR"   },
+    [FUSE_REMOVEXATTR] = { do_removexattr, "REMOVEXATTR" },
+    [FUSE_FLUSH]       = { do_flush,       "FLUSH"       },
+    [FUSE_INIT]        = { do_init,        "INIT"        },
+    [FUSE_OPENDIR]     = { do_opendir,     "OPENDIR"     },
+    [FUSE_READDIR]     = { do_readdir,     "READDIR"     },
+    [FUSE_RELEASEDIR]  = { do_releasedir,  "RELEASEDIR"  },
+    [FUSE_FSYNCDIR]    = { do_fsyncdir,    "FSYNCDIR"    },
+    [FUSE_GETLK]       = { do_getlk,       "GETLK"       },
+    [FUSE_SETLK]       = { do_setlk,       "SETLK"       },
+    [FUSE_SETLKW]      = { do_setlkw,      "SETLKW"      },
+    [FUSE_ACCESS]      = { do_access,      "ACCESS"      },
+    [FUSE_CREATE]      = { do_create,      "CREATE"      },
+    [FUSE_INTERRUPT]   = { do_interrupt,   "INTERRUPT"   },
+    [FUSE_BMAP]        = { do_bmap,        "BMAP"        },
+    [FUSE_IOCTL]       = { do_ioctl,       "IOCTL"       },
+    [FUSE_DESTROY]     = { do_destroy,     "DESTROY"     },
+};
+
+#define FUSE_MAXOP (sizeof(fuse_ll_ops) / sizeof(fuse_ll_ops[0]))
+
+static const char *opname(enum fuse_opcode opcode)
+{
+    if (opcode >= FUSE_MAXOP || !fuse_ll_ops[opcode].name)
+        return "???";
+    else
+        return fuse_ll_ops[opcode].name;
+}
+
+static void fuse_ll_process(void *data, const char *buf, size_t len,
+                     struct fuse_chan *ch)
+{
+    struct fuse_ll *f = (struct fuse_ll *) data;
+    const struct fuse_in_header *in = (const struct fuse_in_header *) buf;
+    const void *inarg = buf + sizeof(struct fuse_in_header);
+    struct fuse_req *req;
+
+    if (f->debug)
+        fprintf(stderr, "unique: %llu, opcode: %s (%i), nodeid: %lu, insize: %zu\n",
+                (unsigned long long) in->unique,
+                opname((enum fuse_opcode) in->opcode), in->opcode,
+                (unsigned long) in->nodeid, len);
+
+    req = (struct fuse_req *) calloc(1, sizeof(struct fuse_req));
+    if (req == NULL) {
+        fprintf(stderr, "fuse: failed to allocate request\n");
+        return;
+    }
+
+    req->f = f;
+    req->unique = in->unique;
+    req->ctx.uid = in->uid;
+    req->ctx.gid = in->gid;
+    req->ctx.pid = in->pid;
+    req->ch = ch;
+    req->ctr = 1;
+    list_init_req(req);
+    fuse_mutex_init(&req->lock);
+
+    if (!f->got_init && in->opcode != FUSE_INIT)
+        fuse_reply_err(req, EIO);
+    else if (f->allow_root && in->uid != f->owner && in->uid != 0 &&
+             in->opcode != FUSE_INIT && in->opcode != FUSE_READ &&
+             in->opcode != FUSE_WRITE && in->opcode != FUSE_FSYNC &&
+             in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR &&
+             in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR) {
+        fuse_reply_err(req, EACCES);
+    } else if (in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func)
+        fuse_reply_err(req, ENOSYS);
+    else {
+        if (in->opcode != FUSE_INTERRUPT) {
+            struct fuse_req *intr;
+            pthread_mutex_lock(&f->lock);
+            intr = check_interrupt(f, req);
+            list_add_req(req, &f->list);
+            pthread_mutex_unlock(&f->lock);
+            if (intr)
+                fuse_reply_err(intr, EAGAIN);
+        }
+        fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg);
+    }
+}
+
+enum {
+    KEY_HELP,
+    KEY_VERSION,
+};
+
+static struct fuse_opt fuse_ll_opts[] = {
+    { "debug", offsetof(struct fuse_ll, debug), 1 },
+    { "-d", offsetof(struct fuse_ll, debug), 1 },
+    { "allow_root", offsetof(struct fuse_ll, allow_root), 1 },
+    { "max_write=%u", offsetof(struct fuse_ll, conn.max_write), 0 },
+    { "max_readahead=%u", offsetof(struct fuse_ll, conn.max_readahead), 0 },
+    { "async_read", offsetof(struct fuse_ll, conn.async_read), 1 },
+    { "sync_read", offsetof(struct fuse_ll, conn.async_read), 0 },
+    FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_DISCARD),
+    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
+};
+
+static void fuse_ll_version(void)
+{
+    fprintf(stderr, "using FUSE kernel interface version %i.%i\n",
+            FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
+}
+
+static void fuse_ll_help(void)
+{
+    fprintf(stderr,
+"    -o max_write=N         set maximum size of write requests\n"
+"    -o max_readahead=N     set maximum readahead\n"
+"    -o async_read          perform reads asynchronously (default)\n"
+"    -o sync_read           perform reads synchronously\n");
+}
+
+static int fuse_ll_opt_proc(void *data, const char *arg, int key,
+                            struct fuse_args *outargs)
+{
+    (void) data; (void) outargs;
+
+    switch (key) {
+    case KEY_HELP:
+        fuse_ll_help();
+        break;
+
+    case KEY_VERSION:
+        fuse_ll_version();
+        break;
+
+    default:
+        fprintf(stderr, "fuse: unknown option `%s'\n", arg);
+    }
+
+    return -1;
+}
+
+#ifdef __SOLARIS__
+
+int fuse_lowlevel_is_lib_option(const char *opt)
+{
+    return fuse_opt_match(fuse_ll_opts, opt);
+}
+
+#endif /* __SOLARIS__ */
+
+static void fuse_ll_destroy(void *data)
+{
+    struct fuse_ll *f = (struct fuse_ll *) data;
+
+    if (f->got_init && !f->got_destroy) {
+        if (f->op.destroy)
+            f->op.destroy(f->userdata);
+    }
+
+    pthread_mutex_destroy(&f->lock);
+    free(f);
+}
+
+struct fuse_session *fuse_lowlevel_new(struct fuse_args *args,
+				       const struct fuse_lowlevel_ops *op,
+                                       size_t op_size, void *userdata)
+{
+    struct fuse_ll *f;
+    struct fuse_session *se;
+    struct fuse_session_ops sop = {
+        .process = fuse_ll_process,
+        .destroy = fuse_ll_destroy,
+    };
+
+    if (sizeof(struct fuse_lowlevel_ops) < op_size) {
+        fprintf(stderr, "fuse: warning: library too old, some operations may not work\n");
+        op_size = sizeof(struct fuse_lowlevel_ops);
+    }
+
+    f = (struct fuse_ll *) calloc(1, sizeof(struct fuse_ll));
+    if (f == NULL) {
+        fprintf(stderr, "fuse: failed to allocate fuse object\n");
+        goto out;
+    }
+
+    f->conn.async_read = 1;
+    f->conn.max_write = UINT_MAX;
+    f->conn.max_readahead = UINT_MAX;
+    list_init_req(&f->list);
+    list_init_req(&f->interrupts);
+    fuse_mutex_init(&f->lock);
+
+    if (fuse_opt_parse(args, f, fuse_ll_opts, fuse_ll_opt_proc) == -1)
+        goto out_free;
+
+    memcpy(&f->op, op, op_size);
+    f->owner = getuid();
+    f->userdata = userdata;
+
+    se = fuse_session_new(&sop, f);
+    if (!se)
+        goto out_free;
+
+    return se;
+
+ out_free:
+    free(f);
+ out:
+    return NULL;
+}
diff --git a/libfuse-lite/fuse_misc.h b/libfuse-lite/fuse_misc.h
new file mode 100755
index 0000000000000000000000000000000000000000..86309896fd88ac72e882218b0eaad45f396488d5
--- /dev/null
+++ b/libfuse-lite/fuse_misc.h
@@ -0,0 +1,51 @@
+/*
+    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
diff --git a/libfuse-lite/fuse_opt.c b/libfuse-lite/fuse_opt.c
new file mode 100755
index 0000000000000000000000000000000000000000..80b07774812126be6259f71b97b4e43b4ca9977d
--- /dev/null
+++ b/libfuse-lite/fuse_opt.c
@@ -0,0 +1,382 @@
+/*
+    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;
+}
diff --git a/libfuse-lite/fuse_session.c b/libfuse-lite/fuse_session.c
new file mode 100755
index 0000000000000000000000000000000000000000..3773303a55ff379aa5dc131bdf52e68e519e4d20
--- /dev/null
+++ b/libfuse-lite/fuse_session.c
@@ -0,0 +1,193 @@
+/*
+    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);
+}
diff --git a/libfuse-lite/fuse_signals.c b/libfuse-lite/fuse_signals.c
new file mode 100755
index 0000000000000000000000000000000000000000..bf979563268b7dde9d2acaae597697718d0fd674
--- /dev/null
+++ b/libfuse-lite/fuse_signals.c
@@ -0,0 +1,73 @@
+/*
+    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))
+{
+    struct sigaction sa;
+    struct sigaction old_sa;
+
+    memset(&sa, 0, sizeof(struct sigaction));
+    sa.sa_handler = 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 == 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) == -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)
+        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, SIG_DFL);
+    set_one_signal_handler(SIGINT, SIG_DFL);
+    set_one_signal_handler(SIGTERM, SIG_DFL);
+    set_one_signal_handler(SIGPIPE, SIG_DFL);
+}
+
diff --git a/libfuse-lite/fusermount.c b/libfuse-lite/fusermount.c
new file mode 100755
index 0000000000000000000000000000000000000000..c94d5838bec2c5c2ffc3ba674d0c5745182db430
--- /dev/null
+++ b/libfuse-lite/fusermount.c
@@ -0,0 +1,709 @@
+/*
+    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>
+
+#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);
+
+    char * rchr = strchr(source, '@');
+    if (rchr) {
+         rchr[0] = ',';
+    }
+
+    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__ */
diff --git a/libfuse-lite/helper.c b/libfuse-lite/helper.c
new file mode 100755
index 0000000000000000000000000000000000000000..ebd7d77ec6b2778bfeca2af2eb49094af4495123
--- /dev/null
+++ b/libfuse-lite/helper.c
@@ -0,0 +1,61 @@
+/*
+    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__ */
diff --git a/libfuse-lite/mount.c b/libfuse-lite/mount.c
new file mode 100755
index 0000000000000000000000000000000000000000..70454f4e3783555e4c713582e6275a53ed238f2f
--- /dev/null
+++ b/libfuse-lite/mount.c
@@ -0,0 +1,732 @@
+/*
+    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;
+    }
+#ifndef __SOLARIS__
+    close(fd);
+
+    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 = 0;
+    if (mo.ishelp)
+        goto out;
+
+    res = -1;
+    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;
+}
diff --git a/libfuse-lite/mount_util.c b/libfuse-lite/mount_util.c
new file mode 100755
index 0000000000000000000000000000000000000000..1a7ac3c7d1284ee242d7456632d9bedefc416d65
--- /dev/null
+++ b/libfuse-lite/mount_util.c
@@ -0,0 +1,459 @@
+/*
+    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 <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 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);
+        execl("/sbin/mount", "/sbin/mount", "-F", type, "-o", opts,
+              fsname, mnt, NULL);
+        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) {
+        setuid(geteuid());
+        execl("/sbin/umount", "/sbin/umount", !lazy ? "-f" : NULL, mnt,
+              NULL);
+        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 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);
+        execl("/bin/mount", "/bin/mount", "-i", "-f", "-t", type, "-o", opts,
+              fsname, mnt, NULL);
+        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) {
+        if (setuid(geteuid()))
+            fprintf(stderr, "%s: failed to setuid : %s\n", progname,
+                         strerror(errno));
+        execl("/bin/umount", "/bin/umount", "-i", mnt, lazy ? "-l" : NULL,
+              NULL);
+        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__ */
diff --git a/libfuse-lite/mount_util.h b/libfuse-lite/mount_util.h
new file mode 100755
index 0000000000000000000000000000000000000000..0318385f9b78aa252d3dc6e4060db3f8d4a1d34d
--- /dev/null
+++ b/libfuse-lite/mount_util.h
@@ -0,0 +1,27 @@
+/*
+    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__ */
diff --git a/libntfs-3g/Android.mk b/libntfs-3g/Android.mk
new file mode 100755
index 0000000000000000000000000000000000000000..c9962dd4f1953fc3cba4381cc806cc76c3817696
--- /dev/null
+++ b/libntfs-3g/Android.mk
@@ -0,0 +1,57 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+	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 \
+	ioctl.c \
+	index.c \
+	inode.c \
+	lcnalloc.c \
+	logfile.c \
+	logging.c \
+	mft.c \
+	misc.c \
+	mst.c \
+	object_id.c \
+	reparse.c \
+	runlist.c \
+	realpath.c \
+	security.c \
+	unistr.c \
+	volume.c \
+	xattrs.c \
+	unix_io.c
+
+LOCAL_MODULE := libntfs-3g
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := \
+	libc \
+	libutils	\
+	liblog 
+
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH)/.. \
+	$(LOCAL_PATH)/../src \
+	$(LOCAL_PATH)/../include/ntfs-3g
+
+LOCAL_CFLAGS := -O2 -g -W -Wall \
+	-DHAVE_CONFIG_H \
+        -DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION)
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/libntfs-3g/Makefile.am b/libntfs-3g/Makefile.am
new file mode 100755
index 0000000000000000000000000000000000000000..d6b150e59bc58cb17ac04b9914566bba9a76ce2b
--- /dev/null
+++ b/libntfs-3g/Makefile.am
@@ -0,0 +1,84 @@
+
+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) -I$(top_srcdir)/include/ntfs-3g
+libntfs_3g_la_CPPFLAGS= $(AM_CPPFLAGS) $(LIBNTFS_CPPFLAGS)
+libntfs_3g_la_LIBADD  = $(LIBNTFS_LIBS)
+libntfs_3g_la_LDFLAGS = -version-info $(LIBNTFS_3G_VERSION) -no-undefined
+
+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
+
+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
+
+# 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
+
+uninstall-local:
+if INSTALL_LIBRARY
+	$(RM) -f "$(DESTDIR)/$(rootlibdir)"/libntfs-3g.so*
+endif
+
+if ENABLE_NTFSPROGS
+libs:	$(lib_LTLIBRARIES)
+endif
+
diff --git a/libntfs-3g/Makefile.in b/libntfs-3g/Makefile.in
new file mode 100755
index 0000000000000000000000000000000000000000..1ae6bca41388cf87530dfd2f148a4ad74a335f03
--- /dev/null
+++ b/libntfs-3g/Makefile.in
@@ -0,0 +1,1069 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@NTFS_DEVICE_DEFAULT_IO_OPS_TRUE@@WINDOWS_TRUE@am__append_1 = win32_io.c
+@NTFS_DEVICE_DEFAULT_IO_OPS_TRUE@@WINDOWS_FALSE@am__append_2 = unix_io.c
+subdir = libntfs-3g
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+	$(srcdir)/libntfs-3g.pc.in $(srcdir)/libntfs-3g.script.so.in \
+	$(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = libntfs-3g.pc libntfs-3g.script.so
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(rootlibdir)" \
+	"$(DESTDIR)$(pkgconfigdir)"
+LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) \
+	$(rootlib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libntfs_3g_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am__libntfs_3g_la_SOURCES_DIST = 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 \
+	win32_io.c unix_io.c
+@NTFS_DEVICE_DEFAULT_IO_OPS_TRUE@@WINDOWS_TRUE@am__objects_1 = libntfs_3g_la-win32_io.lo
+@NTFS_DEVICE_DEFAULT_IO_OPS_TRUE@@WINDOWS_FALSE@am__objects_2 = libntfs_3g_la-unix_io.lo
+am_libntfs_3g_la_OBJECTS = libntfs_3g_la-acls.lo \
+	libntfs_3g_la-attrib.lo libntfs_3g_la-attrlist.lo \
+	libntfs_3g_la-bitmap.lo libntfs_3g_la-bootsect.lo \
+	libntfs_3g_la-cache.lo libntfs_3g_la-collate.lo \
+	libntfs_3g_la-compat.lo libntfs_3g_la-compress.lo \
+	libntfs_3g_la-debug.lo libntfs_3g_la-device.lo \
+	libntfs_3g_la-dir.lo libntfs_3g_la-ea.lo libntfs_3g_la-efs.lo \
+	libntfs_3g_la-index.lo libntfs_3g_la-inode.lo \
+	libntfs_3g_la-ioctl.lo libntfs_3g_la-lcnalloc.lo \
+	libntfs_3g_la-logfile.lo libntfs_3g_la-logging.lo \
+	libntfs_3g_la-mft.lo libntfs_3g_la-misc.lo \
+	libntfs_3g_la-mst.lo libntfs_3g_la-object_id.lo \
+	libntfs_3g_la-realpath.lo libntfs_3g_la-reparse.lo \
+	libntfs_3g_la-runlist.lo libntfs_3g_la-security.lo \
+	libntfs_3g_la-unistr.lo libntfs_3g_la-volume.lo \
+	libntfs_3g_la-xattrs.lo $(am__objects_1) $(am__objects_2)
+libntfs_3g_la_OBJECTS = $(am_libntfs_3g_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
+libntfs_3g_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(libntfs_3g_la_CFLAGS) \
+	$(CFLAGS) $(libntfs_3g_la_LDFLAGS) $(LDFLAGS) -o $@
+@INSTALL_LIBRARY_FALSE@am_libntfs_3g_la_rpath =
+@INSTALL_LIBRARY_TRUE@am_libntfs_3g_la_rpath = -rpath $(libdir)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
+SOURCES = $(libntfs_3g_la_SOURCES)
+DIST_SOURCES = $(am__libntfs_3g_la_SOURCES_DIST)
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+DATA = $(pkgconfig_DATA)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FUSE_MODULE_CFLAGS = @FUSE_MODULE_CFLAGS@
+FUSE_MODULE_LIBS = @FUSE_MODULE_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDCONFIG = @LDCONFIG@
+LDFLAGS = @LDFLAGS@
+LIBFUSE_LITE_CFLAGS = @LIBFUSE_LITE_CFLAGS@
+LIBFUSE_LITE_LIBS = @LIBFUSE_LITE_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBNTFS_3G_VERSION = @LIBNTFS_3G_VERSION@
+LIBNTFS_CPPFLAGS = @LIBNTFS_CPPFLAGS@
+LIBNTFS_LIBS = @LIBNTFS_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MKNTFS_CPPFLAGS = @MKNTFS_CPPFLAGS@
+MKNTFS_LIBS = @MKNTFS_LIBS@
+MV = @MV@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NTFSPROGS_STATIC_LIBS = @NTFSPROGS_STATIC_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+OUTPUT_FORMAT = @OUTPUT_FORMAT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+RM = @RM@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+all_includes = @all_includes@
+all_libraries = @all_libraries@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+ntfs3gincludedir = @ntfs3gincludedir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgconfigdir = @pkgconfigdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+rootbindir = @rootbindir@
+rootlibdir = @rootlibdir@
+rootsbindir = @rootsbindir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+@INSTALL_LIBRARY_TRUE@rootlib_LTLIBRARIES = #Create directory
+@INSTALL_LIBRARY_TRUE@lib_LTLIBRARIES = libntfs-3g.la
+@INSTALL_LIBRARY_TRUE@pkgconfig_DATA = libntfs-3g.pc
+@INSTALL_LIBRARY_FALSE@noinst_LTLIBRARIES = libntfs-3g.la
+libntfs_3g_la_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/include/ntfs-3g
+libntfs_3g_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBNTFS_CPPFLAGS)
+libntfs_3g_la_LIBADD = $(LIBNTFS_LIBS)
+libntfs_3g_la_LDFLAGS = -version-info $(LIBNTFS_3G_VERSION) -no-undefined
+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 \
+	$(am__append_1) $(am__append_2)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libntfs-3g/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu libntfs-3g/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+libntfs-3g.pc: $(top_builddir)/config.status $(srcdir)/libntfs-3g.pc.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+libntfs-3g.script.so: $(top_builddir)/config.status $(srcdir)/libntfs-3g.script.so.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+	list2=; for p in $$list; do \
+	  if test -f $$p; then \
+	    list2="$$list2 $$p"; \
+	  else :; fi; \
+	done; \
+	test -z "$$list2" || { \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+	}
+
+uninstall-libLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+	for p in $$list; do \
+	  $(am__strip_dir) \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+	done
+
+clean-libLTLIBRARIES:
+	-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+	@list='$(lib_LTLIBRARIES)'; \
+	locs=`for p in $$list; do echo $$p; done | \
+	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+	      sort -u`; \
+	test -z "$$locs" || { \
+	  echo rm -f $${locs}; \
+	  rm -f $${locs}; \
+	}
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; \
+	locs=`for p in $$list; do echo $$p; done | \
+	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+	      sort -u`; \
+	test -z "$$locs" || { \
+	  echo rm -f $${locs}; \
+	  rm -f $${locs}; \
+	}
+
+install-rootlibLTLIBRARIES: $(rootlib_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	@list='$(rootlib_LTLIBRARIES)'; test -n "$(rootlibdir)" || list=; \
+	list2=; for p in $$list; do \
+	  if test -f $$p; then \
+	    list2="$$list2 $$p"; \
+	  else :; fi; \
+	done; \
+	test -z "$$list2" || { \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(rootlibdir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(rootlibdir)" || exit 1; \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(rootlibdir)'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(rootlibdir)"; \
+	}
+
+uninstall-rootlibLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(rootlib_LTLIBRARIES)'; test -n "$(rootlibdir)" || list=; \
+	for p in $$list; do \
+	  $(am__strip_dir) \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(rootlibdir)/$$f'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(rootlibdir)/$$f"; \
+	done
+
+clean-rootlibLTLIBRARIES:
+	-test -z "$(rootlib_LTLIBRARIES)" || rm -f $(rootlib_LTLIBRARIES)
+	@list='$(rootlib_LTLIBRARIES)'; \
+	locs=`for p in $$list; do echo $$p; done | \
+	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+	      sort -u`; \
+	test -z "$$locs" || { \
+	  echo rm -f $${locs}; \
+	  rm -f $${locs}; \
+	}
+
+libntfs-3g.la: $(libntfs_3g_la_OBJECTS) $(libntfs_3g_la_DEPENDENCIES) $(EXTRA_libntfs_3g_la_DEPENDENCIES) 
+	$(AM_V_CCLD)$(libntfs_3g_la_LINK) $(am_libntfs_3g_la_rpath) $(libntfs_3g_la_OBJECTS) $(libntfs_3g_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-acls.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-attrib.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-attrlist.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-bitmap.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-bootsect.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-cache.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-collate.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-compat.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-compress.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-debug.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-device.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-dir.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-ea.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-efs.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-index.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-inode.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-ioctl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-lcnalloc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-logfile.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-logging.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-mft.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-misc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-mst.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-object_id.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-realpath.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-reparse.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-runlist.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-security.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-unistr.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-unix_io.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-volume.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-win32_io.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-xattrs.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+libntfs_3g_la-acls.lo: acls.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-acls.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-acls.Tpo -c -o libntfs_3g_la-acls.lo `test -f 'acls.c' || echo '$(srcdir)/'`acls.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-acls.Tpo $(DEPDIR)/libntfs_3g_la-acls.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='acls.c' object='libntfs_3g_la-acls.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-acls.lo `test -f 'acls.c' || echo '$(srcdir)/'`acls.c
+
+libntfs_3g_la-attrib.lo: attrib.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-attrib.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-attrib.Tpo -c -o libntfs_3g_la-attrib.lo `test -f 'attrib.c' || echo '$(srcdir)/'`attrib.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-attrib.Tpo $(DEPDIR)/libntfs_3g_la-attrib.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='attrib.c' object='libntfs_3g_la-attrib.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-attrib.lo `test -f 'attrib.c' || echo '$(srcdir)/'`attrib.c
+
+libntfs_3g_la-attrlist.lo: attrlist.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-attrlist.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-attrlist.Tpo -c -o libntfs_3g_la-attrlist.lo `test -f 'attrlist.c' || echo '$(srcdir)/'`attrlist.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-attrlist.Tpo $(DEPDIR)/libntfs_3g_la-attrlist.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='attrlist.c' object='libntfs_3g_la-attrlist.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-attrlist.lo `test -f 'attrlist.c' || echo '$(srcdir)/'`attrlist.c
+
+libntfs_3g_la-bitmap.lo: bitmap.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-bitmap.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-bitmap.Tpo -c -o libntfs_3g_la-bitmap.lo `test -f 'bitmap.c' || echo '$(srcdir)/'`bitmap.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-bitmap.Tpo $(DEPDIR)/libntfs_3g_la-bitmap.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='bitmap.c' object='libntfs_3g_la-bitmap.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-bitmap.lo `test -f 'bitmap.c' || echo '$(srcdir)/'`bitmap.c
+
+libntfs_3g_la-bootsect.lo: bootsect.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-bootsect.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-bootsect.Tpo -c -o libntfs_3g_la-bootsect.lo `test -f 'bootsect.c' || echo '$(srcdir)/'`bootsect.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-bootsect.Tpo $(DEPDIR)/libntfs_3g_la-bootsect.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='bootsect.c' object='libntfs_3g_la-bootsect.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-bootsect.lo `test -f 'bootsect.c' || echo '$(srcdir)/'`bootsect.c
+
+libntfs_3g_la-cache.lo: cache.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-cache.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-cache.Tpo -c -o libntfs_3g_la-cache.lo `test -f 'cache.c' || echo '$(srcdir)/'`cache.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-cache.Tpo $(DEPDIR)/libntfs_3g_la-cache.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='cache.c' object='libntfs_3g_la-cache.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-cache.lo `test -f 'cache.c' || echo '$(srcdir)/'`cache.c
+
+libntfs_3g_la-collate.lo: collate.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-collate.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-collate.Tpo -c -o libntfs_3g_la-collate.lo `test -f 'collate.c' || echo '$(srcdir)/'`collate.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-collate.Tpo $(DEPDIR)/libntfs_3g_la-collate.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='collate.c' object='libntfs_3g_la-collate.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-collate.lo `test -f 'collate.c' || echo '$(srcdir)/'`collate.c
+
+libntfs_3g_la-compat.lo: compat.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-compat.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-compat.Tpo -c -o libntfs_3g_la-compat.lo `test -f 'compat.c' || echo '$(srcdir)/'`compat.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-compat.Tpo $(DEPDIR)/libntfs_3g_la-compat.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='compat.c' object='libntfs_3g_la-compat.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-compat.lo `test -f 'compat.c' || echo '$(srcdir)/'`compat.c
+
+libntfs_3g_la-compress.lo: compress.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-compress.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-compress.Tpo -c -o libntfs_3g_la-compress.lo `test -f 'compress.c' || echo '$(srcdir)/'`compress.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-compress.Tpo $(DEPDIR)/libntfs_3g_la-compress.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='compress.c' object='libntfs_3g_la-compress.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-compress.lo `test -f 'compress.c' || echo '$(srcdir)/'`compress.c
+
+libntfs_3g_la-debug.lo: debug.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-debug.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-debug.Tpo -c -o libntfs_3g_la-debug.lo `test -f 'debug.c' || echo '$(srcdir)/'`debug.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-debug.Tpo $(DEPDIR)/libntfs_3g_la-debug.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='debug.c' object='libntfs_3g_la-debug.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-debug.lo `test -f 'debug.c' || echo '$(srcdir)/'`debug.c
+
+libntfs_3g_la-device.lo: device.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-device.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-device.Tpo -c -o libntfs_3g_la-device.lo `test -f 'device.c' || echo '$(srcdir)/'`device.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-device.Tpo $(DEPDIR)/libntfs_3g_la-device.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='device.c' object='libntfs_3g_la-device.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-device.lo `test -f 'device.c' || echo '$(srcdir)/'`device.c
+
+libntfs_3g_la-dir.lo: dir.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-dir.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-dir.Tpo -c -o libntfs_3g_la-dir.lo `test -f 'dir.c' || echo '$(srcdir)/'`dir.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-dir.Tpo $(DEPDIR)/libntfs_3g_la-dir.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='dir.c' object='libntfs_3g_la-dir.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-dir.lo `test -f 'dir.c' || echo '$(srcdir)/'`dir.c
+
+libntfs_3g_la-ea.lo: ea.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-ea.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-ea.Tpo -c -o libntfs_3g_la-ea.lo `test -f 'ea.c' || echo '$(srcdir)/'`ea.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-ea.Tpo $(DEPDIR)/libntfs_3g_la-ea.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ea.c' object='libntfs_3g_la-ea.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-ea.lo `test -f 'ea.c' || echo '$(srcdir)/'`ea.c
+
+libntfs_3g_la-efs.lo: efs.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-efs.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-efs.Tpo -c -o libntfs_3g_la-efs.lo `test -f 'efs.c' || echo '$(srcdir)/'`efs.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-efs.Tpo $(DEPDIR)/libntfs_3g_la-efs.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='efs.c' object='libntfs_3g_la-efs.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-efs.lo `test -f 'efs.c' || echo '$(srcdir)/'`efs.c
+
+libntfs_3g_la-index.lo: index.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-index.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-index.Tpo -c -o libntfs_3g_la-index.lo `test -f 'index.c' || echo '$(srcdir)/'`index.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-index.Tpo $(DEPDIR)/libntfs_3g_la-index.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='index.c' object='libntfs_3g_la-index.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-index.lo `test -f 'index.c' || echo '$(srcdir)/'`index.c
+
+libntfs_3g_la-inode.lo: inode.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-inode.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-inode.Tpo -c -o libntfs_3g_la-inode.lo `test -f 'inode.c' || echo '$(srcdir)/'`inode.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-inode.Tpo $(DEPDIR)/libntfs_3g_la-inode.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='inode.c' object='libntfs_3g_la-inode.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-inode.lo `test -f 'inode.c' || echo '$(srcdir)/'`inode.c
+
+libntfs_3g_la-ioctl.lo: ioctl.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-ioctl.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-ioctl.Tpo -c -o libntfs_3g_la-ioctl.lo `test -f 'ioctl.c' || echo '$(srcdir)/'`ioctl.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-ioctl.Tpo $(DEPDIR)/libntfs_3g_la-ioctl.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ioctl.c' object='libntfs_3g_la-ioctl.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-ioctl.lo `test -f 'ioctl.c' || echo '$(srcdir)/'`ioctl.c
+
+libntfs_3g_la-lcnalloc.lo: lcnalloc.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-lcnalloc.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-lcnalloc.Tpo -c -o libntfs_3g_la-lcnalloc.lo `test -f 'lcnalloc.c' || echo '$(srcdir)/'`lcnalloc.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-lcnalloc.Tpo $(DEPDIR)/libntfs_3g_la-lcnalloc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lcnalloc.c' object='libntfs_3g_la-lcnalloc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-lcnalloc.lo `test -f 'lcnalloc.c' || echo '$(srcdir)/'`lcnalloc.c
+
+libntfs_3g_la-logfile.lo: logfile.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-logfile.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-logfile.Tpo -c -o libntfs_3g_la-logfile.lo `test -f 'logfile.c' || echo '$(srcdir)/'`logfile.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-logfile.Tpo $(DEPDIR)/libntfs_3g_la-logfile.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='logfile.c' object='libntfs_3g_la-logfile.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-logfile.lo `test -f 'logfile.c' || echo '$(srcdir)/'`logfile.c
+
+libntfs_3g_la-logging.lo: logging.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-logging.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-logging.Tpo -c -o libntfs_3g_la-logging.lo `test -f 'logging.c' || echo '$(srcdir)/'`logging.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-logging.Tpo $(DEPDIR)/libntfs_3g_la-logging.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='logging.c' object='libntfs_3g_la-logging.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-logging.lo `test -f 'logging.c' || echo '$(srcdir)/'`logging.c
+
+libntfs_3g_la-mft.lo: mft.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-mft.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-mft.Tpo -c -o libntfs_3g_la-mft.lo `test -f 'mft.c' || echo '$(srcdir)/'`mft.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-mft.Tpo $(DEPDIR)/libntfs_3g_la-mft.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='mft.c' object='libntfs_3g_la-mft.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-mft.lo `test -f 'mft.c' || echo '$(srcdir)/'`mft.c
+
+libntfs_3g_la-misc.lo: misc.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-misc.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-misc.Tpo -c -o libntfs_3g_la-misc.lo `test -f 'misc.c' || echo '$(srcdir)/'`misc.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-misc.Tpo $(DEPDIR)/libntfs_3g_la-misc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='misc.c' object='libntfs_3g_la-misc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-misc.lo `test -f 'misc.c' || echo '$(srcdir)/'`misc.c
+
+libntfs_3g_la-mst.lo: mst.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-mst.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-mst.Tpo -c -o libntfs_3g_la-mst.lo `test -f 'mst.c' || echo '$(srcdir)/'`mst.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-mst.Tpo $(DEPDIR)/libntfs_3g_la-mst.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='mst.c' object='libntfs_3g_la-mst.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-mst.lo `test -f 'mst.c' || echo '$(srcdir)/'`mst.c
+
+libntfs_3g_la-object_id.lo: object_id.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-object_id.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-object_id.Tpo -c -o libntfs_3g_la-object_id.lo `test -f 'object_id.c' || echo '$(srcdir)/'`object_id.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-object_id.Tpo $(DEPDIR)/libntfs_3g_la-object_id.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='object_id.c' object='libntfs_3g_la-object_id.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-object_id.lo `test -f 'object_id.c' || echo '$(srcdir)/'`object_id.c
+
+libntfs_3g_la-realpath.lo: realpath.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-realpath.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-realpath.Tpo -c -o libntfs_3g_la-realpath.lo `test -f 'realpath.c' || echo '$(srcdir)/'`realpath.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-realpath.Tpo $(DEPDIR)/libntfs_3g_la-realpath.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='realpath.c' object='libntfs_3g_la-realpath.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-realpath.lo `test -f 'realpath.c' || echo '$(srcdir)/'`realpath.c
+
+libntfs_3g_la-reparse.lo: reparse.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-reparse.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-reparse.Tpo -c -o libntfs_3g_la-reparse.lo `test -f 'reparse.c' || echo '$(srcdir)/'`reparse.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-reparse.Tpo $(DEPDIR)/libntfs_3g_la-reparse.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='reparse.c' object='libntfs_3g_la-reparse.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-reparse.lo `test -f 'reparse.c' || echo '$(srcdir)/'`reparse.c
+
+libntfs_3g_la-runlist.lo: runlist.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-runlist.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-runlist.Tpo -c -o libntfs_3g_la-runlist.lo `test -f 'runlist.c' || echo '$(srcdir)/'`runlist.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-runlist.Tpo $(DEPDIR)/libntfs_3g_la-runlist.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='runlist.c' object='libntfs_3g_la-runlist.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-runlist.lo `test -f 'runlist.c' || echo '$(srcdir)/'`runlist.c
+
+libntfs_3g_la-security.lo: security.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-security.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-security.Tpo -c -o libntfs_3g_la-security.lo `test -f 'security.c' || echo '$(srcdir)/'`security.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-security.Tpo $(DEPDIR)/libntfs_3g_la-security.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='security.c' object='libntfs_3g_la-security.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-security.lo `test -f 'security.c' || echo '$(srcdir)/'`security.c
+
+libntfs_3g_la-unistr.lo: unistr.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-unistr.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-unistr.Tpo -c -o libntfs_3g_la-unistr.lo `test -f 'unistr.c' || echo '$(srcdir)/'`unistr.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-unistr.Tpo $(DEPDIR)/libntfs_3g_la-unistr.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='unistr.c' object='libntfs_3g_la-unistr.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-unistr.lo `test -f 'unistr.c' || echo '$(srcdir)/'`unistr.c
+
+libntfs_3g_la-volume.lo: volume.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-volume.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-volume.Tpo -c -o libntfs_3g_la-volume.lo `test -f 'volume.c' || echo '$(srcdir)/'`volume.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-volume.Tpo $(DEPDIR)/libntfs_3g_la-volume.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='volume.c' object='libntfs_3g_la-volume.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-volume.lo `test -f 'volume.c' || echo '$(srcdir)/'`volume.c
+
+libntfs_3g_la-xattrs.lo: xattrs.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-xattrs.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-xattrs.Tpo -c -o libntfs_3g_la-xattrs.lo `test -f 'xattrs.c' || echo '$(srcdir)/'`xattrs.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-xattrs.Tpo $(DEPDIR)/libntfs_3g_la-xattrs.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='xattrs.c' object='libntfs_3g_la-xattrs.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-xattrs.lo `test -f 'xattrs.c' || echo '$(srcdir)/'`xattrs.c
+
+libntfs_3g_la-win32_io.lo: win32_io.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-win32_io.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-win32_io.Tpo -c -o libntfs_3g_la-win32_io.lo `test -f 'win32_io.c' || echo '$(srcdir)/'`win32_io.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-win32_io.Tpo $(DEPDIR)/libntfs_3g_la-win32_io.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='win32_io.c' object='libntfs_3g_la-win32_io.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-win32_io.lo `test -f 'win32_io.c' || echo '$(srcdir)/'`win32_io.c
+
+libntfs_3g_la-unix_io.lo: unix_io.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-unix_io.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-unix_io.Tpo -c -o libntfs_3g_la-unix_io.lo `test -f 'unix_io.c' || echo '$(srcdir)/'`unix_io.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libntfs_3g_la-unix_io.Tpo $(DEPDIR)/libntfs_3g_la-unix_io.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='unix_io.c' object='libntfs_3g_la-unix_io.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libntfs_3g_la_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-unix_io.lo `test -f 'unix_io.c' || echo '$(srcdir)/'`unix_io.c
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+install-pkgconfigDATA: $(pkgconfig_DATA)
+	@$(NORMAL_INSTALL)
+	@list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \
+	fi; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \
+	done
+
+uninstall-pkgconfigDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir)
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(DATA)
+installdirs:
+	for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(rootlibdir)" "$(DESTDIR)$(pkgconfigdir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+	clean-noinstLTLIBRARIES clean-rootlibLTLIBRARIES \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pkgconfigDATA install-rootlibLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+	@$(NORMAL_INSTALL)
+	$(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES uninstall-local \
+	uninstall-pkgconfigDATA uninstall-rootlibLTLIBRARIES
+
+.MAKE: install-am install-exec-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+	clean-libLTLIBRARIES clean-libtool clean-noinstLTLIBRARIES \
+	clean-rootlibLTLIBRARIES cscopelist-am ctags ctags-am \
+	distclean distclean-compile distclean-generic \
+	distclean-libtool distclean-tags distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-dvi install-dvi-am install-exec \
+	install-exec-am install-exec-hook install-html install-html-am \
+	install-info install-info-am install-libLTLIBRARIES \
+	install-man install-pdf install-pdf-am install-pkgconfigDATA \
+	install-ps install-ps-am install-rootlibLTLIBRARIES \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \
+	uninstall-libLTLIBRARIES uninstall-local \
+	uninstall-pkgconfigDATA uninstall-rootlibLTLIBRARIES
+
+
+# We may need to move .so files to root
+# And create ldscript or symbolic link from /usr
+install-exec-hook: install-rootlibLTLIBRARIES
+@INSTALL_LIBRARY_TRUE@	if [ ! "$(rootlibdir)" -ef "$(libdir)" ]; then \
+@INSTALL_LIBRARY_TRUE@		$(MV) -f "$(DESTDIR)/$(libdir)"/libntfs-3g.so* "$(DESTDIR)/$(rootlibdir)";  \
+@INSTALL_LIBRARY_TRUE@	fi
+@GENERATE_LDSCRIPT_TRUE@@INSTALL_LIBRARY_TRUE@	if [ ! "$(rootlibdir)" -ef "$(libdir)" ]; then \
+@GENERATE_LDSCRIPT_TRUE@@INSTALL_LIBRARY_TRUE@		$(install_sh_PROGRAM) "libntfs-3g.script.so" "$(DESTDIR)/$(libdir)/libntfs-3g.so"; \
+@GENERATE_LDSCRIPT_TRUE@@INSTALL_LIBRARY_TRUE@	fi
+@GENERATE_LDSCRIPT_FALSE@@INSTALL_LIBRARY_TRUE@	if [ ! "$(rootlibdir)" -ef "$(libdir)" ]; then \
+@GENERATE_LDSCRIPT_FALSE@@INSTALL_LIBRARY_TRUE@		$(LN_S) "$(rootlibdir)/libntfs-3g.so" "$(DESTDIR)/$(libdir)/libntfs-3g.so"; \
+@GENERATE_LDSCRIPT_FALSE@@INSTALL_LIBRARY_TRUE@	fi
+
+uninstall-local:
+@INSTALL_LIBRARY_TRUE@	$(RM) -f "$(DESTDIR)/$(rootlibdir)"/libntfs-3g.so*
+
+@ENABLE_NTFSPROGS_TRUE@libs:	$(lib_LTLIBRARIES)
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/libntfs-3g/acls.c b/libntfs-3g/acls.c
new file mode 100755
index 0000000000000000000000000000000000000000..51a7e7f5919e9992068cf4810e47a738cf455a85
--- /dev/null
+++ b/libntfs-3g/acls.c
@@ -0,0 +1,4502 @@
+/**
+ * acls.c - General function to process NTFS ACLs
+ *
+ *	This module is part of ntfs-3g library, but may also be
+ *	integrated in tools running over Linux or Windows
+ *
+ * Copyright (c) 2007-2014 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
+				/*
+				 * integration into ntfs-3g
+				 */
+#include "config.h"
+
+#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_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYSLOG_H
+#include <syslog.h>
+#endif
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include "types.h"
+#include "layout.h"
+#include "security.h"
+#include "acls.h"
+#include "misc.h"
+#else
+
+				/*
+				 * integration into secaudit, check whether Win32,
+				 * may have to be adapted to compiler or something else
+				 */
+
+#ifndef WIN32
+#if defined(__WIN32) | defined(__WIN32__) | defined(WNSC)
+#define WIN32 1
+#endif
+#endif
+
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <errno.h>
+
+				/*
+				 * integration into secaudit/Win32
+				 */
+#ifdef WIN32
+#include <fcntl.h>
+#include <windows.h>
+#define __LITTLE_ENDIAN 1234
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#else
+				/*
+				 * integration into secaudit/STSC
+				 */
+#ifdef STSC
+#include <stat.h>
+#undef __BYTE_ORDER
+#define __BYTE_ORDER __BIG_ENDIAN
+#else
+				/*
+				 * integration into secaudit/Linux
+				 */
+#include <sys/stat.h>
+#include <endian.h>
+#include <unistd.h>
+#include <dlfcn.h>
+#endif /* STSC */
+#endif /* WIN32 */
+#include "secaudit.h"
+#endif /* HAVE_CONFIG_H */
+
+/*
+ *	A few useful constants
+ */
+
+/*
+ *		null SID (S-1-0-0)
+ */
+
+static const char nullsidbytes[] = {
+		1,		/* revision */
+		1,		/* auth count */
+		0, 0, 0, 0, 0, 0,	/* base */
+		0, 0, 0, 0 	/* 1st level */
+	};
+
+static const SID *nullsid = (const SID*)nullsidbytes;
+
+/*
+ *		SID for world  (S-1-1-0)
+ */
+
+static const char worldsidbytes[] = {
+		1,		/* revision */
+		1,		/* auth count */
+		0, 0, 0, 0, 0, 1,	/* base */
+		0, 0, 0, 0	/* 1st level */
+} ;
+
+const SID *worldsid = (const SID*)worldsidbytes;
+
+/*
+ *		SID for authenticated user (S-1-5-11)
+ */
+
+static const char authsidbytes[] = {
+		1,		/* revision */
+		1,		/* auth count */
+		0, 0, 0, 0, 0, 5,	/* base */
+		11, 0, 0, 0	/* 1st level */ 
+};
+	        
+static const SID *authsid = (const SID*)authsidbytes;
+
+/*
+ *		SID for administrator
+ */
+
+static const char adminsidbytes[] = {
+		1,		/* revision */
+		2,		/* auth count */
+		0, 0, 0, 0, 0, 5,	/* base */
+		32, 0, 0, 0,	/* 1st level */
+		32, 2, 0, 0	/* 2nd level */
+};
+
+const SID *adminsid = (const SID*)adminsidbytes;
+
+/*
+ *		SID for system
+ */
+
+static const char systemsidbytes[] = {
+		1,		/* revision */
+		1,		/* auth count */
+		0, 0, 0, 0, 0, 5,	/* base */
+		18, 0, 0, 0 	/* 1st level */
+	};
+
+static const SID *systemsid = (const SID*)systemsidbytes;
+
+/*
+ *		SID for generic creator-owner
+ *		S-1-3-0
+ */
+
+static const char ownersidbytes[] = {
+		1,		/* revision */
+		1,		/* auth count */
+		0, 0, 0, 0, 0, 3,	/* base */
+		0, 0, 0, 0	/* 1st level */
+} ;
+
+static const SID *ownersid = (const SID*)ownersidbytes;
+
+/*
+ *		SID for generic creator-group
+ *		S-1-3-1
+ */
+
+static const char groupsidbytes[] = {
+		1,		/* revision */
+		1,		/* auth count */
+		0, 0, 0, 0, 0, 3,	/* base */
+		1, 0, 0, 0	/* 1st level */
+} ;
+
+static const SID *groupsid = (const SID*)groupsidbytes;
+
+/*
+ *		Determine the size of a SID
+ */
+
+int ntfs_sid_size(const SID * sid)
+{
+	return (sid->sub_authority_count * 4 + 8);
+}
+
+/*
+ *		Test whether two SID are equal
+ */
+
+BOOL ntfs_same_sid(const SID *first, const SID *second)
+{
+	int size;
+
+	size = ntfs_sid_size(first);
+	return ((ntfs_sid_size(second) == size)
+		&& !memcmp(first, second, size));
+}
+
+/*
+ *		Test whether a SID means "world user"
+ *	Local users group recognized as world
+ *	Also interactive users so that /Users/Public is world accessible,
+ *	but only if Posix ACLs are not enabled (if Posix ACLs are enabled,
+ *	access to /Users/Public should be done by defining interactive users
+ *	as a mapped group.)
+ */
+
+static int is_world_sid(const SID * usid)
+{
+	return (
+	     /* check whether S-1-1-0 : world */
+	       ((usid->sub_authority_count == 1)
+	    && (usid->identifier_authority.high_part ==  const_cpu_to_be16(0))
+	    && (usid->identifier_authority.low_part ==  const_cpu_to_be32(1))
+	    && (usid->sub_authority[0] == const_cpu_to_le32(0)))
+
+	     /* check whether S-1-5-32-545 : local user */
+	  ||   ((usid->sub_authority_count == 2)
+	    && (usid->identifier_authority.high_part ==  const_cpu_to_be16(0))
+	    && (usid->identifier_authority.low_part ==  const_cpu_to_be32(5))
+	    && (usid->sub_authority[0] == const_cpu_to_le32(32))
+	    && (usid->sub_authority[1] == const_cpu_to_le32(545)))
+
+	     /* check whether S-1-5-11 : authenticated user */
+	  ||   ((usid->sub_authority_count == 1)
+	    && (usid->identifier_authority.high_part ==  const_cpu_to_be16(0))
+	    && (usid->identifier_authority.low_part ==  const_cpu_to_be32(5))
+	    && (usid->sub_authority[0] == const_cpu_to_le32(11)))
+
+#if !POSIXACLS
+	     /* check whether S-1-5-4 : interactive user */
+	  ||   ((usid->sub_authority_count == 1)
+	    && (usid->identifier_authority.high_part ==  const_cpu_to_be16(0))
+	    && (usid->identifier_authority.low_part ==  const_cpu_to_be32(5))
+	    && (usid->sub_authority[0] == const_cpu_to_le32(4)))
+#endif /* !POSIXACLS */
+		);
+}
+
+/*
+ *		Test whether a SID means "some user (or group)"
+ *	Currently we only check for S-1-5-21... but we should
+ *	probably test for other configurations
+ */
+
+BOOL ntfs_is_user_sid(const SID *usid)
+{
+	return ((usid->sub_authority_count == 5)
+	    && (usid->identifier_authority.high_part ==  const_cpu_to_be16(0))
+	    && (usid->identifier_authority.low_part ==  const_cpu_to_be32(5))
+	    && (usid->sub_authority[0] ==  const_cpu_to_le32(21)));
+}
+
+/*
+ *		Test whether a SID means "some special group"
+ *	Currently we only check for a few S-1-5-n but we should
+ *	probably test for other configurations.
+ *
+ *	This is useful for granting access to /Users/Public for
+ *	specific users when the Posix ACLs are enabled.
+ */
+
+static BOOL ntfs_known_group_sid(const SID *usid)
+{
+			/* count == 1 excludes S-1-5-5-X-Y (logon) */
+	return ((usid->sub_authority_count == 1)
+	    && (usid->identifier_authority.high_part ==  const_cpu_to_be16(0))
+	    && (usid->identifier_authority.low_part ==  const_cpu_to_be32(5))
+	    && (le32_to_cpu(usid->sub_authority[0]) >=  1)
+	    && (le32_to_cpu(usid->sub_authority[0]) <=  6));
+}
+
+/*
+ *		Determine the size of a security attribute
+ *	whatever the order of fields
+ */
+
+unsigned int ntfs_attr_size(const char *attr)
+{
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	const ACL *pdacl;
+	const ACL *psacl;
+	const SID *psid;
+	unsigned int offdacl;
+	unsigned int offsacl;
+	unsigned int offowner;
+	unsigned int offgroup;
+	unsigned int endsid;
+	unsigned int endacl;
+	unsigned int attrsz;
+
+	phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr;
+		/*
+		 * First check group, which is the last field in all descriptors
+		 * we build, and in most descriptors built by Windows
+		 */
+	attrsz = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
+	offgroup = le32_to_cpu(phead->group);
+	if (offgroup >= attrsz) {
+			/* find end of GSID */
+		psid = (const SID*)&attr[offgroup];
+		endsid = offgroup + ntfs_sid_size(psid);
+		if (endsid > attrsz) attrsz = endsid;
+	}
+	offowner = le32_to_cpu(phead->owner);
+	if (offowner >= attrsz) {
+			/* find end of USID */
+		psid = (const SID*)&attr[offowner];
+		endsid = offowner + ntfs_sid_size(psid);
+		attrsz = endsid;
+	}
+	offsacl = le32_to_cpu(phead->sacl);
+	if (offsacl >= attrsz) {
+			/* find end of SACL */
+		psacl = (const ACL*)&attr[offsacl];
+		endacl = offsacl + le16_to_cpu(psacl->size);
+		if (endacl > attrsz)
+			attrsz = endacl;
+	}
+
+
+		/* find end of DACL */
+	offdacl = le32_to_cpu(phead->dacl);
+	if (offdacl >= attrsz) {
+		pdacl = (const ACL*)&attr[offdacl];
+		endacl = offdacl + le16_to_cpu(pdacl->size);
+		if (endacl > attrsz)
+			attrsz = endacl;
+	}
+	return (attrsz);
+}
+
+/*
+ *		Do sanity checks on a SID read from storage
+ *	(just check revision and number of authorities)
+ */
+
+BOOL ntfs_valid_sid(const SID *sid)
+{
+	return ((sid->revision == SID_REVISION)
+		&& (sid->sub_authority_count >= 1)
+		&& (sid->sub_authority_count <= 8));
+}
+
+/*
+ *		Check whether a SID is acceptable for an implicit
+ *	mapping pattern.
+ *	It should have been already checked it is a valid user SID.
+ *
+ *	The last authority reference has to be >= 1000 (Windows usage)
+ *	and <= 0x7fffffff, so that 30 bits from a uid and 30 more bits
+ *      from a gid an be inserted with no overflow.
+ */
+
+BOOL ntfs_valid_pattern(const SID *sid)
+{
+	int cnt;
+	u32 auth;
+	le32 leauth;
+
+	cnt = sid->sub_authority_count;
+	leauth = sid->sub_authority[cnt-1];
+	auth = le32_to_cpu(leauth);
+	return ((auth >= 1000) && (auth <= 0x7fffffff));
+}
+
+/*
+ *		Compute the uid or gid associated to a SID
+ *	through an implicit mapping
+ *
+ *	Returns 0 (root) if it does not match pattern
+ */
+
+static u32 findimplicit(const SID *xsid, const SID *pattern, int parity)
+{
+	BIGSID defsid;
+	SID *psid;
+	u32 xid; /* uid or gid */
+	int cnt;
+	u32 carry;
+	le32 leauth;
+	u32 uauth;
+	u32 xlast;
+	u32 rlast;
+
+	memcpy(&defsid,pattern,ntfs_sid_size(pattern));
+	psid = (SID*)&defsid;
+	cnt = psid->sub_authority_count;
+	xid = 0;
+	if (xsid->sub_authority_count == cnt) {
+		psid->sub_authority[cnt-1] = xsid->sub_authority[cnt-1];
+		leauth = xsid->sub_authority[cnt-1];
+		xlast = le32_to_cpu(leauth);
+		leauth = pattern->sub_authority[cnt-1];
+		rlast = le32_to_cpu(leauth);
+
+		if ((xlast > rlast) && !((xlast ^ rlast ^ parity) & 1)) {
+			/* direct check for basic situation */
+			if (ntfs_same_sid(psid,xsid))
+				xid = ((xlast - rlast) >> 1) & 0x3fffffff;
+			else {
+				/*
+				 * check whether part of mapping had to be
+				 * recorded in a higher level authority
+			 	 */
+				carry = 1;
+				do {
+					leauth = psid->sub_authority[cnt-2];
+					uauth = le32_to_cpu(leauth) + 1;
+					psid->sub_authority[cnt-2]
+						= cpu_to_le32(uauth);
+				} while (!ntfs_same_sid(psid,xsid)
+					 && (++carry < 4));
+				if (carry < 4)
+					xid = (((xlast - rlast) >> 1)
+						& 0x3fffffff) | (carry << 30);
+			}
+		}
+	}
+	return (xid);
+}
+
+/*
+ *		Find usid mapped to a Linux user
+ *	Returns NULL if not found
+ */
+
+const SID *ntfs_find_usid(const struct MAPPING* usermapping,
+		uid_t uid, SID *defusid)
+{
+	const struct MAPPING *p;
+	const SID *sid;
+	le32 leauth;
+	u32 uauth;
+	int cnt;
+
+	if (!uid)
+		sid = adminsid;
+	else {
+		p = usermapping;
+		while (p && p->xid && ((uid_t)p->xid != uid))
+			p = p->next;
+		if (p && !p->xid) {
+			/*
+			 * default pattern has been reached :
+			 * build an implicit SID according to pattern
+			 * (the pattern format was checked while reading
+			 * the mapping file)
+			 */
+			memcpy(defusid, p->sid, ntfs_sid_size(p->sid));
+			cnt = defusid->sub_authority_count;
+			leauth = defusid->sub_authority[cnt-1];
+			uauth = le32_to_cpu(leauth) + 2*(uid & 0x3fffffff);
+			defusid->sub_authority[cnt-1] = cpu_to_le32(uauth);
+			if (uid & 0xc0000000) {
+				leauth = defusid->sub_authority[cnt-2];
+				uauth = le32_to_cpu(leauth) + ((uid >> 30) & 3);
+				defusid->sub_authority[cnt-2] = cpu_to_le32(uauth);
+			}
+			sid = defusid;
+		} else
+			sid = (p ? p->sid : (const SID*)NULL);
+	}
+	return (sid);
+}
+
+/*
+ *		Find Linux group mapped to a gsid
+ *	Returns 0 (root) if not found
+ */
+
+const SID *ntfs_find_gsid(const struct MAPPING* groupmapping,
+		gid_t gid, SID *defgsid)
+{
+	const struct MAPPING *p;
+	const SID *sid;
+	le32 leauth;
+	u32 uauth;
+	int cnt;
+
+	if (!gid)
+		sid = adminsid;
+	else {
+		p = groupmapping;
+		while (p && p->xid && ((gid_t)p->xid != gid))
+			p = p->next;
+		if (p && !p->xid) {
+			/*
+			 * default pattern has been reached :
+			 * build an implicit SID according to pattern
+			 * (the pattern format was checked while reading
+			 * the mapping file)
+			 */
+			memcpy(defgsid, p->sid, ntfs_sid_size(p->sid));
+			cnt = defgsid->sub_authority_count;
+			leauth = defgsid->sub_authority[cnt-1];
+			uauth = le32_to_cpu(leauth) + 2*(gid & 0x3fffffff) + 1;
+			defgsid->sub_authority[cnt-1] = cpu_to_le32(uauth);
+			if (gid & 0xc0000000) {
+				leauth = defgsid->sub_authority[cnt-2];
+				uauth = le32_to_cpu(leauth) + ((gid >> 30) & 3);
+				defgsid->sub_authority[cnt-2] = cpu_to_le32(uauth);
+			}
+			sid = defgsid;
+		} else
+			sid = (p ? p->sid : (const SID*)NULL);
+	}
+	return (sid);
+}
+
+/*
+ *		Find Linux owner mapped to a usid
+ *	Returns 0 (root) if not found
+ */
+
+uid_t ntfs_find_user(const struct MAPPING* usermapping, const SID *usid)
+{
+	uid_t uid;
+	const struct MAPPING *p;
+
+	p = usermapping;
+	while (p && p->xid && !ntfs_same_sid(usid, p->sid))
+		p = p->next;
+	if (p && !p->xid)
+		/*
+		 * No explicit mapping found, try implicit mapping
+		 */
+		uid = findimplicit(usid,p->sid,0);
+	else
+		uid = (p ? p->xid : 0);
+	return (uid);
+}
+
+/*
+ *		Find Linux group mapped to a gsid
+ *	Returns 0 (root) if not found
+ */
+
+gid_t ntfs_find_group(const struct MAPPING* groupmapping, const SID * gsid)
+{
+	gid_t gid;
+	const struct MAPPING *p;
+
+	p = groupmapping;
+	while (p && p->xid && !ntfs_same_sid(gsid, p->sid))
+		p = p->next;
+	if (p && !p->xid)
+		/*
+		 * No explicit mapping found, try implicit mapping
+		 */
+		gid = findimplicit(gsid,p->sid,1);
+	else
+		gid = (p ? p->xid : 0);
+	return (gid);
+}
+
+/*
+ *		Check the validity of the ACEs in a DACL or SACL
+ */
+
+static BOOL valid_acl(const ACL *pacl, unsigned int end)
+{
+	const ACCESS_ALLOWED_ACE *pace;
+	unsigned int offace;
+	unsigned int acecnt;
+	unsigned int acesz;
+	unsigned int nace;
+	BOOL ok;
+
+	ok = TRUE;
+	acecnt = le16_to_cpu(pacl->ace_count);
+	offace = sizeof(ACL);
+	for (nace = 0; (nace < acecnt) && ok; nace++) {
+		/* be sure the beginning is within range */
+		if ((offace + sizeof(ACCESS_ALLOWED_ACE)) > end)
+			ok = FALSE;
+		else {
+			pace = (const ACCESS_ALLOWED_ACE*)
+				&((const char*)pacl)[offace];
+			acesz = le16_to_cpu(pace->size);
+			if (((offace + acesz) > end)
+			   || !ntfs_valid_sid(&pace->sid)
+			   || ((ntfs_sid_size(&pace->sid) + 8) != (int)acesz))
+				 ok = FALSE;
+			offace += acesz;
+		}
+	}
+	return (ok);
+}
+
+/*
+ *		Do sanity checks on security descriptors read from storage
+ *	basically, we make sure that every field holds within
+ *	allocated storage
+ *	Should not be called with a NULL argument
+ *	returns TRUE if considered safe
+ *		if not, error should be logged by caller
+ */
+
+BOOL ntfs_valid_descr(const char *securattr, unsigned int attrsz)
+{
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	const ACL *pdacl;
+	const ACL *psacl;
+	unsigned int offdacl;
+	unsigned int offsacl;
+	unsigned int offowner;
+	unsigned int offgroup;
+	BOOL ok;
+
+	ok = TRUE;
+
+	/*
+	 * first check overall size if within allocation range
+	 * and a DACL is present
+	 * and owner and group SID are valid
+	 */
+
+	phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr;
+	offdacl = le32_to_cpu(phead->dacl);
+	offsacl = le32_to_cpu(phead->sacl);
+	offowner = le32_to_cpu(phead->owner);
+	offgroup = le32_to_cpu(phead->group);
+	pdacl = (const ACL*)&securattr[offdacl];
+	psacl = (const ACL*)&securattr[offsacl];
+
+		/*
+		 * size check occurs before the above pointers are used
+		 *
+		 * "DR Watson" standard directory on WinXP has an
+		 * old revision and no DACL though SE_DACL_PRESENT is set
+		 */
+	if ((attrsz >= sizeof(SECURITY_DESCRIPTOR_RELATIVE))
+		&& (phead->revision == SECURITY_DESCRIPTOR_REVISION)
+		&& (offowner >= sizeof(SECURITY_DESCRIPTOR_RELATIVE))
+		&& ((offowner + 2) < attrsz)
+		&& (offgroup >= sizeof(SECURITY_DESCRIPTOR_RELATIVE))
+		&& ((offgroup + 2) < attrsz)
+		&& (!offdacl
+			|| ((offdacl >= sizeof(SECURITY_DESCRIPTOR_RELATIVE))
+			    && (offdacl+sizeof(ACL) <= attrsz)))
+		&& (!offsacl
+			|| ((offsacl >= sizeof(SECURITY_DESCRIPTOR_RELATIVE))
+			    && (offsacl+sizeof(ACL) <= attrsz)))
+		&& !(phead->owner & const_cpu_to_le32(3))
+		&& !(phead->group & const_cpu_to_le32(3))
+		&& !(phead->dacl & const_cpu_to_le32(3))
+		&& !(phead->sacl & const_cpu_to_le32(3))
+		&& (ntfs_attr_size(securattr) <= attrsz)
+		&& ntfs_valid_sid((const SID*)&securattr[offowner])
+		&& ntfs_valid_sid((const SID*)&securattr[offgroup])
+			/*
+			 * if there is an ACL, as indicated by offdacl,
+			 * require SE_DACL_PRESENT
+			 * but "Dr Watson" has SE_DACL_PRESENT though no DACL
+			 */
+		&& (!offdacl
+		    || ((phead->control & SE_DACL_PRESENT)
+			&& ((pdacl->revision == ACL_REVISION)
+			   || (pdacl->revision == ACL_REVISION_DS))))
+			/* same for SACL */
+		&& (!offsacl
+		    || ((phead->control & SE_SACL_PRESENT)
+			&& ((psacl->revision == ACL_REVISION)
+			    || (psacl->revision == ACL_REVISION_DS))))) {
+			/*
+			 *  Check the DACL and SACL if present
+			 */
+		if ((offdacl && !valid_acl(pdacl,attrsz - offdacl))
+		   || (offsacl && !valid_acl(psacl,attrsz - offsacl)))
+			ok = FALSE;
+	} else
+		ok = FALSE;
+	return (ok);
+}
+
+/*
+ *		Copy the inheritable parts of an ACL
+ *
+ *	Returns the size of the new ACL
+ *		or zero if nothing is inheritable
+ */
+
+int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl,
+			const SID *usid, const SID *gsid, BOOL fordir,
+			le16 inherited)
+{
+	unsigned int src;
+	unsigned int dst;
+	int oldcnt;
+	int newcnt;
+	unsigned int selection;
+	int nace;
+	int acesz;
+	int usidsz;
+	int gsidsz;
+	const ACCESS_ALLOWED_ACE *poldace;
+	ACCESS_ALLOWED_ACE *pnewace;
+	ACCESS_ALLOWED_ACE *pauthace;
+	ACCESS_ALLOWED_ACE *pownerace;
+
+	pauthace = (ACCESS_ALLOWED_ACE*)NULL;
+	pownerace = (ACCESS_ALLOWED_ACE*)NULL;
+	usidsz = ntfs_sid_size(usid);
+	gsidsz = ntfs_sid_size(gsid);
+
+	/* ACL header */
+
+	newacl->revision = ACL_REVISION;
+	newacl->alignment1 = 0;
+	newacl->alignment2 = const_cpu_to_le16(0);
+	src = dst = sizeof(ACL);
+
+	selection = (fordir ? CONTAINER_INHERIT_ACE : OBJECT_INHERIT_ACE);
+	newcnt = 0;
+	oldcnt = le16_to_cpu(oldacl->ace_count);
+	for (nace = 0; nace < oldcnt; nace++) {
+		poldace = (const ACCESS_ALLOWED_ACE*)((const char*)oldacl + src);
+		acesz = le16_to_cpu(poldace->size);
+		src += acesz;
+		/*
+		 * Extract inheritance for access, including inheritance for
+		 * access from an ACE with is both applied and inheritable.
+		 *
+		 * must not output OBJECT_INHERIT_ACE or CONTAINER_INHERIT_ACE
+		 *
+		 *	According to MSDN :
+		 * "For a case in which a container object inherits an ACE
+		 * "that is both effective on the container and inheritable
+		 * "by its descendants, the container may inherit two ACEs.
+		 * "This occurs if the inheritable ACE contains generic
+		 * "information."
+		 */
+		if ((poldace->flags & selection)
+		    && (!fordir
+			|| (poldace->flags & NO_PROPAGATE_INHERIT_ACE)
+			|| (poldace->mask & (GENERIC_ALL | GENERIC_READ
+					| GENERIC_WRITE | GENERIC_EXECUTE)))
+		    && !ntfs_same_sid(&poldace->sid, ownersid)
+		    && !ntfs_same_sid(&poldace->sid, groupsid)) {
+			pnewace = (ACCESS_ALLOWED_ACE*)
+					((char*)newacl + dst);
+			memcpy(pnewace,poldace,acesz);
+				/* reencode GENERIC_ALL */
+			if (pnewace->mask & GENERIC_ALL) {
+				pnewace->mask &= ~GENERIC_ALL;
+				if (fordir)
+					pnewace->mask |= OWNER_RIGHTS
+							| DIR_READ
+							| DIR_WRITE
+							| DIR_EXEC;
+				else
+			/*
+			 * The last flag is not defined for a file,
+			 * however Windows sets it, so do the same
+			 */
+					pnewace->mask |= OWNER_RIGHTS
+							| FILE_READ
+							| FILE_WRITE
+							| FILE_EXEC
+							| cpu_to_le32(0x40);
+			}
+				/* reencode GENERIC_READ (+ EXECUTE) */
+			if (pnewace->mask & GENERIC_READ) {
+				if (fordir)
+					pnewace->mask |= OWNER_RIGHTS
+							| DIR_READ
+							| DIR_EXEC;
+				else
+					pnewace->mask |= OWNER_RIGHTS
+							| FILE_READ
+							| FILE_EXEC;
+				pnewace->mask &= ~(GENERIC_READ
+						| GENERIC_EXECUTE
+						| WRITE_DAC
+						| WRITE_OWNER
+						| DELETE | FILE_WRITE_EA
+						| FILE_WRITE_ATTRIBUTES);
+			}
+				/* reencode GENERIC_WRITE */
+			if (pnewace->mask & GENERIC_WRITE) {
+				if (fordir)
+					pnewace->mask |= OWNER_RIGHTS
+							| DIR_WRITE;
+				else
+					pnewace->mask |= OWNER_RIGHTS
+							| FILE_WRITE;
+				pnewace->mask &= ~(GENERIC_WRITE
+							| WRITE_DAC
+							| WRITE_OWNER
+							| FILE_DELETE_CHILD);
+			}
+				/* remove inheritance flags */
+			pnewace->flags &= ~(OBJECT_INHERIT_ACE
+						| CONTAINER_INHERIT_ACE
+						| INHERIT_ONLY_ACE);
+			/*
+			 * Group similar ACE for authenticated users
+			 * (should probably be done for other SIDs)
+			 */
+			if ((poldace->type == ACCESS_ALLOWED_ACE_TYPE)
+			    && ntfs_same_sid(&poldace->sid, authsid)) {
+				if (pauthace) {
+					pauthace->flags |= pnewace->flags;
+					pauthace->mask |= pnewace->mask;
+				} else {
+					pauthace = pnewace;
+					if (inherited)
+						pnewace->flags |= INHERITED_ACE;
+					dst += acesz;
+					newcnt++;
+				}
+			} else {
+				if (inherited)
+					pnewace->flags |= INHERITED_ACE;
+				dst += acesz;
+				newcnt++;
+			}
+		}
+			/*
+			 * Inheritance for access, specific to
+			 * creator-owner (and creator-group)
+			 */
+		if (fordir || !inherited
+		   || (poldace->flags
+			   & (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE))) {
+			pnewace = (ACCESS_ALLOWED_ACE*)
+					((char*)newacl + dst);
+			memcpy(pnewace,poldace,acesz);
+				/*
+				 * Replace generic creator-owner and
+				 * creator-group by owner and group
+				 * (but keep for further inheritance)
+				 */
+			if (ntfs_same_sid(&pnewace->sid, ownersid)) {
+				memcpy(&pnewace->sid, usid, usidsz);
+				pnewace->size = cpu_to_le16(usidsz + 8);
+					/* remove inheritance flags */
+				pnewace->flags &= ~(OBJECT_INHERIT_ACE
+						| CONTAINER_INHERIT_ACE
+						| INHERIT_ONLY_ACE);
+				if (inherited)
+					pnewace->flags |= INHERITED_ACE;
+				if ((pnewace->type == ACCESS_ALLOWED_ACE_TYPE)
+				    && pownerace
+				    && !(pnewace->flags & ~pownerace->flags)) {
+					pownerace->mask |= pnewace->mask;
+				} else {
+					dst += usidsz + 8;
+					newcnt++;
+				}
+			}
+			if (ntfs_same_sid(&pnewace->sid, groupsid)) {
+				memcpy(&pnewace->sid, gsid, gsidsz);
+				pnewace->size = cpu_to_le16(gsidsz + 8);
+					/* remove inheritance flags */
+				pnewace->flags &= ~(OBJECT_INHERIT_ACE
+						| CONTAINER_INHERIT_ACE
+						| INHERIT_ONLY_ACE);
+				if (inherited)
+					pnewace->flags |= INHERITED_ACE;
+				dst += gsidsz + 8;
+				newcnt++;
+			}
+		}
+
+			/*
+			 * inheritance for further inheritance
+			 *
+			 * Situations leading to output CONTAINER_INHERIT_ACE
+			 * 	or OBJECT_INHERIT_ACE
+			 */
+		if (fordir
+		   && (poldace->flags
+			   & (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE))) {
+			pnewace = (ACCESS_ALLOWED_ACE*)
+					((char*)newacl + dst);
+			memcpy(pnewace,poldace,acesz);
+			if ((poldace->flags & OBJECT_INHERIT_ACE)
+			   && !(poldace->flags & (CONTAINER_INHERIT_ACE
+					| NO_PROPAGATE_INHERIT_ACE)))
+				pnewace->flags |= INHERIT_ONLY_ACE;
+			if ((poldace->flags & CONTAINER_INHERIT_ACE)
+			    && !(poldace->flags & NO_PROPAGATE_INHERIT_ACE)
+			    && !ntfs_same_sid(&poldace->sid, ownersid)
+			    && !ntfs_same_sid(&poldace->sid, groupsid)) {
+				if ((poldace->mask & (GENERIC_ALL | GENERIC_READ
+					| GENERIC_WRITE | GENERIC_EXECUTE)))
+					pnewace->flags |= INHERIT_ONLY_ACE;
+				else
+					pnewace->flags &= ~INHERIT_ONLY_ACE;
+			}
+			if (inherited)
+				pnewace->flags |= INHERITED_ACE;
+			/*
+			 * Prepare grouping similar ACE for authenticated users
+			 */
+			if ((poldace->type == ACCESS_ALLOWED_ACE_TYPE)
+			    && !pauthace
+			    && !(pnewace->flags & INHERIT_ONLY_ACE)
+			    && ntfs_same_sid(&poldace->sid, authsid)) {
+				pauthace = pnewace;
+			}
+			/*
+			 * Prepare grouping similar ACE for owner
+			 */
+			if ((poldace->type == ACCESS_ALLOWED_ACE_TYPE)
+			    && !pownerace
+			    && !(pnewace->flags & INHERIT_ONLY_ACE)
+			    && ntfs_same_sid(&poldace->sid, usid)) {
+				pownerace = pnewace;
+			}
+			dst += acesz;
+			newcnt++;
+		}
+	}
+		/*
+		 * Adjust header if something was inherited
+		 */
+	if (dst > sizeof(ACL)) {
+		newacl->ace_count = cpu_to_le16(newcnt);
+		newacl->size = cpu_to_le16(dst);
+	} else
+		dst = 0;
+	return (dst);
+}
+
+#if POSIXACLS
+
+/*
+ *		Do sanity checks on a Posix descriptor
+ *	Should not be called with a NULL argument
+ *	returns TRUE if considered safe
+ *		if not, error should be logged by caller
+ */
+
+BOOL ntfs_valid_posix(const struct POSIX_SECURITY *pxdesc)
+{
+	const struct POSIX_ACL *pacl;
+	int i;
+	BOOL ok;
+	u16 tag;
+	u32 id;
+	int perms;
+	struct {
+		u16 previous;
+		u32 previousid;
+		u16 tagsset;
+		mode_t mode;
+		int owners;
+		int groups;
+		int others;
+	} checks[2], *pchk;
+
+	for (i=0; i<2; i++) {
+		checks[i].mode = 0;
+		checks[i].tagsset = 0;
+		checks[i].owners = 0;
+		checks[i].groups = 0;
+		checks[i].others = 0;
+		checks[i].previous = 0;
+		checks[i].previousid = 0;
+	}
+	ok = TRUE;
+	pacl = &pxdesc->acl;
+			/*
+			 * header (strict for now)
+			 */
+	if ((pacl->version != POSIX_VERSION)
+	    || (pacl->flags != 0)
+	    || (pacl->filler != 0))
+		ok = FALSE;
+			/*
+			 * Reject multiple owner, group or other
+			 * but do not require them to be present
+			 * Also check the ACEs are in correct order
+			 * which implies there is no duplicates
+			 */
+	for (i=0; i<pxdesc->acccnt + pxdesc->defcnt; i++) {
+		if (i >= pxdesc->firstdef)
+			pchk = &checks[1];
+		else
+			pchk = &checks[0];
+		perms = pacl->ace[i].perms;
+		tag = pacl->ace[i].tag;
+		pchk->tagsset |= tag;
+		id = pacl->ace[i].id;
+		if (perms & ~7) ok = FALSE;
+		if ((tag < pchk->previous)
+			|| ((tag == pchk->previous)
+			 && (id <= pchk->previousid)))
+				ok = FALSE;
+		pchk->previous = tag;
+		pchk->previousid = id;
+		switch (tag) {
+		case POSIX_ACL_USER_OBJ :
+			if (pchk->owners++)
+				ok = FALSE;
+			if (id != (u32)-1)
+				ok = FALSE;
+			pchk->mode |= perms << 6;
+			break;
+		case POSIX_ACL_GROUP_OBJ :
+			if (pchk->groups++)
+				ok = FALSE;
+			if (id != (u32)-1)
+				ok = FALSE;
+			pchk->mode = (pchk->mode & 07707) | (perms << 3);
+			break;
+		case POSIX_ACL_OTHER :
+			if (pchk->others++)
+				ok = FALSE;
+			if (id != (u32)-1)
+				ok = FALSE;
+			pchk->mode |= perms;
+			break;
+		case POSIX_ACL_USER :
+		case POSIX_ACL_GROUP :
+			if (id == (u32)-1)
+				ok = FALSE;
+			break;
+		case POSIX_ACL_MASK :
+			if (id != (u32)-1)
+				ok = FALSE;
+			pchk->mode = (pchk->mode & 07707) | (perms << 3);
+			break;
+		default :
+			ok = FALSE;
+			break;
+		}
+	}
+	if ((pxdesc->acccnt > 0)
+	   && ((checks[0].owners != 1) || (checks[0].groups != 1) 
+		|| (checks[0].others != 1)))
+		ok = FALSE;
+		/* do not check owner, group or other are present in */
+		/* the default ACL, Windows does not necessarily set them */
+			/* descriptor */
+	if (pxdesc->defcnt && (pxdesc->acccnt > pxdesc->firstdef))
+		ok = FALSE;
+	if ((pxdesc->acccnt < 0) || (pxdesc->defcnt < 0))
+		ok = FALSE;
+			/* check mode, unless null or no tag set */
+	if (pxdesc->mode
+	    && checks[0].tagsset
+	    && (checks[0].mode != (pxdesc->mode & 0777)))
+		ok = FALSE;
+			/* check tagsset */
+	if (pxdesc->tagsset != checks[0].tagsset)
+		ok = FALSE;
+	return (ok);
+}
+
+/*
+ *		Set standard header data into a Posix ACL
+ *	The mode argument should provide the 3 upper bits of target mode
+ */
+
+static mode_t posix_header(struct POSIX_SECURITY *pxdesc, mode_t basemode)
+{
+	mode_t mode;
+	u16 tagsset;
+	struct POSIX_ACE *pace;
+	int i;
+
+	mode = basemode & 07000;
+	tagsset = 0;
+	for (i=0; i<pxdesc->acccnt; i++) {
+		pace = &pxdesc->acl.ace[i];
+		tagsset |= pace->tag;
+		switch(pace->tag) {
+		case POSIX_ACL_USER_OBJ :
+			mode |= (pace->perms & 7) << 6;
+			break;
+		case POSIX_ACL_GROUP_OBJ :
+		case POSIX_ACL_MASK :
+			mode = (mode & 07707) | ((pace->perms & 7) << 3);
+			break;
+		case POSIX_ACL_OTHER :
+			mode |= pace->perms & 7;
+			break;
+		default :
+			break;
+		}
+	}
+	pxdesc->tagsset = tagsset;
+	pxdesc->mode = mode;
+	pxdesc->acl.version = POSIX_VERSION;
+	pxdesc->acl.flags = 0;
+	pxdesc->acl.filler = 0;
+	return (mode);
+}
+
+/*
+ *		Sort ACEs in a Posix ACL
+ *	This is useful for always getting reusable converted ACLs,
+ *	it also helps in merging ACEs.
+ *	Repeated tag+id are allowed and not merged here.
+ *
+ *	Tags should be in ascending sequence and for a repeatable tag
+ *	ids should be in ascending sequence.
+ */
+
+void ntfs_sort_posix(struct POSIX_SECURITY *pxdesc)
+{
+	struct POSIX_ACL *pacl;
+	struct POSIX_ACE ace;
+	int i;
+	int offs;
+	BOOL done;
+	u16 tag;
+	u16 previous;
+	u32 id;
+	u32 previousid;
+
+
+			/*
+			 * Check sequencing of tag+id in access ACE's
+			 */
+	pacl = &pxdesc->acl;
+	do {
+		done = TRUE;
+		previous = pacl->ace[0].tag;
+		previousid = pacl->ace[0].id;
+		for (i=1; i<pxdesc->acccnt; i++) {
+			tag = pacl->ace[i].tag;
+			id = pacl->ace[i].id;
+
+			if ((tag < previous)
+			   || ((tag == previous) && (id < previousid))) {
+				done = FALSE;
+				memcpy(&ace,&pacl->ace[i-1],sizeof(struct POSIX_ACE));
+				memcpy(&pacl->ace[i-1],&pacl->ace[i],sizeof(struct POSIX_ACE));
+				memcpy(&pacl->ace[i],&ace,sizeof(struct POSIX_ACE));
+			} else {
+				previous = tag;
+				previousid = id;
+			}
+		}
+	} while (!done);
+				/*
+				 * Same for default ACEs
+				 */
+	do {
+		done = TRUE;
+		if ((pxdesc->defcnt) > 1) {
+			offs = pxdesc->firstdef;
+			previous = pacl->ace[offs].tag;
+			previousid = pacl->ace[offs].id;
+			for (i=offs+1; i<offs+pxdesc->defcnt; i++) {
+				tag = pacl->ace[i].tag;
+				id = pacl->ace[i].id;
+
+				if ((tag < previous)
+				   || ((tag == previous) && (id < previousid))) {
+					done = FALSE;
+					memcpy(&ace,&pacl->ace[i-1],sizeof(struct POSIX_ACE));
+					memcpy(&pacl->ace[i-1],&pacl->ace[i],sizeof(struct POSIX_ACE));
+					memcpy(&pacl->ace[i],&ace,sizeof(struct POSIX_ACE));
+				} else {
+					previous = tag;
+					previousid = id;
+				}
+			}
+		}
+	} while (!done);
+}
+
+/*
+ *		Merge a new mode into a Posix descriptor
+ *	The Posix descriptor is not reallocated, its size is unchanged
+ *
+ *	returns 0 if ok
+ */
+
+int ntfs_merge_mode_posix(struct POSIX_SECURITY *pxdesc, mode_t mode)
+{
+	int i;
+	BOOL maskfound;
+	struct POSIX_ACE *pace;
+	int todo;
+
+	maskfound = FALSE;
+	todo = POSIX_ACL_USER_OBJ | POSIX_ACL_GROUP_OBJ | POSIX_ACL_OTHER;
+	for (i=pxdesc->acccnt-1; i>=0; i--) {
+		pace = &pxdesc->acl.ace[i];
+		switch(pace->tag) {
+		case POSIX_ACL_USER_OBJ :
+			pace->perms = (mode >> 6) & 7;
+			todo &= ~POSIX_ACL_USER_OBJ;
+			break;
+		case POSIX_ACL_GROUP_OBJ :
+			if (!maskfound)
+				pace->perms = (mode >> 3) & 7;
+			todo &= ~POSIX_ACL_GROUP_OBJ;
+			break;
+		case POSIX_ACL_MASK :
+			pace->perms = (mode >> 3) & 7;
+			maskfound = TRUE;
+			break;
+		case POSIX_ACL_OTHER :
+			pace->perms = mode & 7;
+			todo &= ~POSIX_ACL_OTHER;
+			break;
+		default :
+			break;
+		}
+	}
+	pxdesc->mode = mode;
+	return (todo ? -1 : 0);
+}
+
+/*
+ *		Replace an access or default Posix ACL
+ *	The resulting ACL is checked for validity
+ *
+ *	Returns a new ACL or NULL if there is a problem
+ */
+
+struct POSIX_SECURITY *ntfs_replace_acl(const struct POSIX_SECURITY *oldpxdesc,
+		const struct POSIX_ACL *newacl, int count, BOOL deflt)
+{
+	struct POSIX_SECURITY *newpxdesc;
+	size_t newsize;
+	int offset;
+	int oldoffset;
+	int i;
+
+	if (deflt)
+		newsize = sizeof(struct POSIX_SECURITY)
+			+ (oldpxdesc->acccnt + count)*sizeof(struct POSIX_ACE);
+	else
+		newsize = sizeof(struct POSIX_SECURITY)
+			+ (oldpxdesc->defcnt + count)*sizeof(struct POSIX_ACE);
+	newpxdesc = (struct POSIX_SECURITY*)malloc(newsize);
+	if (newpxdesc) {
+		if (deflt) {
+			offset = oldpxdesc->acccnt;
+			newpxdesc->acccnt = oldpxdesc->acccnt;
+			newpxdesc->defcnt = count;
+			newpxdesc->firstdef = offset;
+					/* copy access ACEs */
+			for (i=0; i<newpxdesc->acccnt; i++)
+				newpxdesc->acl.ace[i] = oldpxdesc->acl.ace[i];
+					/* copy default ACEs */
+			for (i=0; i<count; i++)
+				newpxdesc->acl.ace[i + offset] = newacl->ace[i];
+		} else {
+			offset = count;
+			newpxdesc->acccnt = count;
+			newpxdesc->defcnt = oldpxdesc->defcnt;
+			newpxdesc->firstdef = count;
+					/* copy access ACEs */
+			for (i=0; i<count; i++)
+				newpxdesc->acl.ace[i] = newacl->ace[i];
+					/* copy default ACEs */
+			oldoffset = oldpxdesc->firstdef;
+			for (i=0; i<newpxdesc->defcnt; i++)
+				newpxdesc->acl.ace[i + offset] = oldpxdesc->acl.ace[i + oldoffset];
+		}
+			/* assume special flags unchanged */
+		posix_header(newpxdesc, oldpxdesc->mode);
+		if (!ntfs_valid_posix(newpxdesc)) {
+			/* do not log, this is an application error */
+			free(newpxdesc);
+			newpxdesc = (struct POSIX_SECURITY*)NULL;
+			errno = EINVAL;
+		}
+	} else
+		errno = ENOMEM;
+	return (newpxdesc);
+}
+
+/*
+ *		Build a basic Posix ACL from a mode and umask,
+ *	ignoring inheritance from the parent directory
+ */
+
+struct POSIX_SECURITY *ntfs_build_basic_posix(
+		const struct POSIX_SECURITY *pxdesc __attribute__((unused)),
+		mode_t mode, mode_t mask, BOOL isdir __attribute__((unused)))
+{
+	struct POSIX_SECURITY *pydesc;
+	struct POSIX_ACE *pyace;
+
+	pydesc = (struct POSIX_SECURITY*)malloc(
+		sizeof(struct POSIX_SECURITY) + 3*sizeof(struct POSIX_ACE));
+	if (pydesc) {
+		pyace = &pydesc->acl.ace[0];
+		pyace->tag = POSIX_ACL_USER_OBJ;
+		pyace->perms = ((mode & ~mask) >> 6) & 7;
+		pyace->id = -1;
+		pyace = &pydesc->acl.ace[1];
+		pyace->tag = POSIX_ACL_GROUP_OBJ;
+		pyace->perms = ((mode & ~mask) >> 3) & 7;
+		pyace->id = -1;
+		pyace = &pydesc->acl.ace[2];
+		pyace->tag = POSIX_ACL_OTHER;
+		pyace->perms = (mode & ~mask) & 7;
+		pyace->id = -1;
+		pydesc->mode = mode;
+		pydesc->tagsset = POSIX_ACL_USER_OBJ
+				| POSIX_ACL_GROUP_OBJ
+				| POSIX_ACL_OTHER;
+		pydesc->acccnt = 3;
+		pydesc->defcnt = 0;
+		pydesc->firstdef = 6;
+	} else
+		errno = ENOMEM;
+	return (pydesc);
+}
+
+/*
+ *		Build an inherited Posix descriptor from parent
+ *	descriptor (if any) restricted to creation mode
+ *
+ *	Returns the inherited descriptor or NULL if there is a problem
+ */
+
+struct POSIX_SECURITY *ntfs_build_inherited_posix(
+		const struct POSIX_SECURITY *pxdesc, mode_t mode,
+		mode_t mask, BOOL isdir)
+{
+	struct POSIX_SECURITY *pydesc;
+	struct POSIX_ACE *pyace;
+	int count;
+	int defcnt;
+	int size;
+	int i;
+	s16 tagsset;
+
+	if (pxdesc && pxdesc->defcnt) {
+		if (isdir)
+			count = 2*pxdesc->defcnt + 3;
+		else
+			count = pxdesc->defcnt + 3;
+	} else
+		count = 3;
+	pydesc = (struct POSIX_SECURITY*)malloc(
+		sizeof(struct POSIX_SECURITY) + count*sizeof(struct POSIX_ACE));
+	if (pydesc) {
+			/*
+			 * Copy inherited tags and adapt perms
+			 * Use requested mode, ignoring umask
+			 * (not possible with older versions of fuse)
+			 */
+		tagsset = 0;
+		defcnt = (pxdesc ? pxdesc->defcnt : 0);
+		for (i=defcnt-1; i>=0; i--) {
+			pyace = &pydesc->acl.ace[i];
+			*pyace = pxdesc->acl.ace[pxdesc->firstdef + i];
+			switch (pyace->tag) {
+			case POSIX_ACL_USER_OBJ :
+				pyace->perms &= (mode >> 6) & 7;
+				break;
+			case POSIX_ACL_GROUP_OBJ :
+				if (!(tagsset & POSIX_ACL_MASK))
+					pyace->perms &= (mode >> 3) & 7;
+				break;
+			case POSIX_ACL_OTHER :
+				pyace->perms &= mode & 7;
+				break;
+			case POSIX_ACL_MASK :
+				pyace->perms &= (mode >> 3) & 7;
+				break;
+			default :
+				break;
+			}
+			tagsset |= pyace->tag;
+		}
+		pydesc->acccnt = defcnt;
+		/*
+		 * If some standard tags were missing, append them from mode
+		 * and sort the list
+		 * Here we have to use the umask'ed mode
+		 */
+		if (~tagsset & (POSIX_ACL_USER_OBJ
+				 | POSIX_ACL_GROUP_OBJ | POSIX_ACL_OTHER)) {
+			i = defcnt;
+				/* owner was missing */
+			if (!(tagsset & POSIX_ACL_USER_OBJ)) {
+				pyace = &pydesc->acl.ace[i];
+				pyace->tag = POSIX_ACL_USER_OBJ;
+				pyace->id = -1;
+				pyace->perms = ((mode & ~mask) >> 6) & 7;
+				tagsset |= POSIX_ACL_USER_OBJ;
+				i++;
+			}
+				/* owning group was missing */
+			if (!(tagsset & POSIX_ACL_GROUP_OBJ)) {
+				pyace = &pydesc->acl.ace[i];
+				pyace->tag = POSIX_ACL_GROUP_OBJ;
+				pyace->id = -1;
+				pyace->perms = ((mode & ~mask) >> 3) & 7;
+				tagsset |= POSIX_ACL_GROUP_OBJ;
+				i++;
+			}
+				/* other was missing */
+			if (!(tagsset & POSIX_ACL_OTHER)) {
+				pyace = &pydesc->acl.ace[i];
+				pyace->tag = POSIX_ACL_OTHER;
+				pyace->id = -1;
+				pyace->perms = mode & ~mask & 7;
+				tagsset |= POSIX_ACL_OTHER;
+				i++;
+			}
+			pydesc->acccnt = i;
+			pydesc->firstdef = i;
+			pydesc->defcnt = 0;
+			ntfs_sort_posix(pydesc);
+		}
+
+		/*
+		 * append as a default ACL if a directory
+		 */
+		pydesc->firstdef = pydesc->acccnt;
+		if (defcnt && isdir) {
+			size = sizeof(struct POSIX_ACE)*defcnt;
+			memcpy(&pydesc->acl.ace[pydesc->firstdef],
+				 &pxdesc->acl.ace[pxdesc->firstdef],size);
+			pydesc->defcnt = defcnt;
+		} else {
+			pydesc->defcnt = 0;
+		}
+			/* assume special bits are not inherited */
+		posix_header(pydesc, mode & 07000);
+		if (!ntfs_valid_posix(pydesc)) {
+			ntfs_log_error("Error building an inherited Posix desc\n");
+			errno = EIO;
+			free(pydesc);
+			pydesc = (struct POSIX_SECURITY*)NULL;
+		}
+	} else
+		errno = ENOMEM;
+	return (pydesc);
+}
+
+static int merge_lists_posix(struct POSIX_ACE *targetace,
+		const struct POSIX_ACE *firstace,
+		const struct POSIX_ACE *secondace,
+		int firstcnt, int secondcnt)
+{
+	int k;
+
+	k = 0;
+		/*
+		 * No list is exhausted :
+		 *    if same tag+id in both list :
+		 *       ignore ACE from second list
+		 *    else take the one with smaller tag+id
+		 */
+	while ((firstcnt > 0) && (secondcnt > 0))
+		if ((firstace->tag == secondace->tag)
+		    && (firstace->id == secondace->id)) {
+			secondace++;
+			secondcnt--;
+		} else
+			if ((firstace->tag < secondace->tag)
+			   || ((firstace->tag == secondace->tag)
+				&& (firstace->id < secondace->id))) {
+				targetace->tag = firstace->tag;
+				targetace->id = firstace->id;
+				targetace->perms = firstace->perms;
+				firstace++;
+				targetace++;
+				firstcnt--;
+				k++;
+			} else {
+				targetace->tag = secondace->tag;
+				targetace->id = secondace->id;
+				targetace->perms = secondace->perms;
+				secondace++;
+				targetace++;
+				secondcnt--;
+				k++;
+			}
+		/*
+		 * One list is exhausted, copy the other one
+		 */
+	while (firstcnt > 0) {
+		targetace->tag = firstace->tag;
+		targetace->id = firstace->id;
+		targetace->perms = firstace->perms;
+		firstace++;
+		targetace++;
+		firstcnt--;
+		k++;
+	}
+	while (secondcnt > 0) {
+		targetace->tag = secondace->tag;
+		targetace->id = secondace->id;
+		targetace->perms = secondace->perms;
+		secondace++;
+		targetace++;
+		secondcnt--;
+		k++;
+	}
+	return (k);
+}
+
+/*
+ *		Merge two Posix ACLs
+ *	The input ACLs have to be adequately sorted
+ *
+ *	Returns the merged ACL, which is allocated and has to be freed by caller,
+ *	or NULL if failed
+ */
+
+struct POSIX_SECURITY *ntfs_merge_descr_posix(const struct POSIX_SECURITY *first,
+			const struct POSIX_SECURITY *second)
+{
+	struct POSIX_SECURITY *pxdesc;
+	struct POSIX_ACE *targetace;
+	const struct POSIX_ACE *firstace;
+	const struct POSIX_ACE *secondace;
+	size_t size;
+	int k;
+
+	size = sizeof(struct POSIX_SECURITY)
+		+ (first->acccnt + first->defcnt
+			+ second->acccnt + second->defcnt)*sizeof(struct POSIX_ACE);
+	pxdesc = (struct POSIX_SECURITY*)malloc(size);
+	if (pxdesc) {
+			/*
+			 * merge access ACEs
+			 */
+		firstace = first->acl.ace;
+		secondace = second->acl.ace;
+		targetace = pxdesc->acl.ace;
+		k = merge_lists_posix(targetace,firstace,secondace,
+			first->acccnt,second->acccnt);
+		pxdesc->acccnt = k;
+			/*
+			 * merge default ACEs
+			 */
+		pxdesc->firstdef = k;
+		firstace = &first->acl.ace[first->firstdef];
+		secondace = &second->acl.ace[second->firstdef];
+		targetace = &pxdesc->acl.ace[k];
+		k = merge_lists_posix(targetace,firstace,secondace,
+			first->defcnt,second->defcnt);
+		pxdesc->defcnt = k;
+			/*
+			 * build header
+			 */
+		pxdesc->acl.version = POSIX_VERSION;
+		pxdesc->acl.flags = 0;
+		pxdesc->acl.filler = 0;
+		pxdesc->mode = 0;
+		pxdesc->tagsset = 0;
+	} else
+		errno = ENOMEM;
+	return (pxdesc);
+}
+
+struct BUILD_CONTEXT {
+	BOOL isdir;
+	BOOL adminowns;
+	BOOL groupowns;
+	u16 selfuserperms;
+	u16 selfgrpperms;
+	u16 grpperms;
+	u16 othperms;
+	u16 mask;
+	u16 designates;
+	u16 withmask;
+	u16 rootspecial;
+} ;
+
+
+
+static BOOL build_user_denials(ACL *pacl,
+		const SID *usid, struct MAPPING* const mapping[],
+		ACE_FLAGS flags, const struct POSIX_ACE *pxace,
+		struct BUILD_CONTEXT *pset)
+{
+	BIGSID defsid;
+	ACCESS_ALLOWED_ACE *pdace;
+	const SID *sid;
+	int sidsz;
+	int pos;
+	int acecnt;
+	le32 grants;
+	le32 denials;
+	u16 perms;
+	u16 mixperms;
+	u16 tag;
+	BOOL rejected;
+	BOOL rootuser;
+	BOOL avoidmask;
+
+	rejected = FALSE;
+	tag = pxace->tag;
+	perms = pxace->perms;
+	rootuser = FALSE;
+	pos = le16_to_cpu(pacl->size);
+	acecnt = le16_to_cpu(pacl->ace_count);
+	avoidmask = (pset->mask == (POSIX_PERM_R | POSIX_PERM_W | POSIX_PERM_X))
+			&& ((pset->designates && pset->withmask)
+			   || (!pset->designates && !pset->withmask));
+	if (tag == POSIX_ACL_USER_OBJ) {
+		sid = usid;
+		sidsz = ntfs_sid_size(sid);
+		grants = OWNER_RIGHTS;
+	} else {
+		if (pxace->id) {
+			sid = NTFS_FIND_USID(mapping[MAPUSERS],
+				pxace->id, (SID*)&defsid);
+			grants = WORLD_RIGHTS;
+		} else {
+			sid = adminsid;
+			rootuser = TRUE;
+			grants = WORLD_RIGHTS & ~ROOT_OWNER_UNMARK;
+		}
+		if (sid) {
+			sidsz = ntfs_sid_size(sid);
+			/*
+			 * Insert denial of complement of mask for
+			 * each designated user (except root)
+			 * WRITE_OWNER is inserted so that
+			 * the mask can be identified
+			 */
+			if (!avoidmask && !rootuser) {
+				denials = WRITE_OWNER;
+				pdace = (ACCESS_DENIED_ACE*)&((char*)pacl)[pos];
+				if (pset->isdir) {
+					if (!(pset->mask & POSIX_PERM_X))
+						denials |= DIR_EXEC;
+					if (!(pset->mask & POSIX_PERM_W))
+						denials |= DIR_WRITE;
+					if (!(pset->mask & POSIX_PERM_R))
+						denials |= DIR_READ;
+				} else {
+					if (!(pset->mask & POSIX_PERM_X))
+						denials |= FILE_EXEC;
+					if (!(pset->mask & POSIX_PERM_W))
+						denials |= FILE_WRITE;
+					if (!(pset->mask & POSIX_PERM_R))
+						denials |= FILE_READ;
+				}
+				if (rootuser)
+					grants &= ~ROOT_OWNER_UNMARK;
+				pdace->type = ACCESS_DENIED_ACE_TYPE;
+				pdace->flags = flags;
+				pdace->size = cpu_to_le16(sidsz + 8);
+				pdace->mask = denials;
+				memcpy((char*)&pdace->sid, sid, sidsz);
+				pos += sidsz + 8;
+				acecnt++;
+			}
+		} else
+			rejected = TRUE;
+	}
+	if (!rejected) {
+		if (pset->isdir) {
+			if (perms & POSIX_PERM_X)
+				grants |= DIR_EXEC;
+			if (perms & POSIX_PERM_W)
+				grants |= DIR_WRITE;
+			if (perms & POSIX_PERM_R)
+				grants |= DIR_READ;
+		} else {
+			if (perms & POSIX_PERM_X)
+				grants |= FILE_EXEC;
+			if (perms & POSIX_PERM_W)
+				grants |= FILE_WRITE;
+			if (perms & POSIX_PERM_R)
+				grants |= FILE_READ;
+		}
+
+		/* a possible ACE to deny owner what he/she would */
+		/* induely get from administrator, group or world */
+		/* unless owner is administrator or group */
+
+		denials = const_cpu_to_le32(0);
+		pdace = (ACCESS_DENIED_ACE*)&((char*)pacl)[pos];
+		if (!pset->adminowns && !rootuser) {
+			if (!pset->groupowns) {
+				mixperms = pset->grpperms | pset->othperms;
+				if (tag == POSIX_ACL_USER_OBJ)
+					mixperms |= pset->selfuserperms;
+				if (pset->isdir) {
+					if (mixperms & POSIX_PERM_X)
+						denials |= DIR_EXEC;
+					if (mixperms & POSIX_PERM_W)
+						denials |= DIR_WRITE;
+					if (mixperms & POSIX_PERM_R)
+						denials |= DIR_READ;
+				} else {
+					if (mixperms & POSIX_PERM_X)
+						denials |= FILE_EXEC;
+					if (mixperms & POSIX_PERM_W)
+						denials |= FILE_WRITE;
+					if (mixperms & POSIX_PERM_R)
+						denials |= FILE_READ;
+				}
+			} else {
+				mixperms = ~pset->grpperms & pset->othperms;
+				if (tag == POSIX_ACL_USER_OBJ)
+					mixperms |= pset->selfuserperms;
+				if (pset->isdir) {
+					if (mixperms & POSIX_PERM_X)
+						denials |= DIR_EXEC;
+					if (mixperms & POSIX_PERM_W)
+						denials |= DIR_WRITE;
+					if (mixperms & POSIX_PERM_R)
+						denials |= DIR_READ;
+				} else {
+					if (mixperms & POSIX_PERM_X)
+						denials |= FILE_EXEC;
+					if (mixperms & POSIX_PERM_W)
+						denials |= FILE_WRITE;
+					if (mixperms & POSIX_PERM_R)
+						denials |= FILE_READ;
+				}
+			}
+			denials &= ~grants;
+			if (denials) {
+				pdace->type = ACCESS_DENIED_ACE_TYPE;
+				pdace->flags = flags;
+				pdace->size = cpu_to_le16(sidsz + 8);
+				pdace->mask = denials;
+				memcpy((char*)&pdace->sid, sid, sidsz);
+				pos += sidsz + 8;
+				acecnt++;
+			}
+		}
+	}
+	pacl->size = cpu_to_le16(pos);
+	pacl->ace_count = cpu_to_le16(acecnt);
+	return (!rejected);
+}
+
+static BOOL build_user_grants(ACL *pacl,
+		const SID *usid, struct MAPPING* const mapping[],
+		ACE_FLAGS flags, const struct POSIX_ACE *pxace,
+		struct BUILD_CONTEXT *pset)
+{
+	BIGSID defsid;
+	ACCESS_ALLOWED_ACE *pgace;
+	const SID *sid;
+	int sidsz;
+	int pos;
+	int acecnt;
+	le32 grants;
+	u16 perms;
+	u16 tag;
+	BOOL rejected;
+	BOOL rootuser;
+
+	rejected = FALSE;
+	tag = pxace->tag;
+	perms = pxace->perms;
+	rootuser = FALSE;
+	pos = le16_to_cpu(pacl->size);
+	acecnt = le16_to_cpu(pacl->ace_count);
+	if (tag == POSIX_ACL_USER_OBJ) {
+		sid = usid;
+		sidsz = ntfs_sid_size(sid);
+		grants = OWNER_RIGHTS;
+	} else {
+		if (pxace->id) {
+			sid = NTFS_FIND_USID(mapping[MAPUSERS],
+				pxace->id, (SID*)&defsid);
+			if (sid)
+				sidsz = ntfs_sid_size(sid);
+			else
+				rejected = TRUE;
+			grants = WORLD_RIGHTS;
+		} else {
+			sid = adminsid;
+			sidsz = ntfs_sid_size(sid);
+			rootuser = TRUE;
+			grants = WORLD_RIGHTS & ~ROOT_OWNER_UNMARK;
+		}
+	}
+	if (!rejected) {
+		if (pset->isdir) {
+			if (perms & POSIX_PERM_X)
+				grants |= DIR_EXEC;
+			if (perms & POSIX_PERM_W)
+				grants |= DIR_WRITE;
+			if (perms & POSIX_PERM_R)
+				grants |= DIR_READ;
+		} else {
+			if (perms & POSIX_PERM_X)
+				grants |= FILE_EXEC;
+			if (perms & POSIX_PERM_W)
+				grants |= FILE_WRITE;
+			if (perms & POSIX_PERM_R)
+				grants |= FILE_READ;
+		}
+		if (rootuser)
+			grants &= ~ROOT_OWNER_UNMARK;
+		pgace = (ACCESS_DENIED_ACE*)&((char*)pacl)[pos];
+		pgace->type = ACCESS_ALLOWED_ACE_TYPE;
+		pgace->size = cpu_to_le16(sidsz + 8);
+		pgace->flags = flags;
+		pgace->mask = grants;
+		memcpy((char*)&pgace->sid, sid, sidsz);
+		pos += sidsz + 8;
+		acecnt = le16_to_cpu(pacl->ace_count) + 1;
+		pacl->ace_count = cpu_to_le16(acecnt);
+		pacl->size = cpu_to_le16(pos);
+	}
+	return (!rejected);
+}
+
+
+			/* a grant ACE for group */
+			/* unless group-obj has the same rights as world */
+			/* but present if group is owner or owner is administrator */
+			/* this ACE will be inserted after denials for group */
+
+static BOOL build_group_denials_grant(ACL *pacl,
+		const SID *gsid, struct MAPPING* const mapping[],
+		ACE_FLAGS flags, const struct POSIX_ACE *pxace,
+		struct BUILD_CONTEXT *pset)
+{
+	BIGSID defsid;
+	ACCESS_ALLOWED_ACE *pdace;
+	ACCESS_ALLOWED_ACE *pgace;
+	const SID *sid;
+	int sidsz;
+	int pos;
+	int acecnt;
+	le32 grants;
+	le32 denials;
+	u16 perms;
+	u16 mixperms;
+	u16 tag;
+	BOOL avoidmask;
+	BOOL rootgroup;
+	BOOL rejected;
+
+	rejected = FALSE;
+	tag = pxace->tag;
+	perms = pxace->perms;
+	pos = le16_to_cpu(pacl->size);
+	acecnt = le16_to_cpu(pacl->ace_count);
+	rootgroup = FALSE;
+	avoidmask = (pset->mask == (POSIX_PERM_R | POSIX_PERM_W | POSIX_PERM_X))
+			&& ((pset->designates && pset->withmask)
+			   || (!pset->designates && !pset->withmask));
+	if (tag == POSIX_ACL_GROUP_OBJ)
+		sid = gsid;
+	else
+		if (pxace->id)
+			sid = NTFS_FIND_GSID(mapping[MAPGROUPS],
+				pxace->id, (SID*)&defsid);
+		else {
+			sid = adminsid;
+			rootgroup = TRUE;
+		}
+	if (sid) {
+		sidsz = ntfs_sid_size(sid);
+		/*
+		 * Insert denial of complement of mask for
+		 * each group
+		 * WRITE_OWNER is inserted so that
+		 * the mask can be identified
+		 * Note : this mask may lead on Windows to
+		 * deny rights to administrators belonging
+		 * to some user group
+		 */
+		if ((!avoidmask && !rootgroup)
+		    || (pset->rootspecial
+			&& (tag == POSIX_ACL_GROUP_OBJ))) {
+			denials = WRITE_OWNER;
+			pdace = (ACCESS_DENIED_ACE*)&((char*)pacl)[pos];
+			if (pset->isdir) {
+				if (!(pset->mask & POSIX_PERM_X))
+					denials |= DIR_EXEC;
+				if (!(pset->mask & POSIX_PERM_W))
+					denials |= DIR_WRITE;
+				if (!(pset->mask & POSIX_PERM_R))
+					denials |= DIR_READ;
+			} else {
+				if (!(pset->mask & POSIX_PERM_X))
+					denials |= FILE_EXEC;
+				if (!(pset->mask & POSIX_PERM_W))
+					denials |= FILE_WRITE;
+				if (!(pset->mask & POSIX_PERM_R))
+					denials |= FILE_READ;
+			}
+			pdace->type = ACCESS_DENIED_ACE_TYPE;
+			pdace->flags = flags;
+			pdace->size = cpu_to_le16(sidsz + 8);
+			pdace->mask = denials;
+			memcpy((char*)&pdace->sid, sid, sidsz);
+			pos += sidsz + 8;
+			acecnt++;
+		}
+	} else
+		rejected = TRUE;
+	if (!rejected
+	    && (pset->adminowns
+		|| pset->groupowns
+		|| avoidmask
+		|| rootgroup
+		|| (perms != pset->othperms))) {
+		grants = WORLD_RIGHTS;
+		if (rootgroup)
+			grants &= ~ROOT_GROUP_UNMARK;
+		if (pset->isdir) {
+			if (perms & POSIX_PERM_X)
+				grants |= DIR_EXEC;
+			if (perms & POSIX_PERM_W)
+				grants |= DIR_WRITE;
+			if (perms & POSIX_PERM_R)
+				grants |= DIR_READ;
+		} else {
+			if (perms & POSIX_PERM_X)
+				grants |= FILE_EXEC;
+			if (perms & POSIX_PERM_W)
+				grants |= FILE_WRITE;
+			if (perms & POSIX_PERM_R)
+				grants |= FILE_READ;
+		}
+
+		/* a possible ACE to deny group what it would get from world */
+		/* or administrator, unless owner is administrator or group */
+
+		denials = const_cpu_to_le32(0);
+		pdace = (ACCESS_DENIED_ACE*)&((char*)pacl)[pos];
+		if (!pset->adminowns
+		    && !pset->groupowns
+		    && !rootgroup) {
+			mixperms = pset->othperms;
+			if (tag == POSIX_ACL_GROUP_OBJ)
+				mixperms |= pset->selfgrpperms;
+			if (pset->isdir) {
+				if (mixperms & POSIX_PERM_X)
+					denials |= DIR_EXEC;
+				if (mixperms & POSIX_PERM_W)
+					denials |= DIR_WRITE;
+				if (mixperms & POSIX_PERM_R)
+					denials |= DIR_READ;
+			} else {
+				if (mixperms & POSIX_PERM_X)
+					denials |= FILE_EXEC;
+				if (mixperms & POSIX_PERM_W)
+					denials |= FILE_WRITE;
+				if (mixperms & POSIX_PERM_R)
+					denials |= FILE_READ;
+			}
+			denials &= ~(grants | OWNER_RIGHTS);
+			if (denials) {
+				pdace->type = ACCESS_DENIED_ACE_TYPE;
+				pdace->flags = flags;
+				pdace->size = cpu_to_le16(sidsz + 8);
+				pdace->mask = denials;
+				memcpy((char*)&pdace->sid, sid, sidsz);
+				pos += sidsz + 8;
+				acecnt++;
+			}
+		}
+
+			/* now insert grants to group if more than world */
+		if (pset->adminowns
+			|| pset->groupowns
+			|| (avoidmask && (pset->designates || pset->withmask))
+			|| (perms & ~pset->othperms)
+			|| (pset->rootspecial
+			   && (tag == POSIX_ACL_GROUP_OBJ))
+			|| (tag == POSIX_ACL_GROUP)) {
+			if (rootgroup)
+				grants &= ~ROOT_GROUP_UNMARK;
+			pgace = (ACCESS_DENIED_ACE*)&((char*)pacl)[pos];
+			pgace->type = ACCESS_ALLOWED_ACE_TYPE;
+			pgace->flags = flags;
+			pgace->size = cpu_to_le16(sidsz + 8);
+			pgace->mask = grants;
+			memcpy((char*)&pgace->sid, sid, sidsz);
+			pos += sidsz + 8;
+			acecnt++;
+		}
+	}
+	pacl->size = cpu_to_le16(pos);
+	pacl->ace_count = cpu_to_le16(acecnt);
+	return (!rejected);
+}
+
+
+/*
+ *		Build an ACL composed of several ACE's
+ *	returns size of ACL or zero if failed
+ *
+ *	Three schemes are defined :
+ *
+ *	1) if root is neither owner nor group up to 7 ACE's are set up :
+ *	- denials to owner (preventing grants to world or group to apply)
+ *        + mask denials to designated user (unless mask allows all)
+ *        + denials to designated user
+ *	- grants to owner (always present - first grant)
+ *        + grants to designated user
+ *        + mask denial to group (unless mask allows all)
+ *	- denials to group (preventing grants to world to apply) 
+ *	- grants to group (unless group has no more than world rights)
+ *        + mask denials to designated group (unless mask allows all)
+ *        + grants to designated group
+ *        + denials to designated group
+ *	- grants to world (unless none)
+ *	- full privileges to administrator, always present
+ *	- full privileges to system, always present
+ *
+ *	The same scheme is applied for Posix ACLs, with the mask represented
+ *	as denials prepended to grants for designated users and groups
+ *
+ *	This is inspired by an Internet Draft from Marius Aamodt Eriksen
+ *	for mapping NFSv4 ACLs to Posix ACLs (draft-ietf-nfsv4-acl-mapping-00.txt)
+ *	More recent versions of the draft (draft-ietf-nfsv4-acl-mapping-05.txt)
+ *	are not followed, as they ignore the Posix mask and lead to
+ *	loss of compatibility with Linux implementations on other fs.
+ *
+ *	Note that denials to group are located after grants to owner.
+ *	This only occurs in the unfrequent situation where world
+ *	has more rights than group and cannot be avoided if owner and other
+ *	have some common right which is denied to group (eg for mode 745
+ *	executing has to be denied to group, but not to owner or world).
+ *	This rare situation is processed by Windows correctly, but
+ *	Windows utilities may want to change the order, with a
+ *	consequence of applying the group denials to the Windows owner.
+ *	The interpretation on Linux is not affected by the order change.
+ *
+ *	2) if root is either owner or group, two problems arise :
+ *	- granting full rights to administrator (as needed to transpose
+ *	  to Windows rights bypassing granting to root) would imply
+ *	  Linux permissions to always be seen as rwx, no matter the chmod
+ *	- there is no different SID to separate an administrator owner
+ *	  from an administrator group. Hence Linux permissions for owner
+ *	  would always be similar to permissions to group.
+ *
+ *	as a work-around, up to 5 ACE's are set up if owner or group :
+ *	- grants to owner, always present at first position
+ *	- grants to group, always present
+ *	- grants to world, unless none
+ *	- full privileges to administrator, always present
+ *	- full privileges to system, always present
+ *
+ *	On Windows, these ACE's are processed normally, though they
+ *	are redundant (owner, group and administrator are the same,
+ *	as a consequence any denials would damage administrator rights)
+ *	but on Linux, privileges to administrator are ignored (they
+ *	are not needed as root has always full privileges), and
+ *	neither grants to group are applied to owner, nor grants to
+ *	world are applied to owner or group.
+ *
+ *	3) finally a similar situation arises when group is owner (they
+ *	 have the same SID), but is not root.
+ *	 In this situation up to 6 ACE's are set up :
+ *
+ *	- denials to owner (preventing grants to world to apply)
+ *	- grants to owner (always present)
+ *	- grants to group (unless groups has same rights as world)
+ *	- grants to world (unless none)
+ *	- full privileges to administrator, always present
+ *	- full privileges to system, always present
+ *
+ *	On Windows, these ACE's are processed normally, though they
+ *	are redundant (as owner and group are the same), but this has
+ *	no impact on administrator rights
+ *
+ *	Special flags (S_ISVTX, S_ISGID, S_ISUID) :
+ *	an extra null ACE is inserted to hold these flags, using
+ *	the same conventions as cygwin.
+ *
+ */
+
+static int buildacls_posix(struct MAPPING* const mapping[],
+		char *secattr, int offs, const struct POSIX_SECURITY *pxdesc,
+		int isdir, const SID *usid, const SID *gsid)
+{
+        struct BUILD_CONTEXT aceset[2], *pset;
+	BOOL adminowns;
+	BOOL groupowns;
+	ACL *pacl;
+	ACCESS_ALLOWED_ACE *pgace;
+	ACCESS_ALLOWED_ACE *pdace;
+	const struct POSIX_ACE *pxace;
+	BOOL ok;
+	mode_t mode;
+	u16 tag;
+	u16 perms;
+	ACE_FLAGS flags;
+	int pos;
+	int i;
+	int k;
+	BIGSID defsid;
+	const SID *sid;
+	int acecnt;
+	int usidsz;
+	int wsidsz;
+	int asidsz;
+	int ssidsz;
+	int nsidsz;
+	le32 grants;
+
+	usidsz = ntfs_sid_size(usid);
+	wsidsz = ntfs_sid_size(worldsid);
+	asidsz = ntfs_sid_size(adminsid);
+	ssidsz = ntfs_sid_size(systemsid);
+	mode = pxdesc->mode;
+		/* adminowns and groupowns are used for both lists */
+	adminowns = ntfs_same_sid(usid, adminsid)
+		 || ntfs_same_sid(gsid, adminsid);
+	groupowns = !adminowns && ntfs_same_sid(usid, gsid);
+
+	ok = TRUE;
+
+	/* ACL header */
+	pacl = (ACL*)&secattr[offs];
+	pacl->revision = ACL_REVISION;
+	pacl->alignment1 = 0;
+	pacl->size = cpu_to_le16(sizeof(ACL) + usidsz + 8);
+	pacl->ace_count = const_cpu_to_le16(0);
+	pacl->alignment2 = const_cpu_to_le16(0);
+
+		/*
+		 * Determine what is allowed to some group or world
+		 * to prevent designated users or other groups to get
+		 * rights from groups or world
+		 * Do the same if owner and group appear as designated
+		 * user or group
+		 * Also get global mask
+		 */
+	for (k=0; k<2; k++) {
+		pset = &aceset[k];
+		pset->selfuserperms = 0;
+		pset->selfgrpperms = 0;
+		pset->grpperms = 0;
+		pset->othperms = 0;
+		pset->mask = (POSIX_PERM_R | POSIX_PERM_W | POSIX_PERM_X);
+		pset->designates = 0;
+		pset->withmask = 0;
+		pset->rootspecial = 0;
+		pset->adminowns = adminowns;
+		pset->groupowns = groupowns;
+		pset->isdir = isdir;
+	}
+
+	for (i=pxdesc->acccnt+pxdesc->defcnt-1; i>=0; i--) {
+		if (i >= pxdesc->acccnt) {
+			pset = &aceset[1];
+			pxace = &pxdesc->acl.ace[i + pxdesc->firstdef - pxdesc->acccnt];
+		} else {
+			pset = &aceset[0];
+			pxace = &pxdesc->acl.ace[i];
+		}
+		switch (pxace->tag) {
+		case POSIX_ACL_USER :
+			pset->designates++;
+			if (pxace->id) {
+				sid = NTFS_FIND_USID(mapping[MAPUSERS],
+					pxace->id, (SID*)&defsid);
+				if (sid && ntfs_same_sid(sid,usid))
+					pset->selfuserperms |= pxace->perms;
+			} else
+				/* root as designated user is processed apart */
+				pset->rootspecial = TRUE;
+			break;
+		case POSIX_ACL_GROUP :
+			pset->designates++;
+			if (pxace->id) {
+				sid = NTFS_FIND_GSID(mapping[MAPUSERS],
+					pxace->id, (SID*)&defsid);
+				if (sid && ntfs_same_sid(sid,gsid))
+					pset->selfgrpperms |= pxace->perms;
+			} else
+				/* root as designated group is processed apart */
+				pset->rootspecial = TRUE;
+			/* fall through */
+		case POSIX_ACL_GROUP_OBJ :
+			pset->grpperms |= pxace->perms;
+			break;
+		case POSIX_ACL_OTHER :
+			pset->othperms = pxace->perms;
+			break;
+		case POSIX_ACL_MASK :
+			pset->withmask++;
+			pset->mask = pxace->perms;
+		default :
+			break;
+		}
+	}
+
+if (pxdesc->defcnt && (pxdesc->firstdef != pxdesc->acccnt)) {
+ntfs_log_error("** error : access and default not consecutive\n");
+return (0);
+}
+			/*
+			 * First insert all denials for owner and each
+			 * designated user (with mask if needed)
+			 */
+
+	pacl->ace_count = const_cpu_to_le16(0);
+	pacl->size = const_cpu_to_le16(sizeof(ACL));
+	for (i=0; (i<(pxdesc->acccnt + pxdesc->defcnt)) && ok; i++) {
+		if (i >= pxdesc->acccnt) {
+			flags = INHERIT_ONLY_ACE
+				| OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
+			pset = &aceset[1];
+			pxace = &pxdesc->acl.ace[i + pxdesc->firstdef - pxdesc->acccnt];
+		} else {
+			if (pxdesc->defcnt)
+				flags = NO_PROPAGATE_INHERIT_ACE;
+			else
+				flags = (isdir ? DIR_INHERITANCE
+					   : FILE_INHERITANCE);
+			pset = &aceset[0];
+			pxace = &pxdesc->acl.ace[i];
+		}
+		tag = pxace->tag;
+		perms = pxace->perms;
+		switch (tag) {
+
+			/* insert denial ACEs for each owner or allowed user */
+
+		case POSIX_ACL_USER :
+		case POSIX_ACL_USER_OBJ :
+
+			ok = build_user_denials(pacl,
+				usid, mapping, flags, pxace, pset);
+			break;
+		default :
+			break;
+		}
+	}
+
+		/*
+		 * for directories, insert a world execution denial
+		 * inherited to plain files.
+		 * This is to prevent Windows from granting execution
+		 * of files through inheritance from parent directory
+		 */
+
+	if (isdir && ok) {
+		pos = le16_to_cpu(pacl->size);
+		pdace = (ACCESS_DENIED_ACE*) &secattr[offs + pos];
+		pdace->type = ACCESS_DENIED_ACE_TYPE;
+		pdace->flags = INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE;
+		pdace->size = cpu_to_le16(wsidsz + 8);
+		pdace->mask = FILE_EXEC;
+		memcpy((char*)&pdace->sid, worldsid, wsidsz);
+		pos += wsidsz + 8;
+		acecnt = le16_to_cpu(pacl->ace_count) + 1;
+		pacl->ace_count = cpu_to_le16(acecnt);
+		pacl->size = cpu_to_le16(pos);
+	}
+
+			/*
+			 * now insert (if needed)
+			 * - grants to owner and designated users
+			 * - mask and denials for all groups
+			 * - grants to other
+			 */
+
+	for (i=0; (i<(pxdesc->acccnt + pxdesc->defcnt)) && ok; i++) {
+		if (i >= pxdesc->acccnt) {
+			flags = INHERIT_ONLY_ACE
+				| OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
+			pset = &aceset[1];
+			pxace = &pxdesc->acl.ace[i + pxdesc->firstdef - pxdesc->acccnt];
+		} else {
+			if (pxdesc->defcnt)
+				flags = NO_PROPAGATE_INHERIT_ACE;
+			else
+				flags = (isdir ? DIR_INHERITANCE
+					   : FILE_INHERITANCE);
+			pset = &aceset[0];
+			pxace = &pxdesc->acl.ace[i];
+		}
+		tag = pxace->tag;
+		perms = pxace->perms;
+		switch (tag) {
+
+			/* ACE for each owner or allowed user */
+
+		case POSIX_ACL_USER :
+		case POSIX_ACL_USER_OBJ :
+			ok = build_user_grants(pacl,usid,
+					mapping,flags,pxace,pset);
+			break;
+
+		case POSIX_ACL_GROUP :
+		case POSIX_ACL_GROUP_OBJ :
+
+			/* denials and grants for groups */
+
+			ok = build_group_denials_grant(pacl,gsid,
+					mapping,flags,pxace,pset);
+			break;
+
+		case POSIX_ACL_OTHER :
+
+			/* grants for other users */
+
+			pos = le16_to_cpu(pacl->size);
+			pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos];
+			grants = WORLD_RIGHTS;
+			if (isdir) {
+				if (perms & POSIX_PERM_X)
+					grants |= DIR_EXEC;
+				if (perms & POSIX_PERM_W)
+					grants |= DIR_WRITE;
+				if (perms & POSIX_PERM_R)
+					grants |= DIR_READ;
+			} else {
+				if (perms & POSIX_PERM_X)
+					grants |= FILE_EXEC;
+				if (perms & POSIX_PERM_W)
+					grants |= FILE_WRITE;
+				if (perms & POSIX_PERM_R)
+					grants |= FILE_READ;
+			}
+			pgace->type = ACCESS_ALLOWED_ACE_TYPE;
+			pgace->flags = flags;
+			pgace->size = cpu_to_le16(wsidsz + 8);
+			pgace->mask = grants;
+			memcpy((char*)&pgace->sid, worldsid, wsidsz);
+			pos += wsidsz + 8;
+			acecnt = le16_to_cpu(pacl->ace_count) + 1;
+			pacl->ace_count = cpu_to_le16(acecnt);
+			pacl->size = cpu_to_le16(pos);
+			break;
+		}
+	}
+
+	if (!ok) {
+		errno = EINVAL;
+		pos = 0;
+	} else {
+		/* an ACE for administrators */
+		/* always full access */
+
+		pos = le16_to_cpu(pacl->size);
+		acecnt = le16_to_cpu(pacl->ace_count);
+		if (isdir)
+			flags = OBJECT_INHERIT_ACE
+				| CONTAINER_INHERIT_ACE;
+		else
+			flags = NO_PROPAGATE_INHERIT_ACE;
+		pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos];
+		pgace->type = ACCESS_ALLOWED_ACE_TYPE;
+		pgace->flags = flags;
+		pgace->size = cpu_to_le16(asidsz + 8);
+		grants = OWNER_RIGHTS | FILE_READ | FILE_WRITE | FILE_EXEC;
+		pgace->mask = grants;
+		memcpy((char*)&pgace->sid, adminsid, asidsz);
+		pos += asidsz + 8;
+		acecnt++;
+
+		/* an ACE for system (needed ?) */
+		/* always full access */
+
+		pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos];
+		pgace->type = ACCESS_ALLOWED_ACE_TYPE;
+		pgace->flags = flags;
+		pgace->size = cpu_to_le16(ssidsz + 8);
+		grants = OWNER_RIGHTS | FILE_READ | FILE_WRITE | FILE_EXEC;
+		pgace->mask = grants;
+		memcpy((char*)&pgace->sid, systemsid, ssidsz);
+		pos += ssidsz + 8;
+		acecnt++;
+
+		/* a null ACE to hold special flags */
+		/* using the same representation as cygwin */
+
+		if (mode & (S_ISVTX | S_ISGID | S_ISUID)) {
+			nsidsz = ntfs_sid_size(nullsid);
+			pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos];
+			pgace->type = ACCESS_ALLOWED_ACE_TYPE;
+			pgace->flags = NO_PROPAGATE_INHERIT_ACE;
+			pgace->size = cpu_to_le16(nsidsz + 8);
+			grants = const_cpu_to_le32(0);
+			if (mode & S_ISUID)
+				grants |= FILE_APPEND_DATA;
+			if (mode & S_ISGID)
+				grants |= FILE_WRITE_DATA;
+			if (mode & S_ISVTX)
+				grants |= FILE_READ_DATA;
+			pgace->mask = grants;
+			memcpy((char*)&pgace->sid, nullsid, nsidsz);
+			pos += nsidsz + 8;
+			acecnt++;
+		}
+
+		/* fix ACL header */
+		pacl->size = cpu_to_le16(pos);
+		pacl->ace_count = cpu_to_le16(acecnt);
+	}
+	return (ok ? pos : 0);
+}
+
+#endif /* POSIXACLS */
+
+static int buildacls(char *secattr, int offs, mode_t mode, int isdir,
+	       const SID * usid, const SID * gsid)
+{
+	ACL *pacl;
+	ACCESS_ALLOWED_ACE *pgace;
+	ACCESS_ALLOWED_ACE *pdace;
+	BOOL adminowns;
+	BOOL groupowns;
+	ACE_FLAGS gflags;
+	int pos;
+	int acecnt;
+	int usidsz;
+	int gsidsz;
+	int wsidsz;
+	int asidsz;
+	int ssidsz;
+	int nsidsz;
+	le32 grants;
+	le32 denials;
+
+	usidsz = ntfs_sid_size(usid);
+	gsidsz = ntfs_sid_size(gsid);
+	wsidsz = ntfs_sid_size(worldsid);
+	asidsz = ntfs_sid_size(adminsid);
+	ssidsz = ntfs_sid_size(systemsid);
+	adminowns = ntfs_same_sid(usid, adminsid)
+	         || ntfs_same_sid(gsid, adminsid);
+	groupowns = !adminowns && ntfs_same_sid(usid, gsid);
+
+	/* ACL header */
+	pacl = (ACL*)&secattr[offs];
+	pacl->revision = ACL_REVISION;
+	pacl->alignment1 = 0;
+	pacl->size = cpu_to_le16(sizeof(ACL) + usidsz + 8);
+	pacl->ace_count = const_cpu_to_le16(1);
+	pacl->alignment2 = const_cpu_to_le16(0);
+	pos = sizeof(ACL);
+	acecnt = 0;
+
+	/* compute a grant ACE for owner */
+	/* this ACE will be inserted after denial for owner */
+
+	grants = OWNER_RIGHTS;
+	if (isdir) {
+		gflags = DIR_INHERITANCE;
+		if (mode & S_IXUSR)
+			grants |= DIR_EXEC;
+		if (mode & S_IWUSR)
+			grants |= DIR_WRITE;
+		if (mode & S_IRUSR)
+			grants |= DIR_READ;
+	} else {
+		gflags = FILE_INHERITANCE;
+		if (mode & S_IXUSR)
+			grants |= FILE_EXEC;
+		if (mode & S_IWUSR)
+			grants |= FILE_WRITE;
+		if (mode & S_IRUSR)
+			grants |= FILE_READ;
+	}
+
+	/* a possible ACE to deny owner what he/she would */
+	/* induely get from administrator, group or world */
+        /* unless owner is administrator or group */
+
+	denials = const_cpu_to_le32(0);
+	pdace = (ACCESS_DENIED_ACE*) &secattr[offs + pos];
+	if (!adminowns) {
+		if (!groupowns) {
+			if (isdir) {
+				pdace->flags = DIR_INHERITANCE;
+				if (mode & (S_IXGRP | S_IXOTH))
+					denials |= DIR_EXEC;
+				if (mode & (S_IWGRP | S_IWOTH))
+					denials |= DIR_WRITE;
+				if (mode & (S_IRGRP | S_IROTH))
+					denials |= DIR_READ;
+			} else {
+				pdace->flags = FILE_INHERITANCE;
+				if (mode & (S_IXGRP | S_IXOTH))
+					denials |= FILE_EXEC;
+				if (mode & (S_IWGRP | S_IWOTH))
+					denials |= FILE_WRITE;
+				if (mode & (S_IRGRP | S_IROTH))
+					denials |= FILE_READ;
+			}
+		} else {
+			if (isdir) {
+				pdace->flags = DIR_INHERITANCE;
+				if ((mode & S_IXOTH) && !(mode & S_IXGRP))
+					denials |= DIR_EXEC;
+				if ((mode & S_IWOTH) && !(mode & S_IWGRP))
+					denials |= DIR_WRITE;
+				if ((mode & S_IROTH) && !(mode & S_IRGRP))
+					denials |= DIR_READ;
+			} else {
+				pdace->flags = FILE_INHERITANCE;
+				if ((mode & S_IXOTH) && !(mode & S_IXGRP))
+					denials |= FILE_EXEC;
+				if ((mode & S_IWOTH) && !(mode & S_IWGRP))
+					denials |= FILE_WRITE;
+				if ((mode & S_IROTH) && !(mode & S_IRGRP))
+					denials |= FILE_READ;
+			}
+		}
+		denials &= ~grants;
+		if (denials) {
+			pdace->type = ACCESS_DENIED_ACE_TYPE;
+			pdace->size = cpu_to_le16(usidsz + 8);
+			pdace->mask = denials;
+			memcpy((char*)&pdace->sid, usid, usidsz);
+			pos += usidsz + 8;
+			acecnt++;
+		}
+	}
+		/*
+		 * for directories, a world execution denial
+		 * inherited to plain files
+		 */
+
+	if (isdir) {
+		pdace = (ACCESS_DENIED_ACE*) &secattr[offs + pos];
+			pdace->type = ACCESS_DENIED_ACE_TYPE;
+			pdace->flags = INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE;
+			pdace->size = cpu_to_le16(wsidsz + 8);
+			pdace->mask = FILE_EXEC;
+			memcpy((char*)&pdace->sid, worldsid, wsidsz);
+			pos += wsidsz + 8;
+			acecnt++;
+	}
+
+
+		/* now insert grants to owner */
+	pgace = (ACCESS_ALLOWED_ACE*) &secattr[offs + pos];
+	pgace->type = ACCESS_ALLOWED_ACE_TYPE;
+	pgace->size = cpu_to_le16(usidsz + 8);
+	pgace->flags = gflags;
+	pgace->mask = grants;
+	memcpy((char*)&pgace->sid, usid, usidsz);
+	pos += usidsz + 8;
+	acecnt++;
+
+	/* a grant ACE for group */
+	/* unless group has the same rights as world */
+	/* but present if group is owner or owner is administrator */
+	/* this ACE will be inserted after denials for group */
+
+	if (adminowns
+	    || groupowns
+	    || (((mode >> 3) ^ mode) & 7)) {
+		grants = WORLD_RIGHTS;
+		if (isdir) {
+			gflags = DIR_INHERITANCE;
+			if (mode & S_IXGRP)
+				grants |= DIR_EXEC;
+			if (mode & S_IWGRP)
+				grants |= DIR_WRITE;
+			if (mode & S_IRGRP)
+				grants |= DIR_READ;
+		} else {
+			gflags = FILE_INHERITANCE;
+			if (mode & S_IXGRP)
+				grants |= FILE_EXEC;
+			if (mode & S_IWGRP)
+				grants |= FILE_WRITE;
+			if (mode & S_IRGRP)
+				grants |= FILE_READ;
+		}
+
+		/* a possible ACE to deny group what it would get from world */
+		/* or administrator, unless owner is administrator or group */
+
+		denials = const_cpu_to_le32(0);
+		pdace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos];
+		if (!adminowns && !groupowns) {
+			if (isdir) {
+				pdace->flags = DIR_INHERITANCE;
+				if (mode & S_IXOTH)
+					denials |= DIR_EXEC;
+				if (mode & S_IWOTH)
+					denials |= DIR_WRITE;
+				if (mode & S_IROTH)
+					denials |= DIR_READ;
+			} else {
+				pdace->flags = FILE_INHERITANCE;
+				if (mode & S_IXOTH)
+					denials |= FILE_EXEC;
+				if (mode & S_IWOTH)
+					denials |= FILE_WRITE;
+				if (mode & S_IROTH)
+					denials |= FILE_READ;
+			}
+			denials &= ~(grants | OWNER_RIGHTS);
+			if (denials) {
+				pdace->type = ACCESS_DENIED_ACE_TYPE;
+				pdace->size = cpu_to_le16(gsidsz + 8);
+				pdace->mask = denials;
+				memcpy((char*)&pdace->sid, gsid, gsidsz);
+				pos += gsidsz + 8;
+				acecnt++;
+			}
+		}
+
+		if (adminowns
+		   || groupowns
+		   || ((mode >> 3) & ~mode & 7)) {
+				/* now insert grants to group */
+				/* if more rights than other */
+			pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos];
+			pgace->type = ACCESS_ALLOWED_ACE_TYPE;
+			pgace->flags = gflags;
+			pgace->size = cpu_to_le16(gsidsz + 8);
+			pgace->mask = grants;
+			memcpy((char*)&pgace->sid, gsid, gsidsz);
+			pos += gsidsz + 8;
+			acecnt++;
+		}
+	}
+
+	/* an ACE for world users */
+
+	pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos];
+	pgace->type = ACCESS_ALLOWED_ACE_TYPE;
+	grants = WORLD_RIGHTS;
+	if (isdir) {
+		pgace->flags = DIR_INHERITANCE;
+		if (mode & S_IXOTH)
+			grants |= DIR_EXEC;
+		if (mode & S_IWOTH)
+			grants |= DIR_WRITE;
+		if (mode & S_IROTH)
+			grants |= DIR_READ;
+	} else {
+		pgace->flags = FILE_INHERITANCE;
+		if (mode & S_IXOTH)
+			grants |= FILE_EXEC;
+		if (mode & S_IWOTH)
+			grants |= FILE_WRITE;
+		if (mode & S_IROTH)
+			grants |= FILE_READ;
+	}
+	pgace->size = cpu_to_le16(wsidsz + 8);
+	pgace->mask = grants;
+	memcpy((char*)&pgace->sid, worldsid, wsidsz);
+	pos += wsidsz + 8;
+	acecnt++;
+
+	/* an ACE for administrators */
+	/* always full access */
+
+	pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos];
+	pgace->type = ACCESS_ALLOWED_ACE_TYPE;
+	if (isdir)
+		pgace->flags = DIR_INHERITANCE;
+	else
+		pgace->flags = FILE_INHERITANCE;
+	pgace->size = cpu_to_le16(asidsz + 8);
+	grants = OWNER_RIGHTS | FILE_READ | FILE_WRITE | FILE_EXEC;
+	pgace->mask = grants;
+	memcpy((char*)&pgace->sid, adminsid, asidsz);
+	pos += asidsz + 8;
+	acecnt++;
+
+	/* an ACE for system (needed ?) */
+	/* always full access */
+
+	pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos];
+	pgace->type = ACCESS_ALLOWED_ACE_TYPE;
+	if (isdir)
+		pgace->flags = DIR_INHERITANCE;
+	else
+		pgace->flags = FILE_INHERITANCE;
+	pgace->size = cpu_to_le16(ssidsz + 8);
+	grants = OWNER_RIGHTS | FILE_READ | FILE_WRITE | FILE_EXEC;
+	pgace->mask = grants;
+	memcpy((char*)&pgace->sid, systemsid, ssidsz);
+	pos += ssidsz + 8;
+	acecnt++;
+
+	/* a null ACE to hold special flags */
+	/* using the same representation as cygwin */
+
+	if (mode & (S_ISVTX | S_ISGID | S_ISUID)) {
+		nsidsz = ntfs_sid_size(nullsid);
+		pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos];
+		pgace->type = ACCESS_ALLOWED_ACE_TYPE;
+		pgace->flags = NO_PROPAGATE_INHERIT_ACE;
+		pgace->size = cpu_to_le16(nsidsz + 8);
+		grants = const_cpu_to_le32(0);
+		if (mode & S_ISUID)
+			grants |= FILE_APPEND_DATA;
+		if (mode & S_ISGID)
+			grants |= FILE_WRITE_DATA;
+		if (mode & S_ISVTX)
+			grants |= FILE_READ_DATA;
+		pgace->mask = grants;
+		memcpy((char*)&pgace->sid, nullsid, nsidsz);
+		pos += nsidsz + 8;
+		acecnt++;
+	}
+
+	/* fix ACL header */
+	pacl->size = cpu_to_le16(pos);
+	pacl->ace_count = cpu_to_le16(acecnt);
+	return (pos);
+}
+
+#if POSIXACLS
+
+/*
+ *		Build a full security descriptor from a Posix ACL
+ *	returns descriptor in allocated memory, must free() after use
+ */
+
+char *ntfs_build_descr_posix(struct MAPPING* const mapping[],
+			struct POSIX_SECURITY *pxdesc,
+			int isdir, const SID *usid, const SID *gsid)
+{
+	int newattrsz;
+	SECURITY_DESCRIPTOR_RELATIVE *pnhead;
+	char *newattr;
+	int aclsz;
+	int usidsz;
+	int gsidsz;
+	int wsidsz;
+	int asidsz;
+	int ssidsz;
+	int k;
+
+	usidsz = ntfs_sid_size(usid);
+	gsidsz = ntfs_sid_size(gsid);
+	wsidsz = ntfs_sid_size(worldsid);
+	asidsz = ntfs_sid_size(adminsid);
+	ssidsz = ntfs_sid_size(systemsid);
+
+	/* allocate enough space for the new security attribute */
+	newattrsz = sizeof(SECURITY_DESCRIPTOR_RELATIVE)	/* header */
+	    + usidsz + gsidsz	/* usid and gsid */
+	    + sizeof(ACL)	/* acl header */
+	    + 2*(8 + usidsz)	/* two possible ACE for user */
+	    + 3*(8 + gsidsz)	/* three possible ACE for group and mask */
+	    + 8 + wsidsz	/* one ACE for world */
+	    + 8 + asidsz	/* one ACE for admin */
+	    + 8 + ssidsz;	/* one ACE for system */
+	if (isdir)			/* a world denial for directories */
+		newattrsz += 8 + wsidsz;
+	if (pxdesc->mode & 07000)	/* a NULL ACE for special modes */
+		newattrsz += 8 + ntfs_sid_size(nullsid);
+				/* account for non-owning users and groups */
+	for (k=0; k<pxdesc->acccnt; k++) {
+		if ((pxdesc->acl.ace[k].tag == POSIX_ACL_USER)
+		    || (pxdesc->acl.ace[k].tag == POSIX_ACL_GROUP))
+			newattrsz += 3*40; /* fixme : maximum size */
+	}
+				/* account for default ACE's */
+	newattrsz += 2*40*pxdesc->defcnt;  /* fixme : maximum size */
+	newattr = (char*)ntfs_malloc(newattrsz);
+	if (newattr) {
+		/* build the main header part */
+		pnhead = (SECURITY_DESCRIPTOR_RELATIVE*)newattr;
+		pnhead->revision = SECURITY_DESCRIPTOR_REVISION;
+		pnhead->alignment = 0;
+			/*
+			 * The flag SE_DACL_PROTECTED prevents the ACL
+			 * to be changed in an inheritance after creation
+			 */
+		pnhead->control = SE_DACL_PRESENT | SE_DACL_PROTECTED
+				    | SE_SELF_RELATIVE;
+			/*
+			 * Windows prefers ACL first, do the same to
+			 * get the same hash value and avoid duplication
+			 */
+		/* build permissions */
+		aclsz = buildacls_posix(mapping,newattr,
+			  sizeof(SECURITY_DESCRIPTOR_RELATIVE),
+			  pxdesc, isdir, usid, gsid);
+		if (aclsz && ((int)(sizeof(SECURITY_DESCRIPTOR_RELATIVE)
+				+ aclsz + usidsz + gsidsz) <= newattrsz)) {
+			/* append usid and gsid */
+			memcpy(&newattr[sizeof(SECURITY_DESCRIPTOR_RELATIVE)
+				 + aclsz], usid, usidsz);
+			memcpy(&newattr[sizeof(SECURITY_DESCRIPTOR_RELATIVE)
+				+ aclsz + usidsz], gsid, gsidsz);
+			/* positions of ACL, USID and GSID into header */
+			pnhead->owner =
+			    cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE)
+				 + aclsz);
+			pnhead->group =
+			    cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE)
+				 + aclsz + usidsz);
+			pnhead->sacl = const_cpu_to_le32(0);
+			pnhead->dacl =
+			    const_cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE));
+		} else {
+			/* ACL failure (errno set) or overflow */
+			free(newattr);
+			newattr = (char*)NULL;
+			if (aclsz) {
+				/* hope error was detected before overflowing */
+				ntfs_log_error("Security descriptor is longer than expected\n");
+				errno = EIO;
+			}
+		}
+	} else
+		errno = ENOMEM;
+	return (newattr);
+}
+
+#endif /* POSIXACLS */
+
+/*
+ *		Build a full security descriptor
+ *	returns descriptor in allocated memory, must free() after use
+ */
+
+char *ntfs_build_descr(mode_t mode,
+			int isdir, const SID * usid, const SID * gsid)
+{
+	int newattrsz;
+	SECURITY_DESCRIPTOR_RELATIVE *pnhead;
+	char *newattr;
+	int aclsz;
+	int usidsz;
+	int gsidsz;
+	int wsidsz;
+	int asidsz;
+	int ssidsz;
+
+	usidsz = ntfs_sid_size(usid);
+	gsidsz = ntfs_sid_size(gsid);
+	wsidsz = ntfs_sid_size(worldsid);
+	asidsz = ntfs_sid_size(adminsid);
+	ssidsz = ntfs_sid_size(systemsid);
+
+	/* allocate enough space for the new security attribute */
+	newattrsz = sizeof(SECURITY_DESCRIPTOR_RELATIVE)	/* header */
+	    + usidsz + gsidsz	/* usid and gsid */
+	    + sizeof(ACL)	/* acl header */
+	    + 2*(8 + usidsz)	/* two possible ACE for user */
+	    + 2*(8 + gsidsz)	/* two possible ACE for group */
+	    + 8 + wsidsz	/* one ACE for world */
+	    + 8 + asidsz 	/* one ACE for admin */
+	    + 8 + ssidsz;	/* one ACE for system */
+	if (isdir)			/* a world denial for directories */
+		newattrsz += 8 + wsidsz;
+	if (mode & 07000)	/* a NULL ACE for special modes */
+		newattrsz += 8 + ntfs_sid_size(nullsid);
+	newattr = (char*)ntfs_malloc(newattrsz);
+	if (newattr) {
+		/* build the main header part */
+		pnhead = (SECURITY_DESCRIPTOR_RELATIVE*) newattr;
+		pnhead->revision = SECURITY_DESCRIPTOR_REVISION;
+		pnhead->alignment = 0;
+			/*
+			 * The flag SE_DACL_PROTECTED prevents the ACL
+			 * to be changed in an inheritance after creation
+			 */
+		pnhead->control = SE_DACL_PRESENT | SE_DACL_PROTECTED
+				    | SE_SELF_RELATIVE;
+			/*
+			 * Windows prefers ACL first, do the same to
+			 * get the same hash value and avoid duplication
+			 */
+		/* build permissions */
+		aclsz = buildacls(newattr,
+			  sizeof(SECURITY_DESCRIPTOR_RELATIVE),
+			  mode, isdir, usid, gsid);
+		if (((int)sizeof(SECURITY_DESCRIPTOR_RELATIVE)
+				+ aclsz + usidsz + gsidsz) <= newattrsz) {
+			/* append usid and gsid */
+			memcpy(&newattr[sizeof(SECURITY_DESCRIPTOR_RELATIVE)
+				 + aclsz], usid, usidsz);
+			memcpy(&newattr[sizeof(SECURITY_DESCRIPTOR_RELATIVE)
+				+ aclsz + usidsz], gsid, gsidsz);
+			/* positions of ACL, USID and GSID into header */
+			pnhead->owner =
+			    cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE)
+				 + aclsz);
+			pnhead->group =
+			    cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE)
+				 + aclsz + usidsz);
+			pnhead->sacl = const_cpu_to_le32(0);
+			pnhead->dacl =
+			    const_cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE));
+		} else {
+			/* hope error was detected before overflowing */
+			free(newattr);
+			newattr = (char*)NULL;
+			ntfs_log_error("Security descriptor is longer than expected\n");
+			errno = EIO;
+		}
+	} else
+		errno = ENOMEM;
+	return (newattr);
+}
+
+/*
+ *		Create a mode_t permission set
+ *	from owner, group and world grants as represented in ACEs
+ */
+
+static int merge_permissions(BOOL isdir,
+		le32 owner, le32 group, le32 world, le32 special)
+
+{
+	int perm;
+
+	perm = 0;
+	/* build owner permission */
+	if (owner) {
+		if (isdir) {
+			/* exec if any of list, traverse */
+			if (owner & DIR_GEXEC)
+				perm |= S_IXUSR;
+			/* write if any of addfile, adddir, delchild */
+			if (owner & DIR_GWRITE)
+				perm |= S_IWUSR;
+			/* read if any of list */
+			if (owner & DIR_GREAD)
+				perm |= S_IRUSR;
+		} else {
+			/* exec if execute or generic execute */
+			if (owner & FILE_GEXEC)
+				perm |= S_IXUSR;
+			/* write if any of writedata or generic write */
+			if (owner & FILE_GWRITE)
+				perm |= S_IWUSR;
+			/* read if any of readdata or generic read */
+			if (owner & FILE_GREAD)
+				perm |= S_IRUSR;
+		}
+	}
+	/* build group permission */
+	if (group) {
+		if (isdir) {
+			/* exec if any of list, traverse */
+			if (group & DIR_GEXEC)
+				perm |= S_IXGRP;
+			/* write if any of addfile, adddir, delchild */
+			if (group & DIR_GWRITE)
+				perm |= S_IWGRP;
+			/* read if any of list */
+			if (group & DIR_GREAD)
+				perm |= S_IRGRP;
+		} else {
+			/* exec if execute */
+			if (group & FILE_GEXEC)
+				perm |= S_IXGRP;
+			/* write if any of writedata, appenddata */
+			if (group & FILE_GWRITE)
+				perm |= S_IWGRP;
+			/* read if any of readdata */
+			if (group & FILE_GREAD)
+				perm |= S_IRGRP;
+		}
+	}
+	/* build world permission */
+	if (world) {
+		if (isdir) {
+			/* exec if any of list, traverse */
+			if (world & DIR_GEXEC)
+				perm |= S_IXOTH;
+			/* write if any of addfile, adddir, delchild */
+			if (world & DIR_GWRITE)
+				perm |= S_IWOTH;
+			/* read if any of list */
+			if (world & DIR_GREAD)
+				perm |= S_IROTH;
+		} else {
+			/* exec if execute */
+			if (world & FILE_GEXEC)
+				perm |= S_IXOTH;
+			/* write if any of writedata, appenddata */
+			if (world & FILE_GWRITE)
+				perm |= S_IWOTH;
+			/* read if any of readdata */
+			if (world & FILE_GREAD)
+				perm |= S_IROTH;
+		}
+	}
+	/* build special permission flags */
+	if (special) {
+		if (special & FILE_APPEND_DATA)
+			perm |= S_ISUID;
+		if (special & FILE_WRITE_DATA)
+			perm |= S_ISGID;
+		if (special & FILE_READ_DATA)
+			perm |= S_ISVTX;
+	}
+	return (perm);
+}
+
+#if POSIXACLS
+
+/*
+ *		Normalize a Posix ACL either from a sorted raw set of
+ *		access ACEs or default ACEs
+ *		(standard case : different owner, group and administrator)
+ */
+
+static int norm_std_permissions_posix(struct POSIX_SECURITY *posix_desc,
+		BOOL groupowns, int start, int count, int target)
+{
+	int j,k;
+	s32 id;
+	u16 tag;
+	u16 tagsset;
+	struct POSIX_ACE *pxace;
+	mode_t grantgrps;
+	mode_t grantwrld;
+	mode_t denywrld;
+	mode_t allow;
+	mode_t deny;
+	mode_t perms;
+	mode_t mode;
+
+	mode = 0;
+	tagsset = 0;
+		/*
+		 * Determine what is granted to some group or world
+		 * Also get denials to world which are meant to prevent
+		 * execution flags to be inherited by plain files
+		 */
+	pxace = posix_desc->acl.ace;
+	grantgrps = 0;
+	grantwrld = 0;
+	denywrld = 0;
+	for (j=start; j<(start + count); j++) {
+		if (pxace[j].perms & POSIX_PERM_DENIAL) {
+				/* deny world exec unless for default */
+			if ((pxace[j].tag == POSIX_ACL_OTHER)
+			&& !start)
+				denywrld = pxace[j].perms;
+		} else {
+			switch (pxace[j].tag) {
+			case POSIX_ACL_GROUP_OBJ :
+				grantgrps |= pxace[j].perms;
+				break;
+			case POSIX_ACL_GROUP :
+				if (pxace[j].id)
+					grantgrps |= pxace[j].perms;
+				break;
+			case POSIX_ACL_OTHER :
+				grantwrld = pxace[j].perms;
+				break;
+			default :
+				break;
+			}
+		}
+	}
+		/*
+		 * Collect groups of ACEs related to the same id
+		 * and determine what is granted and what is denied.
+		 * It is important the ACEs have been sorted
+		 */
+	j = start;
+	k = target;
+	while (j < (start + count)) {
+		tag = pxace[j].tag;
+		id = pxace[j].id;
+		if (pxace[j].perms & POSIX_PERM_DENIAL) {
+			deny = pxace[j].perms | denywrld;
+			allow = 0;
+		} else {
+			deny = denywrld;
+			allow = pxace[j].perms;
+		}
+		j++;
+		while ((j < (start + count))
+		    && (pxace[j].tag == tag)
+		    && (pxace[j].id == id)) {
+			if (pxace[j].perms & POSIX_PERM_DENIAL)
+				deny |= pxace[j].perms;
+			else
+				allow |= pxace[j].perms;
+			j++;
+		}
+			/*
+			 * Build the permissions equivalent to grants and denials
+			 */
+		if (groupowns) {
+			if (tag == POSIX_ACL_MASK)
+				perms = ~deny;
+			else
+				perms = allow & ~deny;
+		} else
+			switch (tag) {
+			case POSIX_ACL_USER_OBJ :
+				perms = (allow | grantgrps | grantwrld) & ~deny;
+				break;
+			case POSIX_ACL_USER :
+				if (id)
+					perms = (allow | grantgrps | grantwrld)
+						& ~deny;
+				else
+					perms = allow;
+				break;
+			case POSIX_ACL_GROUP_OBJ :
+				perms = (allow | grantwrld) & ~deny;
+				break;
+			case POSIX_ACL_GROUP :
+				if (id)
+					perms = (allow | grantwrld) & ~deny;
+				else
+					perms = allow;
+				break;
+			case POSIX_ACL_MASK :
+				perms = ~deny;
+				break;
+			default :
+				perms = allow & ~deny;
+				break;
+			}
+			/*
+			 * Store into a Posix ACE
+			 */
+		if (tag != POSIX_ACL_SPECIAL) {
+			pxace[k].tag = tag;
+			pxace[k].id = id;
+			pxace[k].perms = perms
+				 & (POSIX_PERM_R | POSIX_PERM_W | POSIX_PERM_X);
+			tagsset |= tag;
+			k++;
+		}
+		switch (tag) {
+		case POSIX_ACL_USER_OBJ :
+			mode |= ((perms & 7) << 6);
+			break;
+		case POSIX_ACL_GROUP_OBJ :
+		case POSIX_ACL_MASK :
+			mode = (mode & 07707) | ((perms & 7) << 3);
+			break;
+		case POSIX_ACL_OTHER :
+			mode |= perms & 7;
+			break;
+		case POSIX_ACL_SPECIAL :
+			mode |= (perms & (S_ISVTX | S_ISUID | S_ISGID));
+			break;
+		default :
+			break;
+		}
+	}
+	if (!start) { /* not satisfactory */
+		posix_desc->mode = mode;
+		posix_desc->tagsset = tagsset;
+	}
+	return (k - target);
+}
+
+#endif /* POSIXACLS */
+
+/*
+ *		Interpret an ACL and extract meaningful grants
+ *		(standard case : different owner, group and administrator)
+ */
+
+static int build_std_permissions(const char *securattr,
+		const SID *usid, const SID *gsid, BOOL isdir)
+{
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	const ACL *pacl;
+	const ACCESS_ALLOWED_ACE *pace;
+	int offdacl;
+	int offace;
+	int acecnt;
+	int nace;
+	BOOL noown;
+	le32 special;
+	le32 allowown, allowgrp, allowall;
+	le32 denyown, denygrp, denyall;
+
+	phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr;
+	offdacl = le32_to_cpu(phead->dacl);
+	pacl = (const ACL*)&securattr[offdacl];
+	special = const_cpu_to_le32(0);
+	allowown = allowgrp = allowall = const_cpu_to_le32(0);
+	denyown = denygrp = denyall = const_cpu_to_le32(0);
+	noown = TRUE;
+	if (offdacl) {
+		acecnt = le16_to_cpu(pacl->ace_count);
+		offace = offdacl + sizeof(ACL);
+	} else {
+		acecnt = 0;
+		offace = 0;
+	}
+	for (nace = 0; nace < acecnt; nace++) {
+		pace = (const ACCESS_ALLOWED_ACE*)&securattr[offace];
+		if (!(pace->flags & INHERIT_ONLY_ACE)) {
+			if (ntfs_same_sid(usid, &pace->sid)
+			  || ntfs_same_sid(ownersid, &pace->sid)) {
+				noown = FALSE;
+				if (pace->type == ACCESS_ALLOWED_ACE_TYPE)
+					allowown |= pace->mask;
+				else if (pace->type == ACCESS_DENIED_ACE_TYPE)
+					denyown |= pace->mask;
+				} else
+				if (ntfs_same_sid(gsid, &pace->sid)
+				    && !(pace->mask & WRITE_OWNER)) {
+					if (pace->type == ACCESS_ALLOWED_ACE_TYPE)
+						allowgrp |= pace->mask;
+					else if (pace->type == ACCESS_DENIED_ACE_TYPE)
+						denygrp |= pace->mask;
+				} else
+					if (is_world_sid((const SID*)&pace->sid)) {
+						if (pace->type == ACCESS_ALLOWED_ACE_TYPE)
+							allowall |= pace->mask;
+						else
+							if (pace->type == ACCESS_DENIED_ACE_TYPE)
+								denyall |= pace->mask;
+					} else
+					if ((ntfs_same_sid((const SID*)&pace->sid,nullsid))
+					   && (pace->type == ACCESS_ALLOWED_ACE_TYPE))
+						special |= pace->mask;
+			}
+			offace += le16_to_cpu(pace->size);
+		}
+		/*
+		 * No indication about owner's rights : grant basic rights
+		 * This happens for files created by Windows in directories
+		 * created by Linux and owned by root, because Windows
+		 * merges the admin ACEs
+		 */
+	if (noown)
+		allowown = (FILE_READ_DATA | FILE_WRITE_DATA | FILE_EXECUTE);
+		/*
+		 *  Add to owner rights granted to group or world
+		 * unless denied personaly, and add to group rights
+		 * granted to world unless denied specifically
+		 */
+	allowown |= (allowgrp | allowall);
+	allowgrp |= allowall;
+	return (merge_permissions(isdir,
+				allowown & ~(denyown | denyall),
+				allowgrp & ~(denygrp | denyall),
+				allowall & ~denyall,
+				special));
+}
+
+/*
+ *		Interpret an ACL and extract meaningful grants
+ *		(special case : owner and group are the same,
+ *		and not administrator)
+ */
+
+static int build_owngrp_permissions(const char *securattr,
+			const SID *usid, BOOL isdir)
+{
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	const ACL *pacl;
+	const ACCESS_ALLOWED_ACE *pace;
+	int offdacl;
+	int offace;
+	int acecnt;
+	int nace;
+	le32 special;
+	BOOL grppresent;
+	BOOL ownpresent;
+	le32 allowown, allowgrp, allowall;
+	le32 denyown, denygrp, denyall;
+
+	phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr;
+	offdacl = le32_to_cpu(phead->dacl);
+	pacl = (const ACL*)&securattr[offdacl];
+	special = const_cpu_to_le32(0);
+	allowown = allowgrp = allowall = const_cpu_to_le32(0);
+	denyown = denygrp = denyall = const_cpu_to_le32(0);
+	ownpresent = FALSE;
+	grppresent = FALSE;
+	if (offdacl) {
+		acecnt = le16_to_cpu(pacl->ace_count);
+		offace = offdacl + sizeof(ACL);
+	} else {
+		acecnt = 0;
+		offace = 0;
+	}
+	for (nace = 0; nace < acecnt; nace++) {
+		pace = (const ACCESS_ALLOWED_ACE*)&securattr[offace];
+		if (!(pace->flags & INHERIT_ONLY_ACE)) {
+			if ((ntfs_same_sid(usid, &pace->sid)
+			   || ntfs_same_sid(ownersid, &pace->sid))
+			    && (pace->mask & WRITE_OWNER)) {
+				if (pace->type == ACCESS_ALLOWED_ACE_TYPE) {
+					allowown |= pace->mask;
+					ownpresent = TRUE;
+				}
+			} else
+				if (ntfs_same_sid(usid, &pace->sid)
+				   && (!(pace->mask & WRITE_OWNER))) {
+					if (pace->type == ACCESS_ALLOWED_ACE_TYPE) {
+						allowgrp |= pace->mask;
+						grppresent = TRUE;
+					}
+				} else
+					if (is_world_sid((const SID*)&pace->sid)) {
+						if (pace->type == ACCESS_ALLOWED_ACE_TYPE)
+							allowall |= pace->mask;
+						else
+							if (pace->type == ACCESS_DENIED_ACE_TYPE)
+								denyall |= pace->mask;
+					} else
+					if ((ntfs_same_sid((const SID*)&pace->sid,nullsid))
+					   && (pace->type == ACCESS_ALLOWED_ACE_TYPE))
+						special |= pace->mask;
+			}
+			offace += le16_to_cpu(pace->size);
+		}
+	if (!ownpresent)
+		allowown = allowall;
+	if (!grppresent)
+		allowgrp = allowall;
+	return (merge_permissions(isdir,
+				allowown & ~(denyown | denyall),
+				allowgrp & ~(denygrp | denyall),
+				allowall & ~denyall,
+				special));
+}
+
+#if POSIXACLS
+
+/*
+ *		Normalize a Posix ACL either from a sorted raw set of
+ *		access ACEs or default ACEs
+ *		(special case : owner or/and group is administrator)
+ */
+
+static int norm_ownadmin_permissions_posix(struct POSIX_SECURITY *posix_desc,
+		int start, int count, int target)
+{
+	int j,k;
+	s32 id;
+	u16 tag;
+	u16 tagsset;
+	struct POSIX_ACE *pxace;
+	mode_t denywrld;
+	mode_t allow;
+	mode_t deny;
+	mode_t perms;
+	mode_t mode;
+
+	mode = 0;
+	pxace = posix_desc->acl.ace;
+	tagsset = 0;
+	denywrld = 0;
+		/*
+		 * Get denials to world which are meant to prevent
+		 * execution flags to be inherited by plain files
+		 */
+	for (j=start; j<(start + count); j++) {
+		if (pxace[j].perms & POSIX_PERM_DENIAL) {
+				/* deny world exec not for default */
+			if ((pxace[j].tag == POSIX_ACL_OTHER)
+			&& !start)
+				denywrld = pxace[j].perms;
+		}
+	}
+		/*
+		 * Collect groups of ACEs related to the same id
+		 * and determine what is granted (denials are ignored)
+		 * It is important the ACEs have been sorted
+		 */
+	j = start;
+	k = target;
+	deny = 0;
+	while (j < (start + count)) {
+		allow = 0;
+		tag = pxace[j].tag;
+		id = pxace[j].id;
+		if (tag == POSIX_ACL_MASK) {
+			deny = pxace[j].perms;
+			j++;
+			while ((j < (start + count))
+			    && (pxace[j].tag == POSIX_ACL_MASK))
+				j++;
+		} else {
+			if (!(pxace[j].perms & POSIX_PERM_DENIAL))
+				allow = pxace[j].perms;
+			j++;
+			while ((j < (start + count))
+			    && (pxace[j].tag == tag)
+			    && (pxace[j].id == id)) {
+				if (!(pxace[j].perms & POSIX_PERM_DENIAL))
+					allow |= pxace[j].perms;
+				j++;
+			}
+		}
+
+			/*
+			 * Store the grants into a Posix ACE
+			 */
+		if (tag == POSIX_ACL_MASK)
+			perms = ~deny;
+		else
+			perms = allow & ~denywrld;
+		if (tag != POSIX_ACL_SPECIAL) {
+			pxace[k].tag = tag;
+			pxace[k].id = id;
+			pxace[k].perms = perms
+				 & (POSIX_PERM_R | POSIX_PERM_W | POSIX_PERM_X);
+			tagsset |= tag;
+			k++;
+		}
+		switch (tag) {
+		case POSIX_ACL_USER_OBJ :
+			mode |= ((perms & 7) << 6);
+			break;
+		case POSIX_ACL_GROUP_OBJ :
+		case POSIX_ACL_MASK :
+			mode = (mode & 07707) | ((perms & 7) << 3);
+			break;
+		case POSIX_ACL_OTHER :
+			mode |= perms & 7;
+			break;
+		case POSIX_ACL_SPECIAL :
+			mode |= perms & (S_ISVTX | S_ISUID | S_ISGID);
+			break;
+		default :
+			break;
+		}
+	}
+	if (!start) { /* not satisfactory */
+		posix_desc->mode = mode;
+		posix_desc->tagsset = tagsset;
+	}
+	return (k - target);
+}
+
+#endif /* POSIXACLS */
+
+/*
+ *		Interpret an ACL and extract meaningful grants
+ *		(special case : owner or/and group is administrator)
+ */
+
+
+static int build_ownadmin_permissions(const char *securattr,
+			const SID *usid, const SID *gsid, BOOL isdir)
+{
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	const ACL *pacl;
+	const ACCESS_ALLOWED_ACE *pace;
+	int offdacl;
+	int offace;
+	int acecnt;
+	int nace;
+	BOOL firstapply;
+	int isforeign;
+	le32 special;
+	le32 allowown, allowgrp, allowall;
+	le32 denyown, denygrp, denyall;
+
+	phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr;
+	offdacl = le32_to_cpu(phead->dacl);
+	pacl = (const ACL*)&securattr[offdacl];
+	special = const_cpu_to_le32(0);
+	allowown = allowgrp = allowall = const_cpu_to_le32(0);
+	denyown = denygrp = denyall = const_cpu_to_le32(0);
+	if (offdacl) {
+		acecnt = le16_to_cpu(pacl->ace_count);
+		offace = offdacl + sizeof(ACL);
+	} else {
+		acecnt = 0;
+		offace = 0;
+	}
+	firstapply = TRUE;
+	isforeign = 3;
+	for (nace = 0; nace < acecnt; nace++) {
+		pace = (const ACCESS_ALLOWED_ACE*)&securattr[offace];
+		if (!(pace->flags & INHERIT_ONLY_ACE)
+		   && !(~pace->mask & (ROOT_OWNER_UNMARK | ROOT_GROUP_UNMARK))) {
+			if ((ntfs_same_sid(usid, &pace->sid)
+			   || ntfs_same_sid(ownersid, &pace->sid))
+			     && (((pace->mask & WRITE_OWNER) && firstapply))) {
+				if (pace->type == ACCESS_ALLOWED_ACE_TYPE) {
+					allowown |= pace->mask;
+					isforeign &= ~1;
+				} else
+					if (pace->type == ACCESS_DENIED_ACE_TYPE)
+						denyown |= pace->mask;
+				} else
+				    if (ntfs_same_sid(gsid, &pace->sid)
+					&& (!(pace->mask & WRITE_OWNER))) {
+						if (pace->type == ACCESS_ALLOWED_ACE_TYPE) {
+							allowgrp |= pace->mask;
+							isforeign &= ~2;
+						} else
+							if (pace->type == ACCESS_DENIED_ACE_TYPE)
+								denygrp |= pace->mask;
+					} else if (is_world_sid((const SID*)&pace->sid)) {
+						if (pace->type == ACCESS_ALLOWED_ACE_TYPE)
+							allowall |= pace->mask;
+						else
+							if (pace->type == ACCESS_DENIED_ACE_TYPE)
+								denyall |= pace->mask;
+					}
+			firstapply = FALSE;
+			} else
+				if (!(pace->flags & INHERIT_ONLY_ACE))
+					if ((ntfs_same_sid((const SID*)&pace->sid,nullsid))
+					   && (pace->type == ACCESS_ALLOWED_ACE_TYPE))
+						special |= pace->mask;
+			offace += le16_to_cpu(pace->size);
+		}
+	if (isforeign) {
+		allowown |= (allowgrp | allowall);
+		allowgrp |= allowall;
+	}
+	return (merge_permissions(isdir,
+				allowown & ~(denyown | denyall),
+				allowgrp & ~(denygrp | denyall),
+				allowall & ~denyall,
+				special));
+}
+
+#if OWNERFROMACL
+
+/*
+ *		Define the owner of a file as the first user allowed
+ *	to change the owner, instead of the user defined as owner.
+ *
+ *	This produces better approximations for files written by a
+ *	Windows user in an inheritable directory owned by another user,
+ *	as the access rights are inheritable but the ownership is not.
+ *
+ *	An important case is the directories "Documents and Settings/user"
+ *	which the users must have access to, though Windows considers them
+ *	as owned by administrator.
+ */
+
+const SID *ntfs_acl_owner(const char *securattr)
+{
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	const SID *usid;
+	const ACL *pacl;
+	const ACCESS_ALLOWED_ACE *pace;
+	int offdacl;
+	int offace;
+	int acecnt;
+	int nace;
+	BOOL found;
+
+	found = FALSE;
+	phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr;
+	offdacl = le32_to_cpu(phead->dacl);
+	if (offdacl) {
+		pacl = (const ACL*)&securattr[offdacl];
+		acecnt = le16_to_cpu(pacl->ace_count);
+		offace = offdacl + sizeof(ACL);
+		nace = 0;
+		do {
+			pace = (const ACCESS_ALLOWED_ACE*)&securattr[offace];
+			if ((pace->mask & WRITE_OWNER)
+			   && (pace->type == ACCESS_ALLOWED_ACE_TYPE)
+			   && ntfs_is_user_sid(&pace->sid))
+				found = TRUE;
+			offace += le16_to_cpu(pace->size);
+		} while (!found && (++nace < acecnt));
+	}
+	if (found)
+		usid = &pace->sid;
+	else
+		usid = (const SID*)&securattr[le32_to_cpu(phead->owner)];
+	return (usid);
+}
+
+#else
+
+/*
+ *		Special case for files owned by administrator with full
+ *	access granted to a mapped user : consider this user as the tenant
+ *	of the file.
+ *
+ *	This situation cannot be represented with Linux concepts and can
+ *	only be found for files or directories created by Windows.
+ *	Typical situation : directory "Documents and Settings/user" which
+ *	is on the path to user's files and must be given access to user
+ *	only.
+ *
+ *	Check file is owned by administrator and no user has rights before
+ *	calling.
+ *	Returns the uid of tenant or zero if none
+ */
+
+
+static uid_t find_tenant(struct MAPPING *const mapping[],
+			const char *securattr)
+{
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	const ACL *pacl;
+	const ACCESS_ALLOWED_ACE *pace;
+	int offdacl;
+	int offace;
+	int acecnt;
+	int nace;
+	uid_t tid;
+	uid_t xid;
+
+	phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr;
+	offdacl = le32_to_cpu(phead->dacl);
+	pacl = (const ACL*)&securattr[offdacl];
+	tid = 0;
+	if (offdacl) {
+		acecnt = le16_to_cpu(pacl->ace_count);
+		offace = offdacl + sizeof(ACL);
+	} else
+		acecnt = 0;
+	for (nace = 0; nace < acecnt; nace++) {
+		pace = (const ACCESS_ALLOWED_ACE*)&securattr[offace];
+		if ((pace->type == ACCESS_ALLOWED_ACE_TYPE)
+		   && (pace->mask & DIR_WRITE)) {
+			xid = NTFS_FIND_USER(mapping[MAPUSERS], &pace->sid);
+			if (xid) tid = xid;
+		}
+		offace += le16_to_cpu(pace->size);
+	}
+	return (tid);
+}
+
+#endif /* OWNERFROMACL */
+
+#if POSIXACLS
+
+/*
+ *		Build Posix permissions from an ACL
+ *	returns a pointer to the requested permissions
+ *	or a null pointer (with errno set) if there is a problem
+ *
+ *	If the NTFS ACL was created according to our rules, the retrieved
+ *	Posix ACL should be the exact ACL which was set. However if
+ *	the NTFS ACL was built by a different tool, the result could
+ *	be a a poor approximation of what was expected
+ */
+
+struct POSIX_SECURITY *ntfs_build_permissions_posix(
+			struct MAPPING *const mapping[],
+			const char *securattr,
+			const SID *usid, const SID *gsid, BOOL isdir)
+{
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	struct POSIX_SECURITY *pxdesc;
+	const ACL *pacl;
+	const ACCESS_ALLOWED_ACE *pace;
+	struct POSIX_ACE *pxace;
+	struct {
+		uid_t prevuid;
+		gid_t prevgid;
+		int groupmasks;
+		s16 tagsset;
+		BOOL gotowner;
+		BOOL gotownermask;
+		BOOL gotgroup;
+		mode_t permswrld;
+	} ctx[2], *pctx;
+	int offdacl;
+	int offace;
+	int alloccnt;
+	int acecnt;
+	uid_t uid;
+	gid_t gid;
+	int i,j;
+	int k,l;
+	BOOL ignore;
+	BOOL adminowns;
+	BOOL groupowns;
+	BOOL firstinh;
+	BOOL genericinh;
+
+	phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr;
+	offdacl = le32_to_cpu(phead->dacl);
+	if (offdacl) {
+		pacl = (const ACL*)&securattr[offdacl];
+		acecnt = le16_to_cpu(pacl->ace_count);
+		offace = offdacl + sizeof(ACL);
+	} else {
+		acecnt = 0;
+		offace = 0;
+	}
+	adminowns = FALSE;
+	groupowns = ntfs_same_sid(gsid,usid);
+	firstinh = FALSE;
+	genericinh = FALSE;
+		/*
+		 * Build a raw posix security descriptor
+		 * by just translating permissions and ids
+		 * Add 2 to the count of ACE to be able to insert
+		 * a group ACE later in access and default ACLs
+		 * and add 2 more to be able to insert ACEs for owner
+		 * and 2 more for other
+		 */
+	alloccnt = acecnt + 6;
+	pxdesc = (struct POSIX_SECURITY*)malloc(
+				sizeof(struct POSIX_SECURITY)
+				+ alloccnt*sizeof(struct POSIX_ACE));
+	k = 0;
+	l = alloccnt;
+	for (i=0; i<2; i++) {
+		pctx = &ctx[i];
+		pctx->permswrld = 0;
+		pctx->prevuid = -1;
+		pctx->prevgid = -1;
+		pctx->groupmasks = 0;
+		pctx->tagsset = 0;
+		pctx->gotowner = FALSE;
+		pctx->gotgroup = FALSE;
+		pctx->gotownermask = FALSE;
+	}
+	for (j=0; j<acecnt; j++) {
+		pace = (const ACCESS_ALLOWED_ACE*)&securattr[offace];
+		if (pace->flags & INHERIT_ONLY_ACE) {
+			pxace = &pxdesc->acl.ace[l - 1];
+			pctx = &ctx[1];
+		} else {
+			pxace = &pxdesc->acl.ace[k];
+			pctx = &ctx[0];
+		}
+		ignore = FALSE;
+			/*
+			 * grants for root as a designated user or group
+			 */
+		if ((~pace->mask & (ROOT_OWNER_UNMARK | ROOT_GROUP_UNMARK))
+		   && (pace->type == ACCESS_ALLOWED_ACE_TYPE)
+		   && ntfs_same_sid(&pace->sid, adminsid)) {
+			pxace->tag = (pace->mask & ROOT_OWNER_UNMARK ? POSIX_ACL_GROUP : POSIX_ACL_USER);
+			pxace->id = 0;
+			if ((pace->mask & (GENERIC_ALL | WRITE_OWNER))
+			   && (pace->flags & INHERIT_ONLY_ACE))
+				ignore = genericinh = TRUE;
+		} else
+		if (ntfs_same_sid(usid, &pace->sid)) {
+			pxace->id = -1;
+				/*
+				 * Owner has no write-owner right :
+				 * a group was defined same as owner
+				 * or admin was owner or group :
+				 * denials are meant to owner
+				 * and grants are meant to group
+				 */
+			if (!(pace->mask & (WRITE_OWNER | GENERIC_ALL))
+			    && (pace->type == ACCESS_ALLOWED_ACE_TYPE)) {
+				if (ntfs_same_sid(gsid,usid)) {
+					pxace->tag = POSIX_ACL_GROUP_OBJ;
+					pxace->id = -1;
+				} else {
+					if (ntfs_same_sid(&pace->sid,usid))
+						groupowns = TRUE;
+					gid = NTFS_FIND_GROUP(mapping[MAPGROUPS],&pace->sid);
+					if (gid) {
+						pxace->tag = POSIX_ACL_GROUP;
+						pxace->id = gid;
+						pctx->prevgid = gid;
+					} else {
+					uid = NTFS_FIND_USER(mapping[MAPUSERS],&pace->sid);
+					if (uid) {
+						pxace->tag = POSIX_ACL_USER;
+						pxace->id = uid;
+					} else
+						ignore = TRUE;
+					}
+				}
+			} else {
+				/*
+				 * when group owns, late denials for owner
+				 * mean group mask
+				 */
+				if ((pace->type == ACCESS_DENIED_ACE_TYPE)
+				    && (pace->mask & WRITE_OWNER)) {
+					pxace->tag = POSIX_ACL_MASK;
+					pctx->gotownermask = TRUE;
+					if (pctx->gotowner)
+						pctx->groupmasks++;
+				} else {
+					if (pace->type == ACCESS_ALLOWED_ACE_TYPE)
+						pctx->gotowner = TRUE;
+					if (pctx->gotownermask && !pctx->gotowner) {
+						uid = NTFS_FIND_USER(mapping[MAPUSERS],&pace->sid);
+						pxace->id = uid;
+						pxace->tag = POSIX_ACL_USER;
+					} else
+						pxace->tag = POSIX_ACL_USER_OBJ;
+						/* system ignored, and admin */
+						/* ignored at first position */
+					if (pace->flags & INHERIT_ONLY_ACE) {
+						if ((firstinh && ntfs_same_sid(&pace->sid,adminsid))
+						   || ntfs_same_sid(&pace->sid,systemsid))
+							ignore = TRUE;
+						if (!firstinh) {
+							firstinh = TRUE;
+						}
+					} else {
+						if ((adminowns && ntfs_same_sid(&pace->sid,adminsid))
+						   || ntfs_same_sid(&pace->sid,systemsid))
+							ignore = TRUE;
+						if (ntfs_same_sid(usid,adminsid))
+							adminowns = TRUE;
+					}
+				}
+			}
+		} else if (ntfs_same_sid(gsid, &pace->sid)) {
+			if ((pace->type == ACCESS_DENIED_ACE_TYPE)
+			    && (pace->mask & WRITE_OWNER)) {
+				pxace->tag = POSIX_ACL_MASK;
+				pxace->id = -1;
+				if (pctx->gotowner)
+					pctx->groupmasks++;
+			} else {
+				if (pctx->gotgroup || (pctx->groupmasks > 1)) {
+					gid = NTFS_FIND_GROUP(mapping[MAPGROUPS],&pace->sid);
+					if (gid) {
+						pxace->id = gid;
+						pxace->tag = POSIX_ACL_GROUP;
+						pctx->prevgid = gid;
+					} else
+						ignore = TRUE;
+				} else {
+					pxace->id = -1;
+					pxace->tag = POSIX_ACL_GROUP_OBJ;
+					if (pace->type == ACCESS_ALLOWED_ACE_TYPE)
+						pctx->gotgroup = TRUE;
+				}
+
+				if (ntfs_same_sid(gsid,adminsid)
+				    || ntfs_same_sid(gsid,systemsid)) {
+					if (pace->mask & (WRITE_OWNER | GENERIC_ALL))
+						ignore = TRUE;
+					if (ntfs_same_sid(gsid,adminsid))
+						adminowns = TRUE;
+					else
+						genericinh = ignore;
+				}
+			}
+		} else if (is_world_sid((const SID*)&pace->sid)) {
+			pxace->id = -1;
+			pxace->tag = POSIX_ACL_OTHER;
+			if ((pace->type == ACCESS_DENIED_ACE_TYPE)
+			   && (pace->flags & INHERIT_ONLY_ACE))
+				ignore = TRUE;
+		} else if (ntfs_same_sid((const SID*)&pace->sid,nullsid)) {
+			pxace->id = -1;
+			pxace->tag = POSIX_ACL_SPECIAL;
+		} else {
+			uid = NTFS_FIND_USER(mapping[MAPUSERS],&pace->sid);
+			if (uid) {
+				if ((pace->type == ACCESS_DENIED_ACE_TYPE)
+				    && (pace->mask & WRITE_OWNER)
+				    && (pctx->prevuid != uid)) {
+					pxace->id = -1;
+					pxace->tag = POSIX_ACL_MASK;
+				} else {
+					pxace->id = uid;
+					pxace->tag = POSIX_ACL_USER;
+				}
+				pctx->prevuid = uid;
+			} else {
+				gid = NTFS_FIND_GROUP(mapping[MAPGROUPS],&pace->sid);
+				if (gid) {
+					if ((pace->type == ACCESS_DENIED_ACE_TYPE)
+					    && (pace->mask & WRITE_OWNER)
+					    && (pctx->prevgid != gid)) {
+						pxace->tag = POSIX_ACL_MASK;
+						pctx->groupmasks++;
+					} else {
+						pxace->tag = POSIX_ACL_GROUP;
+					}
+					pxace->id = gid;
+					pctx->prevgid = gid;
+				} else {
+					/*
+					 * do not grant rights to unknown
+					 * people and do not define root as a
+					 * designated user or group
+					 */
+					ignore = TRUE;
+				}
+			}
+		}
+		if (!ignore) {
+			pxace->perms = 0;
+				/* specific decoding for vtx/uid/gid */
+			if (pxace->tag == POSIX_ACL_SPECIAL) {
+				if (pace->mask & FILE_APPEND_DATA)
+					pxace->perms |= S_ISUID;
+				if (pace->mask & FILE_WRITE_DATA)
+					pxace->perms |= S_ISGID;
+				if (pace->mask & FILE_READ_DATA)
+					pxace->perms |= S_ISVTX;
+			} else
+				if (isdir) {
+					if (pace->mask & DIR_GEXEC)
+						pxace->perms |= POSIX_PERM_X;
+					if (pace->mask & DIR_GWRITE)
+						pxace->perms |= POSIX_PERM_W;
+					if (pace->mask & DIR_GREAD)
+						pxace->perms |= POSIX_PERM_R;
+					if ((pace->mask & GENERIC_ALL)
+					   && (pace->flags & INHERIT_ONLY_ACE))
+						pxace->perms |= POSIX_PERM_X
+								| POSIX_PERM_W
+								| POSIX_PERM_R;
+				} else {
+					if (pace->mask & FILE_GEXEC)
+						pxace->perms |= POSIX_PERM_X;
+					if (pace->mask & FILE_GWRITE)
+						pxace->perms |= POSIX_PERM_W;
+					if (pace->mask & FILE_GREAD)
+						pxace->perms |= POSIX_PERM_R;
+				}
+
+			if (pace->type != ACCESS_ALLOWED_ACE_TYPE)
+				pxace->perms |= POSIX_PERM_DENIAL;
+			else
+				if (pxace->tag == POSIX_ACL_OTHER)
+					pctx->permswrld |= pxace->perms;
+			pctx->tagsset |= pxace->tag;
+			if (pace->flags & INHERIT_ONLY_ACE) {
+				l--;
+			} else {
+				k++;
+			}
+		}
+		offace += le16_to_cpu(pace->size);
+	}
+		/*
+		 * Create world perms if none (both lists)
+		 */
+	for (i=0; i<2; i++)
+		if ((genericinh || !i)
+		    && !(ctx[i].tagsset & POSIX_ACL_OTHER)) {
+			if (i)
+				pxace = &pxdesc->acl.ace[--l];
+			else
+				pxace = &pxdesc->acl.ace[k++];
+			pxace->tag = POSIX_ACL_OTHER;
+			pxace->id = -1;
+			pxace->perms = 0;
+			ctx[i].tagsset |= POSIX_ACL_OTHER;
+			ctx[i].permswrld = 0;
+		}
+		/*
+		 * Set basic owner perms if none (both lists)
+		 * This happens for files created by Windows in directories
+		 * created by Linux and owned by root, because Windows
+		 * merges the admin ACEs
+		 */
+	for (i=0; i<2; i++)
+		if (!(ctx[i].tagsset & POSIX_ACL_USER_OBJ)
+		  && (ctx[i].tagsset & POSIX_ACL_OTHER)) {
+			if (i)
+				pxace = &pxdesc->acl.ace[--l];
+			else
+				pxace = &pxdesc->acl.ace[k++];
+			pxace->tag = POSIX_ACL_USER_OBJ;
+			pxace->id = -1;
+			pxace->perms = POSIX_PERM_R | POSIX_PERM_W | POSIX_PERM_X;
+			ctx[i].tagsset |= POSIX_ACL_USER_OBJ;
+		}
+		/*
+		 * Duplicate world perms as group_obj perms if none
+		 */
+	for (i=0; i<2; i++)
+		if ((ctx[i].tagsset & POSIX_ACL_OTHER)
+		    && !(ctx[i].tagsset & POSIX_ACL_GROUP_OBJ)) {
+			if (i)
+				pxace = &pxdesc->acl.ace[--l];
+			else
+				pxace = &pxdesc->acl.ace[k++];
+			pxace->tag = POSIX_ACL_GROUP_OBJ;
+			pxace->id = -1;
+			pxace->perms = ctx[i].permswrld;
+			ctx[i].tagsset |= POSIX_ACL_GROUP_OBJ;
+		}
+		/*
+		 * Also duplicate world perms as group perms if they
+		 * were converted to mask and not followed by a group entry
+		 */
+	if (ctx[0].groupmasks) {
+		for (j=k-2; j>=0; j--) {
+			if ((pxdesc->acl.ace[j].tag == POSIX_ACL_MASK)
+			   && (pxdesc->acl.ace[j].id != -1)
+			   && ((pxdesc->acl.ace[j+1].tag != POSIX_ACL_GROUP)
+			     || (pxdesc->acl.ace[j+1].id
+				!= pxdesc->acl.ace[j].id))) {
+				pxace = &pxdesc->acl.ace[k];
+				pxace->tag = POSIX_ACL_GROUP;
+				pxace->id = pxdesc->acl.ace[j].id;
+				pxace->perms = ctx[0].permswrld;
+				ctx[0].tagsset |= POSIX_ACL_GROUP;
+				k++;
+			}
+			if (pxdesc->acl.ace[j].tag == POSIX_ACL_MASK)
+				pxdesc->acl.ace[j].id = -1;
+		}
+	}
+	if (ctx[1].groupmasks) {
+		for (j=l; j<(alloccnt-1); j++) {
+			if ((pxdesc->acl.ace[j].tag == POSIX_ACL_MASK)
+			   && (pxdesc->acl.ace[j].id != -1)
+			   && ((pxdesc->acl.ace[j+1].tag != POSIX_ACL_GROUP)
+			     || (pxdesc->acl.ace[j+1].id
+				!= pxdesc->acl.ace[j].id))) {
+				pxace = &pxdesc->acl.ace[l - 1];
+				pxace->tag = POSIX_ACL_GROUP;
+				pxace->id = pxdesc->acl.ace[j].id;
+				pxace->perms = ctx[1].permswrld;
+				ctx[1].tagsset |= POSIX_ACL_GROUP;
+				l--;
+			}
+			if (pxdesc->acl.ace[j].tag == POSIX_ACL_MASK)
+				pxdesc->acl.ace[j].id = -1;
+		}
+	}
+
+		/*
+		 * Insert default mask if none present and
+		 * there are designated users or groups
+		 * (the space for it has not beed used)
+		 */
+	for (i=0; i<2; i++)
+		if ((ctx[i].tagsset & (POSIX_ACL_USER | POSIX_ACL_GROUP))
+		    && !(ctx[i].tagsset & POSIX_ACL_MASK)) {
+			if (i)
+				pxace = &pxdesc->acl.ace[--l];
+			else
+				pxace = &pxdesc->acl.ace[k++];
+			pxace->tag = POSIX_ACL_MASK;
+			pxace->id = -1;
+			pxace->perms = POSIX_PERM_DENIAL;
+			ctx[i].tagsset |= POSIX_ACL_MASK;
+		}
+
+	if (k > l) {
+		ntfs_log_error("Posix descriptor is longer than expected\n");
+		errno = EIO;
+		free(pxdesc);
+		pxdesc = (struct POSIX_SECURITY*)NULL;
+	} else {
+		pxdesc->acccnt = k;
+		pxdesc->defcnt = alloccnt - l;
+		pxdesc->firstdef = l;
+		pxdesc->tagsset = ctx[0].tagsset;
+		pxdesc->acl.version = POSIX_VERSION;
+		pxdesc->acl.flags = 0;
+		pxdesc->acl.filler = 0;
+		ntfs_sort_posix(pxdesc);
+		if (adminowns) {
+			k = norm_ownadmin_permissions_posix(pxdesc,
+					0, pxdesc->acccnt, 0);
+			pxdesc->acccnt = k;
+			l = norm_ownadmin_permissions_posix(pxdesc,
+					pxdesc->firstdef, pxdesc->defcnt, k);
+			pxdesc->firstdef = k;
+			pxdesc->defcnt = l;
+		} else {
+			k = norm_std_permissions_posix(pxdesc,groupowns,
+					0, pxdesc->acccnt, 0);
+			pxdesc->acccnt = k;
+			l = norm_std_permissions_posix(pxdesc,groupowns,
+					pxdesc->firstdef, pxdesc->defcnt, k);
+			pxdesc->firstdef = k;
+			pxdesc->defcnt = l;
+		}
+	}
+	if (pxdesc && !ntfs_valid_posix(pxdesc)) {
+		ntfs_log_error("Invalid Posix descriptor built\n");
+                errno = EIO;
+                free(pxdesc);
+                pxdesc = (struct POSIX_SECURITY*)NULL;
+	}
+	return (pxdesc);
+}
+
+#endif /* POSIXACLS */
+
+/*
+ *		Build unix-style (mode_t) permissions from an ACL
+ *	returns the requested permissions
+ *	or a negative result (with errno set) if there is a problem
+ */
+
+int ntfs_build_permissions(const char *securattr,
+			const SID *usid, const SID *gsid, BOOL isdir)
+{
+	int perm;
+	BOOL adminowns;
+	BOOL groupowns;
+
+	adminowns = ntfs_same_sid(usid,adminsid)
+	         || ntfs_same_sid(gsid,adminsid);
+	groupowns = !adminowns && ntfs_same_sid(gsid,usid);
+	if (adminowns)
+		perm = build_ownadmin_permissions(securattr, usid, gsid, isdir);
+	else
+		if (groupowns)
+			perm = build_owngrp_permissions(securattr, usid, isdir);
+		else
+			perm = build_std_permissions(securattr, usid, gsid, isdir);
+	return (perm);
+}
+
+/*
+ *		The following must be in some library...
+ */
+
+static unsigned long atoul(const char *p)
+{				/* must be somewhere ! */
+	unsigned long v;
+
+	v = 0;
+	while ((*p >= '0') && (*p <= '9'))
+		v = v * 10 + (*p++) - '0';
+	return (v);
+}
+
+/*
+ *		Build an internal representation of a SID
+ *	Returns a copy in allocated memory if it succeeds
+ *	The SID is checked to be a valid user one.
+ */
+
+static SID *encodesid(const char *sidstr)
+{
+	SID *sid;
+	int cnt;
+	BIGSID bigsid;
+	SID *bsid;
+	u32 auth;
+	const char *p;
+
+	sid = (SID*) NULL;
+	if (!strncmp(sidstr, "S-1-", 4)) {
+		bsid = (SID*)&bigsid;
+		bsid->revision = SID_REVISION;
+		p = &sidstr[4];
+		auth = atoul(p);
+		bsid->identifier_authority.high_part = const_cpu_to_be16(0);
+		bsid->identifier_authority.low_part = cpu_to_be32(auth);
+		cnt = 0;
+		p = strchr(p, '-');
+		while (p && (cnt < 8)) {
+			p++;
+			auth = atoul(p);
+			bsid->sub_authority[cnt] = cpu_to_le32(auth);
+			p = strchr(p, '-');
+			cnt++;
+		}
+		bsid->sub_authority_count = cnt;
+		if ((cnt > 0) && ntfs_valid_sid(bsid)
+		    && (ntfs_is_user_sid(bsid) || ntfs_known_group_sid(bsid))) {
+			sid = (SID*) ntfs_malloc(4 * cnt + 8);
+			if (sid)
+				memcpy(sid, bsid, 4 * cnt + 8);
+		}
+	}
+	return (sid);
+}
+
+/*
+ *		Get a single mapping item from buffer
+ *
+ *	Always reads a full line, truncating long lines
+ *	Refills buffer when exhausted
+ *	Returns pointer to item, or NULL when there is no more
+ */
+
+static struct MAPLIST *getmappingitem(FILEREADER reader, void *fileid,
+		off_t *poffs, char *buf, int *psrc, s64 *psize)
+{
+	int src;
+	int dst;
+	char *q;
+	char *pu;
+	char *pg;
+	int gotend;
+	struct MAPLIST *item;
+
+	src = *psrc;
+	dst = 0;
+			/* allocate and get a full line */
+	item = (struct MAPLIST*)ntfs_malloc(sizeof(struct MAPLIST));
+	if (item) {
+		do {
+			gotend = 0;
+			while ((src < *psize)
+			       && (buf[src] != '\n')) {
+				if (dst < LINESZ)
+					item->maptext[dst++] = buf[src];
+				src++;
+			}
+			if (src >= *psize) {
+				*poffs += *psize;
+				*psize = reader(fileid, buf, (size_t)BUFSZ, *poffs);
+				src = 0;
+			} else {
+				gotend = 1;
+				src++;
+				item->maptext[dst] = '\0';
+				dst = 0;
+			}
+		} while (*psize && ((item->maptext[0] == '#') || !gotend));
+		if (gotend) {
+			pu = pg = (char*)NULL;
+			/* decompose into uid, gid and sid */
+			item->uidstr = item->maptext;
+			item->gidstr = strchr(item->uidstr, ':');
+			if (item->gidstr) {
+				pu = item->gidstr++;
+				item->sidstr = strchr(item->gidstr, ':');
+				if (item->sidstr) {
+					pg = item->sidstr++;
+					q = strchr(item->sidstr, ':');
+					if (q) *q = 0;
+				}
+			}
+			if (pu && pg)
+				*pu = *pg = '\0';
+			else {
+				ntfs_log_early_error("Bad mapping item \"%s\"\n",
+					item->maptext);
+				free(item);
+				item = (struct MAPLIST*)NULL;
+			}
+		} else {
+			free(item);	/* free unused item */
+			item = (struct MAPLIST*)NULL;
+		}
+	}
+	*psrc = src;
+	return (item);
+}
+
+/*
+ *		Read user mapping file and split into their attribute.
+ *	Parameters are kept as text in a chained list until logins
+ *	are converted to uid.
+ *	Returns the head of list, if any
+ *
+ *	If an absolute path is provided, the mapping file is assumed
+ *	to be located in another mounted file system, and plain read()
+ *	are used to get its contents.
+ *	If a relative path is provided, the mapping file is assumed
+ *	to be located on the current file system, and internal IO
+ *	have to be used since we are still mounting and we have not
+ *	entered the fuse loop yet.
+ */
+
+struct MAPLIST *ntfs_read_mapping(FILEREADER reader, void *fileid)
+{
+	char buf[BUFSZ];
+	struct MAPLIST *item;
+	struct MAPLIST *firstitem;
+	struct MAPLIST *lastitem;
+	int src;
+	off_t offs;
+	s64 size;
+
+	firstitem = (struct MAPLIST*)NULL;
+	lastitem = (struct MAPLIST*)NULL;
+	offs = 0;
+	size = reader(fileid, buf, (size_t)BUFSZ, (off_t)0);
+	if (size > 0) {
+		src = 0;
+		do {
+			item = getmappingitem(reader, fileid, &offs,
+				buf, &src, &size);
+			if (item) {
+				item->next = (struct MAPLIST*)NULL;
+				if (lastitem)
+					lastitem->next = item;
+				else
+					firstitem = item;
+				lastitem = item;
+			}
+		} while (item);
+	}
+	return (firstitem);
+}
+
+/*
+ *		Free memory used to store the user mapping
+ *	The only purpose is to facilitate the detection of memory leaks
+ */
+
+void ntfs_free_mapping(struct MAPPING *mapping[])
+{
+	struct MAPPING *user;
+	struct MAPPING *group;
+
+		/* free user mappings */
+	while (mapping[MAPUSERS]) {
+		user = mapping[MAPUSERS];
+		/* do not free SIDs used for group mappings */
+		group = mapping[MAPGROUPS];
+		while (group && (group->sid != user->sid))
+			group = group->next;
+		if (!group)
+			free(user->sid);
+			/* free group list if any */
+		if (user->grcnt)
+			free(user->groups);
+			/* unchain item and free */
+		mapping[MAPUSERS] = user->next;
+		free(user);
+	}
+		/* free group mappings */
+	while (mapping[MAPGROUPS]) {
+		group = mapping[MAPGROUPS];
+		free(group->sid);
+			/* unchain item and free */
+		mapping[MAPGROUPS] = group->next;
+		free(group);
+	}
+}
+
+
+/*
+ *		Build the user mapping list
+ *	user identification may be given in symbolic or numeric format
+ *
+ *	! Note ! : does getpwnam() read /etc/passwd or some other file ?
+ *		if so there is a possible recursion into fuse if this
+ *		file is on NTFS, and fuse is not recursion safe.
+ */
+
+struct MAPPING *ntfs_do_user_mapping(struct MAPLIST *firstitem)
+{
+	struct MAPLIST *item;
+	struct MAPPING *firstmapping;
+	struct MAPPING *lastmapping;
+	struct MAPPING *mapping;
+	struct passwd *pwd;
+	SID *sid;
+	int uid;
+
+	firstmapping = (struct MAPPING*)NULL;
+	lastmapping = (struct MAPPING*)NULL;
+	for (item = firstitem; item; item = item->next) {
+		if ((item->uidstr[0] >= '0') && (item->uidstr[0] <= '9'))
+			uid = atoi(item->uidstr);
+		else {
+			uid = 0;
+			if (item->uidstr[0]) {
+				pwd = getpwnam(item->uidstr);
+				if (pwd)
+					uid = pwd->pw_uid;
+				else
+					ntfs_log_early_error("Invalid user \"%s\"\n",
+						item->uidstr);
+			}
+		}
+			/*
+			 * Records with no uid and no gid are inserted
+			 * to define the implicit mapping pattern
+			 */
+		if (uid
+		   || (!item->uidstr[0] && !item->gidstr[0])) {
+			sid = encodesid(item->sidstr);
+			if (sid && ntfs_known_group_sid(sid)) {
+				ntfs_log_error("Bad user SID %s\n",
+					item->sidstr);
+				free(sid);
+				sid = (SID*)NULL;
+			}
+			if (sid && !item->uidstr[0] && !item->gidstr[0]
+			    && !ntfs_valid_pattern(sid)) {
+				ntfs_log_error("Bad implicit SID pattern %s\n",
+					item->sidstr);
+				sid = (SID*)NULL;
+				}
+			if (sid) {
+				mapping =
+				    (struct MAPPING*)
+				    ntfs_malloc(sizeof(struct MAPPING));
+				if (mapping) {
+					mapping->sid = sid;
+					mapping->xid = uid;
+					mapping->grcnt = 0;
+					mapping->next = (struct MAPPING*)NULL;
+					if (lastmapping)
+						lastmapping->next = mapping;
+					else
+						firstmapping = mapping;
+					lastmapping = mapping;
+				}
+			}
+		}
+	}
+	return (firstmapping);
+}
+
+/*
+ *		Build the group mapping list
+ *	group identification may be given in symbolic or numeric format
+ *
+ *	gid not associated to a uid are processed first in order
+ *	to favour real groups
+ *
+ *	! Note ! : does getgrnam() read /etc/group or some other file ?
+ *		if so there is a possible recursion into fuse if this
+ *		file is on NTFS, and fuse is not recursion safe.
+ */
+
+struct MAPPING *ntfs_do_group_mapping(struct MAPLIST *firstitem)
+{
+	struct MAPLIST *item;
+	struct MAPPING *firstmapping;
+	struct MAPPING *lastmapping;
+	struct MAPPING *mapping;
+	struct group *grp;
+	BOOL secondstep;
+	BOOL ok;
+	int step;
+	SID *sid;
+	int gid;
+
+	firstmapping = (struct MAPPING*)NULL;
+	lastmapping = (struct MAPPING*)NULL;
+	for (step=1; step<=2; step++) {
+		for (item = firstitem; item; item = item->next) {
+			secondstep = (item->uidstr[0] != '\0')
+				|| !item->gidstr[0];
+			ok = (step == 1 ? !secondstep : secondstep);
+			if ((item->gidstr[0] >= '0')
+			     && (item->gidstr[0] <= '9'))
+				gid = atoi(item->gidstr);
+			else {
+				gid = 0;
+				if (item->gidstr[0]) {
+					grp = getgrnam(item->gidstr);
+					if (grp)
+						gid = grp->gr_gid;
+					else
+						ntfs_log_early_error("Invalid group \"%s\"\n",
+							item->gidstr);
+				}
+			}
+			/*
+			 * Records with no uid and no gid are inserted in the
+			 * second step to define the implicit mapping pattern
+			 */
+			if (ok
+			    && (gid
+				 || (!item->uidstr[0] && !item->gidstr[0]))) {
+				sid = encodesid(item->sidstr);
+				if (sid && !item->uidstr[0] && !item->gidstr[0]
+				    && !ntfs_valid_pattern(sid)) {
+					/* error already logged */
+					sid = (SID*)NULL;
+					}
+				if (sid) {
+					mapping = (struct MAPPING*)
+					    ntfs_malloc(sizeof(struct MAPPING));
+					if (mapping) {
+						mapping->sid = sid;
+						mapping->xid = gid;
+					/* special groups point to themselves */
+						if (ntfs_known_group_sid(sid)) {
+							mapping->groups =
+							  (gid_t*)&mapping->xid;
+							mapping->grcnt = 1;
+						} else
+							mapping->grcnt = 0;
+
+
+						mapping->next = (struct MAPPING*)NULL;
+						if (lastmapping)
+							lastmapping->next = mapping;
+						else
+							firstmapping = mapping;
+						lastmapping = mapping;
+					}
+				}
+			}
+		}
+	}
+	return (firstmapping);
+}
diff --git a/libntfs-3g/attrib.c b/libntfs-3g/attrib.c
new file mode 100755
index 0000000000000000000000000000000000000000..77b1f03ae3d7c35cadfabecaa353e6978822cf29
--- /dev/null
+++ b/libntfs-3g/attrib.c
@@ -0,0 +1,6886 @@
+/**
+ * attrib.c - Attribute handling code. Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2000-2010 Anton Altaparmakov
+ * Copyright (c) 2002-2005 Richard Russon
+ * Copyright (c) 2002-2008 Szabolcs Szakacsits
+ * Copyright (c) 2004-2007 Yura Pakhuchiy
+ * Copyright (c) 2007-2014 Jean-Pierre Andre
+ * Copyright (c) 2010      Erik Larsson
+ *
+ * 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_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#include "param.h"
+#include "compat.h"
+#include "attrib.h"
+#include "attrlist.h"
+#include "device.h"
+#include "mft.h"
+#include "debug.h"
+#include "mst.h"
+#include "volume.h"
+#include "types.h"
+#include "layout.h"
+#include "inode.h"
+#include "runlist.h"
+#include "lcnalloc.h"
+#include "dir.h"
+#include "compress.h"
+#include "bitmap.h"
+#include "logging.h"
+#include "misc.h"
+#include "efs.h"
+
+ntfschar AT_UNNAMED[] = { const_cpu_to_le16('\0') };
+ntfschar STREAM_SDS[] = { const_cpu_to_le16('$'),
+			const_cpu_to_le16('S'),
+			const_cpu_to_le16('D'),
+			const_cpu_to_le16('S'),
+			const_cpu_to_le16('\0') };
+
+ntfschar TXF_DATA[] = { const_cpu_to_le16('$'),
+			const_cpu_to_le16('T'),
+			const_cpu_to_le16('X'),
+			const_cpu_to_le16('F'),
+			const_cpu_to_le16('_'),
+			const_cpu_to_le16('D'),
+			const_cpu_to_le16('A'),
+			const_cpu_to_le16('T'),
+			const_cpu_to_le16('A'),
+			const_cpu_to_le16('\0') };
+
+static int NAttrFlag(ntfs_attr *na, FILE_ATTR_FLAGS flag)
+{
+	if (na->type == AT_DATA && na->name == AT_UNNAMED)
+		return (na->ni->flags & flag);
+	return 0;
+}
+
+static void NAttrSetFlag(ntfs_attr *na, FILE_ATTR_FLAGS flag)
+{
+	if (na->type == AT_DATA && na->name == AT_UNNAMED)
+		na->ni->flags |= flag;
+	else
+		ntfs_log_trace("Denied setting flag %d for not unnamed data "
+			       "attribute\n", flag);
+}
+
+static void NAttrClearFlag(ntfs_attr *na, FILE_ATTR_FLAGS flag)
+{
+	if (na->type == AT_DATA && na->name == AT_UNNAMED)
+		na->ni->flags &= ~flag;
+}
+
+#define GenNAttrIno(func_name, flag)					\
+int NAttr##func_name(ntfs_attr *na) { return NAttrFlag   (na, flag); } 	\
+void NAttrSet##func_name(ntfs_attr *na)	 { NAttrSetFlag  (na, flag); }	\
+void NAttrClear##func_name(ntfs_attr *na){ NAttrClearFlag(na, flag); }
+
+GenNAttrIno(Compressed, FILE_ATTR_COMPRESSED)
+GenNAttrIno(Encrypted, 	FILE_ATTR_ENCRYPTED)
+GenNAttrIno(Sparse, 	FILE_ATTR_SPARSE_FILE)
+
+/**
+ * ntfs_get_attribute_value_length - Find the length of an attribute
+ * @a:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+s64 ntfs_get_attribute_value_length(const ATTR_RECORD *a)
+{
+	if (!a) {
+		errno = EINVAL;
+		return 0;
+	}
+	errno = 0;
+	if (a->non_resident)
+		return sle64_to_cpu(a->data_size);
+	
+	return (s64)le32_to_cpu(a->value_length);
+}
+
+/**
+ * ntfs_get_attribute_value - Get a copy of an attribute
+ * @vol:	
+ * @a:	
+ * @b:	
+ *
+ * Description...
+ *
+ * Returns:
+ */
+s64 ntfs_get_attribute_value(const ntfs_volume *vol,
+		const ATTR_RECORD *a, u8 *b)
+{
+	runlist *rl;
+	s64 total, r;
+	int i;
+
+	/* Sanity checks. */
+	if (!vol || !a || !b) {
+		errno = EINVAL;
+		return 0;
+	}
+	/* Complex attribute? */
+	/*
+	 * Ignore the flags in case they are not zero for an attribute list
+	 * attribute.  Windows does not complain about invalid flags and chkdsk
+	 * does not detect or fix them so we need to cope with it, too.
+	 */
+	if (a->type != AT_ATTRIBUTE_LIST && a->flags) {
+		ntfs_log_error("Non-zero (%04x) attribute flags. Cannot handle "
+			       "this yet.\n", le16_to_cpu(a->flags));
+		errno = EOPNOTSUPP;
+		return 0;
+	}
+	if (!a->non_resident) {
+		/* Attribute is resident. */
+
+		/* Sanity check. */
+		if (le32_to_cpu(a->value_length) + le16_to_cpu(a->value_offset)
+				> le32_to_cpu(a->length)) {
+			return 0;
+		}
+
+		memcpy(b, (const char*)a + le16_to_cpu(a->value_offset),
+				le32_to_cpu(a->value_length));
+		errno = 0;
+		return (s64)le32_to_cpu(a->value_length);
+	}
+
+	/* Attribute is not resident. */
+
+	/* If no data, return 0. */
+	if (!(a->data_size)) {
+		errno = 0;
+		return 0;
+	}
+	/*
+	 * FIXME: What about attribute lists?!? (AIA)
+	 */
+	/* Decompress the mapping pairs array into a runlist. */
+	rl = ntfs_mapping_pairs_decompress(vol, a, NULL);
+	if (!rl) {
+		errno = EINVAL;
+		return 0;
+	}
+	/*
+	 * FIXED: We were overflowing here in a nasty fashion when we
+	 * reach the last cluster in the runlist as the buffer will
+	 * only be big enough to hold data_size bytes while we are
+	 * reading in allocated_size bytes which is usually larger
+	 * than data_size, since the actual data is unlikely to have a
+	 * size equal to a multiple of the cluster size!
+	 * FIXED2:  We were also overflowing here in the same fashion
+	 * when the data_size was more than one run smaller than the
+	 * allocated size which happens with Windows XP sometimes.
+	 */
+	/* Now load all clusters in the runlist into b. */
+	for (i = 0, total = 0; rl[i].length; i++) {
+		if (total + (rl[i].length << vol->cluster_size_bits) >=
+				sle64_to_cpu(a->data_size)) {
+			unsigned char *intbuf = NULL;
+			/*
+			 * We have reached the last run so we were going to
+			 * overflow when executing the ntfs_pread() which is
+			 * BAAAAAAAD!
+			 * Temporary fix:
+			 *	Allocate a new buffer with size:
+			 *	rl[i].length << vol->cluster_size_bits, do the
+			 *	read into our buffer, then memcpy the correct
+			 *	amount of data into the caller supplied buffer,
+			 *	free our buffer, and continue.
+			 * We have reached the end of data size so we were
+			 * going to overflow in the same fashion.
+			 * Temporary fix:  same as above.
+			 */
+			intbuf = ntfs_malloc(rl[i].length << vol->cluster_size_bits);
+			if (!intbuf) {
+				free(rl);
+				return 0;
+			}
+			/*
+			 * FIXME: If compressed file: Only read if lcn != -1.
+			 * Otherwise, we are dealing with a sparse run and we
+			 * just memset the user buffer to 0 for the length of
+			 * the run, which should be 16 (= compression unit
+			 * size).
+			 * FIXME: Really only when file is compressed, or can
+			 * we have sparse runs in uncompressed files as well?
+			 * - Yes we can, in sparse files! But not necessarily
+			 * size of 16, just run length.
+			 */
+			r = ntfs_pread(vol->dev, rl[i].lcn <<
+					vol->cluster_size_bits, rl[i].length <<
+					vol->cluster_size_bits, intbuf);
+			if (r != rl[i].length << vol->cluster_size_bits) {
+#define ESTR "Error reading attribute value"
+				if (r == -1)
+					ntfs_log_perror(ESTR);
+				else if (r < rl[i].length <<
+						vol->cluster_size_bits) {
+					ntfs_log_debug(ESTR ": Ran out of input data.\n");
+					errno = EIO;
+				} else {
+					ntfs_log_debug(ESTR ": unknown error\n");
+					errno = EIO;
+				}
+#undef ESTR
+				free(rl);
+				free(intbuf);
+				return 0;
+			}
+			memcpy(b + total, intbuf, sle64_to_cpu(a->data_size) -
+					total);
+			free(intbuf);
+			total = sle64_to_cpu(a->data_size);
+			break;
+		}
+		/*
+		 * FIXME: If compressed file: Only read if lcn != -1.
+		 * Otherwise, we are dealing with a sparse run and we just
+		 * memset the user buffer to 0 for the length of the run, which
+		 * should be 16 (= compression unit size).
+		 * FIXME: Really only when file is compressed, or can
+		 * we have sparse runs in uncompressed files as well?
+		 * - Yes we can, in sparse files! But not necessarily size of
+		 * 16, just run length.
+		 */
+		r = ntfs_pread(vol->dev, rl[i].lcn << vol->cluster_size_bits,
+				rl[i].length << vol->cluster_size_bits,
+				b + total);
+		if (r != rl[i].length << vol->cluster_size_bits) {
+#define ESTR "Error reading attribute value"
+			if (r == -1)
+				ntfs_log_perror(ESTR);
+			else if (r < rl[i].length << vol->cluster_size_bits) {
+				ntfs_log_debug(ESTR ": Ran out of input data.\n");
+				errno = EIO;
+			} else {
+				ntfs_log_debug(ESTR ": unknown error\n");
+				errno = EIO;
+			}
+#undef ESTR
+			free(rl);
+			return 0;
+		}
+		total += r;
+	}
+	free(rl);
+	return total;
+}
+
+/* Already cleaned up code below, but still look for FIXME:... */
+
+/**
+ * __ntfs_attr_init - primary initialization of an ntfs attribute structure
+ * @na:		ntfs attribute to initialize
+ * @ni:		ntfs inode with which to initialize the ntfs attribute
+ * @type:	attribute type
+ * @name:	attribute name in little endian Unicode or NULL
+ * @name_len:	length of attribute @name in Unicode characters (if @name given)
+ *
+ * Initialize the ntfs attribute @na with @ni, @type, @name, and @name_len.
+ */
+static void __ntfs_attr_init(ntfs_attr *na, ntfs_inode *ni,
+		const ATTR_TYPES type, ntfschar *name, const u32 name_len)
+{
+	na->rl = NULL;
+	na->ni = ni;
+	na->type = type;
+	na->name = name;
+	if (name)
+		na->name_len = name_len;
+	else
+		na->name_len = 0;
+}
+
+/**
+ * ntfs_attr_init - initialize an ntfs_attr with data sizes and status
+ * @na:
+ * @non_resident:
+ * @compressed:
+ * @encrypted:
+ * @sparse:
+ * @allocated_size:
+ * @data_size:
+ * @initialized_size:
+ * @compressed_size:
+ * @compression_unit:
+ *
+ * Final initialization for an ntfs attribute.
+ */
+void ntfs_attr_init(ntfs_attr *na, const BOOL non_resident,
+		const ATTR_FLAGS data_flags,
+		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)
+{
+	if (!NAttrInitialized(na)) {
+		na->data_flags = data_flags;
+		if (non_resident)
+			NAttrSetNonResident(na);
+		if (data_flags & ATTR_COMPRESSION_MASK)
+			NAttrSetCompressed(na);
+		if (encrypted)
+			NAttrSetEncrypted(na);
+		if (sparse)
+			NAttrSetSparse(na);
+		na->allocated_size = allocated_size;
+		na->data_size = data_size;
+		na->initialized_size = initialized_size;
+		if ((data_flags & ATTR_COMPRESSION_MASK) || sparse) {
+			ntfs_volume *vol = na->ni->vol;
+
+			na->compressed_size = compressed_size;
+			na->compression_block_clusters = 1 << compression_unit;
+			na->compression_block_size = 1 << (compression_unit +
+					vol->cluster_size_bits);
+			na->compression_block_size_bits = ffs(
+					na->compression_block_size) - 1;
+		}
+		NAttrSetInitialized(na);
+	}
+}
+
+/**
+ * ntfs_attr_open - open an ntfs attribute for access
+ * @ni:		open ntfs inode in which the ntfs attribute resides
+ * @type:	attribute type
+ * @name:	attribute name in little endian Unicode or AT_UNNAMED or NULL
+ * @name_len:	length of attribute @name in Unicode characters (if @name given)
+ *
+ * Allocate a new ntfs attribute structure, initialize it with @ni, @type,
+ * @name, and @name_len, then return it. Return NULL on error with
+ * errno set to the error code.
+ *
+ * If @name is AT_UNNAMED look specifically for an unnamed attribute.  If you
+ * do not care whether the attribute is named or not set @name to NULL.  In
+ * both those cases @name_len is not used at all.
+ */
+ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type,
+		ntfschar *name, u32 name_len)
+{
+	ntfs_attr_search_ctx *ctx;
+	ntfs_attr *na = NULL;
+	ntfschar *newname = NULL;
+	ATTR_RECORD *a;
+	le16 cs;
+
+	ntfs_log_enter("Entering for inode %lld, attr 0x%x.\n",
+		       (unsigned long long)ni->mft_no, type);
+	
+	if (!ni || !ni->vol || !ni->mrec) {
+		errno = EINVAL;
+		goto out;
+	}
+	na = ntfs_calloc(sizeof(ntfs_attr));
+	if (!na)
+		goto out;
+	if (name && name != AT_UNNAMED && name != NTFS_INDEX_I30) {
+		name = ntfs_ucsndup(name, name_len);
+		if (!name)
+			goto err_out;
+		newname = name;
+	}
+
+	ctx = ntfs_attr_get_search_ctx(ni, NULL);
+	if (!ctx)
+		goto err_out;
+
+	if (ntfs_attr_lookup(type, name, name_len, 0, 0, NULL, 0, ctx))
+		goto put_err_out;
+
+	a = ctx->attr;
+	
+	if (!name) {
+		if (a->name_length) {
+			name = ntfs_ucsndup((ntfschar*)((u8*)a + le16_to_cpu(
+					a->name_offset)), a->name_length);
+			if (!name)
+				goto put_err_out;
+			newname = name;
+			name_len = a->name_length;
+		} else {
+			name = AT_UNNAMED;
+			name_len = 0;
+		}
+	}
+	
+	__ntfs_attr_init(na, ni, type, name, name_len);
+	
+	/*
+	 * Wipe the flags in case they are not zero for an attribute list
+	 * attribute.  Windows does not complain about invalid flags and chkdsk
+	 * does not detect or fix them so we need to cope with it, too.
+	 */
+	if (type == AT_ATTRIBUTE_LIST)
+		a->flags = 0;
+
+	if ((type == AT_DATA)
+	   && (a->non_resident ? !a->initialized_size : !a->value_length)) {
+		/*
+		 * Define/redefine the compression state if stream is
+		 * empty, based on the compression mark on parent
+		 * directory (for unnamed data streams) or on current
+		 * inode (for named data streams). The compression mark
+		 * may change any time, the compression state can only
+		 * change when stream is wiped out.
+		 * 
+		 * Also prevent compression on NTFS version < 3.0
+		 * or cluster size > 4K or compression is disabled
+		 */
+		a->flags &= ~ATTR_COMPRESSION_MASK;
+		if ((ni->flags & FILE_ATTR_COMPRESSED)
+		    && (ni->vol->major_ver >= 3)
+		    && NVolCompression(ni->vol)
+		    && (ni->vol->cluster_size <= MAX_COMPRESSION_CLUSTER_SIZE))
+			a->flags |= ATTR_IS_COMPRESSED;
+	}
+	
+	cs = a->flags & (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE);
+
+	/* a file may be sparse though its unnamed data is not (cf $UsnJrnl) */
+	if (na->type == AT_DATA && na->name == AT_UNNAMED &&
+	    (((a->flags & ATTR_IS_SPARSE)     && !NAttrSparse(na)) ||
+	     (!(a->flags & ATTR_IS_ENCRYPTED)  != !NAttrEncrypted(na)))) {
+		errno = EIO;
+		ntfs_log_perror("Inode %lld has corrupt attribute flags "
+				"(0x%x <> 0x%x)",(unsigned long long)ni->mft_no,
+				a->flags, na->ni->flags);
+		goto put_err_out;
+	}
+
+	if (a->non_resident) {
+		if ((a->flags & ATTR_COMPRESSION_MASK)
+				 && !a->compression_unit) {
+			errno = EIO;
+			ntfs_log_perror("Compressed inode %lld attr 0x%x has "
+					"no compression unit",
+					(unsigned long long)ni->mft_no, type);
+			goto put_err_out;
+		}
+		ntfs_attr_init(na, TRUE, a->flags,
+				a->flags & ATTR_IS_ENCRYPTED,
+				a->flags & ATTR_IS_SPARSE,
+				sle64_to_cpu(a->allocated_size),
+				sle64_to_cpu(a->data_size),
+				sle64_to_cpu(a->initialized_size),
+				cs ? sle64_to_cpu(a->compressed_size) : 0,
+				cs ? a->compression_unit : 0);
+	} else {
+		s64 l = le32_to_cpu(a->value_length);
+		ntfs_attr_init(na, FALSE, a->flags,
+				a->flags & ATTR_IS_ENCRYPTED,
+				a->flags & ATTR_IS_SPARSE, (l + 7) & ~7, l, l,
+				cs ? (l + 7) & ~7 : 0, 0);
+	}
+	ntfs_attr_put_search_ctx(ctx);
+out:
+	ntfs_log_leave("\n");	
+	return na;
+
+put_err_out:
+	ntfs_attr_put_search_ctx(ctx);
+err_out:
+	free(newname);
+	free(na);
+	na = NULL;
+	goto out;
+}
+
+/**
+ * ntfs_attr_close - free an ntfs attribute structure
+ * @na:		ntfs attribute structure to free
+ *
+ * Release all memory associated with the ntfs attribute @na and then release
+ * @na itself.
+ */
+void ntfs_attr_close(ntfs_attr *na)
+{
+	if (!na)
+		return;
+	if (NAttrNonResident(na) && na->rl)
+		free(na->rl);
+	/* Don't release if using an internal constant. */
+	if (na->name != AT_UNNAMED && na->name != NTFS_INDEX_I30
+				&& na->name != STREAM_SDS)
+		free(na->name);
+	free(na);
+}
+
+/**
+ * ntfs_attr_map_runlist - map (a part of) a runlist of an ntfs attribute
+ * @na:		ntfs attribute for which to map (part of) a runlist
+ * @vcn:	map runlist part containing this vcn
+ *
+ * Map the part of a runlist containing the @vcn of the ntfs attribute @na.
+ *
+ * Return 0 on success and -1 on error with errno set to the error code.
+ */
+int ntfs_attr_map_runlist(ntfs_attr *na, VCN vcn)
+{
+	LCN lcn;
+	ntfs_attr_search_ctx *ctx;
+
+	ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, vcn 0x%llx.\n",
+		(unsigned long long)na->ni->mft_no, na->type, (long long)vcn);
+
+	lcn = ntfs_rl_vcn_to_lcn(na->rl, vcn);
+	if (lcn >= 0 || lcn == LCN_HOLE || lcn == LCN_ENOENT)
+		return 0;
+
+	ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
+	if (!ctx)
+		return -1;
+
+	/* Find the attribute in the mft record. */
+	if (!ntfs_attr_lookup(na->type, na->name, na->name_len, CASE_SENSITIVE,
+			vcn, NULL, 0, ctx)) {
+		runlist_element *rl;
+
+		/* Decode the runlist. */
+		rl = ntfs_mapping_pairs_decompress(na->ni->vol, ctx->attr,
+				na->rl);
+		if (rl) {
+			na->rl = rl;
+			ntfs_attr_put_search_ctx(ctx);
+			return 0;
+		}
+	}
+	
+	ntfs_attr_put_search_ctx(ctx);
+	return -1;
+}
+
+#if PARTIAL_RUNLIST_UPDATING
+
+/*
+ *		Map the runlist of an attribute from some point to the end
+ *
+ *	Returns 0 if success,
+ *		-1 if it failed (errno telling why)
+ */
+
+static int ntfs_attr_map_partial_runlist(ntfs_attr *na, VCN vcn)
+{
+	VCN last_vcn;
+	VCN highest_vcn;
+	VCN needed;
+	runlist_element *rl;
+	ATTR_RECORD *a;
+	BOOL startseen;
+	ntfs_attr_search_ctx *ctx;
+	BOOL done;
+	BOOL newrunlist;
+
+	if (NAttrFullyMapped(na))
+		return 0;
+
+	ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
+	if (!ctx)
+		return -1;
+
+	/* Get the last vcn in the attribute. */
+	last_vcn = na->allocated_size >> na->ni->vol->cluster_size_bits;
+
+	needed = vcn;
+	highest_vcn = 0;
+	startseen = FALSE;
+	done = FALSE;
+	rl = (runlist_element*)NULL;
+	do {
+		newrunlist = FALSE;
+		/* Find the attribute in the mft record. */
+		if (!ntfs_attr_lookup(na->type, na->name, na->name_len, CASE_SENSITIVE,
+				needed, NULL, 0, ctx)) {
+
+			a = ctx->attr;
+				/* Decode and merge the runlist. */
+			if (ntfs_rl_vcn_to_lcn(na->rl, needed)
+						== LCN_RL_NOT_MAPPED) {
+				rl = ntfs_mapping_pairs_decompress(na->ni->vol,
+					a, na->rl);
+				newrunlist = TRUE;
+			} else
+				rl = na->rl;
+			if (rl) {
+				na->rl = rl;
+				highest_vcn = le64_to_cpu(a->highest_vcn);
+				if (highest_vcn < needed) {
+				/* corruption detection on unchanged runlists */
+					if (newrunlist
+					    && ((highest_vcn + 1) < last_vcn)) {
+						ntfs_log_error("Corrupt attribute list\n");
+						rl = (runlist_element*)NULL;
+						errno = EIO;
+					}
+					done = TRUE;
+				}
+				needed = highest_vcn + 1;
+				if (!a->lowest_vcn)
+					startseen = TRUE;
+			}
+		} else {
+			done = TRUE;
+		}
+	} while (rl && !done && (needed < last_vcn));
+	ntfs_attr_put_search_ctx(ctx);
+		/*
+		 * Make sure we reached the end, unless the last
+		 * runlist was modified earlier (using HOLES_DELAY
+		 * leads to have a visibility over attributes which
+		 * have not yet been fully updated)
+		 */
+	if (done && newrunlist && (needed < last_vcn)) {
+		ntfs_log_error("End of runlist not reached\n");
+		rl = (runlist_element*)NULL;
+		errno = EIO;
+	}
+		/* mark fully mapped if we did so */
+	if (rl && startseen)
+		NAttrSetFullyMapped(na);
+	return (rl ? 0 : -1);
+}
+
+#endif
+
+/**
+ * ntfs_attr_map_whole_runlist - map the whole runlist of an ntfs attribute
+ * @na:		ntfs attribute for which to map the runlist
+ *
+ * Map the whole runlist of the ntfs attribute @na.  For an attribute made up
+ * of only one attribute extent this is the same as calling
+ * ntfs_attr_map_runlist(na, 0) but for an attribute with multiple extents this
+ * will map the runlist fragments from each of the extents thus giving access
+ * to the entirety of the disk allocation of an attribute.
+ *
+ * Return 0 on success and -1 on error with errno set to the error code.
+ */
+int ntfs_attr_map_whole_runlist(ntfs_attr *na)
+{
+	VCN next_vcn, last_vcn, highest_vcn;
+	ntfs_attr_search_ctx *ctx;
+	ntfs_volume *vol = na->ni->vol;
+	ATTR_RECORD *a;
+	int ret = -1;
+	int not_mapped;
+
+	ntfs_log_enter("Entering for inode %llu, attr 0x%x.\n",
+		       (unsigned long long)na->ni->mft_no, na->type);
+
+		/* avoid multiple full runlist mappings */
+	if (NAttrFullyMapped(na)) {
+		ret = 0;
+		goto out;
+	}
+	ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
+	if (!ctx)
+		goto out;
+
+	/* Map all attribute extents one by one. */
+	next_vcn = last_vcn = highest_vcn = 0;
+	a = NULL;
+	while (1) {
+		runlist_element *rl;
+
+		not_mapped = 0;
+		if (ntfs_rl_vcn_to_lcn(na->rl, next_vcn) == LCN_RL_NOT_MAPPED)
+			not_mapped = 1;
+
+		if (ntfs_attr_lookup(na->type, na->name, na->name_len,
+				CASE_SENSITIVE, next_vcn, NULL, 0, ctx))
+			break;
+
+		a = ctx->attr;
+
+		if (not_mapped) {
+			/* Decode the runlist. */
+			rl = ntfs_mapping_pairs_decompress(na->ni->vol,
+								a, na->rl);
+			if (!rl)
+				goto err_out;
+			na->rl = rl;
+		}
+
+		/* Are we in the first extent? */
+		if (!next_vcn) {
+			 if (a->lowest_vcn) {
+				 errno = EIO;
+				 ntfs_log_perror("First extent of inode %llu "
+					"attribute has non-zero lowest_vcn",
+					(unsigned long long)na->ni->mft_no);
+				 goto err_out;
+			}
+			/* Get the last vcn in the attribute. */
+			last_vcn = sle64_to_cpu(a->allocated_size) >>
+					vol->cluster_size_bits;
+		}
+
+		/* Get the lowest vcn for the next extent. */
+		highest_vcn = sle64_to_cpu(a->highest_vcn);
+		next_vcn = highest_vcn + 1;
+
+		/* Only one extent or error, which we catch below. */
+		if (next_vcn <= 0) {
+			errno = ENOENT;
+			break;
+		}
+
+		/* Avoid endless loops due to corruption. */
+		if (next_vcn < sle64_to_cpu(a->lowest_vcn)) {
+			errno = EIO;
+			ntfs_log_perror("Inode %llu has corrupt attribute list",
+					(unsigned long long)na->ni->mft_no);
+			goto err_out;
+		}
+	}
+	if (!a) {
+		ntfs_log_perror("Couldn't find attribute for runlist mapping");
+		goto err_out;
+	}
+		/*
+		 * Cannot check highest_vcn when the last runlist has
+		 * been modified earlier, as runlists and sizes may be
+		 * updated without highest_vcn being in sync, when
+		 * HOLES_DELAY is used
+		 */
+	if (not_mapped && highest_vcn && highest_vcn != last_vcn - 1) {
+		errno = EIO;
+		ntfs_log_perror("Failed to load full runlist: inode: %llu "
+				"highest_vcn: 0x%llx last_vcn: 0x%llx",
+				(unsigned long long)na->ni->mft_no, 
+				(long long)highest_vcn, (long long)last_vcn);
+		goto err_out;
+	}
+	if (errno == ENOENT) {
+		NAttrSetFullyMapped(na);
+		ret = 0;
+	}
+err_out:	
+	ntfs_attr_put_search_ctx(ctx);
+out:
+	ntfs_log_leave("\n");
+	return ret;
+}
+
+/**
+ * ntfs_attr_vcn_to_lcn - convert a vcn into a lcn given an ntfs attribute
+ * @na:		ntfs attribute whose runlist to use for conversion
+ * @vcn:	vcn to convert
+ *
+ * Convert the virtual cluster number @vcn of an attribute into a logical
+ * cluster number (lcn) of a device using the runlist @na->rl to map vcns to
+ * their corresponding lcns.
+ *
+ * If the @vcn is not mapped yet, attempt to map the attribute extent
+ * containing the @vcn and retry the vcn to lcn conversion.
+ *
+ * Since lcns must be >= 0, we use negative return values with special meaning:
+ *
+ * Return value		Meaning / Description
+ * ==========================================
+ *  -1 = LCN_HOLE	Hole / not allocated on disk.
+ *  -3 = LCN_ENOENT	There is no such vcn in the attribute.
+ *  -4 = LCN_EINVAL	Input parameter error.
+ *  -5 = LCN_EIO	Corrupt fs, disk i/o error, or not enough memory.
+ */
+LCN ntfs_attr_vcn_to_lcn(ntfs_attr *na, const VCN vcn)
+{
+	LCN lcn;
+	BOOL is_retry = FALSE;
+
+	if (!na || !NAttrNonResident(na) || vcn < 0)
+		return (LCN)LCN_EINVAL;
+
+	ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", (unsigned long
+			long)na->ni->mft_no, na->type);
+retry:
+	/* Convert vcn to lcn. If that fails map the runlist and retry once. */
+	lcn = ntfs_rl_vcn_to_lcn(na->rl, vcn);
+	if (lcn >= 0)
+		return lcn;
+	if (!is_retry && !ntfs_attr_map_runlist(na, vcn)) {
+		is_retry = TRUE;
+		goto retry;
+	}
+	/*
+	 * If the attempt to map the runlist failed, or we are getting
+	 * LCN_RL_NOT_MAPPED despite having mapped the attribute extent
+	 * successfully, something is really badly wrong...
+	 */
+	if (!is_retry || lcn == (LCN)LCN_RL_NOT_MAPPED)
+		return (LCN)LCN_EIO;
+	/* lcn contains the appropriate error code. */
+	return lcn;
+}
+
+/**
+ * ntfs_attr_find_vcn - find a vcn in the runlist of an ntfs attribute
+ * @na:		ntfs attribute whose runlist to search
+ * @vcn:	vcn to find
+ *
+ * Find the virtual cluster number @vcn in the runlist of the ntfs attribute
+ * @na and return the the address of the runlist element containing the @vcn.
+ *
+ * Note you need to distinguish between the lcn of the returned runlist
+ * element being >= 0 and LCN_HOLE. In the later case you have to return zeroes
+ * on read and allocate clusters on write. You need to update the runlist, the
+ * attribute itself as well as write the modified mft record to disk.
+ *
+ * If there is an error return NULL with errno set to the error code. The
+ * following error codes are defined:
+ *	EINVAL		Input parameter error.
+ *	ENOENT		There is no such vcn in the runlist.
+ *	ENOMEM		Not enough memory.
+ *	EIO		I/O error or corrupt metadata.
+ */
+runlist_element *ntfs_attr_find_vcn(ntfs_attr *na, const VCN vcn)
+{
+	runlist_element *rl;
+	BOOL is_retry = FALSE;
+
+	if (!na || !NAttrNonResident(na) || vcn < 0) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, vcn %llx\n",
+		       (unsigned long long)na->ni->mft_no, na->type,
+		       (long long)vcn);
+retry:
+	rl = na->rl;
+	if (!rl)
+		goto map_rl;
+	if (vcn < rl[0].vcn)
+		goto map_rl;
+	while (rl->length) {
+		if (vcn < rl[1].vcn) {
+			if (rl->lcn >= (LCN)LCN_HOLE)
+				return rl;
+			break;
+		}
+		rl++;
+	}
+	switch (rl->lcn) {
+	case (LCN)LCN_RL_NOT_MAPPED:
+		goto map_rl;
+	case (LCN)LCN_ENOENT:
+		errno = ENOENT;
+		break;
+	case (LCN)LCN_EINVAL:
+		errno = EINVAL;
+		break;
+	default:
+		errno = EIO;
+		break;
+	}
+	return NULL;
+map_rl:
+	/* The @vcn is in an unmapped region, map the runlist and retry. */
+	if (!is_retry && !ntfs_attr_map_runlist(na, vcn)) {
+		is_retry = TRUE;
+		goto retry;
+	}
+	/*
+	 * If we already retried or the mapping attempt failed something has
+	 * gone badly wrong. EINVAL and ENOENT coming from a failed mapping
+	 * attempt are equivalent to errors for us as they should not happen
+	 * in our code paths.
+	 */
+	if (is_retry || errno == EINVAL || errno == ENOENT)
+		errno = EIO;
+	return NULL;
+}
+
+/**
+ * ntfs_attr_pread_i - see description at ntfs_attr_pread()
+ */ 
+static s64 ntfs_attr_pread_i(ntfs_attr *na, const s64 pos, s64 count, void *b)
+{
+	s64 br, to_read, ofs, total, total2, max_read, max_init;
+	ntfs_volume *vol;
+	runlist_element *rl;
+	u16 efs_padding_length;
+
+	/* Sanity checking arguments is done in ntfs_attr_pread(). */
+	
+	if ((na->data_flags & ATTR_COMPRESSION_MASK) && NAttrNonResident(na)) {
+		if ((na->data_flags & ATTR_COMPRESSION_MASK)
+		    == ATTR_IS_COMPRESSED)
+			return ntfs_compressed_attr_pread(na, pos, count, b);
+		else {
+				/* compression mode not supported */
+			errno = EOPNOTSUPP;
+			return -1;
+		}
+	}
+	/*
+	 * Encrypted non-resident attributes are not supported.  We return
+	 * access denied, which is what Windows NT4 does, too.
+	 * However, allow if mounted with efs_raw option
+	 */
+	vol = na->ni->vol;
+	if (!vol->efs_raw && NAttrEncrypted(na) && NAttrNonResident(na)) {
+		errno = EACCES;
+		return -1;
+	}
+	
+	if (!count)
+		return 0;
+		/*
+		 * Truncate reads beyond end of attribute,
+		 * but round to next 512 byte boundary for encrypted
+		 * attributes with efs_raw mount option
+		 */
+	max_read = na->data_size;
+	max_init = na->initialized_size;
+	if (na->ni->vol->efs_raw
+	    && (na->data_flags & ATTR_IS_ENCRYPTED)
+	    && NAttrNonResident(na)) {
+		if (na->data_size != na->initialized_size) {
+			ntfs_log_error("uninitialized encrypted file not supported\n");
+			errno = EINVAL;
+			return -1;
+		}	
+		max_init = max_read = ((na->data_size + 511) & ~511) + 2;
+	}
+	if (pos + count > max_read) {
+		if (pos >= max_read)
+			return 0;
+		count = max_read - pos;
+	}
+	/* If it is a resident attribute, get the value from the mft record. */
+	if (!NAttrNonResident(na)) {
+		ntfs_attr_search_ctx *ctx;
+		char *val;
+
+		ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
+		if (!ctx)
+			return -1;
+		if (ntfs_attr_lookup(na->type, na->name, na->name_len, 0,
+				0, NULL, 0, ctx)) {
+res_err_out:
+			ntfs_attr_put_search_ctx(ctx);
+			return -1;
+		}
+		val = (char*)ctx->attr + le16_to_cpu(ctx->attr->value_offset);
+		if (val < (char*)ctx->attr || val +
+				le32_to_cpu(ctx->attr->value_length) >
+				(char*)ctx->mrec + vol->mft_record_size) {
+			errno = EIO;
+			ntfs_log_perror("%s: Sanity check failed", __FUNCTION__);
+			goto res_err_out;
+		}
+		memcpy(b, val + pos, count);
+		ntfs_attr_put_search_ctx(ctx);
+		return count;
+	}
+	total = total2 = 0;
+	/* Zero out reads beyond initialized size. */
+	if (pos + count > max_init) {
+		if (pos >= max_init) {
+			memset(b, 0, count);
+			return count;
+		}
+		total2 = pos + count - max_init;
+		count -= total2;
+		memset((u8*)b + count, 0, total2);
+	}
+		/*
+		 * for encrypted non-resident attributes with efs_raw set 
+		 * the last two bytes aren't read from disk but contain
+		 * the number of padding bytes so original size can be 
+		 * restored
+		 */
+	if (na->ni->vol->efs_raw && 
+			(na->data_flags & ATTR_IS_ENCRYPTED) && 
+			((pos + count) > max_init-2)) {
+		efs_padding_length = 511 - ((na->data_size - 1) & 511);
+		if (pos+count == max_init) {
+			if (count == 1) {
+				*((u8*)b+count-1) = (u8)(efs_padding_length >> 8);
+				count--;
+				total2++;
+			} else {
+				*(u16*)((u8*)b+count-2) = cpu_to_le16(efs_padding_length);
+				count -= 2;
+				total2 +=2;
+			}
+		} else {
+			*((u8*)b+count-1) = (u8)(efs_padding_length & 0xff);
+			count--;
+			total2++;
+		}
+	}
+	
+	/* Find the runlist element containing the vcn. */
+	rl = ntfs_attr_find_vcn(na, pos >> vol->cluster_size_bits);
+	if (!rl) {
+		/*
+		 * If the vcn is not present it is an out of bounds read.
+		 * However, we already truncated the read to the data_size,
+		 * so getting this here is an error.
+		 */
+		if (errno == ENOENT) {
+			errno = EIO;
+			ntfs_log_perror("%s: Failed to find VCN #1", __FUNCTION__);
+		}
+		return -1;
+	}
+	/*
+	 * Gather the requested data into the linear destination buffer. Note,
+	 * a partial final vcn is taken care of by the @count capping of read
+	 * length.
+	 */
+	ofs = pos - (rl->vcn << vol->cluster_size_bits);
+	for (; count; rl++, ofs = 0) {
+		if (rl->lcn == LCN_RL_NOT_MAPPED) {
+			rl = ntfs_attr_find_vcn(na, rl->vcn);
+			if (!rl) {
+				if (errno == ENOENT) {
+					errno = EIO;
+					ntfs_log_perror("%s: Failed to find VCN #2",
+							__FUNCTION__);
+				}
+				goto rl_err_out;
+			}
+			/* Needed for case when runs merged. */
+			ofs = pos + total - (rl->vcn << vol->cluster_size_bits);
+		}
+		if (!rl->length) {
+			errno = EIO;
+			ntfs_log_perror("%s: Zero run length", __FUNCTION__);
+			goto rl_err_out;
+		}
+		if (rl->lcn < (LCN)0) {
+			if (rl->lcn != (LCN)LCN_HOLE) {
+				ntfs_log_perror("%s: Bad run (%lld)", 
+						__FUNCTION__,
+						(long long)rl->lcn);
+				goto rl_err_out;
+			}
+			/* It is a hole, just zero the matching @b range. */
+			to_read = min(count, (rl->length <<
+					vol->cluster_size_bits) - ofs);
+			memset(b, 0, to_read);
+			/* Update progress counters. */
+			total += to_read;
+			count -= to_read;
+			b = (u8*)b + to_read;
+			continue;
+		}
+		/* It is a real lcn, read it into @dst. */
+		to_read = min(count, (rl->length << vol->cluster_size_bits) -
+				ofs);
+retry:
+		ntfs_log_trace("Reading %lld bytes from vcn %lld, lcn %lld, ofs"
+				" %lld.\n", (long long)to_read, (long long)rl->vcn,
+			       (long long )rl->lcn, (long long)ofs);
+		br = ntfs_pread(vol->dev, (rl->lcn << vol->cluster_size_bits) +
+				ofs, to_read, b);
+		/* If everything ok, update progress counters and continue. */
+		if (br > 0) {
+			total += br;
+			count -= br;
+			b = (u8*)b + br;
+		}
+		if (br == to_read)
+			continue;
+		/* If the syscall was interrupted, try again. */
+		if (br == (s64)-1 && errno == EINTR)
+			goto retry;
+		if (total)
+			return total;
+		if (!br)
+			errno = EIO;
+		ntfs_log_perror("%s: ntfs_pread failed", __FUNCTION__);
+		return -1;
+	}
+	/* Finally, return the number of bytes read. */
+	return total + total2;
+rl_err_out:
+	if (total)
+		return total;
+	errno = EIO;
+	return -1;
+}
+
+/**
+ * ntfs_attr_pread - read from an attribute specified by an ntfs_attr structure
+ * @na:		ntfs attribute to read from
+ * @pos:	byte position in the attribute to begin reading from
+ * @count:	number of bytes to read
+ * @b:		output data buffer
+ *
+ * This function will read @count bytes starting at offset @pos from the ntfs
+ * attribute @na into the data buffer @b.
+ *
+ * On success, return the number of successfully read bytes. If this number is
+ * lower than @count this means that the read reached end of file or that an
+ * error was encountered during the read so that the read is partial. 0 means
+ * end of file or nothing was read (also return 0 when @count is 0).
+ *
+ * On error and nothing has been read, return -1 with errno set appropriately
+ * to the return code of ntfs_pread(), or to EINVAL in case of invalid
+ * arguments.
+ */
+s64 ntfs_attr_pread(ntfs_attr *na, const s64 pos, s64 count, void *b)
+{
+	s64 ret;
+	
+	if (!na || !na->ni || !na->ni->vol || !b || pos < 0 || count < 0) {
+		errno = EINVAL;
+		ntfs_log_perror("%s: na=%p  b=%p  pos=%lld  count=%lld",
+				__FUNCTION__, na, b, (long long)pos,
+				(long long)count);
+		return -1;
+	}
+	
+	ntfs_log_enter("Entering for inode %lld attr 0x%x pos %lld count "
+		       "%lld\n", (unsigned long long)na->ni->mft_no,
+		       na->type, (long long)pos, (long long)count);
+
+	ret = ntfs_attr_pread_i(na, pos, count, b);
+	
+	ntfs_log_leave("\n");
+	return ret;
+}
+
+static int ntfs_attr_fill_zero(ntfs_attr *na, s64 pos, s64 count)
+{
+	char *buf;
+	s64 written, size, end = pos + count;
+	s64 ofsi;
+	const runlist_element *rli;
+	ntfs_volume *vol;
+	int ret = -1;
+
+	ntfs_log_trace("pos %lld, count %lld\n", (long long)pos, 
+		       (long long)count);
+	
+	if (!na || pos < 0 || count < 0) {
+		errno = EINVAL;
+		goto err_out;
+	}
+	
+	buf = ntfs_calloc(NTFS_BUF_SIZE);
+	if (!buf)
+		goto err_out;
+	
+	rli = na->rl;
+	ofsi = 0;
+	vol = na->ni->vol;
+	while (pos < end) {
+		while (rli->length && (ofsi + (rli->length <<
+	                        vol->cluster_size_bits) <= pos)) {
+	                ofsi += (rli->length << vol->cluster_size_bits);
+			rli++;
+		}
+		size = min(end - pos, NTFS_BUF_SIZE);
+			/*
+			 * If the zeroed block is fully within a hole,
+			 * we need not write anything, so advance as far
+			 * as possible within the hole.
+			 */
+		if ((rli->lcn == (LCN)LCN_HOLE)
+		    && (ofsi <= pos)
+		    && (ofsi + (rli->length << vol->cluster_size_bits)
+				>= (pos + size))) {
+			size = min(end - pos, ofsi - pos
+				+ (rli->length << vol->cluster_size_bits));
+			pos += size;
+		} else {
+			written = ntfs_rl_pwrite(vol, rli, ofsi, pos,
+							size, buf);
+			if (written <= 0) {
+				ntfs_log_perror("Failed to zero space");
+				goto err_free;
+			}
+			pos += written;
+		}
+	}
+	
+	ret = 0;
+err_free:	
+	free(buf);
+err_out:
+	return ret;	
+}
+
+static int ntfs_attr_fill_hole(ntfs_attr *na, s64 count, s64 *ofs, 
+			       runlist_element **rl, VCN *update_from)
+{
+	s64 to_write;
+	s64 need;
+	ntfs_volume *vol = na->ni->vol;
+	int eo, ret = -1;
+	runlist *rlc;
+	LCN lcn_seek_from = -1;
+	VCN cur_vcn, from_vcn;
+
+	to_write = min(count, ((*rl)->length << vol->cluster_size_bits) - *ofs);
+	
+	cur_vcn = (*rl)->vcn;
+	from_vcn = (*rl)->vcn + (*ofs >> vol->cluster_size_bits);
+	
+	ntfs_log_trace("count: %lld, cur_vcn: %lld, from: %lld, to: %lld, ofs: "
+		       "%lld\n", (long long)count, (long long)cur_vcn, 
+		       (long long)from_vcn, (long long)to_write, (long long)*ofs);
+	 
+	/* Map the runlist to be able to update mapping pairs later. */
+#if PARTIAL_RUNLIST_UPDATING
+	if (!na->rl) {
+		if (ntfs_attr_map_whole_runlist(na))
+			goto err_out;
+	} else {
+		/* make sure the run ahead of hole is mapped */
+		if ((*rl)->lcn == LCN_HOLE) {
+			if (ntfs_attr_map_partial_runlist(na,
+				(cur_vcn ? cur_vcn - 1 : cur_vcn)))
+					goto err_out;
+		}
+	}
+#else
+	if (ntfs_attr_map_whole_runlist(na))
+		goto err_out;
+#endif
+	 
+	/* Restore @*rl, it probably get lost during runlist mapping. */
+	*rl = ntfs_attr_find_vcn(na, cur_vcn);
+	if (!*rl) {
+		ntfs_log_error("Failed to find run after mapping runlist. "
+			       "Please report to %s.\n", NTFS_DEV_LIST);
+		errno = EIO;
+		goto err_out;
+	}
+	
+	/* Search backwards to find the best lcn to start seek from. */
+	rlc = *rl;
+	while (rlc->vcn) {
+		rlc--;
+		if (rlc->lcn >= 0) {
+				/*
+				 * avoid fragmenting a compressed file
+				 * Windows does not do that, and that may
+				 * not be desirable for files which can
+				 * be updated
+				 */
+			if (na->data_flags & ATTR_COMPRESSION_MASK)
+				lcn_seek_from = rlc->lcn + rlc->length;
+			else
+				lcn_seek_from = rlc->lcn + (from_vcn - rlc->vcn);
+			break;
+		}
+	}
+	if (lcn_seek_from == -1) {
+		/* Backwards search failed, search forwards. */
+		rlc = *rl;
+		while (rlc->length) {
+			rlc++;
+			if (rlc->lcn >= 0) {
+				lcn_seek_from = rlc->lcn - (rlc->vcn - from_vcn);
+				if (lcn_seek_from < -1)
+					lcn_seek_from = -1;
+				break;
+			}
+		}
+	}
+	
+	need = ((*ofs + to_write - 1) >> vol->cluster_size_bits)
+			 + 1 + (*rl)->vcn - from_vcn;
+	if ((na->data_flags & ATTR_COMPRESSION_MASK)
+	    && (need < na->compression_block_clusters)) {
+		/*
+		 * for a compressed file, be sure to allocate the full
+		 * compression block, as we may need space to decompress
+		 * existing compressed data.
+		 * So allocate the space common to compression block
+		 * and existing hole.
+		 */
+		VCN alloc_vcn;
+
+		if ((from_vcn & -na->compression_block_clusters) <= (*rl)->vcn)
+			alloc_vcn = (*rl)->vcn;
+		else
+			alloc_vcn = from_vcn & -na->compression_block_clusters;
+		need = (alloc_vcn | (na->compression_block_clusters - 1))
+			+ 1 - alloc_vcn;
+		if (need > (*rl)->length) {
+			ntfs_log_error("Cannot allocate %lld clusters"
+					" within a hole of %lld\n",
+					(long long)need,
+					(long long)(*rl)->length);
+			errno = EIO;
+			goto err_out;
+		}
+		rlc = ntfs_cluster_alloc(vol, alloc_vcn, need,
+				 lcn_seek_from, DATA_ZONE);
+	} else
+		rlc = ntfs_cluster_alloc(vol, from_vcn, need,
+				 lcn_seek_from, DATA_ZONE);
+	if (!rlc)
+		goto err_out;
+	if (na->data_flags & (ATTR_COMPRESSION_MASK | ATTR_IS_SPARSE))
+		na->compressed_size += need << vol->cluster_size_bits;
+	
+	*rl = ntfs_runlists_merge(na->rl, rlc);
+	NAttrSetRunlistDirty(na);
+		/*
+		 * For a compressed attribute, we must be sure there are two
+		 * available entries, so reserve them before it gets too late.
+		 */
+	if (*rl && (na->data_flags & ATTR_COMPRESSION_MASK)) {
+		runlist_element *oldrl = na->rl;
+		na->rl = *rl;
+		*rl = ntfs_rl_extend(na,*rl,2);
+		if (!*rl) na->rl = oldrl; /* restore to original if failed */
+	}
+	if (!*rl) {
+		eo = errno;
+		ntfs_log_perror("Failed to merge runlists");
+		if (ntfs_cluster_free_from_rl(vol, rlc)) {
+			ntfs_log_perror("Failed to free hot clusters. "
+					"Please run chkdsk /f");
+		}
+		errno = eo;
+		goto err_out;
+	}
+	na->unused_runs = 2;
+	na->rl = *rl;
+	if ((*update_from == -1) || (from_vcn < *update_from))
+		*update_from = from_vcn;
+	*rl = ntfs_attr_find_vcn(na, cur_vcn);
+	if (!*rl) {
+		/*
+		 * It's definitely a BUG, if we failed to find @cur_vcn, because
+		 * we missed it during instantiating of the hole.
+		 */
+		ntfs_log_error("Failed to find run after hole instantiation. "
+			       "Please report to %s.\n", NTFS_DEV_LIST);
+		errno = EIO;
+		goto err_out;
+	}
+	/* If leaved part of the hole go to the next run. */
+	if ((*rl)->lcn < 0)
+		(*rl)++;
+	/* Now LCN shoudn't be less than 0. */
+	if ((*rl)->lcn < 0) {
+		ntfs_log_error("BUG! LCN is lesser than 0. "
+			       "Please report to the %s.\n", NTFS_DEV_LIST);
+		errno = EIO;
+		goto err_out;
+	}
+	if (*ofs) {
+		/* Clear non-sparse region from @cur_vcn to @*ofs. */
+		if (ntfs_attr_fill_zero(na, cur_vcn << vol->cluster_size_bits,
+					*ofs))
+			goto err_out;
+	}
+	if ((*rl)->vcn < cur_vcn) {
+		/*
+		 * Clusters that replaced hole are merged with
+		 * previous run, so we need to update offset.
+		 */
+		*ofs += (cur_vcn - (*rl)->vcn) << vol->cluster_size_bits;
+	}
+	if ((*rl)->vcn > cur_vcn) {
+		/*
+		 * We left part of the hole, so we need to update offset
+		 */
+		*ofs -= ((*rl)->vcn - cur_vcn) << vol->cluster_size_bits;
+	}
+	
+	ret = 0;
+err_out:
+	return ret;
+}
+
+static int stuff_hole(ntfs_attr *na, const s64 pos);
+
+/*
+ *		Split an existing hole for overwriting with data
+ *	The hole may have to be split into two or three parts, so
+ *	that the overwritten part fits within a single compression block
+ *
+ *	No cluster allocation is needed, this will be done later in
+ *	standard hole filling, hence no need to reserve runs for
+ *	future needs.
+ *
+ *	Returns the number of clusters with existing compressed data
+ *		in the compression block to be written to
+ *		(or the full block, if it was a full hole)
+ *		-1 if there were an error
+ */
+
+static int split_compressed_hole(ntfs_attr *na, runlist_element **prl,
+    		s64 pos, s64 count, VCN *update_from)
+{
+	int compressed_part;
+	int cluster_size_bits = na->ni->vol->cluster_size_bits;
+	runlist_element *rl = *prl;
+
+	compressed_part
+		= na->compression_block_clusters;
+		/* reserve entries in runlist if we have to split */
+	if (rl->length > na->compression_block_clusters) {
+		*prl = ntfs_rl_extend(na,*prl,2);
+		if (!*prl) {
+			compressed_part = -1;
+		} else {
+			rl = *prl;
+			na->unused_runs = 2;
+		}
+	}
+	if (*prl && (rl->length > na->compression_block_clusters)) {
+		/*
+		 * Locate the update part relative to beginning of
+		 * current run
+		 */
+		int beginwrite = (pos >> cluster_size_bits) - rl->vcn;
+		s32 endblock = (((pos + count - 1) >> cluster_size_bits)
+			| (na->compression_block_clusters - 1)) + 1 - rl->vcn;
+
+		compressed_part = na->compression_block_clusters
+			- (rl->length & (na->compression_block_clusters - 1));
+		if ((beginwrite + compressed_part) >= na->compression_block_clusters)
+			compressed_part = na->compression_block_clusters;
+			/*
+			 * if the run ends beyond end of needed block
+			 * we have to split the run
+			 */
+		if (endblock < rl[0].length) {
+			runlist_element *xrl;
+			int n;
+
+			/*
+			 * we have to split into three parts if the run
+			 * does not end within the first compression block.
+			 * This means the hole begins before the
+			 * compression block.
+			 */
+			if (endblock > na->compression_block_clusters) {
+				if (na->unused_runs < 2) {
+ntfs_log_error("No free run, case 1\n");
+				}
+				na->unused_runs -= 2;
+				xrl = rl;
+				n = 0;
+				while (xrl->length) {
+					xrl++;
+					n++;
+				}
+				do {
+					xrl[2] = *xrl;
+					xrl--;
+				} while (xrl != rl);
+				rl[1].length = na->compression_block_clusters;
+				rl[2].length = rl[0].length - endblock;
+				rl[0].length = endblock
+					- na->compression_block_clusters;
+				rl[1].lcn = LCN_HOLE;
+				rl[2].lcn = LCN_HOLE;
+				rl[1].vcn = rl[0].vcn + rl[0].length;
+				rl[2].vcn = rl[1].vcn
+					+ na->compression_block_clusters;
+				rl = ++(*prl);
+			} else {
+				/*
+				 * split into two parts and use the
+				 * first one
+				 */
+				if (!na->unused_runs) {
+ntfs_log_error("No free run, case 2\n");
+				}
+				na->unused_runs--;
+				xrl = rl;
+				n = 0;
+				while (xrl->length) {
+					xrl++;
+					n++;
+				}
+				do {
+					xrl[1] = *xrl;
+					xrl--;
+				} while (xrl != rl);
+				if (beginwrite < endblock) {
+					/* we will write into the first part of hole */
+					rl[1].length = rl[0].length - endblock;
+					rl[0].length = endblock;
+					rl[1].vcn = rl[0].vcn + rl[0].length;
+					rl[1].lcn = LCN_HOLE;
+				} else {
+					/* we will write into the second part of hole */
+// impossible ?
+					rl[1].length = rl[0].length - endblock;
+					rl[0].length = endblock;
+					rl[1].vcn = rl[0].vcn + rl[0].length;
+					rl[1].lcn = LCN_HOLE;
+					rl = ++(*prl);
+				}
+			}
+		} else {
+			if (rl[1].length) {
+				runlist_element *xrl;
+				int n;
+
+				/*
+				 * split into two parts and use the
+				 * last one
+				 */
+				if (!na->unused_runs) {
+ntfs_log_error("No free run, case 4\n");
+				}
+				na->unused_runs--;
+				xrl = rl;
+				n = 0;
+				while (xrl->length) {
+					xrl++;
+					n++;
+				}
+				do {
+					xrl[1] = *xrl;
+					xrl--;
+				} while (xrl != rl);
+			} else {
+				rl[2].lcn = rl[1].lcn;
+				rl[2].vcn = rl[1].vcn;
+				rl[2].length = rl[1].length;
+			}
+			rl[1].vcn -= na->compression_block_clusters;
+			rl[1].lcn = LCN_HOLE;
+			rl[1].length = na->compression_block_clusters;
+			rl[0].length -= na->compression_block_clusters;
+			if (pos >= (rl[1].vcn << cluster_size_bits)) {
+				rl = ++(*prl);
+			}
+		}
+	NAttrSetRunlistDirty(na);
+	if ((*update_from == -1) || ((*prl)->vcn < *update_from))
+		*update_from = (*prl)->vcn;
+	}
+	return (compressed_part);
+}
+
+/*
+ *		Borrow space from adjacent hole for appending data
+ *	The hole may have to be split so that the end of hole is not
+ *	affected by cluster allocation and overwriting
+ *	Cluster allocation is needed for the overwritten compression block
+ *
+ *	Must always leave two unused entries in the runlist
+ *
+ *	Returns the number of clusters with existing compressed data
+ *		in the compression block to be written to
+ *		-1 if there were an error
+ */
+
+static int borrow_from_hole(ntfs_attr *na, runlist_element **prl,
+    		s64 pos, s64 count, VCN *update_from, BOOL wasnonresident)
+{
+	int compressed_part = 0;
+	int cluster_size_bits = na->ni->vol->cluster_size_bits;
+	runlist_element *rl = *prl;
+	s32 endblock;
+	long long allocated;
+	runlist_element *zrl;
+	int irl;
+	BOOL undecided;
+	BOOL nothole;
+
+		/* check whether the compression block is fully allocated */
+	endblock = (((pos + count - 1) >> cluster_size_bits) | (na->compression_block_clusters - 1)) + 1 - rl->vcn;
+	allocated = 0;
+	zrl = rl;
+	irl = 0;
+	while (zrl->length && (zrl->lcn >= 0) && (allocated < endblock)) {
+		allocated += zrl->length;
+		zrl++;
+		irl++;
+	}
+
+	undecided = (allocated < endblock) && (zrl->lcn == LCN_RL_NOT_MAPPED);
+	nothole = (allocated >= endblock) || (zrl->lcn != LCN_HOLE);
+
+	if (undecided || nothole) {
+		runlist_element *orl = na->rl;
+		s64 olcn = (*prl)->lcn;
+#if PARTIAL_RUNLIST_UPDATING
+		VCN prevblock;
+#endif
+			/*
+			 * Map the runlist, unless it has not been created.
+			 * If appending data, a partial mapping from the
+			 * end of previous block will do.
+			 */
+		irl = *prl - na->rl;
+#if PARTIAL_RUNLIST_UPDATING
+		prevblock = pos >> cluster_size_bits;
+		if (prevblock)
+			prevblock--;
+		if (!NAttrBeingNonResident(na)
+		    && (NAttrDataAppending(na)
+			? ntfs_attr_map_partial_runlist(na,prevblock)
+			: ntfs_attr_map_whole_runlist(na))) {
+#else
+		if (!NAttrBeingNonResident(na)
+			&& ntfs_attr_map_whole_runlist(na)) {
+#endif
+			rl = (runlist_element*)NULL;
+		} else {
+			/*
+			 * Mapping the runlist may cause its relocation,
+			 * and relocation may be at the same place with
+			 * relocated contents.
+			 * Have to find the current run again when this
+			 * happens.
+			 */
+			if ((na->rl != orl) || ((*prl)->lcn != olcn)) {
+				zrl = &na->rl[irl];
+				while (zrl->length && (zrl->lcn != olcn))
+					zrl++;
+				*prl = zrl;
+			}
+			if (!(*prl)->length) {
+				 ntfs_log_error("Mapped run not found,"
+					" inode %lld lcn 0x%llx\n",
+					(long long)na->ni->mft_no,
+					(long long)olcn);
+				rl = (runlist_element*)NULL;
+			} else {
+				rl = ntfs_rl_extend(na,*prl,2);
+				na->unused_runs = 2;
+			}
+		}
+		*prl = rl;
+		if (rl && undecided) {
+			allocated = 0;
+			zrl = rl;
+			irl = 0;
+			while (zrl->length && (zrl->lcn >= 0)
+			    && (allocated < endblock)) {
+				allocated += zrl->length;
+				zrl++;
+				irl++;
+			}
+		}
+	}
+		/*
+		 * compression block not fully allocated and followed
+		 * by a hole : we must allocate in the hole.
+		 */
+	if (rl && (allocated < endblock) && (zrl->lcn == LCN_HOLE)) {
+		s64 xofs;
+
+			/*
+			 * split the hole if not fully needed
+			 */
+		if ((allocated + zrl->length) > endblock) {
+			runlist_element *xrl;
+
+			*prl = ntfs_rl_extend(na,*prl,1);
+			if (*prl) {
+					/* beware : rl was reallocated */
+				rl = *prl;
+				zrl = &rl[irl];
+				na->unused_runs = 0;
+				xrl = zrl;
+				while (xrl->length) xrl++;
+				do {
+					xrl[1] = *xrl;
+				} while (xrl-- != zrl);
+				zrl->length = endblock - allocated;
+				zrl[1].length -= zrl->length;
+				zrl[1].vcn = zrl->vcn + zrl->length;
+				NAttrSetRunlistDirty(na);
+			}
+		}
+		if (*prl) {
+			if (wasnonresident)
+				compressed_part = na->compression_block_clusters
+				   - zrl->length;
+			xofs = 0;
+			if (ntfs_attr_fill_hole(na,
+				    zrl->length << cluster_size_bits,
+				    &xofs, &zrl, update_from))
+					compressed_part = -1;
+			else {
+			/* go back to initial cluster, now reallocated */
+				while (zrl->vcn > (pos >> cluster_size_bits))
+					zrl--;
+				*prl = zrl;
+			}
+		}
+	}
+	if (!*prl) {
+		ntfs_log_error("No elements to borrow from a hole\n");
+		compressed_part = -1;
+	} else
+		if ((*update_from == -1) || ((*prl)->vcn < *update_from))
+			*update_from = (*prl)->vcn;
+	return (compressed_part);
+}
+
+static int ntfs_attr_truncate_i(ntfs_attr *na, const s64 newsize,
+				hole_type holes);
+
+/**
+ * ntfs_attr_pwrite - positioned write to an ntfs attribute
+ * @na:		ntfs attribute to write to
+ * @pos:	position in the attribute to write to
+ * @count:	number of bytes to write
+ * @b:		data buffer to write to disk
+ *
+ * This function will write @count bytes from data buffer @b to ntfs attribute
+ * @na at position @pos.
+ *
+ * On success, return the number of successfully written bytes. If this number
+ * is lower than @count this means that an error was encountered during the
+ * write so that the write is partial. 0 means nothing was written (also return
+ * 0 when @count is 0).
+ *
+ * On error and nothing has been written, return -1 with errno set
+ * appropriately to the return code of ntfs_pwrite(), or to EINVAL in case of
+ * invalid arguments.
+ */
+s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b)
+{
+	s64 written, to_write, ofs, old_initialized_size, old_data_size;
+	s64 total = 0;
+	VCN update_from = -1;
+	ntfs_volume *vol;
+	s64 fullcount;
+	ntfs_attr_search_ctx *ctx = NULL;
+	runlist_element *rl;
+	s64 hole_end;
+	int eo;
+	int compressed_part;
+	struct {
+		unsigned int undo_initialized_size	: 1;
+		unsigned int undo_data_size		: 1;
+	} need_to = { 0, 0 };
+	BOOL wasnonresident = FALSE;
+	BOOL compressed;
+
+	ntfs_log_enter("Entering for inode %lld, attr 0x%x, pos 0x%llx, count "
+		       "0x%llx.\n", (long long)na->ni->mft_no, na->type,
+		       (long long)pos, (long long)count);
+	
+	if (!na || !na->ni || !na->ni->vol || !b || pos < 0 || count < 0) {
+		errno = EINVAL;
+		ntfs_log_perror("%s", __FUNCTION__);
+		goto errno_set;
+	}
+	vol = na->ni->vol;
+	compressed = (na->data_flags & ATTR_COMPRESSION_MASK)
+			 != const_cpu_to_le16(0);
+	na->unused_runs = 0; /* prepare overflow checks */
+	/*
+	 * Encrypted attributes are only supported in raw mode.  We return
+	 * access denied, which is what Windows NT4 does, too.
+	 * Moreover a file cannot be both encrypted and compressed.
+	 */
+	if ((na->data_flags & ATTR_IS_ENCRYPTED)
+	   && (compressed || !vol->efs_raw)) {
+		errno = EACCES;
+		goto errno_set;
+	}
+		/*
+		 * Fill the gap, when writing beyond the end of a compressed
+		 * file. This will make recursive calls
+		 */
+	if (compressed
+	    && (na->type == AT_DATA)
+	    && (pos > na->initialized_size)
+	    && stuff_hole(na,pos))
+		goto errno_set;
+	/* If this is a compressed attribute it needs special treatment. */
+	wasnonresident = NAttrNonResident(na) != 0;
+		/*
+		 * Compression is restricted to data streams and
+		 * only ATTR_IS_COMPRESSED compression mode is supported.
+                 */
+	if (compressed
+	    && ((na->type != AT_DATA)
+		|| ((na->data_flags & ATTR_COMPRESSION_MASK)
+			 != ATTR_IS_COMPRESSED))) {
+		errno = EOPNOTSUPP;
+		goto errno_set;
+	}
+	
+	if (!count)
+		goto out;
+	/* for a compressed file, get prepared to reserve a full block */
+	fullcount = count;
+	/* If the write reaches beyond the end, extend the attribute. */
+	old_data_size = na->data_size;
+	/* identify whether this is appending to a non resident data attribute */
+	if ((na->type == AT_DATA) && (pos >= old_data_size)
+	    && NAttrNonResident(na))
+		NAttrSetDataAppending(na);
+	if (pos + count > na->data_size) {
+#if PARTIAL_RUNLIST_UPDATING
+		/*
+		 * When appending data, the attribute is first extended
+		 * before being filled with data. This may cause the
+		 * attribute to be made temporarily sparse, which
+		 * implies reformating the inode and reorganizing the
+		 * full runlist. To avoid unnecessary reorganization,
+		 * we avoid sparse testing until the data is filled in.
+		 */
+		if (ntfs_attr_truncate_i(na, pos + count,
+					(NAttrDataAppending(na) ?
+						HOLES_DELAY : HOLES_OK))) {
+			ntfs_log_perror("Failed to enlarge attribute");
+			goto errno_set;
+		}
+		/*
+		 * If we avoided updating the runlist, we must be sure
+		 * to cancel the enlargement and put back the runlist to
+		 * a clean state if we get into some error.
+		 */
+		if (NAttrDataAppending(na))
+			need_to.undo_data_size = 1;
+#else
+		if (ntfs_attr_truncate_i(na, pos + count, HOLES_OK)) {
+			ntfs_log_perror("Failed to enlarge attribute");
+			goto errno_set;
+		}
+#endif
+			/* resizing may change the compression mode */
+		compressed = (na->data_flags & ATTR_COMPRESSION_MASK)
+				!= const_cpu_to_le16(0);
+		need_to.undo_data_size = 1;
+	}
+		/*
+		 * For compressed data, a single full block was allocated
+		 * to deal with compression, possibly in a previous call.
+		 * We are not able to process several blocks because
+		 * some clusters are freed after compression and
+		 * new allocations have to be done before proceeding,
+		 * so truncate the requested count if needed (big buffers).
+		 */
+	if (compressed) {
+		fullcount = (pos | (na->compression_block_size - 1)) + 1 - pos;
+		if (count > fullcount)
+			count = fullcount;
+	}
+	old_initialized_size = na->initialized_size;
+	/* If it is a resident attribute, write the data to the mft record. */
+	if (!NAttrNonResident(na)) {
+		char *val;
+
+		ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
+		if (!ctx)
+			goto err_out;
+		if (ntfs_attr_lookup(na->type, na->name, na->name_len, 0,
+				0, NULL, 0, ctx)) {
+			ntfs_log_perror("%s: lookup failed", __FUNCTION__);
+			goto err_out;
+		}
+		val = (char*)ctx->attr + le16_to_cpu(ctx->attr->value_offset);
+		if (val < (char*)ctx->attr || val +
+				le32_to_cpu(ctx->attr->value_length) >
+				(char*)ctx->mrec + vol->mft_record_size) {
+			errno = EIO;
+			ntfs_log_perror("%s: Sanity check failed", __FUNCTION__);
+			goto err_out;
+		}
+		memcpy(val + pos, b, count);
+		if (ntfs_mft_record_write(vol, ctx->ntfs_ino->mft_no,
+				ctx->mrec)) {
+			/*
+			 * NOTE: We are in a bad state at this moment. We have
+			 * dirtied the mft record but we failed to commit it to
+			 * disk. Since we have read the mft record ok before,
+			 * it is unlikely to fail writing it, so is ok to just
+			 * return error here... (AIA)
+			 */
+			ntfs_log_perror("%s: failed to write mft record", __FUNCTION__);
+			goto err_out;
+		}
+		ntfs_attr_put_search_ctx(ctx);
+		total = count;
+		goto out;
+	}
+	
+	/* Handle writes beyond initialized_size. */
+
+	if (pos + count > na->initialized_size) {
+#if PARTIAL_RUNLIST_UPDATING
+		/*
+		 * When appending, we only need to map the end of the runlist,
+		 * starting at the last previously allocated run, so that
+		 * we are able a new one to it.
+		 * However, for compressed file, we need the full compression
+		 * block, which may be split in several extents.
+		 */
+		if (compressed && !NAttrDataAppending(na)) {
+			if (ntfs_attr_map_whole_runlist(na))
+				goto err_out;
+		} else {
+			VCN block_begin;
+
+			if (NAttrDataAppending(na)
+			    || (pos < na->initialized_size))
+				block_begin = pos >> vol->cluster_size_bits;
+			else
+				block_begin = na->initialized_size >> vol->cluster_size_bits;
+
+			if (compressed)
+				block_begin &= -na->compression_block_clusters;
+			if (block_begin)
+				block_begin--;
+			if (ntfs_attr_map_partial_runlist(na, block_begin))
+				goto err_out;
+			if ((update_from == -1) || (block_begin < update_from))
+				update_from = block_begin;
+		}
+#else
+			if (ntfs_attr_map_whole_runlist(na))
+				goto err_out;
+#endif
+		/*
+		 * For a compressed attribute, we must be sure there is an
+		 * available entry, and, when reopening a compressed file,
+		 * we may need to split a hole. So reserve the entries
+		 * before it gets too late.
+		 */
+		if (compressed) {
+			na->rl = ntfs_rl_extend(na,na->rl,2);
+			if (!na->rl)
+				goto err_out;
+			na->unused_runs = 2;
+		}
+		/* Set initialized_size to @pos + @count. */
+		ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
+		if (!ctx)
+			goto err_out;
+		if (ntfs_attr_lookup(na->type, na->name, na->name_len, 0,
+				0, NULL, 0, ctx))
+			goto err_out;
+		
+		/* If write starts beyond initialized_size, zero the gap. */
+		if (pos > na->initialized_size)
+			if (ntfs_attr_fill_zero(na, na->initialized_size, 
+						pos - na->initialized_size))
+				goto err_out;
+			
+		ctx->attr->initialized_size = cpu_to_sle64(pos + count);
+		/* fix data_size for compressed files */
+		if (compressed) {
+			na->data_size = pos + count;
+			ctx->attr->data_size = ctx->attr->initialized_size;
+		}
+		if (ntfs_mft_record_write(vol, ctx->ntfs_ino->mft_no,
+				ctx->mrec)) {
+			/*
+			 * Undo the change in the in-memory copy and send it
+			 * back for writing.
+			 */
+			ctx->attr->initialized_size =
+					cpu_to_sle64(old_initialized_size);
+			ntfs_mft_record_write(vol, ctx->ntfs_ino->mft_no,
+					ctx->mrec);
+			goto err_out;
+		}
+		na->initialized_size = pos + count;
+#if CACHE_NIDATA_SIZE
+		if (na->ni->mrec->flags & MFT_RECORD_IS_DIRECTORY
+		    ? na->type == AT_INDEX_ROOT && na->name == NTFS_INDEX_I30
+		    : na->type == AT_DATA && na->name == AT_UNNAMED) {
+			na->ni->data_size = na->data_size;
+			if ((compressed || NAttrSparse(na))
+					&& NAttrNonResident(na))
+				na->ni->allocated_size = na->compressed_size;
+			else
+				na->ni->allocated_size = na->allocated_size;
+			set_nino_flag(na->ni,KnownSize);
+		}
+#endif
+		ntfs_attr_put_search_ctx(ctx);
+		ctx = NULL;
+		/*
+		 * NOTE: At this point the initialized_size in the mft record
+		 * has been updated BUT there is random data on disk thus if
+		 * we decide to abort, we MUST change the initialized_size
+		 * again.
+		 */
+		need_to.undo_initialized_size = 1;
+	}
+	/* Find the runlist element containing the vcn. */
+	rl = ntfs_attr_find_vcn(na, pos >> vol->cluster_size_bits);
+	if (!rl) {
+		/*
+		 * If the vcn is not present it is an out of bounds write.
+		 * However, we already extended the size of the attribute,
+		 * so getting this here must be an error of some kind.
+		 */
+		if (errno == ENOENT) {
+			errno = EIO;
+			ntfs_log_perror("%s: Failed to find VCN #3", __FUNCTION__);
+		}
+		goto err_out;
+	}
+		/*
+		 * Determine if there is compressed data in the current
+		 * compression block (when appending to an existing file).
+		 * If so, decompression will be needed, and the full block
+		 * must be allocated to be identified as uncompressed.
+		 * This comes in two variants, depending on whether
+		 * compression has saved at least one cluster.
+		 * The compressed size can never be over full size by
+		 * more than 485 (maximum for 15 compression blocks
+		 * compressed to 4098 and the last 3640 bytes compressed
+		 * to 3640 + 3640/8 = 4095, with 15*2 + 4095 - 3640 = 485)
+		 * This is less than the smallest cluster, so the hole is
+		 * is never beyond the cluster next to the position of
+		 * the first uncompressed byte to write.
+		 */
+	compressed_part = 0;
+	if (compressed) {
+		if ((rl->lcn == (LCN)LCN_HOLE)
+		    && wasnonresident) {
+			if (rl->length < na->compression_block_clusters)
+				/*
+				 * the needed block is in a hole smaller
+				 * than the compression block : we can use
+				 * it fully
+				 */
+				compressed_part
+					= na->compression_block_clusters
+					   - rl->length;
+			else {
+				/*
+				 * the needed block is in a hole bigger
+				 * than the compression block : we must
+				 * split the hole and use it partially
+				 */
+				compressed_part = split_compressed_hole(na,
+					&rl, pos, count, &update_from);
+			}
+		} else {
+			if (rl->lcn >= 0) {
+				/*
+				 * the needed block contains data, make
+				 * sure the full compression block is
+				 * allocated. Borrow from hole if needed
+				 */
+				compressed_part = borrow_from_hole(na,
+					&rl, pos, count, &update_from,
+					wasnonresident);
+			}
+		}
+
+		if (compressed_part < 0)
+			goto err_out;
+
+			/* just making non-resident, so not yet compressed */
+		if (NAttrBeingNonResident(na)
+		    && (compressed_part < na->compression_block_clusters))
+			compressed_part = 0;
+	}
+	ofs = pos - (rl->vcn << vol->cluster_size_bits);
+	/*
+	 * Scatter the data from the linear data buffer to the volume. Note, a
+	 * partial final vcn is taken care of by the @count capping of write
+	 * length.
+	 */
+	for (hole_end = 0; count; rl++, ofs = 0) {
+		if (rl->lcn == LCN_RL_NOT_MAPPED) {
+			rl = ntfs_attr_find_vcn(na, rl->vcn);
+			if (!rl) {
+				if (errno == ENOENT) {
+					errno = EIO;
+					ntfs_log_perror("%s: Failed to find VCN"
+							" #4", __FUNCTION__);
+				}
+				goto rl_err_out;
+			}
+			/* Needed for case when runs merged. */
+			ofs = pos + total - (rl->vcn << vol->cluster_size_bits);
+		}
+		if (!rl->length) {
+			errno = EIO;
+			ntfs_log_perror("%s: Zero run length", __FUNCTION__);
+			goto rl_err_out;
+		}
+		if (rl->lcn < (LCN)0) {
+			hole_end = rl->vcn + rl->length;
+
+			if (rl->lcn != (LCN)LCN_HOLE) {
+				errno = EIO;
+				ntfs_log_perror("%s: Unexpected LCN (%lld)", 
+						__FUNCTION__,
+						(long long)rl->lcn);
+				goto rl_err_out;
+			}
+			if (ntfs_attr_fill_hole(na, fullcount, &ofs, &rl,
+					 &update_from))
+				goto err_out;
+		}
+		if (compressed) {
+			while (rl->length
+			    && (ofs >= (rl->length << vol->cluster_size_bits))) {
+				ofs -= rl->length << vol->cluster_size_bits;
+				rl++;
+			}
+		}
+
+		/* It is a real lcn, write it to the volume. */
+		to_write = min(count, (rl->length << vol->cluster_size_bits) - ofs);
+retry:
+		ntfs_log_trace("Writing %lld bytes to vcn %lld, lcn %lld, ofs "
+			       "%lld.\n", (long long)to_write, (long long)rl->vcn,
+			       (long long)rl->lcn, (long long)ofs);
+		if (!NVolReadOnly(vol)) {
+			
+			s64 wpos = (rl->lcn << vol->cluster_size_bits) + ofs;
+			s64 wend = (rl->vcn << vol->cluster_size_bits) + ofs + to_write;
+			u32 bsize = vol->cluster_size;
+			/* Byte size needed to zero fill a cluster */
+			s64 rounding = ((wend + bsize - 1) & ~(s64)(bsize - 1)) - wend;
+			/**
+			 * Zero fill to cluster boundary if we're writing at the
+			 * end of the attribute or into an ex-sparse cluster.
+			 * This will cause the kernel not to seek and read disk 
+			 * blocks during write(2) to fill the end of the buffer 
+			 * which increases write speed by 2-10 fold typically.
+			 *
+			 * This is done even for compressed files, because
+			 * data is generally first written uncompressed.
+			 */
+			if (rounding && ((wend == na->initialized_size) ||
+				(wend < (hole_end << vol->cluster_size_bits)))){
+				
+				char *cb;
+				
+				rounding += to_write;
+				
+				cb = ntfs_malloc(rounding);
+				if (!cb)
+					goto err_out;
+				
+				memcpy(cb, b, to_write);
+				memset(cb + to_write, 0, rounding - to_write);
+				
+				if (compressed) {
+					written = ntfs_compressed_pwrite(na,
+						rl, wpos, ofs, to_write,
+						rounding, cb, compressed_part,
+						&update_from);
+				} else {
+					written = ntfs_pwrite(vol->dev, wpos,
+						rounding, cb); 
+					if (written == rounding)
+						written = to_write;
+				}
+				
+				free(cb);
+			} else {
+				if (compressed) {
+					written = ntfs_compressed_pwrite(na,
+						rl, wpos, ofs, to_write, 
+						to_write, b, compressed_part,
+						&update_from);
+				} else
+					written = ntfs_pwrite(vol->dev, wpos,
+						to_write, b);
+				}
+		} else
+			written = to_write;
+		/* If everything ok, update progress counters and continue. */
+		if (written > 0) {
+			total += written;
+			count -= written;
+			fullcount -= written;
+			b = (const u8*)b + written;
+		}
+		if (written != to_write) {
+			/* Partial write cannot be dealt with, stop there */
+			/* If the syscall was interrupted, try again. */
+			if (written == (s64)-1 && errno == EINTR)
+				goto retry;
+			if (!written)
+				errno = EIO;
+			goto rl_err_out;
+		}
+		compressed_part = 0;
+	}
+done:
+	if (ctx)
+		ntfs_attr_put_search_ctx(ctx);
+		/*
+		 *	 Update mapping pairs if needed.
+		 * For a compressed file, we try to make a partial update
+		 * of the mapping list. This makes a difference only if
+		 * inode extents were needed.
+		 */
+	if (NAttrRunlistDirty(na)) {
+		if (ntfs_attr_update_mapping_pairs(na,
+				(update_from < 0 ? 0 : update_from))) {
+			/*
+			 * FIXME: trying to recover by goto rl_err_out; 
+			 * could cause driver hang by infinite looping.
+			 */
+			total = -1;
+			goto out;
+		}
+		if (!wasnonresident)
+			NAttrClearBeingNonResident(na);
+		NAttrClearDataAppending(na);
+	}
+out:	
+	ntfs_log_leave("\n");
+	return total;
+rl_err_out:
+	eo = errno;
+	if (total) {
+		if (need_to.undo_initialized_size) {
+			if (pos + total > na->initialized_size)
+				goto done;
+			/*
+			 * TODO: Need to try to change initialized_size. If it
+			 * succeeds goto done, otherwise goto err_out. (AIA)
+			 */
+			goto err_out;
+		}
+		goto done;
+	}
+	errno = eo;
+err_out:
+	eo = errno;
+	if (need_to.undo_initialized_size) {
+		int err;
+
+		err = 0;
+		if (!ctx) {
+			ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
+			if (!ctx)
+				err = 1;
+		} else
+			ntfs_attr_reinit_search_ctx(ctx);
+		if (!err) {
+			err = ntfs_attr_lookup(na->type, na->name,
+					na->name_len, 0, 0, NULL, 0, ctx);
+			if (!err) {
+				na->initialized_size = old_initialized_size;
+				ctx->attr->initialized_size = cpu_to_sle64(
+						old_initialized_size);
+				err = ntfs_mft_record_write(vol,
+						ctx->ntfs_ino->mft_no,
+						ctx->mrec);
+			}
+		}
+		if (err) {
+			/*
+			 * FIXME: At this stage could try to recover by filling
+			 * old_initialized_size -> new_initialized_size with
+			 * data or at least zeroes. (AIA)
+			 */
+			ntfs_log_error("Eeek! Failed to recover from error. "
+					"Leaving metadata in inconsistent "
+					"state! Run chkdsk!\n");
+		}
+	}
+	if (ctx)
+		ntfs_attr_put_search_ctx(ctx);
+	/* Update mapping pairs if needed. */
+	if (NAttrRunlistDirty(na))
+		ntfs_attr_update_mapping_pairs(na, 0);
+	/* Restore original data_size if needed. */
+	if (need_to.undo_data_size
+			&& ntfs_attr_truncate_i(na, old_data_size, HOLES_OK))
+		ntfs_log_perror("Failed to restore data_size");
+	errno = eo;
+errno_set:
+	total = -1;
+	goto out;
+}
+
+int ntfs_attr_pclose(ntfs_attr *na)
+{
+	s64 ofs;
+	int failed;
+	BOOL ok = TRUE;
+	VCN update_from = -1;
+	ntfs_volume *vol;
+	ntfs_attr_search_ctx *ctx = NULL;
+	runlist_element *rl;
+	int eo;
+	int compressed_part;
+	BOOL compressed;
+
+	ntfs_log_enter("Entering for inode 0x%llx, attr 0x%x.\n",
+			na->ni->mft_no, na->type);
+	
+	if (!na || !na->ni || !na->ni->vol) {
+		errno = EINVAL;
+		ntfs_log_perror("%s", __FUNCTION__);
+		goto errno_set;
+	}
+	vol = na->ni->vol;
+	na->unused_runs = 0;
+	compressed = (na->data_flags & ATTR_COMPRESSION_MASK)
+			 != const_cpu_to_le16(0);
+	/*
+	 * Encrypted non-resident attributes are not supported.  We return
+	 * access denied, which is what Windows NT4 does, too.
+	 */
+	if (NAttrEncrypted(na) && NAttrNonResident(na)) {
+		errno = EACCES;
+		goto errno_set;
+	}
+	/* If this is not a compressed attribute get out */
+	/* same if it is resident */
+	if (!compressed || !NAttrNonResident(na))
+		goto out;
+
+		/* safety check : no recursion on close */
+	if (NAttrComprClosing(na)) {
+		errno = EIO;
+		ntfs_log_error("Bad ntfs_attr_pclose"
+				" recursion on inode %lld\n",
+				(long long)na->ni->mft_no);
+		goto out;
+	}
+	NAttrSetComprClosing(na);
+		/*
+		 * For a compressed attribute, we must be sure there are two
+		 * available entries, so reserve them before it gets too late.
+		 */
+	if (ntfs_attr_map_whole_runlist(na))
+		goto err_out;
+	na->rl = ntfs_rl_extend(na,na->rl,2);
+	if (!na->rl)
+		goto err_out;
+	na->unused_runs = 2;
+	/* Find the runlist element containing the terminal vcn. */
+	rl = ntfs_attr_find_vcn(na, (na->initialized_size - 1) >> vol->cluster_size_bits);
+	if (!rl) {
+		/*
+		 * If the vcn is not present it is an out of bounds write.
+		 * However, we have already written the last byte uncompressed,
+		 * so getting this here must be an error of some kind.
+		 */
+		if (errno == ENOENT) {
+			errno = EIO;
+			ntfs_log_perror("%s: Failed to find VCN #5", __FUNCTION__);
+		}
+		goto err_out;
+	}
+	/*
+	 * Scatter the data from the linear data buffer to the volume. Note, a
+	 * partial final vcn is taken care of by the @count capping of write
+	 * length.
+	 */
+	compressed_part = 0;
+ 	if (rl->lcn >= 0) {
+		runlist_element *xrl;
+
+		xrl = rl;
+		do {
+			xrl++;
+		} while (xrl->lcn >= 0);
+		compressed_part = (-xrl->length)
+					& (na->compression_block_clusters - 1);
+	} else
+		if (rl->lcn == (LCN)LCN_HOLE) {
+			if (rl->length < na->compression_block_clusters)
+				compressed_part
+        	                        = na->compression_block_clusters
+                	                           - rl->length;
+			else
+				compressed_part
+					= na->compression_block_clusters;
+		}
+		/* done, if the last block set was compressed */
+	if (compressed_part)
+		goto out;
+
+	ofs = na->initialized_size - (rl->vcn << vol->cluster_size_bits);
+
+	if (rl->lcn == LCN_RL_NOT_MAPPED) {
+		rl = ntfs_attr_find_vcn(na, rl->vcn);
+		if (!rl) {
+			if (errno == ENOENT) {
+				errno = EIO;
+				ntfs_log_perror("%s: Failed to find VCN"
+						" #6", __FUNCTION__);
+			}
+			goto rl_err_out;
+		}
+			/* Needed for case when runs merged. */
+		ofs = na->initialized_size - (rl->vcn << vol->cluster_size_bits);
+	}
+	if (!rl->length) {
+		errno = EIO;
+		ntfs_log_perror("%s: Zero run length", __FUNCTION__);
+		goto rl_err_out;
+	}
+	if (rl->lcn < (LCN)0) {
+		if (rl->lcn != (LCN)LCN_HOLE) {
+			errno = EIO;
+			ntfs_log_perror("%s: Unexpected LCN (%lld)", 
+					__FUNCTION__,
+					(long long)rl->lcn);
+			goto rl_err_out;
+		}
+			
+		if (ntfs_attr_fill_hole(na, (s64)0, &ofs, &rl, &update_from))
+			goto err_out;
+	}
+	while (rl->length
+	    && (ofs >= (rl->length << vol->cluster_size_bits))) {
+		ofs -= rl->length << vol->cluster_size_bits;
+		rl++;
+	}
+
+retry:
+	failed = 0;
+	if (update_from < 0) update_from = 0;
+	if (!NVolReadOnly(vol)) {
+		failed = ntfs_compressed_close(na, rl, ofs, &update_from);
+#if CACHE_NIDATA_SIZE
+		if (na->ni->mrec->flags & MFT_RECORD_IS_DIRECTORY
+		    ? na->type == AT_INDEX_ROOT && na->name == NTFS_INDEX_I30
+		    : na->type == AT_DATA && na->name == AT_UNNAMED) {
+			na->ni->data_size = na->data_size;
+			na->ni->allocated_size = na->compressed_size;
+			set_nino_flag(na->ni,KnownSize);
+		}
+#endif
+	}
+	if (failed) {
+		/* If the syscall was interrupted, try again. */
+		if (errno == EINTR)
+			goto retry;
+		else
+			goto rl_err_out;
+	}
+	if (ctx)
+		ntfs_attr_put_search_ctx(ctx);
+	/* Update mapping pairs if needed. */
+	if (NAttrFullyMapped(na))
+		if (ntfs_attr_update_mapping_pairs(na, update_from)) {
+			/*
+			 * FIXME: trying to recover by goto rl_err_out; 
+			 * could cause driver hang by infinite looping.
+			 */
+			ok = FALSE;
+			goto out;
+	}
+out:	
+	NAttrClearComprClosing(na);
+	ntfs_log_leave("\n");
+	return (!ok);
+rl_err_out:
+		/*
+		 * need not restore old sizes, only compressed_size
+		 * can have changed. It has been set according to
+		 * the current runlist while updating the mapping pairs,
+		 * and must be kept consistent with the runlists.
+		 */
+err_out:
+	eo = errno;
+	if (ctx)
+		ntfs_attr_put_search_ctx(ctx);
+	/* Update mapping pairs if needed. */
+	if (NAttrFullyMapped(na))
+		ntfs_attr_update_mapping_pairs(na, 0);
+	errno = eo;
+errno_set:
+	ok = FALSE;
+	goto out;
+}
+
+/**
+ * ntfs_attr_mst_pread - multi sector transfer protected ntfs attribute read
+ * @na:		multi sector transfer protected ntfs attribute to read from
+ * @pos:	byte position in the attribute to begin reading from
+ * @bk_cnt:	number of mst protected blocks to read
+ * @bk_size:	size of each mst protected block in bytes
+ * @dst:	output data buffer
+ *
+ * This function will read @bk_cnt blocks of size @bk_size bytes each starting
+ * at offset @pos from the ntfs attribute @na into the data buffer @b.
+ *
+ * On success, the multi sector transfer fixups are applied and the number of
+ * read blocks is returned. If this number is lower than @bk_cnt this means
+ * that the read has either reached end of attribute or that an error was
+ * encountered during the read so that the read is partial. 0 means end of
+ * attribute or nothing to read (also return 0 when @bk_cnt or @bk_size are 0).
+ *
+ * On error and nothing has been read, return -1 with errno set appropriately
+ * to the return code of ntfs_attr_pread() or to EINVAL in case of invalid
+ * arguments.
+ *
+ * NOTE: If an incomplete multi sector transfer is detected the magic is
+ * changed to BAAD but no error is returned, i.e. it is possible that any of
+ * the returned blocks have multi sector transfer errors. This should be
+ * detected by the caller by checking each block with is_baad_recordp(&block).
+ * The reasoning is that we want to fixup as many blocks as possible and we
+ * want to return even bad ones to the caller so, e.g. in case of ntfsck, the
+ * errors can be repaired.
+ */
+s64 ntfs_attr_mst_pread(ntfs_attr *na, const s64 pos, const s64 bk_cnt,
+		const u32 bk_size, void *dst)
+{
+	s64 br;
+	u8 *end;
+	BOOL warn;
+
+	ntfs_log_trace("Entering for inode 0x%llx, attr type 0x%x, pos 0x%llx.\n",
+			(unsigned long long)na->ni->mft_no, na->type,
+			(long long)pos);
+	if (bk_cnt < 0 || bk_size % NTFS_BLOCK_SIZE) {
+		errno = EINVAL;
+		ntfs_log_perror("%s", __FUNCTION__);
+		return -1;
+	}
+	br = ntfs_attr_pread(na, pos, bk_cnt * bk_size, dst);
+	if (br <= 0)
+		return br;
+	br /= bk_size;
+		/* log errors unless silenced */
+	warn = !na->ni || !na->ni->vol || !NVolNoFixupWarn(na->ni->vol);
+	for (end = (u8*)dst + br * bk_size; (u8*)dst < end; dst = (u8*)dst +
+			bk_size)
+		ntfs_mst_post_read_fixup_warn((NTFS_RECORD*)dst, bk_size, warn);
+	/* Finally, return the number of blocks read. */
+	return br;
+}
+
+/**
+ * ntfs_attr_mst_pwrite - multi sector transfer protected ntfs attribute write
+ * @na:		multi sector transfer protected ntfs attribute to write to
+ * @pos:	position in the attribute to write to
+ * @bk_cnt:	number of mst protected blocks to write
+ * @bk_size:	size of each mst protected block in bytes
+ * @src:	data buffer to write to disk
+ *
+ * This function will write @bk_cnt blocks of size @bk_size bytes each from
+ * data buffer @b to multi sector transfer (mst) protected ntfs attribute @na
+ * at position @pos.
+ *
+ * On success, return the number of successfully written blocks. If this number
+ * is lower than @bk_cnt this means that an error was encountered during the
+ * write so that the write is partial. 0 means nothing was written (also
+ * return 0 when @bk_cnt or @bk_size are 0).
+ *
+ * On error and nothing has been written, return -1 with errno set
+ * appropriately to the return code of ntfs_attr_pwrite(), or to EINVAL in case
+ * of invalid arguments.
+ *
+ * NOTE: We mst protect the data, write it, then mst deprotect it using a quick
+ * deprotect algorithm (no checking). This saves us from making a copy before
+ * the write and at the same time causes the usn to be incremented in the
+ * buffer. This conceptually fits in better with the idea that cached data is
+ * always deprotected and protection is performed when the data is actually
+ * going to hit the disk and the cache is immediately deprotected again
+ * simulating an mst read on the written data. This way cache coherency is
+ * achieved.
+ */
+s64 ntfs_attr_mst_pwrite(ntfs_attr *na, const s64 pos, s64 bk_cnt,
+		const u32 bk_size, void *src)
+{
+	s64 written, i;
+
+	ntfs_log_trace("Entering for inode 0x%llx, attr type 0x%x, pos 0x%llx.\n",
+			(unsigned long long)na->ni->mft_no, na->type,
+			(long long)pos);
+	if (bk_cnt < 0 || bk_size % NTFS_BLOCK_SIZE) {
+		errno = EINVAL;
+		return -1;
+	}
+	if (!bk_cnt)
+		return 0;
+	/* Prepare data for writing. */
+	for (i = 0; i < bk_cnt; ++i) {
+		int err;
+
+		err = ntfs_mst_pre_write_fixup((NTFS_RECORD*)
+				((u8*)src + i * bk_size), bk_size);
+		if (err < 0) {
+			/* Abort write at this position. */
+			ntfs_log_perror("%s #1", __FUNCTION__);
+			if (!i)
+				return err;
+			bk_cnt = i;
+			break;
+		}
+	}
+	/* Write the prepared data. */
+	written = ntfs_attr_pwrite(na, pos, bk_cnt * bk_size, src);
+	if (written <= 0) {
+		ntfs_log_perror("%s: written=%lld", __FUNCTION__,
+				(long long)written);
+	}
+	/* Quickly deprotect the data again. */
+	for (i = 0; i < bk_cnt; ++i)
+		ntfs_mst_post_write_fixup((NTFS_RECORD*)((u8*)src + i *
+				bk_size));
+	if (written <= 0)
+		return written;
+	/* Finally, return the number of complete blocks written. */
+	return written / bk_size;
+}
+
+/**
+ * ntfs_attr_find - find (next) attribute in mft record
+ * @type:	attribute type to find
+ * @name:	attribute name to find (optional, i.e. NULL means don't care)
+ * @name_len:	attribute name length (only needed if @name present)
+ * @ic:		IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present)
+ * @val:	attribute value to find (optional, resident attributes only)
+ * @val_len:	attribute value length
+ * @ctx:	search context with mft record and attribute to search from
+ *
+ * You shouldn't need to call this function directly. Use lookup_attr() instead.
+ *
+ * ntfs_attr_find() takes a search context @ctx as parameter and searches the
+ * mft record specified by @ctx->mrec, beginning at @ctx->attr, for an
+ * attribute of @type, optionally @name and @val. If found, ntfs_attr_find()
+ * returns 0 and @ctx->attr will point to the found attribute.
+ *
+ * If not found, ntfs_attr_find() returns -1, with errno set to ENOENT and
+ * @ctx->attr will point to the attribute before which the attribute being
+ * searched for would need to be inserted if such an action were to be desired.
+ *
+ * On actual error, ntfs_attr_find() returns -1 with errno set to the error
+ * code but not to ENOENT.  In this case @ctx->attr is undefined and in
+ * particular do not rely on it not changing.
+ *
+ * If @ctx->is_first is TRUE, the search begins with @ctx->attr itself. If it
+ * is FALSE, the search begins after @ctx->attr.
+ *
+ * If @type is AT_UNUSED, return the first found attribute, i.e. one can
+ * enumerate all attributes by setting @type to AT_UNUSED and then calling
+ * ntfs_attr_find() repeatedly until it returns -1 with errno set to ENOENT to
+ * indicate that there are no more entries. During the enumeration, each
+ * successful call of ntfs_attr_find() will return the next attribute in the
+ * mft record @ctx->mrec.
+ *
+ * If @type is AT_END, seek to the end and return -1 with errno set to ENOENT.
+ * AT_END is not a valid attribute, its length is zero for example, thus it is
+ * safer to return error instead of success in this case. This also allows us
+ * to interoperate cleanly with ntfs_external_attr_find().
+ *
+ * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present
+ * but not AT_UNNAMED search for a named attribute matching @name. Otherwise,
+ * match both named and unnamed attributes.
+ *
+ * If @ic is IGNORE_CASE, the @name comparison is not case sensitive and
+ * @ctx->ntfs_ino must be set to the ntfs inode to which the mft record
+ * @ctx->mrec belongs. This is so we can get at the ntfs volume and hence at
+ * the upcase table. If @ic is CASE_SENSITIVE, the comparison is case
+ * sensitive. When @name is present, @name_len is the @name length in Unicode
+ * characters.
+ *
+ * If @name is not present (NULL), we assume that the unnamed attribute is
+ * being searched for.
+ *
+ * Finally, the resident attribute value @val is looked for, if present.
+ * If @val is not present (NULL), @val_len is ignored.
+ *
+ * ntfs_attr_find() only searches the specified mft record and it ignores the
+ * presence of an attribute list attribute (unless it is the one being searched
+ * for, obviously). If you need to take attribute lists into consideration, use
+ * ntfs_attr_lookup() instead (see below). This also means that you cannot use
+ * ntfs_attr_find() to search for extent records of non-resident attributes, as
+ * extents with lowest_vcn != 0 are usually described by the attribute list
+ * attribute only. - Note that it is possible that the first extent is only in
+ * the attribute list while the last extent is in the base mft record, so don't
+ * rely on being able to find the first extent in the base mft record.
+ *
+ * Warning: Never use @val when looking for attribute types which can be
+ *	    non-resident as this most likely will result in a crash!
+ */
+static int ntfs_attr_find(const ATTR_TYPES type, const ntfschar *name,
+		const u32 name_len, const IGNORE_CASE_BOOL ic,
+		const u8 *val, const u32 val_len, ntfs_attr_search_ctx *ctx)
+{
+	ATTR_RECORD *a;
+	ntfs_volume *vol;
+	ntfschar *upcase;
+	u32 upcase_len;
+
+	ntfs_log_trace("attribute type 0x%x.\n", type);
+
+	if (ctx->ntfs_ino) {
+		vol = ctx->ntfs_ino->vol;
+		upcase = vol->upcase;
+		upcase_len = vol->upcase_len;
+	} else {
+		if (name && name != AT_UNNAMED) {
+			errno = EINVAL;
+			ntfs_log_perror("%s", __FUNCTION__);
+			return -1;
+		}
+		vol = NULL;
+		upcase = NULL;
+		upcase_len = 0;
+	}
+	/*
+	 * Iterate over attributes in mft record starting at @ctx->attr, or the
+	 * attribute following that, if @ctx->is_first is TRUE.
+	 */
+	if (ctx->is_first) {
+		a = ctx->attr;
+		ctx->is_first = FALSE;
+	} else
+		a = (ATTR_RECORD*)((char*)ctx->attr +
+				le32_to_cpu(ctx->attr->length));
+	for (;;	a = (ATTR_RECORD*)((char*)a + le32_to_cpu(a->length))) {
+		if (p2n(a) < p2n(ctx->mrec) || (char*)a > (char*)ctx->mrec +
+				le32_to_cpu(ctx->mrec->bytes_allocated))
+			break;
+		ctx->attr = a;
+		if (((type != AT_UNUSED) && (le32_to_cpu(a->type) >
+				le32_to_cpu(type))) ||
+				(a->type == AT_END)) {
+			errno = ENOENT;
+			return -1;
+		}
+		if (!a->length)
+			break;
+		/* If this is an enumeration return this attribute. */
+		if (type == AT_UNUSED)
+			return 0;
+		if (a->type != type)
+			continue;
+		/*
+		 * If @name is AT_UNNAMED we want an unnamed attribute.
+		 * If @name is present, compare the two names.
+		 * Otherwise, match any attribute.
+		 */
+		if (name == AT_UNNAMED) {
+			/* The search failed if the found attribute is named. */
+			if (a->name_length) {
+				errno = ENOENT;
+				return -1;
+			}
+		} else {
+			register int rc;
+			if (name && ((rc = ntfs_names_full_collate(name,
+					name_len, (ntfschar*)((char*)a +
+						le16_to_cpu(a->name_offset)),
+					a->name_length, ic,
+					upcase, upcase_len)))) {
+				/*
+				 * If @name collates before a->name,
+				 * there is no matching attribute.
+				 */
+				if (rc < 0) {
+					errno = ENOENT;
+					return -1;
+				}
+			/* If the strings are not equal, continue search. */
+			continue;
+			}
+		}
+		/*
+		 * The names match or @name not present and attribute is
+		 * unnamed. If no @val specified, we have found the attribute
+		 * and are done.
+		 */
+		if (!val)
+			return 0;
+		/* @val is present; compare values. */
+		else {
+			register int rc;
+
+			rc = memcmp(val, (char*)a +le16_to_cpu(a->value_offset),
+					min(val_len,
+					le32_to_cpu(a->value_length)));
+			/*
+			 * If @val collates before the current attribute's
+			 * value, there is no matching attribute.
+			 */
+			if (!rc) {
+				register u32 avl;
+				avl = le32_to_cpu(a->value_length);
+				if (val_len == avl)
+					return 0;
+				if (val_len < avl) {
+					errno = ENOENT;
+					return -1;
+				}
+			} else if (rc < 0) {
+				errno = ENOENT;
+				return -1;
+			}
+		}
+	}
+	errno = EIO;
+	ntfs_log_perror("%s: Corrupt inode (%lld)", __FUNCTION__, 
+			ctx->ntfs_ino ? (long long)ctx->ntfs_ino->mft_no : -1);
+	return -1;
+}
+
+void ntfs_attr_name_free(char **name)
+{
+	if (*name) {
+		free(*name);
+		*name = NULL;
+	}
+}
+
+char *ntfs_attr_name_get(const ntfschar *uname, const int uname_len)
+{
+	char *name = NULL;
+	int name_len;
+
+	name_len = ntfs_ucstombs(uname, uname_len, &name, 0);
+	if (name_len < 0) {
+		ntfs_log_perror("ntfs_ucstombs");
+		return NULL;
+
+	} else if (name_len > 0)
+		return name;
+
+	ntfs_attr_name_free(&name);
+	return NULL;
+}
+
+/**
+ * ntfs_external_attr_find - find an attribute in the attribute list of an inode
+ * @type:	attribute type to find
+ * @name:	attribute name to find (optional, i.e. NULL means don't care)
+ * @name_len:	attribute name length (only needed if @name present)
+ * @ic:		IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present)
+ * @lowest_vcn:	lowest vcn to find (optional, non-resident attributes only)
+ * @val:	attribute value to find (optional, resident attributes only)
+ * @val_len:	attribute value length
+ * @ctx:	search context with mft record and attribute to search from
+ *
+ * You shouldn't need to call this function directly. Use ntfs_attr_lookup()
+ * instead.
+ *
+ * Find an attribute by searching the attribute list for the corresponding
+ * attribute list entry. Having found the entry, map the mft record for read
+ * if the attribute is in a different mft record/inode, find the attribute in
+ * there and return it.
+ *
+ * If @type is AT_UNUSED, return the first found attribute, i.e. one can
+ * enumerate all attributes by setting @type to AT_UNUSED and then calling
+ * ntfs_external_attr_find() repeatedly until it returns -1 with errno set to
+ * ENOENT to indicate that there are no more entries. During the enumeration,
+ * each successful call of ntfs_external_attr_find() will return the next
+ * attribute described by the attribute list of the base mft record described
+ * by the search context @ctx.
+ *
+ * If @type is AT_END, seek to the end of the base mft record ignoring the
+ * attribute list completely and return -1 with errno set to ENOENT.  AT_END is
+ * not a valid attribute, its length is zero for example, thus it is safer to
+ * return error instead of success in this case.
+ *
+ * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present
+ * but not AT_UNNAMED search for a named attribute matching @name. Otherwise,
+ * match both named and unnamed attributes.
+ *
+ * On first search @ctx->ntfs_ino must be the inode of the base mft record and
+ * @ctx must have been obtained from a call to ntfs_attr_get_search_ctx().
+ * On subsequent calls, @ctx->ntfs_ino can be any extent inode, too
+ * (@ctx->base_ntfs_ino is then the base inode).
+ *
+ * After finishing with the attribute/mft record you need to call
+ * ntfs_attr_put_search_ctx() to cleanup the search context (unmapping any
+ * mapped extent inodes, etc).
+ *
+ * Return 0 if the search was successful and -1 if not, with errno set to the
+ * error code.
+ *
+ * On success, @ctx->attr is the found attribute, it is in mft record
+ * @ctx->mrec, and @ctx->al_entry is the attribute list entry for this
+ * attribute with @ctx->base_* being the base mft record to which @ctx->attr
+ * belongs.
+ *
+ * On error ENOENT, i.e. attribute not found, @ctx->attr is set to the
+ * attribute which collates just after the attribute being searched for in the
+ * base ntfs inode, i.e. if one wants to add the attribute to the mft record
+ * this is the correct place to insert it into, and if there is not enough
+ * space, the attribute should be placed in an extent mft record.
+ * @ctx->al_entry points to the position within @ctx->base_ntfs_ino->attr_list
+ * at which the new attribute's attribute list entry should be inserted.  The
+ * other @ctx fields, base_ntfs_ino, base_mrec, and base_attr are set to NULL.
+ * The only exception to this is when @type is AT_END, in which case
+ * @ctx->al_entry is set to NULL also (see above).
+ *
+ * The following error codes are defined:
+ *	ENOENT	Attribute not found, not an error as such.
+ *	EINVAL	Invalid arguments.
+ *	EIO	I/O error or corrupt data structures found.
+ *	ENOMEM	Not enough memory to allocate necessary buffers.
+ */
+static int ntfs_external_attr_find(ATTR_TYPES type, const ntfschar *name,
+		const u32 name_len, const IGNORE_CASE_BOOL ic,
+		const VCN lowest_vcn, const u8 *val, const u32 val_len,
+		ntfs_attr_search_ctx *ctx)
+{
+	ntfs_inode *base_ni, *ni;
+	ntfs_volume *vol;
+	ATTR_LIST_ENTRY *al_entry, *next_al_entry;
+	u8 *al_start, *al_end;
+	ATTR_RECORD *a;
+	ntfschar *al_name;
+	u32 al_name_len;
+	BOOL is_first_search = FALSE;
+
+	ni = ctx->ntfs_ino;
+	base_ni = ctx->base_ntfs_ino;
+	ntfs_log_trace("Entering for inode %lld, attribute type 0x%x.\n",
+			(unsigned long long)ni->mft_no, type);
+	if (!base_ni) {
+		/* First call happens with the base mft record. */
+		base_ni = ctx->base_ntfs_ino = ctx->ntfs_ino;
+		ctx->base_mrec = ctx->mrec;
+	}
+	if (ni == base_ni)
+		ctx->base_attr = ctx->attr;
+	if (type == AT_END)
+		goto not_found;
+	vol = base_ni->vol;
+	al_start = base_ni->attr_list;
+	al_end = al_start + base_ni->attr_list_size;
+	if (!ctx->al_entry) {
+		ctx->al_entry = (ATTR_LIST_ENTRY*)al_start;
+		is_first_search = TRUE;
+	}
+	/*
+	 * Iterate over entries in attribute list starting at @ctx->al_entry,
+	 * or the entry following that, if @ctx->is_first is TRUE.
+	 */
+	if (ctx->is_first) {
+		al_entry = ctx->al_entry;
+		ctx->is_first = FALSE;
+		/*
+		 * If an enumeration and the first attribute is higher than
+		 * the attribute list itself, need to return the attribute list
+		 * attribute.
+		 */
+		if ((type == AT_UNUSED) && is_first_search &&
+				le32_to_cpu(al_entry->type) >
+				le32_to_cpu(AT_ATTRIBUTE_LIST))
+			goto find_attr_list_attr;
+	} else {
+		al_entry = (ATTR_LIST_ENTRY*)((char*)ctx->al_entry +
+				le16_to_cpu(ctx->al_entry->length));
+		/*
+		 * If this is an enumeration and the attribute list attribute
+		 * is the next one in the enumeration sequence, just return the
+		 * attribute list attribute from the base mft record as it is
+		 * not listed in the attribute list itself.
+		 */
+		if ((type == AT_UNUSED) && le32_to_cpu(ctx->al_entry->type) <
+				le32_to_cpu(AT_ATTRIBUTE_LIST) &&
+				le32_to_cpu(al_entry->type) >
+				le32_to_cpu(AT_ATTRIBUTE_LIST)) {
+			int rc;
+find_attr_list_attr:
+
+			/* Check for bogus calls. */
+			if (name || name_len || val || val_len || lowest_vcn) {
+				errno = EINVAL;
+				ntfs_log_perror("%s", __FUNCTION__);
+				return -1;
+			}
+
+			/* We want the base record. */
+			ctx->ntfs_ino = base_ni;
+			ctx->mrec = ctx->base_mrec;
+			ctx->is_first = TRUE;
+			/* Sanity checks are performed elsewhere. */
+			ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec +
+					le16_to_cpu(ctx->mrec->attrs_offset));
+
+			/* Find the attribute list attribute. */
+			rc = ntfs_attr_find(AT_ATTRIBUTE_LIST, NULL, 0,
+					IGNORE_CASE, NULL, 0, ctx);
+
+			/*
+			 * Setup the search context so the correct
+			 * attribute is returned next time round.
+			 */
+			ctx->al_entry = al_entry;
+			ctx->is_first = TRUE;
+
+			/* Got it. Done. */
+			if (!rc)
+				return 0;
+
+			/* Error! If other than not found return it. */
+			if (errno != ENOENT)
+				return rc;
+
+			/* Not found?!? Absurd! */
+			errno = EIO;
+			ntfs_log_error("Attribute list wasn't found");
+			return -1;
+		}
+	}
+	for (;; al_entry = next_al_entry) {
+		/* Out of bounds check. */
+		if ((u8*)al_entry < base_ni->attr_list ||
+				(u8*)al_entry > al_end)
+			break;	/* Inode is corrupt. */
+		ctx->al_entry = al_entry;
+		/* Catch the end of the attribute list. */
+		if ((u8*)al_entry == al_end)
+			goto not_found;
+		if (!al_entry->length)
+			break;
+		if ((u8*)al_entry + 6 > al_end || (u8*)al_entry +
+				le16_to_cpu(al_entry->length) > al_end)
+			break;
+		next_al_entry = (ATTR_LIST_ENTRY*)((u8*)al_entry +
+				le16_to_cpu(al_entry->length));
+		if (type != AT_UNUSED) {
+			if (le32_to_cpu(al_entry->type) > le32_to_cpu(type))
+				goto not_found;
+			if (type != al_entry->type)
+				continue;
+		}
+		al_name_len = al_entry->name_length;
+		al_name = (ntfschar*)((u8*)al_entry + al_entry->name_offset);
+		/*
+		 * If !@type we want the attribute represented by this
+		 * attribute list entry.
+		 */
+		if (type == AT_UNUSED)
+			goto is_enumeration;
+		/*
+		 * If @name is AT_UNNAMED we want an unnamed attribute.
+		 * If @name is present, compare the two names.
+		 * Otherwise, match any attribute.
+		 */
+		if (name == AT_UNNAMED) {
+			if (al_name_len)
+				goto not_found;
+		} else {
+			int rc;
+
+			if (name && ((rc = ntfs_names_full_collate(name,
+					name_len, al_name, al_name_len, ic,
+					vol->upcase, vol->upcase_len)))) {
+
+				/*
+				 * If @name collates before al_name,
+				 * there is no matching attribute.
+				 */
+				if (rc < 0)
+					goto not_found;
+				/* If the strings are not equal, continue search. */
+				continue;
+			}
+		}
+		/*
+		 * The names match or @name not present and attribute is
+		 * unnamed. Now check @lowest_vcn. Continue search if the
+		 * next attribute list entry still fits @lowest_vcn. Otherwise
+		 * we have reached the right one or the search has failed.
+		 */
+		if (lowest_vcn && (u8*)next_al_entry >= al_start	    &&
+				(u8*)next_al_entry + 6 < al_end	    &&
+				(u8*)next_al_entry + le16_to_cpu(
+					next_al_entry->length) <= al_end    &&
+				sle64_to_cpu(next_al_entry->lowest_vcn) <=
+					lowest_vcn			    &&
+				next_al_entry->type == al_entry->type	    &&
+				next_al_entry->name_length == al_name_len   &&
+				ntfs_names_are_equal((ntfschar*)((char*)
+					next_al_entry +
+					next_al_entry->name_offset),
+					next_al_entry->name_length,
+					al_name, al_name_len, CASE_SENSITIVE,
+					vol->upcase, vol->upcase_len))
+			continue;
+is_enumeration:
+		if (MREF_LE(al_entry->mft_reference) == ni->mft_no) {
+			if (MSEQNO_LE(al_entry->mft_reference) !=
+					le16_to_cpu(
+					ni->mrec->sequence_number)) {
+				ntfs_log_error("Found stale mft reference in "
+						"attribute list!\n");
+				break;
+			}
+		} else { /* Mft references do not match. */
+			/* Do we want the base record back? */
+			if (MREF_LE(al_entry->mft_reference) ==
+					base_ni->mft_no) {
+				ni = ctx->ntfs_ino = base_ni;
+				ctx->mrec = ctx->base_mrec;
+			} else {
+				/* We want an extent record. */
+				ni = ntfs_extent_inode_open(base_ni,
+						al_entry->mft_reference);
+				if (!ni)
+					break;
+				ctx->ntfs_ino = ni;
+				ctx->mrec = ni->mrec;
+			}
+		}
+		a = ctx->attr = (ATTR_RECORD*)((char*)ctx->mrec +
+				le16_to_cpu(ctx->mrec->attrs_offset));
+		/*
+		 * ctx->ntfs_ino, ctx->mrec, and ctx->attr now point to the
+		 * mft record containing the attribute represented by the
+		 * current al_entry.
+		 *
+		 * We could call into ntfs_attr_find() to find the right
+		 * attribute in this mft record but this would be less
+		 * efficient and not quite accurate as ntfs_attr_find() ignores
+		 * the attribute instance numbers for example which become
+		 * important when one plays with attribute lists. Also, because
+		 * a proper match has been found in the attribute list entry
+		 * above, the comparison can now be optimized. So it is worth
+		 * re-implementing a simplified ntfs_attr_find() here.
+		 *
+		 * Use a manual loop so we can still use break and continue
+		 * with the same meanings as above.
+		 */
+do_next_attr_loop:
+		if ((char*)a < (char*)ctx->mrec || (char*)a > (char*)ctx->mrec +
+				le32_to_cpu(ctx->mrec->bytes_allocated))
+			break;
+		if (a->type == AT_END)
+			continue;
+		if (!a->length)
+			break;
+		if (al_entry->instance != a->instance)
+			goto do_next_attr;
+		/*
+		 * If the type and/or the name are/is mismatched between the
+		 * attribute list entry and the attribute record, there is
+		 * corruption so we break and return error EIO.
+		 */
+		if (al_entry->type != a->type)
+			break;
+		if (!ntfs_names_are_equal((ntfschar*)((char*)a +
+				le16_to_cpu(a->name_offset)),
+				a->name_length, al_name,
+				al_name_len, CASE_SENSITIVE,
+				vol->upcase, vol->upcase_len))
+			break;
+		ctx->attr = a;
+		/*
+		 * If no @val specified or @val specified and it matches, we
+		 * have found it! Also, if !@type, it is an enumeration, so we
+		 * want the current attribute.
+		 */
+		if ((type == AT_UNUSED) || !val || (!a->non_resident &&
+				le32_to_cpu(a->value_length) == val_len &&
+				!memcmp((char*)a + le16_to_cpu(a->value_offset),
+				val, val_len))) {
+			return 0;
+		}
+do_next_attr:
+		/* Proceed to the next attribute in the current mft record. */
+		a = (ATTR_RECORD*)((char*)a + le32_to_cpu(a->length));
+		goto do_next_attr_loop;
+	}
+	if (ni != base_ni) {
+		ctx->ntfs_ino = base_ni;
+		ctx->mrec = ctx->base_mrec;
+		ctx->attr = ctx->base_attr;
+	}
+	errno = EIO;
+	ntfs_log_perror("Inode is corrupt (%lld)", (long long)base_ni->mft_no);
+	return -1;
+not_found:
+	/*
+	 * If we were looking for AT_END or we were enumerating and reached the
+	 * end, we reset the search context @ctx and use ntfs_attr_find() to
+	 * seek to the end of the base mft record.
+	 */
+	if (type == AT_UNUSED || type == AT_END) {
+		ntfs_attr_reinit_search_ctx(ctx);
+		return ntfs_attr_find(AT_END, name, name_len, ic, val, val_len,
+				ctx);
+	}
+	/*
+	 * The attribute wasn't found.  Before we return, we want to ensure
+	 * @ctx->mrec and @ctx->attr indicate the position at which the
+	 * attribute should be inserted in the base mft record.  Since we also
+	 * want to preserve @ctx->al_entry we cannot reinitialize the search
+	 * context using ntfs_attr_reinit_search_ctx() as this would set
+	 * @ctx->al_entry to NULL.  Thus we do the necessary bits manually (see
+	 * ntfs_attr_init_search_ctx() below).  Note, we _only_ preserve
+	 * @ctx->al_entry as the remaining fields (base_*) are identical to
+	 * their non base_ counterparts and we cannot set @ctx->base_attr
+	 * correctly yet as we do not know what @ctx->attr will be set to by
+	 * the call to ntfs_attr_find() below.
+	 */
+	ctx->mrec = ctx->base_mrec;
+	ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec +
+			le16_to_cpu(ctx->mrec->attrs_offset));
+	ctx->is_first = TRUE;
+	ctx->ntfs_ino = ctx->base_ntfs_ino;
+	ctx->base_ntfs_ino = NULL;
+	ctx->base_mrec = NULL;
+	ctx->base_attr = NULL;
+	/*
+	 * In case there are multiple matches in the base mft record, need to
+	 * keep enumerating until we get an attribute not found response (or
+	 * another error), otherwise we would keep returning the same attribute
+	 * over and over again and all programs using us for enumeration would
+	 * lock up in a tight loop.
+	 */
+	{
+		int ret;
+
+		do {
+			ret = ntfs_attr_find(type, name, name_len, ic, val,
+					val_len, ctx);
+		} while (!ret);
+		return ret;
+	}
+}
+
+/**
+ * ntfs_attr_lookup - find an attribute in an ntfs inode
+ * @type:	attribute type to find
+ * @name:	attribute name to find (optional, i.e. NULL means don't care)
+ * @name_len:	attribute name length (only needed if @name present)
+ * @ic:		IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present)
+ * @lowest_vcn:	lowest vcn to find (optional, non-resident attributes only)
+ * @val:	attribute value to find (optional, resident attributes only)
+ * @val_len:	attribute value length
+ * @ctx:	search context with mft record and attribute to search from
+ *
+ * Find an attribute in an ntfs inode. On first search @ctx->ntfs_ino must
+ * be the base mft record and @ctx must have been obtained from a call to
+ * ntfs_attr_get_search_ctx().
+ *
+ * This function transparently handles attribute lists and @ctx is used to
+ * continue searches where they were left off at.
+ *
+ * If @type is AT_UNUSED, return the first found attribute, i.e. one can
+ * enumerate all attributes by setting @type to AT_UNUSED and then calling
+ * ntfs_attr_lookup() repeatedly until it returns -1 with errno set to ENOENT
+ * to indicate that there are no more entries. During the enumeration, each
+ * successful call of ntfs_attr_lookup() will return the next attribute, with
+ * the current attribute being described by the search context @ctx.
+ *
+ * If @type is AT_END, seek to the end of the base mft record ignoring the
+ * attribute list completely and return -1 with errno set to ENOENT.  AT_END is
+ * not a valid attribute, its length is zero for example, thus it is safer to
+ * return error instead of success in this case.  It should never be needed to
+ * do this, but we implement the functionality because it allows for simpler
+ * code inside ntfs_external_attr_find().
+ *
+ * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present
+ * but not AT_UNNAMED search for a named attribute matching @name. Otherwise,
+ * match both named and unnamed attributes.
+ *
+ * After finishing with the attribute/mft record you need to call
+ * ntfs_attr_put_search_ctx() to cleanup the search context (unmapping any
+ * mapped extent inodes, etc).
+ *
+ * Return 0 if the search was successful and -1 if not, with errno set to the
+ * error code.
+ *
+ * On success, @ctx->attr is the found attribute, it is in mft record
+ * @ctx->mrec, and @ctx->al_entry is the attribute list entry for this
+ * attribute with @ctx->base_* being the base mft record to which @ctx->attr
+ * belongs.  If no attribute list attribute is present @ctx->al_entry and
+ * @ctx->base_* are NULL.
+ *
+ * On error ENOENT, i.e. attribute not found, @ctx->attr is set to the
+ * attribute which collates just after the attribute being searched for in the
+ * base ntfs inode, i.e. if one wants to add the attribute to the mft record
+ * this is the correct place to insert it into, and if there is not enough
+ * space, the attribute should be placed in an extent mft record.
+ * @ctx->al_entry points to the position within @ctx->base_ntfs_ino->attr_list
+ * at which the new attribute's attribute list entry should be inserted.  The
+ * other @ctx fields, base_ntfs_ino, base_mrec, and base_attr are set to NULL.
+ * The only exception to this is when @type is AT_END, in which case
+ * @ctx->al_entry is set to NULL also (see above).
+ *
+ *
+ * The following error codes are defined:
+ *	ENOENT	Attribute not found, not an error as such.
+ *	EINVAL	Invalid arguments.
+ *	EIO	I/O error or corrupt data structures found.
+ *	ENOMEM	Not enough memory to allocate necessary buffers.
+ */
+int ntfs_attr_lookup(const ATTR_TYPES type, const ntfschar *name,
+		const u32 name_len, const IGNORE_CASE_BOOL ic,
+		const VCN lowest_vcn, const u8 *val, const u32 val_len,
+		ntfs_attr_search_ctx *ctx)
+{
+	ntfs_volume *vol;
+	ntfs_inode *base_ni;
+	int ret = -1;
+
+	ntfs_log_enter("Entering for attribute type 0x%x\n", type);
+	
+	if (!ctx || !ctx->mrec || !ctx->attr || (name && name != AT_UNNAMED &&
+			(!ctx->ntfs_ino || !(vol = ctx->ntfs_ino->vol) ||
+			!vol->upcase || !vol->upcase_len))) {
+		errno = EINVAL;
+		ntfs_log_perror("%s", __FUNCTION__);
+		goto out;
+	}
+	
+	if (ctx->base_ntfs_ino)
+		base_ni = ctx->base_ntfs_ino;
+	else
+		base_ni = ctx->ntfs_ino;
+	if (!base_ni || !NInoAttrList(base_ni) || type == AT_ATTRIBUTE_LIST)
+		ret = ntfs_attr_find(type, name, name_len, ic, val, val_len, ctx);
+	else
+		ret = ntfs_external_attr_find(type, name, name_len, ic, 
+					      lowest_vcn, val, val_len, ctx);
+out:
+	ntfs_log_leave("\n");
+	return ret;
+}
+
+/**
+ * ntfs_attr_position - find given or next attribute type in an ntfs inode
+ * @type:	attribute type to start lookup
+ * @ctx:	search context with mft record and attribute to search from
+ *
+ * Find an attribute type in an ntfs inode or the next attribute which is not
+ * the AT_END attribute. Please see more details at ntfs_attr_lookup.
+ *
+ * Return 0 if the search was successful and -1 if not, with errno set to the
+ * error code.
+ *
+ * The following error codes are defined:
+ *	EINVAL	Invalid arguments.
+ *	EIO	I/O error or corrupt data structures found.
+ *	ENOMEM	Not enough memory to allocate necessary buffers.
+ * 	ENOSPC  No attribute was found after 'type', only AT_END.
+ */
+int ntfs_attr_position(const ATTR_TYPES type, ntfs_attr_search_ctx *ctx)
+{
+	if (ntfs_attr_lookup(type, NULL, 0, CASE_SENSITIVE, 0, NULL, 0, ctx)) {
+		if (errno != ENOENT)
+			return -1;
+		if (ctx->attr->type == AT_END) {
+			errno = ENOSPC;
+			return -1;
+		}
+	}
+	return 0;
+}
+
+/**
+ * ntfs_attr_init_search_ctx - initialize an attribute search context
+ * @ctx:	attribute search context to initialize
+ * @ni:		ntfs inode with which to initialize the search context
+ * @mrec:	mft record with which to initialize the search context
+ *
+ * Initialize the attribute search context @ctx with @ni and @mrec.
+ */
+static void ntfs_attr_init_search_ctx(ntfs_attr_search_ctx *ctx,
+		ntfs_inode *ni, MFT_RECORD *mrec)
+{
+	if (!mrec)
+		mrec = ni->mrec;
+	ctx->mrec = mrec;
+	/* Sanity checks are performed elsewhere. */
+	ctx->attr = (ATTR_RECORD*)((u8*)mrec + le16_to_cpu(mrec->attrs_offset));
+	ctx->is_first = TRUE;
+	ctx->ntfs_ino = ni;
+	ctx->al_entry = NULL;
+	ctx->base_ntfs_ino = NULL;
+	ctx->base_mrec = NULL;
+	ctx->base_attr = NULL;
+}
+
+/**
+ * ntfs_attr_reinit_search_ctx - reinitialize an attribute search context
+ * @ctx:	attribute search context to reinitialize
+ *
+ * Reinitialize the attribute search context @ctx.
+ *
+ * This is used when a search for a new attribute is being started to reset
+ * the search context to the beginning.
+ */
+void ntfs_attr_reinit_search_ctx(ntfs_attr_search_ctx *ctx)
+{
+	if (!ctx->base_ntfs_ino) {
+		/* No attribute list. */
+		ctx->is_first = TRUE;
+		/* Sanity checks are performed elsewhere. */
+		ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec +
+				le16_to_cpu(ctx->mrec->attrs_offset));
+		/*
+		 * This needs resetting due to ntfs_external_attr_find() which
+		 * can leave it set despite having zeroed ctx->base_ntfs_ino.
+		 */
+		ctx->al_entry = NULL;
+		return;
+	} /* Attribute list. */
+	ntfs_attr_init_search_ctx(ctx, ctx->base_ntfs_ino, ctx->base_mrec);
+	return;
+}
+
+/**
+ * ntfs_attr_get_search_ctx - allocate/initialize a new attribute search context
+ * @ni:		ntfs inode with which to initialize the search context
+ * @mrec:	mft record with which to initialize the search context
+ *
+ * Allocate a new attribute search context, initialize it with @ni and @mrec,
+ * and return it. Return NULL on error with errno set.
+ *
+ * @mrec can be NULL, in which case the mft record is taken from @ni.
+ *
+ * Note: For low level utilities which know what they are doing we allow @ni to
+ * be NULL and @mrec to be set.  Do NOT do this unless you understand the
+ * implications!!!  For example it is no longer safe to call ntfs_attr_lookup().
+ */
+ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec)
+{
+	ntfs_attr_search_ctx *ctx;
+
+	if (!ni && !mrec) {
+		errno = EINVAL;
+		ntfs_log_perror("NULL arguments");
+		return NULL;
+	}
+	ctx = ntfs_malloc(sizeof(ntfs_attr_search_ctx));
+	if (ctx)
+		ntfs_attr_init_search_ctx(ctx, ni, mrec);
+	return ctx;
+}
+
+/**
+ * ntfs_attr_put_search_ctx - release an attribute search context
+ * @ctx:	attribute search context to free
+ *
+ * Release the attribute search context @ctx.
+ */
+void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx)
+{
+	// NOTE: save errno if it could change and function stays void!
+	free(ctx);
+}
+
+/**
+ * ntfs_attr_find_in_attrdef - find an attribute in the $AttrDef system file
+ * @vol:	ntfs volume to which the attribute belongs
+ * @type:	attribute type which to find
+ *
+ * Search for the attribute definition record corresponding to the attribute
+ * @type in the $AttrDef system file.
+ *
+ * Return the attribute type definition record if found and NULL if not found
+ * or an error occurred. On error the error code is stored in errno. The
+ * following error codes are defined:
+ *	ENOENT	- The attribute @type is not specified in $AttrDef.
+ *	EINVAL	- Invalid parameters (e.g. @vol is not valid).
+ */
+ATTR_DEF *ntfs_attr_find_in_attrdef(const ntfs_volume *vol,
+		const ATTR_TYPES type)
+{
+	ATTR_DEF *ad;
+
+	if (!vol || !vol->attrdef || !type) {
+		errno = EINVAL;
+		ntfs_log_perror("%s: type=%d", __FUNCTION__, type);
+		return NULL;
+	}
+	for (ad = vol->attrdef; (u8*)ad - (u8*)vol->attrdef <
+			vol->attrdef_len && ad->type; ++ad) {
+		/* We haven't found it yet, carry on searching. */
+		if (le32_to_cpu(ad->type) < le32_to_cpu(type))
+			continue;
+		/* We found the attribute; return it. */
+		if (ad->type == type)
+			return ad;
+		/* We have gone too far already. No point in continuing. */
+		break;
+	}
+	errno = ENOENT;
+	ntfs_log_perror("%s: type=%d", __FUNCTION__, type);
+	return NULL;
+}
+
+/**
+ * ntfs_attr_size_bounds_check - check a size of an attribute type for validity
+ * @vol:	ntfs volume to which the attribute belongs
+ * @type:	attribute type which to check
+ * @size:	size which to check
+ *
+ * Check whether the @size in bytes is valid for an attribute of @type on the
+ * ntfs volume @vol. This information is obtained from $AttrDef system file.
+ *
+ * Return 0 if valid and -1 if not valid or an error occurred. On error the
+ * error code is stored in errno. The following error codes are defined:
+ *	ERANGE	- @size is not valid for the attribute @type.
+ *	ENOENT	- The attribute @type is not specified in $AttrDef.
+ *	EINVAL	- Invalid parameters (e.g. @size is < 0 or @vol is not valid).
+ */
+int ntfs_attr_size_bounds_check(const ntfs_volume *vol, const ATTR_TYPES type,
+		const s64 size)
+{
+	ATTR_DEF *ad;
+	s64 min_size, max_size;
+
+	if (size < 0) {
+		errno = EINVAL;
+		ntfs_log_perror("%s: size=%lld", __FUNCTION__,
+				(long long)size);
+		return -1;
+	}
+
+	/*
+	 * $ATTRIBUTE_LIST shouldn't be greater than 0x40000, otherwise 
+	 * Windows would crash. This is not listed in the AttrDef.
+	 */
+	if (type == AT_ATTRIBUTE_LIST && size > 0x40000) {
+		errno = ERANGE;
+		ntfs_log_perror("Too large attrlist (%lld)", (long long)size);
+		return -1;
+	}
+
+	ad = ntfs_attr_find_in_attrdef(vol, type);
+	if (!ad)
+		return -1;
+	
+	min_size = sle64_to_cpu(ad->min_size);
+	max_size = sle64_to_cpu(ad->max_size);
+
+	/* The $AttrDef generated by Windows specifies 2 as min_size for the
+	 * volume name attribute, but in reality Windows sets it to 0 when
+	 * clearing the volume name. If we want to be able to clear the volume
+	 * name we must also accept 0 as min_size, despite the $AttrDef
+	 * definition. */
+	if(type == AT_VOLUME_NAME)
+		min_size = 0;
+	
+	if ((min_size && (size < min_size)) || 
+	    ((max_size > 0) && (size > max_size))) {
+		errno = ERANGE;
+		ntfs_log_perror("Attr type %d size check failed (min,size,max="
+			"%lld,%lld,%lld)", type, (long long)min_size,
+			(long long)size, (long long)max_size);
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * ntfs_attr_can_be_non_resident - check if an attribute can be non-resident
+ * @vol:	ntfs volume to which the attribute belongs
+ * @type:	attribute type to check
+ * @name:	attribute name to check
+ * @name_len:	attribute name length
+ *
+ * Check whether the attribute of @type and @name with name length @name_len on
+ * the ntfs volume @vol is allowed to be non-resident.  This information is
+ * obtained from $AttrDef system file and is augmented by rules imposed by
+ * Microsoft (e.g. see http://support.microsoft.com/kb/974729/).
+ *
+ * Return 0 if the attribute is allowed to be non-resident and -1 if not or an
+ * error occurred. On error the error code is stored in errno. The following
+ * error codes are defined:
+ *	EPERM	- The attribute is not allowed to be non-resident.
+ *	ENOENT	- The attribute @type is not specified in $AttrDef.
+ *	EINVAL	- Invalid parameters (e.g. @vol is not valid).
+ */
+static int ntfs_attr_can_be_non_resident(const ntfs_volume *vol, const ATTR_TYPES type,
+					const ntfschar *name, int name_len)
+{
+	ATTR_DEF *ad;
+	BOOL allowed;
+
+	/*
+	 * Microsoft has decreed that $LOGGED_UTILITY_STREAM attributes with a
+	 * name of $TXF_DATA must be resident despite the entry for
+	 * $LOGGED_UTILITY_STREAM in $AttrDef allowing them to be non-resident.
+	 * Failure to obey this on the root directory mft record of a volume
+	 * causes Windows Vista and later to see the volume as a RAW volume and
+	 * thus cannot mount it at all.
+	 */
+	if ((type == AT_LOGGED_UTILITY_STREAM)
+	    && name
+	    && ntfs_names_are_equal(TXF_DATA, 9, name, name_len,
+			CASE_SENSITIVE, vol->upcase, vol->upcase_len))
+		allowed = FALSE;
+	else {
+		/* Find the attribute definition record in $AttrDef. */
+		ad = ntfs_attr_find_in_attrdef(vol, type);
+		if (!ad)
+			return -1;
+		/* Check the flags and return the result. */
+		allowed = !(ad->flags & ATTR_DEF_RESIDENT);
+	}
+	if (!allowed) {
+		errno = EPERM;
+		ntfs_log_trace("Attribute can't be non-resident\n");
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * ntfs_attr_can_be_resident - check if an attribute can be resident
+ * @vol:	ntfs volume to which the attribute belongs
+ * @type:	attribute type which to check
+ *
+ * Check whether the attribute of @type on the ntfs volume @vol is allowed to
+ * be resident. This information is derived from our ntfs knowledge and may
+ * not be completely accurate, especially when user defined attributes are
+ * present. Basically we allow everything to be resident except for index
+ * allocation and extended attribute attributes.
+ *
+ * Return 0 if the attribute is allowed to be resident and -1 if not or an
+ * error occurred. On error the error code is stored in errno. The following
+ * error codes are defined:
+ *	EPERM	- The attribute is not allowed to be resident.
+ *	EINVAL	- Invalid parameters (e.g. @vol is not valid).
+ *
+ * Warning: In the system file $MFT the attribute $Bitmap must be non-resident
+ *	    otherwise windows will not boot (blue screen of death)!  We cannot
+ *	    check for this here as we don't know which inode's $Bitmap is being
+ *	    asked about so the caller needs to special case this.
+ */
+int ntfs_attr_can_be_resident(const ntfs_volume *vol, const ATTR_TYPES type)
+{
+	if (!vol || !vol->attrdef || !type) {
+		errno = EINVAL;
+		return -1;
+	}
+	if (type != AT_INDEX_ALLOCATION)
+		return 0;
+	
+	ntfs_log_trace("Attribute can't be resident\n");
+	errno = EPERM;
+	return -1;
+}
+
+/**
+ * ntfs_make_room_for_attr - make room for an attribute inside an mft record
+ * @m:		mft record
+ * @pos:	position at which to make space
+ * @size:	byte size to make available at this position
+ *
+ * @pos points to the attribute in front of which we want to make space.
+ *
+ * Return 0 on success or -1 on error. On error the error code is stored in
+ * errno. Possible error codes are:
+ *	ENOSPC	- There is not enough space available to complete operation. The
+ *		  caller has to make space before calling this.
+ *	EINVAL	- Input parameters were faulty.
+ */
+int ntfs_make_room_for_attr(MFT_RECORD *m, u8 *pos, u32 size)
+{
+	u32 biu;
+
+	ntfs_log_trace("Entering for pos 0x%d, size %u.\n",
+		(int)(pos - (u8*)m), (unsigned) size);
+
+	/* Make size 8-byte alignment. */
+	size = (size + 7) & ~7;
+
+	/* Rigorous consistency checks. */
+	if (!m || !pos || pos < (u8*)m) {
+		errno = EINVAL;
+		ntfs_log_perror("%s: pos=%p  m=%p", __FUNCTION__, pos, m);
+		return -1;
+	}
+	/* The -8 is for the attribute terminator. */
+	if (pos - (u8*)m > (int)le32_to_cpu(m->bytes_in_use) - 8) {
+		errno = EINVAL;
+		return -1;
+	}
+	/* Nothing to do. */
+	if (!size)
+		return 0;
+
+	biu = le32_to_cpu(m->bytes_in_use);
+	/* Do we have enough space? */
+	if (biu + size > le32_to_cpu(m->bytes_allocated) ||
+	    pos + size > (u8*)m + le32_to_cpu(m->bytes_allocated)) {
+		errno = ENOSPC;
+		ntfs_log_trace("No enough space in the MFT record\n");
+		return -1;
+	}
+	/* Move everything after pos to pos + size. */
+	memmove(pos + size, pos, biu - (pos - (u8*)m));
+	/* Update mft record. */
+	m->bytes_in_use = cpu_to_le32(biu + size);
+	return 0;
+}
+
+/**
+ * ntfs_resident_attr_record_add - add resident attribute to inode
+ * @ni:		opened ntfs inode to which MFT record add attribute
+ * @type:	type of the new attribute
+ * @name:	name of the new attribute
+ * @name_len:	name length of the new attribute
+ * @val:	value of the new attribute
+ * @size:	size of new attribute (length of @val, if @val != NULL)
+ * @flags:	flags of the new attribute
+ *
+ * Return offset to attribute from the beginning of the mft record on success
+ * and -1 on error. On error the error code is stored in errno.
+ * Possible error codes are:
+ *	EINVAL	- Invalid arguments passed to function.
+ *	EEXIST	- Attribute of such type and with same name already exists.
+ *	EIO	- I/O error occurred or damaged filesystem.
+ */
+int ntfs_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type,
+			const ntfschar *name, u8 name_len, const u8 *val,
+			u32 size, ATTR_FLAGS data_flags)
+{
+	ntfs_attr_search_ctx *ctx;
+	u32 length;
+	ATTR_RECORD *a;
+	MFT_RECORD *m;
+	int err, offset;
+	ntfs_inode *base_ni;
+
+	ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, flags 0x%x.\n",
+		(long long) ni->mft_no, (unsigned) type, (unsigned) data_flags);
+
+	if (!ni || (!name && name_len)) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (ntfs_attr_can_be_resident(ni->vol, type)) {
+		if (errno == EPERM)
+			ntfs_log_trace("Attribute can't be resident.\n");
+		else
+			ntfs_log_trace("ntfs_attr_can_be_resident failed.\n");
+		return -1;
+	}
+
+	/* Locate place where record should be. */
+	ctx = ntfs_attr_get_search_ctx(ni, NULL);
+	if (!ctx)
+		return -1;
+	/*
+	 * Use ntfs_attr_find instead of ntfs_attr_lookup to find place for
+	 * attribute in @ni->mrec, not any extent inode in case if @ni is base
+	 * file record.
+	 */
+	if (!ntfs_attr_find(type, name, name_len, CASE_SENSITIVE, val, size,
+			ctx)) {
+		err = EEXIST;
+		ntfs_log_trace("Attribute already present.\n");
+		goto put_err_out;
+	}
+	if (errno != ENOENT) {
+		err = EIO;
+		goto put_err_out;
+	}
+	a = ctx->attr;
+	m = ctx->mrec;
+
+	/* Make room for attribute. */
+	length = offsetof(ATTR_RECORD, resident_end) +
+				((name_len * sizeof(ntfschar) + 7) & ~7) +
+				((size + 7) & ~7);
+	if (ntfs_make_room_for_attr(ctx->mrec, (u8*) ctx->attr, length)) {
+		err = errno;
+		ntfs_log_trace("Failed to make room for attribute.\n");
+		goto put_err_out;
+	}
+
+	/* Setup record fields. */
+	offset = ((u8*)a - (u8*)m);
+	a->type = type;
+	a->length = cpu_to_le32(length);
+	a->non_resident = 0;
+	a->name_length = name_len;
+	a->name_offset = (name_len
+		? cpu_to_le16(offsetof(ATTR_RECORD, resident_end))
+		: const_cpu_to_le16(0));
+	a->flags = data_flags;
+	a->instance = m->next_attr_instance;
+	a->value_length = cpu_to_le32(size);
+	a->value_offset = cpu_to_le16(length - ((size + 7) & ~7));
+	if (val)
+		memcpy((u8*)a + le16_to_cpu(a->value_offset), val, size);
+	else
+		memset((u8*)a + le16_to_cpu(a->value_offset), 0, size);
+	if (type == AT_FILE_NAME)
+		a->resident_flags = RESIDENT_ATTR_IS_INDEXED;
+	else
+		a->resident_flags = 0;
+	if (name_len)
+		memcpy((u8*)a + le16_to_cpu(a->name_offset),
+			name, sizeof(ntfschar) * name_len);
+	m->next_attr_instance =
+		cpu_to_le16((le16_to_cpu(m->next_attr_instance) + 1) & 0xffff);
+	if (ni->nr_extents == -1)
+		base_ni = ni->base_ni;
+	else
+		base_ni = ni;
+	if (type != AT_ATTRIBUTE_LIST && NInoAttrList(base_ni)) {
+		if (ntfs_attrlist_entry_add(ni, a)) {
+			err = errno;
+			ntfs_attr_record_resize(m, a, 0);
+			ntfs_log_trace("Failed add attribute entry to "
+					"ATTRIBUTE_LIST.\n");
+			goto put_err_out;
+		}
+	}
+	if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY
+	    ? type == AT_INDEX_ROOT && name == NTFS_INDEX_I30
+	    : type == AT_DATA && name == AT_UNNAMED) {
+		ni->data_size = size;
+		ni->allocated_size = (size + 7) & ~7;
+		set_nino_flag(ni,KnownSize);
+	}
+	ntfs_inode_mark_dirty(ni);
+	ntfs_attr_put_search_ctx(ctx);
+	return offset;
+put_err_out:
+	ntfs_attr_put_search_ctx(ctx);
+	errno = err;
+	return -1;
+}
+
+/**
+ * ntfs_non_resident_attr_record_add - add extent of non-resident attribute
+ * @ni:			opened ntfs inode to which MFT record add attribute
+ * @type:		type of the new attribute extent
+ * @name:		name of the new attribute extent
+ * @name_len:		name length of the new attribute extent
+ * @lowest_vcn:		lowest vcn of the new attribute extent
+ * @dataruns_size:	dataruns size of the new attribute extent
+ * @flags:		flags of the new attribute extent
+ *
+ * Return offset to attribute from the beginning of the mft record on success
+ * and -1 on error. On error the error code is stored in errno.
+ * Possible error codes are:
+ *	EINVAL	- Invalid arguments passed to function.
+ *	EEXIST	- Attribute of such type, with same lowest vcn and with same
+ *		  name already exists.
+ *	EIO	- I/O error occurred or damaged filesystem.
+ */
+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)
+{
+	ntfs_attr_search_ctx *ctx;
+	u32 length;
+	ATTR_RECORD *a;
+	MFT_RECORD *m;
+	ntfs_inode *base_ni;
+	int err, offset;
+
+	ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, lowest_vcn %lld, "
+			"dataruns_size %d, flags 0x%x.\n",
+			(long long) ni->mft_no, (unsigned) type,
+			(long long) lowest_vcn, dataruns_size, (unsigned) flags);
+
+	if (!ni || dataruns_size <= 0 || (!name && name_len)) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (ntfs_attr_can_be_non_resident(ni->vol, type, name, name_len)) {
+		if (errno == EPERM)
+			ntfs_log_perror("Attribute can't be non resident");
+		else
+			ntfs_log_perror("ntfs_attr_can_be_non_resident failed");
+		return -1;
+	}
+
+	/* Locate place where record should be. */
+	ctx = ntfs_attr_get_search_ctx(ni, NULL);
+	if (!ctx)
+		return -1;
+	/*
+	 * Use ntfs_attr_find instead of ntfs_attr_lookup to find place for
+	 * attribute in @ni->mrec, not any extent inode in case if @ni is base
+	 * file record.
+	 */
+	if (!ntfs_attr_find(type, name, name_len, CASE_SENSITIVE, NULL, 0,
+			ctx)) {
+		err = EEXIST;
+		ntfs_log_perror("Attribute 0x%x already present", type);
+		goto put_err_out;
+	}
+	if (errno != ENOENT) {
+		ntfs_log_perror("ntfs_attr_find failed");
+		err = EIO;
+		goto put_err_out;
+	}
+	a = ctx->attr;
+	m = ctx->mrec;
+
+	/* Make room for attribute. */
+	dataruns_size = (dataruns_size + 7) & ~7;
+	length = offsetof(ATTR_RECORD, compressed_size) + ((sizeof(ntfschar) *
+			name_len + 7) & ~7) + dataruns_size +
+			((flags & (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE)) ?
+			sizeof(a->compressed_size) : 0);
+	if (ntfs_make_room_for_attr(ctx->mrec, (u8*) ctx->attr, length)) {
+		err = errno;
+		ntfs_log_perror("Failed to make room for attribute");
+		goto put_err_out;
+	}
+
+	/* Setup record fields. */
+	a->type = type;
+	a->length = cpu_to_le32(length);
+	a->non_resident = 1;
+	a->name_length = name_len;
+	a->name_offset = cpu_to_le16(offsetof(ATTR_RECORD, compressed_size) +
+			((flags & (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE)) ?
+			sizeof(a->compressed_size) : 0));
+	a->flags = flags;
+	a->instance = m->next_attr_instance;
+	a->lowest_vcn = cpu_to_sle64(lowest_vcn);
+	a->mapping_pairs_offset = cpu_to_le16(length - dataruns_size);
+	a->compression_unit = (flags & ATTR_IS_COMPRESSED)
+			? STANDARD_COMPRESSION_UNIT : 0;
+	/* If @lowest_vcn == 0, than setup empty attribute. */
+	if (!lowest_vcn) {
+		a->highest_vcn = cpu_to_sle64(-1);
+		a->allocated_size = 0;
+		a->data_size = 0;
+		a->initialized_size = 0;
+		/* Set empty mapping pairs. */
+		*((u8*)a + le16_to_cpu(a->mapping_pairs_offset)) = 0;
+	}
+	if (name_len)
+		memcpy((u8*)a + le16_to_cpu(a->name_offset),
+			name, sizeof(ntfschar) * name_len);
+	m->next_attr_instance =
+		cpu_to_le16((le16_to_cpu(m->next_attr_instance) + 1) & 0xffff);
+	if (ni->nr_extents == -1)
+		base_ni = ni->base_ni;
+	else
+		base_ni = ni;
+	if (type != AT_ATTRIBUTE_LIST && NInoAttrList(base_ni)) {
+		if (ntfs_attrlist_entry_add(ni, a)) {
+			err = errno;
+			ntfs_log_perror("Failed add attr entry to attrlist");
+			ntfs_attr_record_resize(m, a, 0);
+			goto put_err_out;
+		}
+	}
+	ntfs_inode_mark_dirty(ni);
+	/*
+	 * Locate offset from start of the MFT record where new attribute is
+	 * placed. We need relookup it, because record maybe moved during
+	 * update of attribute list.
+	 */
+	ntfs_attr_reinit_search_ctx(ctx);
+	if (ntfs_attr_lookup(type, name, name_len, CASE_SENSITIVE,
+					lowest_vcn, NULL, 0, ctx)) {
+		ntfs_log_perror("%s: attribute lookup failed", __FUNCTION__);
+		ntfs_attr_put_search_ctx(ctx);
+		return -1;
+
+	}
+	offset = (u8*)ctx->attr - (u8*)ctx->mrec;
+	ntfs_attr_put_search_ctx(ctx);
+	return offset;
+put_err_out:
+	ntfs_attr_put_search_ctx(ctx);
+	errno = err;
+	return -1;
+}
+
+/**
+ * ntfs_attr_record_rm - remove attribute extent
+ * @ctx:	search context describing the attribute which should be removed
+ *
+ * If this function succeed, user should reinit search context if he/she wants
+ * use it anymore.
+ *
+ * Return 0 on success and -1 on error. On error the error code is stored in
+ * errno. Possible error codes are:
+ *	EINVAL	- Invalid arguments passed to function.
+ *	EIO	- I/O error occurred or damaged filesystem.
+ */
+int ntfs_attr_record_rm(ntfs_attr_search_ctx *ctx)
+{
+	ntfs_inode *base_ni, *ni;
+	ATTR_TYPES type;
+
+	if (!ctx || !ctx->ntfs_ino || !ctx->mrec || !ctx->attr) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n",
+			(long long) ctx->ntfs_ino->mft_no,
+			(unsigned) le32_to_cpu(ctx->attr->type));
+	type = ctx->attr->type;
+	ni = ctx->ntfs_ino;
+	if (ctx->base_ntfs_ino)
+		base_ni = ctx->base_ntfs_ino;
+	else
+		base_ni = ctx->ntfs_ino;
+
+	/* Remove attribute itself. */
+	if (ntfs_attr_record_resize(ctx->mrec, ctx->attr, 0)) {
+		ntfs_log_trace("Couldn't remove attribute record. Bug or damaged MFT "
+				"record.\n");
+		if (NInoAttrList(base_ni) && type != AT_ATTRIBUTE_LIST)
+			if (ntfs_attrlist_entry_add(ni, ctx->attr))
+				ntfs_log_trace("Rollback failed. Leaving inconstant "
+						"metadata.\n");
+		errno = EIO;
+		return -1;
+	}
+	ntfs_inode_mark_dirty(ni);
+
+	/*
+	 * Remove record from $ATTRIBUTE_LIST if present and we don't want
+	 * delete $ATTRIBUTE_LIST itself.
+	 */
+	if (NInoAttrList(base_ni) && type != AT_ATTRIBUTE_LIST) {
+		if (ntfs_attrlist_entry_rm(ctx)) {
+			ntfs_log_trace("Couldn't delete record from "
+					"$ATTRIBUTE_LIST.\n");
+			return -1;
+		}
+	}
+
+	/* Post $ATTRIBUTE_LIST delete setup. */
+	if (type == AT_ATTRIBUTE_LIST) {
+		if (NInoAttrList(base_ni) && base_ni->attr_list)
+			free(base_ni->attr_list);
+		base_ni->attr_list = NULL;
+		NInoClearAttrList(base_ni);
+		NInoAttrListClearDirty(base_ni);
+	}
+
+	/* Free MFT record, if it doesn't contain attributes. */
+	if (le32_to_cpu(ctx->mrec->bytes_in_use) -
+			le16_to_cpu(ctx->mrec->attrs_offset) == 8) {
+		if (ntfs_mft_record_free(ni->vol, ni)) {
+			// FIXME: We need rollback here.
+			ntfs_log_trace("Couldn't free MFT record.\n");
+			errno = EIO;
+			return -1;
+		}
+		/* Remove done if we freed base inode. */
+		if (ni == base_ni)
+			return 0;
+	}
+
+	if (type == AT_ATTRIBUTE_LIST || !NInoAttrList(base_ni))
+		return 0;
+
+	/* Remove attribute list if we don't need it any more. */
+	if (!ntfs_attrlist_need(base_ni)) {
+		ntfs_attr_reinit_search_ctx(ctx);
+		if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, NULL, 0, CASE_SENSITIVE,
+				0, NULL, 0, ctx)) {
+			/*
+			 * FIXME: Should we succeed here? Definitely something
+			 * goes wrong because NInoAttrList(base_ni) returned
+			 * that we have got attribute list.
+			 */
+			ntfs_log_trace("Couldn't find attribute list. Succeed "
+					"anyway.\n");
+			return 0;
+		}
+		/* Deallocate clusters. */
+		if (ctx->attr->non_resident) {
+			runlist *al_rl;
+
+			al_rl = ntfs_mapping_pairs_decompress(base_ni->vol,
+					ctx->attr, NULL);
+			if (!al_rl) {
+				ntfs_log_trace("Couldn't decompress attribute list "
+						"runlist. Succeed anyway.\n");
+				return 0;
+			}
+			if (ntfs_cluster_free_from_rl(base_ni->vol, al_rl)) {
+				ntfs_log_trace("Leaking clusters! Run chkdsk. "
+						"Couldn't free clusters from "
+						"attribute list runlist.\n");
+			}
+			free(al_rl);
+		}
+		/* Remove attribute record itself. */
+		if (ntfs_attr_record_rm(ctx)) {
+			/*
+			 * FIXME: Should we succeed here? BTW, chkdsk doesn't
+			 * complain if it find MFT record with attribute list,
+			 * but without extents.
+			 */
+			ntfs_log_trace("Couldn't remove attribute list. Succeed "
+					"anyway.\n");
+			return 0;
+		}
+	}
+	return 0;
+}
+
+/**
+ * ntfs_attr_add - add attribute to inode
+ * @ni:		opened ntfs inode to which add attribute
+ * @type:	type of the new attribute
+ * @name:	name in unicode of the new attribute
+ * @name_len:	name length in unicode characters of the new attribute
+ * @val:	value of new attribute
+ * @size:	size of the new attribute / length of @val (if specified)
+ *
+ * @val should always be specified for always resident attributes (eg. FILE_NAME
+ * attribute), for attributes that can become non-resident @val can be NULL
+ * (eg. DATA attribute). @size can be specified even if @val is NULL, in this
+ * case data size will be equal to @size and initialized size will be equal
+ * to 0.
+ *
+ * If inode haven't got enough space to add attribute, add attribute to one of
+ * it extents, if no extents present or no one of them have enough space, than
+ * allocate new extent and add attribute to it.
+ *
+ * If on one of this steps attribute list is needed but not present, than it is
+ * added transparently to caller. So, this function should not be called with
+ * @type == AT_ATTRIBUTE_LIST, if you really need to add attribute list call
+ * ntfs_inode_add_attrlist instead.
+ *
+ * On success return 0. On error return -1 with errno set to the error code.
+ */
+int ntfs_attr_add(ntfs_inode *ni, ATTR_TYPES type,
+		ntfschar *name, u8 name_len, const u8 *val, s64 size)
+{
+	u32 attr_rec_size;
+	int err, i, offset;
+	BOOL is_resident;
+	BOOL can_be_non_resident = FALSE;
+	ntfs_inode *attr_ni;
+	ntfs_attr *na;
+	ATTR_FLAGS data_flags;
+
+	if (!ni || size < 0 || type == AT_ATTRIBUTE_LIST) {
+		errno = EINVAL;
+		ntfs_log_perror("%s: ni=%p  size=%lld", __FUNCTION__, ni,
+				(long long)size);
+		return -1;
+	}
+
+	ntfs_log_trace("Entering for inode %lld, attr %x, size %lld.\n",
+			(long long)ni->mft_no, type, (long long)size);
+
+	if (ni->nr_extents == -1)
+		ni = ni->base_ni;
+
+	/* Check the attribute type and the size. */
+	if (ntfs_attr_size_bounds_check(ni->vol, type, size)) {
+		if (errno == ENOENT)
+			errno = EIO;
+		return -1;
+	}
+
+	/* Sanity checks for always resident attributes. */
+	if (ntfs_attr_can_be_non_resident(ni->vol, type, name, name_len)) {
+		if (errno != EPERM) {
+			err = errno;
+			ntfs_log_perror("ntfs_attr_can_be_non_resident failed");
+			goto err_out;
+		}
+		/* @val is mandatory. */
+		if (!val) {
+			errno = EINVAL;
+			ntfs_log_perror("val is mandatory for always resident "
+					"attributes");
+			return -1;
+		}
+		if (size > ni->vol->mft_record_size) {
+			errno = ERANGE;
+			ntfs_log_perror("Attribute is too big");
+			return -1;
+		}
+	} else
+		can_be_non_resident = TRUE;
+
+	/*
+	 * Determine resident or not will be new attribute. We add 8 to size in
+	 * non resident case for mapping pairs.
+	 */
+	if (!ntfs_attr_can_be_resident(ni->vol, type)) {
+		is_resident = TRUE;
+	} else {
+		if (errno != EPERM) {
+			err = errno;
+			ntfs_log_perror("ntfs_attr_can_be_resident failed");
+			goto err_out;
+		}
+		is_resident = FALSE;
+	}
+	/* Calculate attribute record size. */
+	if (is_resident)
+		attr_rec_size = offsetof(ATTR_RECORD, resident_end) +
+				((name_len * sizeof(ntfschar) + 7) & ~7) +
+				((size + 7) & ~7);
+	else
+		attr_rec_size = offsetof(ATTR_RECORD, non_resident_end) +
+				((name_len * sizeof(ntfschar) + 7) & ~7) + 8;
+
+	/*
+	 * If we have enough free space for the new attribute in the base MFT
+	 * record, then add attribute to it.
+	 */
+	if (le32_to_cpu(ni->mrec->bytes_allocated) -
+			le32_to_cpu(ni->mrec->bytes_in_use) >= attr_rec_size) {
+		attr_ni = ni;
+		goto add_attr_record;
+	}
+
+	/* Try to add to extent inodes. */
+	if (ntfs_inode_attach_all_extents(ni)) {
+		err = errno;
+		ntfs_log_perror("Failed to attach all extents to inode");
+		goto err_out;
+	}
+	for (i = 0; i < ni->nr_extents; i++) {
+		attr_ni = ni->extent_nis[i];
+		if (le32_to_cpu(attr_ni->mrec->bytes_allocated) -
+				le32_to_cpu(attr_ni->mrec->bytes_in_use) >=
+				attr_rec_size)
+			goto add_attr_record;
+	}
+
+	/* There is no extent that contain enough space for new attribute. */
+	if (!NInoAttrList(ni)) {
+		/* Add attribute list not present, add it and retry. */
+		if (ntfs_inode_add_attrlist(ni)) {
+			err = errno;
+			ntfs_log_perror("Failed to add attribute list");
+			goto err_out;
+		}
+		return ntfs_attr_add(ni, type, name, name_len, val, size);
+	}
+	/* Allocate new extent. */
+	attr_ni = ntfs_mft_record_alloc(ni->vol, ni);
+	if (!attr_ni) {
+		err = errno;
+		ntfs_log_perror("Failed to allocate extent record");
+		goto err_out;
+	}
+
+add_attr_record:
+	if ((ni->flags & FILE_ATTR_COMPRESSED)
+	    && (ni->vol->major_ver >= 3)
+	    && NVolCompression(ni->vol)
+	    && (ni->vol->cluster_size <= MAX_COMPRESSION_CLUSTER_SIZE)
+	    && ((type == AT_DATA)
+	       || ((type == AT_INDEX_ROOT) && (name == NTFS_INDEX_I30))))
+		data_flags = ATTR_IS_COMPRESSED;
+	else
+		data_flags = const_cpu_to_le16(0);
+	if (is_resident) {
+		/* Add resident attribute. */
+		offset = ntfs_resident_attr_record_add(attr_ni, type, name,
+				name_len, val, size, data_flags);
+		if (offset < 0) {
+			if (errno == ENOSPC && can_be_non_resident)
+				goto add_non_resident;
+			err = errno;
+			ntfs_log_perror("Failed to add resident attribute");
+			goto free_err_out;
+		}
+		return 0;
+	}
+
+add_non_resident:
+	/* Add non resident attribute. */
+	offset = ntfs_non_resident_attr_record_add(attr_ni, type, name,
+				name_len, 0, 8, data_flags);
+	if (offset < 0) {
+		err = errno;
+		ntfs_log_perror("Failed to add non resident attribute");
+		goto free_err_out;
+	}
+
+	/* If @size == 0, we are done. */
+	if (!size)
+		return 0;
+
+	/* Open new attribute and resize it. */
+	na = ntfs_attr_open(ni, type, name, name_len);
+	if (!na) {
+		err = errno;
+		ntfs_log_perror("Failed to open just added attribute");
+		goto rm_attr_err_out;
+	}
+	/* Resize and set attribute value. */
+	if (ntfs_attr_truncate_i(na, size, HOLES_OK) ||
+			(val && (ntfs_attr_pwrite(na, 0, size, val) != size))) {
+		err = errno;
+		ntfs_log_perror("Failed to initialize just added attribute");
+		if (ntfs_attr_rm(na))
+			ntfs_log_perror("Failed to remove just added attribute");
+		ntfs_attr_close(na);
+		goto err_out;
+	}
+	ntfs_attr_close(na);
+	return 0;
+
+rm_attr_err_out:
+	/* Remove just added attribute. */
+	if (ntfs_attr_record_resize(attr_ni->mrec,
+			(ATTR_RECORD*)((u8*)attr_ni->mrec + offset), 0))
+		ntfs_log_perror("Failed to remove just added attribute #2");
+free_err_out:
+	/* Free MFT record, if it doesn't contain attributes. */
+	if (le32_to_cpu(attr_ni->mrec->bytes_in_use) -
+			le16_to_cpu(attr_ni->mrec->attrs_offset) == 8)
+		if (ntfs_mft_record_free(attr_ni->vol, attr_ni))
+			ntfs_log_perror("Failed to free MFT record");
+err_out:
+	errno = err;
+	return -1;
+}
+
+/*
+ *		Change an attribute flag
+ */
+
+int ntfs_attr_set_flags(ntfs_inode *ni, ATTR_TYPES type, const ntfschar *name,
+		u8 name_len, ATTR_FLAGS flags, ATTR_FLAGS mask)
+{
+	ntfs_attr_search_ctx *ctx;
+	int res;
+
+	res = -1;
+	/* Search for designated attribute */
+	ctx = ntfs_attr_get_search_ctx(ni, NULL);
+	if (ctx) {
+		if (!ntfs_attr_lookup(type, name, name_len,
+					CASE_SENSITIVE, 0, NULL, 0, ctx)) {
+			/* do the requested change (all small endian le16) */
+			ctx->attr->flags = (ctx->attr->flags & ~mask)
+						| (flags & mask);
+			NInoSetDirty(ni);
+			res = 0;
+		}
+		ntfs_attr_put_search_ctx(ctx);
+	}
+	return (res);
+}
+
+
+/**
+ * ntfs_attr_rm - remove attribute from ntfs inode
+ * @na:		opened ntfs attribute to delete
+ *
+ * Remove attribute and all it's extents from ntfs inode. If attribute was non
+ * resident also free all clusters allocated by attribute.
+ *
+ * Return 0 on success or -1 on error with errno set to the error code.
+ */
+int ntfs_attr_rm(ntfs_attr *na)
+{
+	ntfs_attr_search_ctx *ctx;
+	int ret = 0;
+
+	if (!na) {
+		ntfs_log_trace("Invalid arguments passed.\n");
+		errno = EINVAL;
+		return -1;
+	}
+
+	ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n",
+		(long long) na->ni->mft_no, na->type);
+
+	/* Free cluster allocation. */
+	if (NAttrNonResident(na)) {
+		if (ntfs_attr_map_whole_runlist(na))
+			return -1;
+		if (ntfs_cluster_free(na->ni->vol, na, 0, -1) < 0) {
+			ntfs_log_trace("Failed to free cluster allocation. Leaving "
+					"inconstant metadata.\n");
+			ret = -1;
+		}
+	}
+
+	/* Search for attribute extents and remove them all. */
+	ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
+	if (!ctx)
+		return -1;
+	while (!ntfs_attr_lookup(na->type, na->name, na->name_len,
+				CASE_SENSITIVE, 0, NULL, 0, ctx)) {
+		if (ntfs_attr_record_rm(ctx)) {
+			ntfs_log_trace("Failed to remove attribute extent. Leaving "
+					"inconstant metadata.\n");
+			ret = -1;
+		}
+		ntfs_attr_reinit_search_ctx(ctx);
+	}
+	ntfs_attr_put_search_ctx(ctx);
+	if (errno != ENOENT) {
+		ntfs_log_trace("Attribute lookup failed. Probably leaving inconstant "
+				"metadata.\n");
+		ret = -1;
+	}
+
+	return ret;
+}
+
+/**
+ * ntfs_attr_record_resize - resize an attribute record
+ * @m:		mft record containing attribute record
+ * @a:		attribute record to resize
+ * @new_size:	new size in bytes to which to resize the attribute record @a
+ *
+ * Resize the attribute record @a, i.e. the resident part of the attribute, in
+ * the mft record @m to @new_size bytes.
+ *
+ * Return 0 on success and -1 on error with errno set to the error code.
+ * The following error codes are defined:
+ *	ENOSPC	- Not enough space in the mft record @m to perform the resize.
+ * Note that on error no modifications have been performed whatsoever.
+ *
+ * Warning: If you make a record smaller without having copied all the data you
+ *	    are interested in the data may be overwritten!
+ */
+int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size)
+{
+	u32 old_size, alloc_size, attr_size;
+	
+	old_size   = le32_to_cpu(m->bytes_in_use);
+	alloc_size = le32_to_cpu(m->bytes_allocated);
+	attr_size  = le32_to_cpu(a->length);
+	
+	ntfs_log_trace("Sizes: old=%u alloc=%u attr=%u new=%u\n", 
+		       (unsigned)old_size, (unsigned)alloc_size, 
+		       (unsigned)attr_size, (unsigned)new_size);
+
+	/* Align to 8 bytes, just in case the caller hasn't. */
+	new_size = (new_size + 7) & ~7;
+	
+	/* If the actual attribute length has changed, move things around. */
+	if (new_size != attr_size) {
+		
+		u32 new_muse = old_size - attr_size + new_size;
+		
+		/* Not enough space in this mft record. */
+		if (new_muse > alloc_size) {
+			errno = ENOSPC;
+			ntfs_log_trace("Not enough space in the MFT record "
+				       "(%u > %u)\n", new_muse, alloc_size);
+			return -1;
+		}
+
+		if (a->type == AT_INDEX_ROOT && new_size > attr_size &&
+		    new_muse + 120 > alloc_size && old_size + 120 <= alloc_size) {
+			errno = ENOSPC;
+			ntfs_log_trace("Too big INDEX_ROOT (%u > %u)\n",
+					new_muse, alloc_size);
+			return STATUS_RESIDENT_ATTRIBUTE_FILLED_MFT;
+		}
+		
+		/* Move attributes following @a to their new location. */
+		memmove((u8 *)a + new_size, (u8 *)a + attr_size,
+			old_size - ((u8 *)a - (u8 *)m) - attr_size);
+		
+		/* Adjust @m to reflect the change in used space. */
+		m->bytes_in_use = cpu_to_le32(new_muse);
+		
+		/* Adjust @a to reflect the new size. */
+		if (new_size >= offsetof(ATTR_REC, length) + sizeof(a->length))
+			a->length = cpu_to_le32(new_size);
+	}
+	return 0;
+}
+
+/**
+ * ntfs_resident_attr_value_resize - resize the value of a resident attribute
+ * @m:		mft record containing attribute record
+ * @a:		attribute record whose value to resize
+ * @new_size:	new size in bytes to which to resize the attribute value of @a
+ *
+ * Resize the value of the attribute @a in the mft record @m to @new_size bytes.
+ * If the value is made bigger, the newly "allocated" space is cleared.
+ *
+ * Return 0 on success and -1 on error with errno set to the error code.
+ * The following error codes are defined:
+ *	ENOSPC	- Not enough space in the mft record @m to perform the resize.
+ * Note that on error no modifications have been performed whatsoever.
+ */
+int ntfs_resident_attr_value_resize(MFT_RECORD *m, ATTR_RECORD *a,
+		const u32 new_size)
+{
+	int ret;
+	
+	ntfs_log_trace("Entering for new size %u.\n", (unsigned)new_size);
+
+	/* Resize the resident part of the attribute record. */
+	if ((ret = ntfs_attr_record_resize(m, a, (le16_to_cpu(a->value_offset) +
+			new_size + 7) & ~7)) < 0)
+		return ret;
+	/*
+	 * If we made the attribute value bigger, clear the area between the
+	 * old size and @new_size.
+	 */
+	if (new_size > le32_to_cpu(a->value_length))
+		memset((u8*)a + le16_to_cpu(a->value_offset) +
+				le32_to_cpu(a->value_length), 0, new_size -
+				le32_to_cpu(a->value_length));
+	/* Finally update the length of the attribute value. */
+	a->value_length = cpu_to_le32(new_size);
+	return 0;
+}
+
+/**
+ * ntfs_attr_record_move_to - move attribute record to target inode
+ * @ctx:	attribute search context describing the attribute record
+ * @ni:		opened ntfs inode to which move attribute record
+ *
+ * If this function succeed, user should reinit search context if he/she wants
+ * use it anymore.
+ *
+ * Return 0 on success and -1 on error with errno set to the error code.
+ */
+int ntfs_attr_record_move_to(ntfs_attr_search_ctx *ctx, ntfs_inode *ni)
+{
+	ntfs_attr_search_ctx *nctx;
+	ATTR_RECORD *a;
+	int err;
+
+	if (!ctx || !ctx->attr || !ctx->ntfs_ino || !ni) {
+		ntfs_log_trace("Invalid arguments passed.\n");
+		errno = EINVAL;
+		return -1;
+	}
+
+	ntfs_log_trace("Entering for ctx->attr->type 0x%x, ctx->ntfs_ino->mft_no "
+			"0x%llx, ni->mft_no 0x%llx.\n",
+			(unsigned) le32_to_cpu(ctx->attr->type),
+			(long long) ctx->ntfs_ino->mft_no,
+			(long long) ni->mft_no);
+
+	if (ctx->ntfs_ino == ni)
+		return 0;
+
+	if (!ctx->al_entry) {
+		ntfs_log_trace("Inode should contain attribute list to use this "
+				"function.\n");
+		errno = EINVAL;
+		return -1;
+	}
+
+	/* Find place in MFT record where attribute will be moved. */
+	a = ctx->attr;
+	nctx = ntfs_attr_get_search_ctx(ni, NULL);
+	if (!nctx)
+		return -1;
+
+	/*
+	 * Use ntfs_attr_find instead of ntfs_attr_lookup to find place for
+	 * attribute in @ni->mrec, not any extent inode in case if @ni is base
+	 * file record.
+	 */
+	if (!ntfs_attr_find(a->type, (ntfschar*)((u8*)a + le16_to_cpu(
+			a->name_offset)), a->name_length, CASE_SENSITIVE, NULL,
+			0, nctx)) {
+		ntfs_log_trace("Attribute of such type, with same name already "
+				"present in this MFT record.\n");
+		err = EEXIST;
+		goto put_err_out;
+	}
+	if (errno != ENOENT) {
+		err = errno;
+		ntfs_log_debug("Attribute lookup failed.\n");
+		goto put_err_out;
+	}
+
+	/* Make space and move attribute. */
+	if (ntfs_make_room_for_attr(ni->mrec, (u8*) nctx->attr,
+					le32_to_cpu(a->length))) {
+		err = errno;
+		ntfs_log_trace("Couldn't make space for attribute.\n");
+		goto put_err_out;
+	}
+	memcpy(nctx->attr, a, le32_to_cpu(a->length));
+	nctx->attr->instance = nctx->mrec->next_attr_instance;
+	nctx->mrec->next_attr_instance = cpu_to_le16(
+		(le16_to_cpu(nctx->mrec->next_attr_instance) + 1) & 0xffff);
+	ntfs_attr_record_resize(ctx->mrec, a, 0);
+	ntfs_inode_mark_dirty(ctx->ntfs_ino);
+	ntfs_inode_mark_dirty(ni);
+
+	/* Update attribute list. */
+	ctx->al_entry->mft_reference =
+		MK_LE_MREF(ni->mft_no, le16_to_cpu(ni->mrec->sequence_number));
+	ctx->al_entry->instance = nctx->attr->instance;
+	ntfs_attrlist_mark_dirty(ni);
+
+	ntfs_attr_put_search_ctx(nctx);
+	return 0;
+put_err_out:
+	ntfs_attr_put_search_ctx(nctx);
+	errno = err;
+	return -1;
+}
+
+/**
+ * ntfs_attr_record_move_away - move away attribute record from it's mft record
+ * @ctx:	attribute search context describing the attribute record
+ * @extra:	minimum amount of free space in the new holder of record
+ *
+ * New attribute record holder must have free @extra bytes after moving
+ * attribute record to it.
+ *
+ * If this function succeed, user should reinit search context if he/she wants
+ * use it anymore.
+ *
+ * Return 0 on success and -1 on error with errno set to the error code.
+ */
+int ntfs_attr_record_move_away(ntfs_attr_search_ctx *ctx, int extra)
+{
+	ntfs_inode *base_ni, *ni;
+	MFT_RECORD *m;
+	int i;
+
+	if (!ctx || !ctx->attr || !ctx->ntfs_ino || extra < 0) {
+		errno = EINVAL;
+		ntfs_log_perror("%s: ctx=%p ctx->attr=%p extra=%d", __FUNCTION__,
+				ctx, ctx ? ctx->attr : NULL, extra);
+		return -1;
+	}
+
+	ntfs_log_trace("Entering for attr 0x%x, inode %llu\n",
+			(unsigned) le32_to_cpu(ctx->attr->type),
+			(unsigned long long)ctx->ntfs_ino->mft_no);
+
+	if (ctx->ntfs_ino->nr_extents == -1)
+		base_ni = ctx->base_ntfs_ino;
+	else
+		base_ni = ctx->ntfs_ino;
+
+	if (!NInoAttrList(base_ni)) {
+		errno = EINVAL;
+		ntfs_log_perror("Inode %llu has no attrlist", 
+				(unsigned long long)base_ni->mft_no);
+		return -1;
+	}
+
+	if (ntfs_inode_attach_all_extents(ctx->ntfs_ino)) {
+		ntfs_log_perror("Couldn't attach extents, inode=%llu", 
+				(unsigned long long)base_ni->mft_no);
+		return -1;
+	}
+
+	/* Walk through all extents and try to move attribute to them. */
+	for (i = 0; i < base_ni->nr_extents; i++) {
+		ni = base_ni->extent_nis[i];
+		m = ni->mrec;
+
+		if (ctx->ntfs_ino->mft_no == ni->mft_no)
+			continue;
+
+		if (le32_to_cpu(m->bytes_allocated) -
+				le32_to_cpu(m->bytes_in_use) <
+				le32_to_cpu(ctx->attr->length) + extra)
+			continue;
+
+		/*
+		 * ntfs_attr_record_move_to can fail if extent with other lowest
+		 * VCN already present in inode we trying move record to. So,
+		 * do not return error.
+		 */
+		if (!ntfs_attr_record_move_to(ctx, ni))
+			return 0;
+	}
+
+	/*
+	 * Failed to move attribute to one of the current extents, so allocate
+	 * new extent and move attribute to it.
+	 */
+	ni = ntfs_mft_record_alloc(base_ni->vol, base_ni);
+	if (!ni) {
+		ntfs_log_perror("Couldn't allocate MFT record");
+		return -1;
+	}
+	if (ntfs_attr_record_move_to(ctx, ni)) {
+		ntfs_log_perror("Couldn't move attribute to MFT record");
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * ntfs_attr_make_non_resident - convert a resident to a non-resident attribute
+ * @na:		open ntfs attribute to make non-resident
+ * @ctx:	ntfs search context describing the attribute
+ *
+ * Convert a resident ntfs attribute to a non-resident one.
+ *
+ * Return 0 on success and -1 on error with errno set to the error code. The
+ * following error codes are defined:
+ *	EPERM	- The attribute is not allowed to be non-resident.
+ *	TODO: others...
+ *
+ * NOTE to self: No changes in the attribute list are required to move from
+ *		 a resident to a non-resident attribute.
+ *
+ * Warning: We do not set the inode dirty and we do not write out anything!
+ *	    We expect the caller to do this as this is a fairly low level
+ *	    function and it is likely there will be further changes made.
+ */
+int ntfs_attr_make_non_resident(ntfs_attr *na,
+		ntfs_attr_search_ctx *ctx)
+{
+	s64 new_allocated_size, bw;
+	ntfs_volume *vol = na->ni->vol;
+	ATTR_REC *a = ctx->attr;
+	runlist *rl;
+	int mp_size, mp_ofs, name_ofs, arec_size, err;
+
+	ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", (unsigned long
+			long)na->ni->mft_no, na->type);
+
+	/* Some preliminary sanity checking. */
+	if (NAttrNonResident(na)) {
+		ntfs_log_trace("Eeek!  Trying to make non-resident attribute "
+				"non-resident.  Aborting...\n");
+		errno = EINVAL;
+		return -1;
+	}
+
+	/* Check that the attribute is allowed to be non-resident. */
+	if (ntfs_attr_can_be_non_resident(vol, na->type, na->name, na->name_len))
+		return -1;
+
+	new_allocated_size = (le32_to_cpu(a->value_length) + vol->cluster_size
+			- 1) & ~(vol->cluster_size - 1);
+
+	if (new_allocated_size > 0) {
+			if ((a->flags & ATTR_COMPRESSION_MASK)
+					== ATTR_IS_COMPRESSED) {
+				/* must allocate full compression blocks */
+				new_allocated_size = ((new_allocated_size - 1)
+					| ((1L << (STANDARD_COMPRESSION_UNIT
+					   + vol->cluster_size_bits)) - 1)) + 1;
+			}
+		/* Start by allocating clusters to hold the attribute value. */
+		rl = ntfs_cluster_alloc(vol, 0, new_allocated_size >>
+				vol->cluster_size_bits, -1, DATA_ZONE);
+		if (!rl)
+			return -1;
+	} else
+		rl = NULL;
+	/*
+	 * Setup the in-memory attribute structure to be non-resident so that
+	 * we can use ntfs_attr_pwrite().
+	 */
+	NAttrSetNonResident(na);
+	NAttrSetBeingNonResident(na);
+	na->rl = rl;
+	na->allocated_size = new_allocated_size;
+	na->data_size = na->initialized_size = le32_to_cpu(a->value_length);
+	/*
+	 * FIXME: For now just clear all of these as we don't support them when
+	 * writing.
+	 */
+	NAttrClearSparse(na);
+	NAttrClearEncrypted(na);
+	if ((a->flags & ATTR_COMPRESSION_MASK) == ATTR_IS_COMPRESSED) {
+			/* set compression writing parameters */
+		na->compression_block_size
+			= 1 << (STANDARD_COMPRESSION_UNIT + vol->cluster_size_bits);
+		na->compression_block_clusters = 1 << STANDARD_COMPRESSION_UNIT;
+	}
+
+	if (rl) {
+		/* Now copy the attribute value to the allocated cluster(s). */
+		bw = ntfs_attr_pwrite(na, 0, le32_to_cpu(a->value_length),
+				(u8*)a + le16_to_cpu(a->value_offset));
+		if (bw != le32_to_cpu(a->value_length)) {
+			err = errno;
+			ntfs_log_debug("Eeek!  Failed to write out attribute value "
+					"(bw = %lli, errno = %i).  "
+					"Aborting...\n", (long long)bw, err);
+			if (bw >= 0)
+				err = EIO;
+			goto cluster_free_err_out;
+		}
+	}
+	/* Determine the size of the mapping pairs array. */
+	mp_size = ntfs_get_size_for_mapping_pairs(vol, rl, 0, INT_MAX);
+	if (mp_size < 0) {
+		err = errno;
+		ntfs_log_debug("Eeek!  Failed to get size for mapping pairs array.  "
+				"Aborting...\n");
+		goto cluster_free_err_out;
+	}
+	/* Calculate new offsets for the name and the mapping pairs array. */
+	if (na->ni->flags & FILE_ATTR_COMPRESSED)
+		name_ofs = (sizeof(ATTR_REC) + 7) & ~7;
+	else
+		name_ofs = (sizeof(ATTR_REC) - sizeof(a->compressed_size) + 7) & ~7;
+	mp_ofs = (name_ofs + a->name_length * sizeof(ntfschar) + 7) & ~7;
+	/*
+	 * Determine the size of the resident part of the non-resident
+	 * attribute record. (Not compressed thus no compressed_size element
+	 * present.)
+	 */
+	arec_size = (mp_ofs + mp_size + 7) & ~7;
+
+	/* Resize the resident part of the attribute record. */
+	if (ntfs_attr_record_resize(ctx->mrec, a, arec_size) < 0) {
+		err = errno;
+		goto cluster_free_err_out;
+	}
+
+	/*
+	 * Convert the resident part of the attribute record to describe a
+	 * non-resident attribute.
+	 */
+	a->non_resident = 1;
+
+	/* Move the attribute name if it exists and update the offset. */
+	if (a->name_length)
+		memmove((u8*)a + name_ofs, (u8*)a + le16_to_cpu(a->name_offset),
+				a->name_length * sizeof(ntfschar));
+	a->name_offset = cpu_to_le16(name_ofs);
+
+	/* Setup the fields specific to non-resident attributes. */
+	a->lowest_vcn = cpu_to_sle64(0);
+	a->highest_vcn = cpu_to_sle64((new_allocated_size - 1) >>
+						vol->cluster_size_bits);
+
+	a->mapping_pairs_offset = cpu_to_le16(mp_ofs);
+
+	/*
+	 * Update the flags to match the in-memory ones.
+	 * However cannot change the compression state if we had
+	 * a fuse_file_info open with a mark for release.
+	 * The decisions about compression can only be made when
+	 * creating/recreating the stream, not when making non resident.
+	 */
+	a->flags &= ~(ATTR_IS_SPARSE | ATTR_IS_ENCRYPTED);
+	if ((a->flags & ATTR_COMPRESSION_MASK) == ATTR_IS_COMPRESSED) {
+			/* support only ATTR_IS_COMPRESSED compression mode */
+		a->compression_unit = STANDARD_COMPRESSION_UNIT;
+		a->compressed_size = const_cpu_to_le64(0);
+	} else {
+		a->compression_unit = 0;
+		a->flags &= ~ATTR_COMPRESSION_MASK;
+		na->data_flags = a->flags;
+	}
+
+	memset(&a->reserved1, 0, sizeof(a->reserved1));
+
+	a->allocated_size = cpu_to_sle64(new_allocated_size);
+	a->data_size = a->initialized_size = cpu_to_sle64(na->data_size);
+
+	/* Generate the mapping pairs array in the attribute record. */
+	if (ntfs_mapping_pairs_build(vol, (u8*)a + mp_ofs, arec_size - mp_ofs,
+			rl, 0, NULL) < 0) {
+		// FIXME: Eeek! We need rollback! (AIA)
+		ntfs_log_trace("Eeek!  Failed to build mapping pairs.  Leaving "
+				"corrupt attribute record on disk.  In memory "
+				"runlist is still intact!  Error code is %i.  "
+				"FIXME:  Need to rollback instead!\n", errno);
+		return -1;
+	}
+
+	/* Done! */
+	return 0;
+
+cluster_free_err_out:
+	if (rl && ntfs_cluster_free(vol, na, 0, -1) < 0)
+		ntfs_log_trace("Eeek!  Failed to release allocated clusters in error "
+				"code path.  Leaving inconsistent metadata...\n");
+	NAttrClearNonResident(na);
+	NAttrClearFullyMapped(na);
+	na->allocated_size = na->data_size;
+	na->rl = NULL;
+	free(rl);
+	errno = err;
+	return -1;
+}
+
+
+static int ntfs_resident_attr_resize(ntfs_attr *na, const s64 newsize);
+
+/**
+ * ntfs_resident_attr_resize - resize a resident, open ntfs attribute
+ * @na:		resident ntfs attribute to resize
+ * @newsize:	new size (in bytes) to which to resize the attribute
+ *
+ * Change the size of a resident, open ntfs attribute @na to @newsize bytes.
+ * Can also be used to force an attribute non-resident. In this case, the
+ * size cannot be changed.
+ *
+ * On success return 0 
+ * On error return values are:
+ * 	STATUS_RESIDENT_ATTRIBUTE_FILLED_MFT
+ * 	STATUS_ERROR - otherwise
+ * The following error codes are defined:
+ *	ENOMEM - Not enough memory to complete operation.
+ *	ERANGE - @newsize is not valid for the attribute type of @na.
+ *	ENOSPC - There is no enough space in base mft to resize $ATTRIBUTE_LIST.
+ */
+static int ntfs_resident_attr_resize_i(ntfs_attr *na, const s64 newsize,
+			hole_type holes)
+{
+	ntfs_attr_search_ctx *ctx;
+	ntfs_volume *vol;
+	ntfs_inode *ni;
+	int err, ret = STATUS_ERROR;
+
+	ntfs_log_trace("Inode 0x%llx attr 0x%x new size %lld\n", 
+		       (unsigned long long)na->ni->mft_no, na->type, 
+		       (long long)newsize);
+
+	/* Get the attribute record that needs modification. */
+	ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
+	if (!ctx)
+		return -1;
+	if (ntfs_attr_lookup(na->type, na->name, na->name_len, 0, 0, NULL, 0,
+			ctx)) {
+		err = errno;
+		ntfs_log_perror("ntfs_attr_lookup failed");
+		goto put_err_out;
+	}
+	vol = na->ni->vol;
+	/*
+	 * Check the attribute type and the corresponding minimum and maximum
+	 * sizes against @newsize and fail if @newsize is out of bounds.
+	 */
+	if (ntfs_attr_size_bounds_check(vol, na->type, newsize) < 0) {
+		err = errno;
+		if (err == ENOENT)
+			err = EIO;
+		ntfs_log_perror("%s: bounds check failed", __FUNCTION__);
+		goto put_err_out;
+	}
+	/*
+	 * If @newsize is bigger than the mft record we need to make the
+	 * attribute non-resident if the attribute type supports it. If it is
+	 * smaller we can go ahead and attempt the resize.
+	 */
+	if ((newsize < vol->mft_record_size) && (holes != HOLES_NONRES)) {
+		/* Perform the resize of the attribute record. */
+		if (!(ret = ntfs_resident_attr_value_resize(ctx->mrec, ctx->attr,
+				newsize))) {
+			/* Update attribute size everywhere. */
+			na->data_size = na->initialized_size = newsize;
+			na->allocated_size = (newsize + 7) & ~7;
+			if ((na->data_flags & ATTR_COMPRESSION_MASK)
+			    || NAttrSparse(na))
+				na->compressed_size = na->allocated_size;
+			if (na->ni->mrec->flags & MFT_RECORD_IS_DIRECTORY
+			    ? na->type == AT_INDEX_ROOT && na->name == NTFS_INDEX_I30
+			    : na->type == AT_DATA && na->name == AT_UNNAMED) {
+				na->ni->data_size = na->data_size;
+				if (((na->data_flags & ATTR_COMPRESSION_MASK)
+					|| NAttrSparse(na))
+						&& NAttrNonResident(na))
+					na->ni->allocated_size
+						= na->compressed_size;
+				else
+					na->ni->allocated_size
+						= na->allocated_size;
+				set_nino_flag(na->ni,KnownSize);
+				if (na->type == AT_DATA)
+					NInoFileNameSetDirty(na->ni);
+			}
+			goto resize_done;
+		}
+		/* Prefer AT_INDEX_ALLOCATION instead of AT_ATTRIBUTE_LIST */
+		if (ret == STATUS_RESIDENT_ATTRIBUTE_FILLED_MFT) {
+			err = errno;
+			goto put_err_out;
+		}
+	}
+	/* There is not enough space in the mft record to perform the resize. */
+
+	/* Make the attribute non-resident if possible. */
+	if (!ntfs_attr_make_non_resident(na, ctx)) {
+		ntfs_inode_mark_dirty(ctx->ntfs_ino);
+		ntfs_attr_put_search_ctx(ctx);
+		/*
+		 * do not truncate when forcing non-resident, this
+		 * could cause the attribute to be made resident again,
+		 * so size changes are not allowed.
+		 */
+		if (holes == HOLES_NONRES) {
+			ret = 0;
+			if (newsize != na->data_size) {
+				ntfs_log_error("Cannot change size when"
+					" forcing non-resident\n");
+				errno = EIO;
+				ret = STATUS_ERROR;
+			}
+			return (ret);
+		}
+		/* Resize non-resident attribute */
+		return ntfs_attr_truncate_i(na, newsize, holes);
+	} else if (errno != ENOSPC && errno != EPERM) {
+		err = errno;
+		ntfs_log_perror("Failed to make attribute non-resident");
+		goto put_err_out;
+	}
+
+	/* Try to make other attributes non-resident and retry each time. */
+	ntfs_attr_init_search_ctx(ctx, NULL, na->ni->mrec);
+	while (!ntfs_attr_lookup(AT_UNUSED, NULL, 0, 0, 0, NULL, 0, ctx)) {
+		ntfs_attr *tna;
+		ATTR_RECORD *a;
+
+		a = ctx->attr;
+		if (a->non_resident)
+			continue;
+
+		/*
+		 * Check out whether convert is reasonable. Assume that mapping
+		 * pairs will take 8 bytes.
+		 */
+		if (le32_to_cpu(a->length) <= offsetof(ATTR_RECORD,
+				compressed_size) + ((a->name_length *
+				sizeof(ntfschar) + 7) & ~7) + 8)
+			continue;
+
+		tna = ntfs_attr_open(na->ni, a->type, (ntfschar*)((u8*)a +
+				le16_to_cpu(a->name_offset)), a->name_length);
+		if (!tna) {
+			err = errno;
+			ntfs_log_perror("Couldn't open attribute");
+			goto put_err_out;
+		}
+		if (ntfs_attr_make_non_resident(tna, ctx)) {
+			ntfs_attr_close(tna);
+			continue;
+		}
+		if ((tna->type == AT_DATA) && !tna->name_len) {
+			/*
+			 * If we had to make the unnamed data attribute
+			 * non-resident, propagate its new allocated size
+			 * to all name attributes and directory indexes
+			 */
+			tna->ni->allocated_size = tna->allocated_size;
+			NInoFileNameSetDirty(tna->ni);
+		}
+		if (((tna->data_flags & ATTR_COMPRESSION_MASK)
+						== ATTR_IS_COMPRESSED)
+		   && ntfs_attr_pclose(tna)) {
+			err = errno;
+			ntfs_attr_close(tna);
+			goto put_err_out;
+		}
+		ntfs_inode_mark_dirty(tna->ni);
+		ntfs_attr_close(tna);
+		ntfs_attr_put_search_ctx(ctx);
+		return ntfs_resident_attr_resize_i(na, newsize, holes);
+	}
+	/* Check whether error occurred. */
+	if (errno != ENOENT) {
+		err = errno;
+		ntfs_log_perror("%s: Attribute lookup failed 1", __FUNCTION__);
+		goto put_err_out;
+	}
+	
+	/* 
+	 * The standard information and attribute list attributes can't be
+	 * moved out from the base MFT record, so try to move out others. 
+	 */
+	if (na->type==AT_STANDARD_INFORMATION || na->type==AT_ATTRIBUTE_LIST) {
+		ntfs_attr_put_search_ctx(ctx);
+		if (ntfs_inode_free_space(na->ni, offsetof(ATTR_RECORD,
+				non_resident_end) + 8)) {
+			ntfs_log_perror("Could not free space in MFT record");
+			return -1;
+		}
+		return ntfs_resident_attr_resize_i(na, newsize, holes);
+	}
+
+	/*
+	 * Move the attribute to a new mft record, creating an attribute list
+	 * attribute or modifying it if it is already present.
+	 */
+
+	/* Point search context back to attribute which we need resize. */
+	ntfs_attr_init_search_ctx(ctx, na->ni, NULL);
+	if (ntfs_attr_lookup(na->type, na->name, na->name_len, CASE_SENSITIVE,
+			0, NULL, 0, ctx)) {
+		ntfs_log_perror("%s: Attribute lookup failed 2", __FUNCTION__);
+		err = errno;
+		goto put_err_out;
+	}
+
+	/*
+	 * Check whether attribute is already single in this MFT record.
+	 * 8 added for the attribute terminator.
+	 */
+	if (le32_to_cpu(ctx->mrec->bytes_in_use) ==
+			le16_to_cpu(ctx->mrec->attrs_offset) +
+			le32_to_cpu(ctx->attr->length) + 8) {
+		err = ENOSPC;
+		ntfs_log_trace("MFT record is filled with one attribute\n");
+		ret = STATUS_RESIDENT_ATTRIBUTE_FILLED_MFT;
+		goto put_err_out;
+	}
+
+	/* Add attribute list if not present. */
+	if (na->ni->nr_extents == -1)
+		ni = na->ni->base_ni;
+	else
+		ni = na->ni;
+	if (!NInoAttrList(ni)) {
+		ntfs_attr_put_search_ctx(ctx);
+		if (ntfs_inode_add_attrlist(ni))
+			return -1;
+		return ntfs_resident_attr_resize_i(na, newsize, holes);
+	}
+	/* Allocate new mft record. */
+	ni = ntfs_mft_record_alloc(vol, ni);
+	if (!ni) {
+		err = errno;
+		ntfs_log_perror("Couldn't allocate new MFT record");
+		goto put_err_out;
+	}
+	/* Move attribute to it. */
+	if (ntfs_attr_record_move_to(ctx, ni)) {
+		err = errno;
+		ntfs_log_perror("Couldn't move attribute to new MFT record");
+		goto put_err_out;
+	}
+	/* Update ntfs attribute. */
+	if (na->ni->nr_extents == -1)
+		na->ni = ni;
+
+	ntfs_attr_put_search_ctx(ctx);
+	/* Try to perform resize once again. */
+	return ntfs_resident_attr_resize_i(na, newsize, holes);
+
+resize_done:
+	/*
+	 * Set the inode (and its base inode if it exists) dirty so it is
+	 * written out later.
+	 */
+	ntfs_inode_mark_dirty(ctx->ntfs_ino);
+	ntfs_attr_put_search_ctx(ctx);
+	return 0;
+put_err_out:
+	ntfs_attr_put_search_ctx(ctx);
+	errno = err;
+	return ret;
+}
+
+static int ntfs_resident_attr_resize(ntfs_attr *na, const s64 newsize)
+{
+	int ret; 
+	
+	ntfs_log_enter("Entering\n");
+	ret = ntfs_resident_attr_resize_i(na, newsize, HOLES_OK);
+	ntfs_log_leave("\n");
+	return ret;
+}
+
+/*
+ *		Force an attribute to be made non-resident without
+ *	changing its size.
+ *
+ *	This is particularly needed when the attribute has no data,
+ *	as the non-resident variant requires more space in the MFT
+ *	record, and may imply expelling some other attribute.
+ *
+ *	As a consequence the existing ntfs_attr_search_ctx's have to
+ *	be closed or reinitialized.
+ *
+ *	returns 0 if successful,
+ *		< 0 if failed, with errno telling why
+ */
+
+int ntfs_attr_force_non_resident(ntfs_attr *na)
+{
+	int res;
+
+	res = ntfs_resident_attr_resize_i(na, na->data_size, HOLES_NONRES);
+	if (!res && !NAttrNonResident(na)) {
+		res = -1;
+		errno = EIO;
+		ntfs_log_error("Failed to force non-resident\n");
+	}
+	return (res);
+}
+
+/**
+ * ntfs_attr_make_resident - convert a non-resident to a resident attribute
+ * @na:		open ntfs attribute to make resident
+ * @ctx:	ntfs search context describing the attribute
+ *
+ * Convert a non-resident ntfs attribute to a resident one.
+ *
+ * Return 0 on success and -1 on error with errno set to the error code. The
+ * following error codes are defined:
+ *	EINVAL	   - Invalid arguments passed.
+ *	EPERM	   - The attribute is not allowed to be resident.
+ *	EIO	   - I/O error, damaged inode or bug.
+ *	ENOSPC	   - There is no enough space to perform conversion.
+ *	EOPNOTSUPP - Requested conversion is not supported yet.
+ *
+ * Warning: We do not set the inode dirty and we do not write out anything!
+ *	    We expect the caller to do this as this is a fairly low level
+ *	    function and it is likely there will be further changes made.
+ */
+static int ntfs_attr_make_resident(ntfs_attr *na, ntfs_attr_search_ctx *ctx)
+{
+	ntfs_volume *vol = na->ni->vol;
+	ATTR_REC *a = ctx->attr;
+	int name_ofs, val_ofs, err = EIO;
+	s64 arec_size, bytes_read;
+
+	ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", (unsigned long
+			long)na->ni->mft_no, na->type);
+
+	/* Should be called for the first extent of the attribute. */
+	if (sle64_to_cpu(a->lowest_vcn)) {
+		ntfs_log_trace("Eeek!  Should be called for the first extent of the "
+				"attribute.  Aborting...\n");
+		errno = EINVAL;
+		return -1;
+	}
+
+	/* Some preliminary sanity checking. */
+	if (!NAttrNonResident(na)) {
+		ntfs_log_trace("Eeek!  Trying to make resident attribute resident.  "
+				"Aborting...\n");
+		errno = EINVAL;
+		return -1;
+	}
+
+	/* Make sure this is not $MFT/$BITMAP or Windows will not boot! */
+	if (na->type == AT_BITMAP && na->ni->mft_no == FILE_MFT) {
+		errno = EPERM;
+		return -1;
+	}
+
+	/* Check that the attribute is allowed to be resident. */
+	if (ntfs_attr_can_be_resident(vol, na->type))
+		return -1;
+
+	if (na->data_flags & ATTR_IS_ENCRYPTED) {
+		ntfs_log_trace("Making encrypted streams resident is not "
+				"implemented yet.\n");
+		errno = EOPNOTSUPP;
+		return -1;
+	}
+
+	/* Work out offsets into and size of the resident attribute. */
+	name_ofs = 24; /* = sizeof(resident_ATTR_REC); */
+	val_ofs = (name_ofs + a->name_length * sizeof(ntfschar) + 7) & ~7;
+	arec_size = (val_ofs + na->data_size + 7) & ~7;
+
+	/* Sanity check the size before we start modifying the attribute. */
+	if (le32_to_cpu(ctx->mrec->bytes_in_use) - le32_to_cpu(a->length) +
+			arec_size > le32_to_cpu(ctx->mrec->bytes_allocated)) {
+		errno = ENOSPC;
+		ntfs_log_trace("Not enough space to make attribute resident\n");
+		return -1;
+	}
+
+	/* Read and cache the whole runlist if not already done. */
+	if (ntfs_attr_map_whole_runlist(na))
+		return -1;
+
+	/* Move the attribute name if it exists and update the offset. */
+	if (a->name_length) {
+		memmove((u8*)a + name_ofs, (u8*)a + le16_to_cpu(a->name_offset),
+				a->name_length * sizeof(ntfschar));
+	}
+	a->name_offset = cpu_to_le16(name_ofs);
+
+	/* Resize the resident part of the attribute record. */
+	if (ntfs_attr_record_resize(ctx->mrec, a, arec_size) < 0) {
+		/*
+		 * Bug, because ntfs_attr_record_resize should not fail (we
+		 * already checked that attribute fits MFT record).
+		 */
+		ntfs_log_error("BUG! Failed to resize attribute record. "
+				"Please report to the %s.  Aborting...\n",
+				NTFS_DEV_LIST);
+		errno = EIO;
+		return -1;
+	}
+
+	/* Convert the attribute record to describe a resident attribute. */
+	a->non_resident = 0;
+	a->flags = 0;
+	a->value_length = cpu_to_le32(na->data_size);
+	a->value_offset = cpu_to_le16(val_ofs);
+	/*
+	 *  If a data stream was wiped out, adjust the compression mode
+	 *  to current state of compression flag
+	 */
+	if (!na->data_size
+	    && (na->type == AT_DATA)
+	    && (na->ni->vol->major_ver >= 3)
+	    && NVolCompression(na->ni->vol)
+	    && (na->ni->vol->cluster_size <= MAX_COMPRESSION_CLUSTER_SIZE)
+	    && (na->ni->flags & FILE_ATTR_COMPRESSED)) {
+		a->flags |= ATTR_IS_COMPRESSED;
+		na->data_flags = a->flags;
+	}
+	/*
+	 * File names cannot be non-resident so we would never see this here
+	 * but at least it serves as a reminder that there may be attributes
+	 * for which we do need to set this flag. (AIA)
+	 */
+	if (a->type == AT_FILE_NAME)
+		a->resident_flags = RESIDENT_ATTR_IS_INDEXED;
+	else
+		a->resident_flags = 0;
+	a->reservedR = 0;
+
+	/* Sanity fixup...  Shouldn't really happen. (AIA) */
+	if (na->initialized_size > na->data_size)
+		na->initialized_size = na->data_size;
+
+	/* Copy data from run list to resident attribute value. */
+	bytes_read = ntfs_rl_pread(vol, na->rl, 0, na->initialized_size,
+			(u8*)a + val_ofs);
+	if (bytes_read != na->initialized_size) {
+		if (bytes_read < 0)
+			err = errno;
+		ntfs_log_trace("Eeek! Failed to read attribute data. Leaving "
+				"inconstant metadata. Run chkdsk.  "
+				"Aborting...\n");
+		errno = err;
+		return -1;
+	}
+
+	/* Clear memory in gap between initialized_size and data_size. */
+	if (na->initialized_size < na->data_size)
+		memset((u8*)a + val_ofs + na->initialized_size, 0,
+				na->data_size - na->initialized_size);
+
+	/*
+	 * Deallocate clusters from the runlist.
+	 *
+	 * NOTE: We can use ntfs_cluster_free() because we have already mapped
+	 * the whole run list and thus it doesn't matter that the attribute
+	 * record is in a transiently corrupted state at this moment in time.
+	 */
+	if (ntfs_cluster_free(vol, na, 0, -1) < 0) {
+		ntfs_log_perror("Eeek! Failed to release allocated clusters");
+		ntfs_log_trace("Ignoring error and leaving behind wasted "
+				"clusters.\n");
+	}
+
+	/* Throw away the now unused runlist. */
+	free(na->rl);
+	na->rl = NULL;
+
+	/* Update in-memory struct ntfs_attr. */
+	NAttrClearNonResident(na);
+	NAttrClearFullyMapped(na);
+	NAttrClearSparse(na);
+	NAttrClearEncrypted(na);
+	na->initialized_size = na->data_size;
+	na->allocated_size = na->compressed_size = (na->data_size + 7) & ~7;
+	na->compression_block_size = 0;
+	na->compression_block_size_bits = na->compression_block_clusters = 0;
+	return 0;
+}
+
+/*
+ * If we are in the first extent, then set/clean sparse bit,
+ * update allocated and compressed size.
+ */
+static int ntfs_attr_update_meta(ATTR_RECORD *a, ntfs_attr *na, MFT_RECORD *m,
+				hole_type holes, ntfs_attr_search_ctx *ctx)
+{
+	int sparse, ret = 0;
+	
+	ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x\n", 
+		       (unsigned long long)na->ni->mft_no, na->type);
+	
+	if (a->lowest_vcn)
+		goto out;
+
+	a->allocated_size = cpu_to_sle64(na->allocated_size);
+
+	/* Update sparse bit, unless this is an intermediate state */
+	if (holes == HOLES_DELAY)
+		sparse = (a->flags & ATTR_IS_SPARSE) != const_cpu_to_le16(0);
+	else {
+		sparse = ntfs_rl_sparse(na->rl);
+		if (sparse == -1) {
+			errno = EIO;
+			goto error;
+		}
+	}
+
+	/* Check whether attribute becomes sparse, unless check is delayed. */
+	if ((holes != HOLES_DELAY)
+	    && sparse
+	    && !(a->flags & (ATTR_IS_SPARSE | ATTR_IS_COMPRESSED))) {
+		/*
+		 * Move attribute to another mft record, if attribute is too 
+		 * small to add compressed_size field to it and we have no 
+		 * free space in the current mft record.
+		 */
+		if ((le32_to_cpu(a->length) - 
+				le16_to_cpu(a->mapping_pairs_offset) == 8)
+		    && !(le32_to_cpu(m->bytes_allocated) - 
+				le32_to_cpu(m->bytes_in_use))) {
+
+			if (!NInoAttrList(na->ni)) {
+				ntfs_attr_put_search_ctx(ctx);
+				if (ntfs_inode_add_attrlist(na->ni))
+					goto leave;
+				goto retry;
+			}
+			if (ntfs_attr_record_move_away(ctx, 8)) {
+				ntfs_log_perror("Failed to move attribute");
+				goto error;
+			}
+			ntfs_attr_put_search_ctx(ctx);
+			goto retry;
+		}
+		if (!(le32_to_cpu(a->length) - le16_to_cpu(
+						a->mapping_pairs_offset))) {
+			errno = EIO;
+			ntfs_log_perror("Mapping pairs space is 0");
+			goto error;
+		}
+		
+		NAttrSetSparse(na);
+		a->flags |= ATTR_IS_SPARSE;
+		na->data_flags = a->flags;
+		a->compression_unit = STANDARD_COMPRESSION_UNIT;  /* Windows
+		 set it so, even if attribute is not actually compressed. */
+		
+		memmove((u8*)a + le16_to_cpu(a->name_offset) + 8,
+			(u8*)a + le16_to_cpu(a->name_offset),
+			a->name_length * sizeof(ntfschar));
+
+		a->name_offset = cpu_to_le16(le16_to_cpu(a->name_offset) + 8);
+		
+		a->mapping_pairs_offset =
+			cpu_to_le16(le16_to_cpu(a->mapping_pairs_offset) + 8);
+	}
+
+	/* Attribute no longer sparse. */
+	if (!sparse && (a->flags & ATTR_IS_SPARSE) && 
+	    !(a->flags & ATTR_IS_COMPRESSED)) {
+		
+		NAttrClearSparse(na);
+		a->flags &= ~ATTR_IS_SPARSE;
+		na->data_flags = a->flags;
+		a->compression_unit = 0;
+		
+		memmove((u8*)a + le16_to_cpu(a->name_offset) - 8, 
+			(u8*)a + le16_to_cpu(a->name_offset),
+			a->name_length * sizeof(ntfschar));
+		
+		if (le16_to_cpu(a->name_offset) >= 8)
+			a->name_offset = cpu_to_le16(le16_to_cpu(a->name_offset) - 8);
+
+		a->mapping_pairs_offset = 
+			cpu_to_le16(le16_to_cpu(a->mapping_pairs_offset) - 8);
+	}
+
+	/* Update compressed size if required. */
+	if (NAttrFullyMapped(na)
+	    && (sparse || (na->data_flags & ATTR_COMPRESSION_MASK))) {
+		s64 new_compr_size;
+
+		new_compr_size = ntfs_rl_get_compressed_size(na->ni->vol, na->rl);
+		if (new_compr_size == -1)
+			goto error;
+		
+		na->compressed_size = new_compr_size;
+		a->compressed_size = cpu_to_sle64(new_compr_size);
+	}
+	/*
+	 * Set FILE_NAME dirty flag, to update sparse bit and
+	 * allocated size in the index.
+	 */
+	if (na->type == AT_DATA && na->name == AT_UNNAMED) {
+		if (sparse || (na->data_flags & ATTR_COMPRESSION_MASK))
+			na->ni->allocated_size = na->compressed_size;
+		else
+			na->ni->allocated_size = na->allocated_size;
+		NInoFileNameSetDirty(na->ni);
+	}
+out:
+	return ret;
+leave:	ret = -1; goto out;  /* return -1 */
+retry:	ret = -2; goto out;
+error:  ret = -3; goto out;
+}
+
+#define NTFS_VCN_DELETE_MARK -2
+/**
+ * ntfs_attr_update_mapping_pairs_i - see ntfs_attr_update_mapping_pairs
+ */
+static int ntfs_attr_update_mapping_pairs_i(ntfs_attr *na, VCN from_vcn,
+					hole_type holes)
+{
+	ntfs_attr_search_ctx *ctx;
+	ntfs_inode *ni, *base_ni;
+	MFT_RECORD *m;
+	ATTR_RECORD *a;
+	VCN stop_vcn;
+	const runlist_element *stop_rl;
+	int err, mp_size, cur_max_mp_size, exp_max_mp_size, ret = -1;
+	BOOL finished_build;
+	BOOL first_updated = FALSE;
+
+retry:
+	if (!na || !na->rl) {
+		errno = EINVAL;
+		ntfs_log_perror("%s: na=%p", __FUNCTION__, na);
+		return -1;
+	}
+
+	ntfs_log_trace("Entering for inode %llu, attr 0x%x\n", 
+		       (unsigned long long)na->ni->mft_no, na->type);
+
+	if (!NAttrNonResident(na)) {
+		errno = EINVAL;
+		ntfs_log_perror("%s: resident attribute", __FUNCTION__);
+		return -1;
+	}
+
+#if PARTIAL_RUNLIST_UPDATING
+		/*
+		 * For a file just been made sparse, we will have
+		 * to reformat the first extent, so be sure the
+		 * runlist is fully mapped and fully processed.
+		 * Same if the file was sparse and is not any more.
+		 * Note : not needed if the full runlist is to be processed
+		 */
+	if ((holes != HOLES_DELAY)
+	   && (!NAttrFullyMapped(na) || from_vcn)
+	   && !(na->data_flags & ATTR_IS_COMPRESSED)) {
+		BOOL changed;
+
+		if (!(na->data_flags & ATTR_IS_SPARSE)) {
+			int sparse = 0;
+			runlist_element *xrl;
+
+				/*
+				 * If attribute was not sparse, we only
+				 * have to check whether there is a hole
+				 * in the updated region.
+				 */
+			for (xrl = na->rl; xrl->length; xrl++) {
+				if (xrl->lcn < 0) {
+					if (xrl->lcn == LCN_HOLE) {
+						sparse = 1;
+						break;
+					}
+					if (xrl->lcn != LCN_RL_NOT_MAPPED) {
+						sparse = -1;
+						break;
+					}
+				}
+			}
+			if (sparse < 0) {
+				ntfs_log_error("Could not check whether sparse\n");
+				errno = EIO;
+				return (-1);
+			}
+			changed = sparse > 0;
+		} else {
+				/*
+				 * If attribute was sparse, the compressed
+				 * size has been maintained, and it gives
+				 * and easy way to check whether the
+				 * attribute is still sparse.
+				 */
+			changed = (((na->data_size - 1)
+					| (na->ni->vol->cluster_size - 1)) + 1)
+				== na->compressed_size;
+		}
+		if (changed) {
+			if (ntfs_attr_map_whole_runlist(na)) {
+				ntfs_log_error("Could not map whole for sparse change\n");
+				errno = EIO;
+				return (-1);
+			}
+			from_vcn = 0;
+		}
+	}
+#endif
+	if (na->ni->nr_extents == -1)
+		base_ni = na->ni->base_ni;
+	else
+		base_ni = na->ni;
+
+	ctx = ntfs_attr_get_search_ctx(base_ni, NULL);
+	if (!ctx)
+		return -1;
+
+	/* Fill attribute records with new mapping pairs. */
+	stop_vcn = 0;
+	stop_rl = na->rl;
+	finished_build = FALSE;
+	while (!ntfs_attr_lookup(na->type, na->name, na->name_len,
+				CASE_SENSITIVE, from_vcn, NULL, 0, ctx)) {
+		a = ctx->attr;
+		m = ctx->mrec;
+		if (!a->lowest_vcn)
+			first_updated = TRUE;
+		/*
+		 * If runlist is updating not from the beginning, then set
+		 * @stop_vcn properly, i.e. to the lowest vcn of record that
+		 * contain @from_vcn. Also we do not need @from_vcn anymore,
+		 * set it to 0 to make ntfs_attr_lookup enumerate attributes.
+		 */
+		if (from_vcn) {
+			LCN first_lcn;
+
+			stop_vcn = sle64_to_cpu(a->lowest_vcn);
+			from_vcn = 0;
+			/*
+			 * Check whether the first run we need to update is
+			 * the last run in runlist, if so, then deallocate
+			 * all attrubute extents starting this one.
+			 */
+			first_lcn = ntfs_rl_vcn_to_lcn(na->rl, stop_vcn);
+			if (first_lcn == LCN_EINVAL) {
+				errno = EIO;
+				ntfs_log_perror("Bad runlist");
+				goto put_err_out;
+			}
+			if (first_lcn == LCN_ENOENT ||
+					first_lcn == LCN_RL_NOT_MAPPED)
+				finished_build = TRUE;
+		}
+
+		/*
+		 * Check whether we finished mapping pairs build, if so mark
+		 * extent as need to delete (by setting highest vcn to
+		 * NTFS_VCN_DELETE_MARK (-2), we shall check it later and
+		 * delete extent) and continue search.
+		 */
+		if (finished_build) {
+			ntfs_log_trace("Mark attr 0x%x for delete in inode "
+				"%lld.\n", (unsigned)le32_to_cpu(a->type),
+				(long long)ctx->ntfs_ino->mft_no);
+			a->highest_vcn = cpu_to_sle64(NTFS_VCN_DELETE_MARK);
+			ntfs_inode_mark_dirty(ctx->ntfs_ino);
+			continue;
+		}
+
+		switch (ntfs_attr_update_meta(a, na, m, holes, ctx)) {
+			case -1: return -1;
+			case -2: goto retry;
+			case -3: goto put_err_out;
+		}
+
+		/*
+		 * Determine maximum possible length of mapping pairs,
+		 * if we shall *not* expand space for mapping pairs.
+		 */
+		cur_max_mp_size = le32_to_cpu(a->length) -
+				le16_to_cpu(a->mapping_pairs_offset);
+		/*
+		 * Determine maximum possible length of mapping pairs in the
+		 * current mft record, if we shall expand space for mapping
+		 * pairs.
+		 */
+		exp_max_mp_size = le32_to_cpu(m->bytes_allocated) -
+				le32_to_cpu(m->bytes_in_use) + cur_max_mp_size;
+		/* Get the size for the rest of mapping pairs array. */
+		mp_size = ntfs_get_size_for_mapping_pairs(na->ni->vol, stop_rl,
+						stop_vcn, exp_max_mp_size);
+		if (mp_size <= 0) {
+			ntfs_log_perror("%s: get MP size failed", __FUNCTION__);
+			goto put_err_out;
+		}
+		/* Test mapping pairs for fitting in the current mft record. */
+		if (mp_size > exp_max_mp_size) {
+			/*
+			 * Mapping pairs of $ATTRIBUTE_LIST attribute must fit
+			 * in the base mft record. Try to move out other
+			 * attributes and try again.
+			 */
+			if (na->type == AT_ATTRIBUTE_LIST) {
+				ntfs_attr_put_search_ctx(ctx);
+				if (ntfs_inode_free_space(na->ni, mp_size -
+							cur_max_mp_size)) {
+					ntfs_log_perror("Attribute list is too "
+							"big. Defragment the "
+							"volume\n");
+					return -1;
+				}
+				goto retry;
+			}
+
+			/* Add attribute list if it isn't present, and retry. */
+			if (!NInoAttrList(base_ni)) {
+				ntfs_attr_put_search_ctx(ctx);
+				if (ntfs_inode_add_attrlist(base_ni)) {
+					ntfs_log_perror("Can not add attrlist");
+					return -1;
+				}
+				goto retry;
+			}
+
+			/*
+			 * Set mapping pairs size to maximum possible for this
+			 * mft record. We shall write the rest of mapping pairs
+			 * to another MFT records.
+			 */
+			mp_size = exp_max_mp_size;
+		}
+
+		/* Change space for mapping pairs if we need it. */
+		if (((mp_size + 7) & ~7) != cur_max_mp_size) {
+			if (ntfs_attr_record_resize(m, a,
+					le16_to_cpu(a->mapping_pairs_offset) +
+					mp_size)) {
+				errno = EIO;
+				ntfs_log_perror("Failed to resize attribute");
+				goto put_err_out;
+			}
+		}
+
+		/* Update lowest vcn. */
+		a->lowest_vcn = cpu_to_sle64(stop_vcn);
+		ntfs_inode_mark_dirty(ctx->ntfs_ino);
+		if ((ctx->ntfs_ino->nr_extents == -1 ||
+					NInoAttrList(ctx->ntfs_ino)) &&
+					ctx->attr->type != AT_ATTRIBUTE_LIST) {
+			ctx->al_entry->lowest_vcn = cpu_to_sle64(stop_vcn);
+			ntfs_attrlist_mark_dirty(ctx->ntfs_ino);
+		}
+
+		/*
+		 * Generate the new mapping pairs array directly into the
+		 * correct destination, i.e. the attribute record itself.
+		 */
+		if (!ntfs_mapping_pairs_build(na->ni->vol, (u8*)a + le16_to_cpu(
+				a->mapping_pairs_offset), mp_size, na->rl,
+				stop_vcn, &stop_rl))
+			finished_build = TRUE;
+		if (stop_rl)
+			stop_vcn = stop_rl->vcn;
+		else
+			stop_vcn = 0;
+		if (!finished_build && errno != ENOSPC) {
+			ntfs_log_perror("Failed to build mapping pairs");
+			goto put_err_out;
+		}
+		a->highest_vcn = cpu_to_sle64(stop_vcn - 1);
+	}
+	/* Check whether error occurred. */
+	if (errno != ENOENT) {
+		ntfs_log_perror("%s: Attribute lookup failed", __FUNCTION__);
+		goto put_err_out;
+	}
+		/*
+		 * If the base extent was skipped in the above process,
+		 * we still may have to update the sizes.
+		 */
+	if (!first_updated) {
+		le16 spcomp;
+
+		ntfs_attr_reinit_search_ctx(ctx);
+		if (!ntfs_attr_lookup(na->type, na->name, na->name_len,
+				CASE_SENSITIVE, 0, NULL, 0, ctx)) {
+			a = ctx->attr;
+			a->allocated_size = cpu_to_sle64(na->allocated_size);
+			spcomp = na->data_flags
+				& (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE);
+			if (spcomp)
+				a->compressed_size = cpu_to_sle64(na->compressed_size);
+			if ((na->type == AT_DATA) && (na->name == AT_UNNAMED)) {
+				na->ni->allocated_size
+					= (spcomp
+						? na->compressed_size
+						: na->allocated_size);
+				NInoFileNameSetDirty(na->ni);
+			}
+		} else {
+			ntfs_log_error("Failed to update sizes in base extent\n");
+			goto put_err_out;
+		}
+	}
+
+	/* Deallocate not used attribute extents and return with success. */
+	if (finished_build) {
+		ntfs_attr_reinit_search_ctx(ctx);
+		ntfs_log_trace("Deallocate marked extents.\n");
+		while (!ntfs_attr_lookup(na->type, na->name, na->name_len,
+				CASE_SENSITIVE, 0, NULL, 0, ctx)) {
+			if (sle64_to_cpu(ctx->attr->highest_vcn) !=
+							NTFS_VCN_DELETE_MARK)
+				continue;
+			/* Remove unused attribute record. */
+			if (ntfs_attr_record_rm(ctx)) {
+				ntfs_log_perror("Could not remove unused attr");
+				goto put_err_out;
+			}
+			ntfs_attr_reinit_search_ctx(ctx);
+		}
+		if (errno != ENOENT) {
+			ntfs_log_perror("%s: Attr lookup failed", __FUNCTION__);
+			goto put_err_out;
+		}
+		ntfs_log_trace("Deallocate done.\n");
+		ntfs_attr_put_search_ctx(ctx);
+		goto ok;
+	}
+	ntfs_attr_put_search_ctx(ctx);
+	ctx = NULL;
+
+	/* Allocate new MFT records for the rest of mapping pairs. */
+	while (1) {
+		/* Calculate size of rest mapping pairs. */
+		mp_size = ntfs_get_size_for_mapping_pairs(na->ni->vol,
+						na->rl, stop_vcn, INT_MAX);
+		if (mp_size <= 0) {
+			ntfs_log_perror("%s: get mp size failed", __FUNCTION__);
+			goto put_err_out;
+		}
+		/* Allocate new mft record, with special case for mft itself */
+		if (!na->ni->mft_no)
+			ni = ntfs_mft_rec_alloc(na->ni->vol,
+				na->type == AT_DATA);
+		else
+			ni = ntfs_mft_record_alloc(na->ni->vol, base_ni);
+		if (!ni) {
+			ntfs_log_perror("Could not allocate new MFT record");
+			goto put_err_out;
+		}
+		m = ni->mrec;
+		/*
+		 * If mapping size exceed available space, set them to
+		 * possible maximum.
+		 */
+		cur_max_mp_size = le32_to_cpu(m->bytes_allocated) -
+				le32_to_cpu(m->bytes_in_use) -
+				(offsetof(ATTR_RECORD, compressed_size) +
+				(((na->data_flags & ATTR_COMPRESSION_MASK)
+				    || NAttrSparse(na)) ?
+				sizeof(a->compressed_size) : 0)) -
+				((sizeof(ntfschar) * na->name_len + 7) & ~7);
+		if (mp_size > cur_max_mp_size)
+			mp_size = cur_max_mp_size;
+		/* Add attribute extent to new record. */
+		err = ntfs_non_resident_attr_record_add(ni, na->type,
+			na->name, na->name_len, stop_vcn, mp_size,
+			na->data_flags);
+		if (err == -1) {
+			err = errno;
+			ntfs_log_perror("Could not add attribute extent");
+			if (ntfs_mft_record_free(na->ni->vol, ni))
+				ntfs_log_perror("Could not free MFT record");
+			errno = err;
+			goto put_err_out;
+		}
+		a = (ATTR_RECORD*)((u8*)m + err);
+
+		err = ntfs_mapping_pairs_build(na->ni->vol, (u8*)a +
+			le16_to_cpu(a->mapping_pairs_offset), mp_size, na->rl,
+			stop_vcn, &stop_rl);
+		if (stop_rl)
+			stop_vcn = stop_rl->vcn;
+		else
+			stop_vcn = 0;
+		if (err < 0 && errno != ENOSPC) {
+			err = errno;
+			ntfs_log_perror("Failed to build MP");
+			if (ntfs_mft_record_free(na->ni->vol, ni))
+				ntfs_log_perror("Couldn't free MFT record");
+			errno = err;
+			goto put_err_out;
+		}
+		a->highest_vcn = cpu_to_sle64(stop_vcn - 1);
+		ntfs_inode_mark_dirty(ni);
+		/* All mapping pairs has been written. */
+		if (!err)
+			break;
+	}
+ok:
+	NAttrClearRunlistDirty(na);
+	ret = 0;
+out:
+	return ret;
+put_err_out:
+	if (ctx)
+		ntfs_attr_put_search_ctx(ctx);
+	goto out;
+}
+#undef NTFS_VCN_DELETE_MARK
+
+/**
+ * ntfs_attr_update_mapping_pairs - update mapping pairs for ntfs attribute
+ * @na:		non-resident ntfs open attribute for which we need update
+ * @from_vcn:	update runlist starting this VCN
+ *
+ * Build mapping pairs from @na->rl and write them to the disk. Also, this
+ * function updates sparse bit, allocated and compressed size (allocates/frees
+ * space for this field if required).
+ *
+ * @na->allocated_size should be set to correct value for the new runlist before
+ * call to this function. Vice-versa @na->compressed_size will be calculated and
+ * set to correct value during this function.
+ *
+ * FIXME: This function does not update sparse bit and compressed size correctly
+ * if called with @from_vcn != 0.
+ *
+ * FIXME: Rewrite without using NTFS_VCN_DELETE_MARK define.
+ *
+ * On success return 0 and on error return -1 with errno set to the error code.
+ * The following error codes are defined:
+ *	EINVAL - Invalid arguments passed.
+ *	ENOMEM - Not enough memory to complete operation.
+ *	ENOSPC - There is no enough space in base mft to resize $ATTRIBUTE_LIST
+ *		 or there is no free MFT records left to allocate.
+ */
+int ntfs_attr_update_mapping_pairs(ntfs_attr *na, VCN from_vcn)
+{
+	int ret; 
+	
+	ntfs_log_enter("Entering\n");
+	ret = ntfs_attr_update_mapping_pairs_i(na, from_vcn, HOLES_OK);
+	ntfs_log_leave("\n");
+	return ret;
+}
+
+/**
+ * ntfs_non_resident_attr_shrink - shrink a non-resident, open ntfs attribute
+ * @na:		non-resident ntfs attribute to shrink
+ * @newsize:	new size (in bytes) to which to shrink the attribute
+ *
+ * Reduce the size of a non-resident, open ntfs attribute @na to @newsize bytes.
+ *
+ * On success return 0 and on error return -1 with errno set to the error code.
+ * The following error codes are defined:
+ *	ENOMEM	- Not enough memory to complete operation.
+ *	ERANGE	- @newsize is not valid for the attribute type of @na.
+ */
+static int ntfs_non_resident_attr_shrink(ntfs_attr *na, const s64 newsize)
+{
+	ntfs_volume *vol;
+	ntfs_attr_search_ctx *ctx;
+	VCN first_free_vcn;
+	s64 nr_freed_clusters;
+	int err;
+
+	ntfs_log_trace("Inode 0x%llx attr 0x%x new size %lld\n", (unsigned long long)
+		       na->ni->mft_no, na->type, (long long)newsize);
+
+	vol = na->ni->vol;
+
+	/*
+	 * Check the attribute type and the corresponding minimum size
+	 * against @newsize and fail if @newsize is too small.
+	 */
+	if (ntfs_attr_size_bounds_check(vol, na->type, newsize) < 0) {
+		if (errno == ERANGE) {
+			ntfs_log_trace("Eeek! Size bounds check failed. "
+					"Aborting...\n");
+		} else if (errno == ENOENT)
+			errno = EIO;
+		return -1;
+	}
+
+	/* The first cluster outside the new allocation. */
+	if (na->data_flags & ATTR_COMPRESSION_MASK)
+		/*
+		 * For compressed files we must keep full compressions blocks,
+		 * but currently we do not decompress/recompress the last
+		 * block to truncate the data, so we may leave more allocated
+		 * clusters than really needed.
+		 */
+		first_free_vcn = (((newsize - 1)
+				 | (na->compression_block_size - 1)) + 1)
+				   >> vol->cluster_size_bits;
+	else
+		first_free_vcn = (newsize + vol->cluster_size - 1) >>
+				vol->cluster_size_bits;
+	/*
+	 * Compare the new allocation with the old one and only deallocate
+	 * clusters if there is a change.
+	 */
+	if ((na->allocated_size >> vol->cluster_size_bits) != first_free_vcn) {
+		if (ntfs_attr_map_whole_runlist(na)) {
+			ntfs_log_trace("Eeek! ntfs_attr_map_whole_runlist "
+					"failed.\n");
+			return -1;
+		}
+		/* Deallocate all clusters starting with the first free one. */
+		nr_freed_clusters = ntfs_cluster_free(vol, na, first_free_vcn,
+				-1);
+		if (nr_freed_clusters < 0) {
+			ntfs_log_trace("Eeek! Freeing of clusters failed. "
+					"Aborting...\n");
+			return -1;
+		}
+
+		/* Truncate the runlist itself. */
+		if (ntfs_rl_truncate(&na->rl, first_free_vcn)) {
+			/*
+			 * Failed to truncate the runlist, so just throw it
+			 * away, it will be mapped afresh on next use.
+			 */
+			free(na->rl);
+			na->rl = NULL;
+			ntfs_log_trace("Eeek! Run list truncation failed.\n");
+			return -1;
+		}
+		NAttrSetRunlistDirty(na);
+
+		/* Prepare to mapping pairs update. */
+		na->allocated_size = first_free_vcn << vol->cluster_size_bits;
+		/* Write mapping pairs for new runlist. */
+		if (ntfs_attr_update_mapping_pairs(na, 0 /*first_free_vcn*/)) {
+			ntfs_log_trace("Eeek! Mapping pairs update failed. "
+					"Leaving inconstant metadata. "
+					"Run chkdsk.\n");
+			return -1;
+		}
+	}
+
+	/* Get the first attribute record. */
+	ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
+	if (!ctx)
+		return -1;
+
+	if (ntfs_attr_lookup(na->type, na->name, na->name_len, CASE_SENSITIVE,
+			0, NULL, 0, ctx)) {
+		err = errno;
+		if (err == ENOENT)
+			err = EIO;
+		ntfs_log_trace("Eeek! Lookup of first attribute extent failed. "
+				"Leaving inconstant metadata.\n");
+		goto put_err_out;
+	}
+
+	/* Update data and initialized size. */
+	na->data_size = newsize;
+	ctx->attr->data_size = cpu_to_sle64(newsize);
+	if (newsize < na->initialized_size) {
+		na->initialized_size = newsize;
+		ctx->attr->initialized_size = cpu_to_sle64(newsize);
+	}
+	/* Update data size in the index. */
+	if (na->ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
+		if (na->type == AT_INDEX_ROOT && na->name == NTFS_INDEX_I30) {
+			na->ni->data_size = na->data_size;
+			na->ni->allocated_size = na->allocated_size;
+			set_nino_flag(na->ni,KnownSize);
+		}
+	} else {
+		if (na->type == AT_DATA && na->name == AT_UNNAMED) {
+			na->ni->data_size = na->data_size;
+			NInoFileNameSetDirty(na->ni);
+		}
+	}
+
+	/* If the attribute now has zero size, make it resident. */
+	if (!newsize) {
+		if (!(na->data_flags & ATTR_IS_ENCRYPTED)
+		    && ntfs_attr_make_resident(na, ctx)) {
+			/* If couldn't make resident, just continue. */
+			if (errno != EPERM)
+				ntfs_log_error("Failed to make attribute "
+						"resident. Leaving as is...\n");
+		}
+	}
+
+	/* Set the inode dirty so it is written out later. */
+	ntfs_inode_mark_dirty(ctx->ntfs_ino);
+	/* Done! */
+	ntfs_attr_put_search_ctx(ctx);
+	return 0;
+put_err_out:
+	ntfs_attr_put_search_ctx(ctx);
+	errno = err;
+	return -1;
+}
+
+/**
+ * ntfs_non_resident_attr_expand - expand a non-resident, open ntfs attribute
+ * @na:		non-resident ntfs attribute to expand
+ * @newsize:	new size (in bytes) to which to expand the attribute
+ *
+ * Expand the size of a non-resident, open ntfs attribute @na to @newsize bytes,
+ * by allocating new clusters.
+ *
+ * On success return 0 and on error return -1 with errno set to the error code.
+ * The following error codes are defined:
+ *	ENOMEM - Not enough memory to complete operation.
+ *	ERANGE - @newsize is not valid for the attribute type of @na.
+ *	ENOSPC - There is no enough space in base mft to resize $ATTRIBUTE_LIST.
+ */
+static int ntfs_non_resident_attr_expand_i(ntfs_attr *na, const s64 newsize,
+					hole_type holes)
+{
+	LCN lcn_seek_from;
+	VCN first_free_vcn;
+	ntfs_volume *vol;
+	ntfs_attr_search_ctx *ctx;
+	runlist *rl, *rln;
+	s64 org_alloc_size;
+	int err;
+
+	ntfs_log_trace("Inode %lld, attr 0x%x, new size %lld old size %lld\n",
+			(unsigned long long)na->ni->mft_no, na->type,
+			(long long)newsize, (long long)na->data_size);
+
+	vol = na->ni->vol;
+
+	/*
+	 * Check the attribute type and the corresponding maximum size
+	 * against @newsize and fail if @newsize is too big.
+	 */
+	if (ntfs_attr_size_bounds_check(vol, na->type, newsize) < 0) {
+		if (errno == ENOENT)
+			errno = EIO;
+		ntfs_log_perror("%s: bounds check failed", __FUNCTION__);
+		return -1;
+	}
+
+	if (na->type == AT_DATA)
+		NAttrSetDataAppending(na);
+	/* Save for future use. */
+	org_alloc_size = na->allocated_size;
+	/* The first cluster outside the new allocation. */
+	first_free_vcn = (newsize + vol->cluster_size - 1) >>
+			vol->cluster_size_bits;
+	/*
+	 * Compare the new allocation with the old one and only allocate
+	 * clusters if there is a change.
+	 */
+	if ((na->allocated_size >> vol->cluster_size_bits) < first_free_vcn) {
+#if PARTIAL_RUNLIST_UPDATING
+		s64 start_update;
+
+		/*
+		 * Update from the last previously allocated run,
+		 * as we may have to expand an existing hole.
+		 */
+		start_update = na->allocated_size >> vol->cluster_size_bits;
+		if (start_update)
+			start_update--;
+		if (ntfs_attr_map_partial_runlist(na, start_update)) {
+			ntfs_log_perror("failed to map partial runlist");
+			return -1;
+		}
+#else
+		if (ntfs_attr_map_whole_runlist(na)) {
+			ntfs_log_perror("ntfs_attr_map_whole_runlist failed");
+			return -1;
+		}
+#endif
+
+		/*
+		 * If we extend $DATA attribute on NTFS 3+ volume, we can add
+		 * sparse runs instead of real allocation of clusters.
+		 */
+		if ((na->type == AT_DATA) && (vol->major_ver >= 3)
+					 && (holes != HOLES_NO)) {
+			rl = ntfs_malloc(0x1000);
+			if (!rl)
+				return -1;
+			
+			rl[0].vcn = (na->allocated_size >>
+					vol->cluster_size_bits);
+			rl[0].lcn = LCN_HOLE;
+			rl[0].length = first_free_vcn -
+				(na->allocated_size >> vol->cluster_size_bits);
+			rl[1].vcn = first_free_vcn;
+			rl[1].lcn = LCN_ENOENT;
+			rl[1].length = 0;
+		} else {
+			/*
+			 * Determine first after last LCN of attribute.
+			 * We will start seek clusters from this LCN to avoid
+			 * fragmentation.  If there are no valid LCNs in the
+			 * attribute let the cluster allocator choose the
+			 * starting LCN.
+			 */
+			lcn_seek_from = -1;
+			if (na->rl->length) {
+				/* Seek to the last run list element. */
+				for (rl = na->rl; (rl + 1)->length; rl++)
+					;
+				/*
+				 * If the last LCN is a hole or similar seek
+				 * back to last valid LCN.
+				 */
+				while (rl->lcn < 0 && rl != na->rl)
+					rl--;
+				/*
+				 * Only set lcn_seek_from it the LCN is valid.
+				 */
+				if (rl->lcn >= 0)
+					lcn_seek_from = rl->lcn + rl->length;
+			}
+
+			rl = ntfs_cluster_alloc(vol, na->allocated_size >>
+					vol->cluster_size_bits, first_free_vcn -
+					(na->allocated_size >>
+					vol->cluster_size_bits), lcn_seek_from,
+					DATA_ZONE);
+			if (!rl) {
+				ntfs_log_perror("Cluster allocation failed "
+						"(%lld)",
+						(long long)first_free_vcn -
+						((long long)na->allocated_size >>
+						 vol->cluster_size_bits));
+				return -1;
+			}
+		}
+
+		/* Append new clusters to attribute runlist. */
+		rln = ntfs_runlists_merge(na->rl, rl);
+		if (!rln) {
+			/* Failed, free just allocated clusters. */
+			err = errno;
+			ntfs_log_perror("Run list merge failed");
+			ntfs_cluster_free_from_rl(vol, rl);
+			free(rl);
+			errno = err;
+			return -1;
+		}
+		na->rl = rln;
+		NAttrSetRunlistDirty(na);
+
+		/* Prepare to mapping pairs update. */
+		na->allocated_size = first_free_vcn << vol->cluster_size_bits;
+#if PARTIAL_RUNLIST_UPDATING
+		/*
+		 * Write mapping pairs for new runlist, unless this is
+		 * a temporary state before appending data.
+		 * If the update is not done, we must be sure to do
+		 * it later, and to get to a clean state even on errors.
+		 */
+		if ((holes != HOLES_DELAY)
+		   && ntfs_attr_update_mapping_pairs_i(na, start_update,
+					holes)) {
+#else
+		/* Write mapping pairs for new runlist. */
+		if (ntfs_attr_update_mapping_pairs(na, 0)) {
+#endif
+			err = errno;
+			ntfs_log_perror("Mapping pairs update failed");
+			goto rollback;
+		}
+	}
+
+	ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
+	if (!ctx) {
+		err = errno;
+		if (na->allocated_size == org_alloc_size) {
+			errno = err;
+			return -1;
+		} else
+			goto rollback;
+	}
+
+	if (ntfs_attr_lookup(na->type, na->name, na->name_len, CASE_SENSITIVE,
+			0, NULL, 0, ctx)) {
+		err = errno;
+		ntfs_log_perror("Lookup of first attribute extent failed");
+		if (err == ENOENT)
+			err = EIO;
+		if (na->allocated_size != org_alloc_size) {
+			ntfs_attr_put_search_ctx(ctx);
+			goto rollback;
+		} else
+			goto put_err_out;
+	}
+
+	/* Update data size. */
+	na->data_size = newsize;
+	ctx->attr->data_size = cpu_to_sle64(newsize);
+	/* Update data size in the index. */
+	if (na->ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
+		if (na->type == AT_INDEX_ROOT && na->name == NTFS_INDEX_I30) {
+			na->ni->data_size = na->data_size;
+			na->ni->allocated_size = na->allocated_size;
+			set_nino_flag(na->ni,KnownSize);
+		}
+	} else {
+		if (na->type == AT_DATA && na->name == AT_UNNAMED) {
+			na->ni->data_size = na->data_size;
+			NInoFileNameSetDirty(na->ni);
+		}
+	}
+	/* Set the inode dirty so it is written out later. */
+	ntfs_inode_mark_dirty(ctx->ntfs_ino);
+	/* Done! */
+	ntfs_attr_put_search_ctx(ctx);
+	return 0;
+rollback:
+	/* Free allocated clusters. */
+	if (ntfs_cluster_free(vol, na, org_alloc_size >>
+			vol->cluster_size_bits, -1) < 0) {
+		err = EIO;
+		ntfs_log_perror("Leaking clusters");
+	}
+	/* Now, truncate the runlist itself. */
+	if (ntfs_rl_truncate(&na->rl, org_alloc_size >>
+			vol->cluster_size_bits)) {
+		/*
+		 * Failed to truncate the runlist, so just throw it away, it
+		 * will be mapped afresh on next use.
+		 */
+		free(na->rl);
+		na->rl = NULL;
+		ntfs_log_perror("Couldn't truncate runlist. Rollback failed");
+	} else {
+		NAttrSetRunlistDirty(na);
+		/* Prepare to mapping pairs update. */
+		na->allocated_size = org_alloc_size;
+		/* Restore mapping pairs. */
+		if (ntfs_attr_update_mapping_pairs(na, 0 /*na->allocated_size >>
+					vol->cluster_size_bits*/)) {
+			ntfs_log_perror("Failed to restore old mapping pairs");
+		}
+	}
+	errno = err;
+	return -1;
+put_err_out:
+	ntfs_attr_put_search_ctx(ctx);
+	errno = err;
+	return -1;
+}
+
+
+static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize,
+				hole_type holes)
+{
+	int ret; 
+	
+	ntfs_log_enter("Entering\n");
+	ret = ntfs_non_resident_attr_expand_i(na, newsize, holes);
+	ntfs_log_leave("\n");
+	return ret;
+}
+
+/**
+ * ntfs_attr_truncate - resize an ntfs attribute
+ * @na:		open ntfs attribute to resize
+ * @newsize:	new size (in bytes) to which to resize the attribute
+ * @holes:	how to create a hole if expanding
+ *
+ * Change the size of an open ntfs attribute @na to @newsize bytes. If the
+ * attribute is made bigger and the attribute is resident the newly
+ * "allocated" space is cleared and if the attribute is non-resident the
+ * newly allocated space is marked as not initialised and no real allocation
+ * on disk is performed.
+ *
+ * On success return 0.
+ * On error return values are:
+ * 	STATUS_RESIDENT_ATTRIBUTE_FILLED_MFT
+ * 	STATUS_ERROR - otherwise
+ * The following error codes are defined:
+ *	EINVAL	   - Invalid arguments were passed to the function.
+ *	EOPNOTSUPP - The desired resize is not implemented yet.
+ * 	EACCES     - Encrypted attribute.
+ */
+static int ntfs_attr_truncate_i(ntfs_attr *na, const s64 newsize,
+					hole_type holes)
+{
+	int ret = STATUS_ERROR;
+	s64 fullsize;
+	BOOL compressed;
+
+	if (!na || newsize < 0 ||
+			(na->ni->mft_no == FILE_MFT && na->type == AT_DATA)) {
+		ntfs_log_trace("Invalid arguments passed.\n");
+		errno = EINVAL;
+		return STATUS_ERROR;
+	}
+
+	ntfs_log_enter("Entering for inode %lld, attr 0x%x, size %lld\n",
+		       (unsigned long long)na->ni->mft_no, na->type, 
+		       (long long)newsize);
+
+	if (na->data_size == newsize) {
+		ntfs_log_trace("Size is already ok\n");
+		ret = STATUS_OK;
+		goto out;
+	}
+	/*
+	 * Encrypted attributes are not supported. We return access denied,
+	 * which is what Windows NT4 does, too.
+	 */
+	if ((na->data_flags & ATTR_IS_ENCRYPTED) && !na->ni->vol->efs_raw) {
+		errno = EACCES;
+		ntfs_log_trace("Cannot truncate encrypted attribute\n");
+		goto out;
+	}
+	/*
+	 * TODO: Implement making handling of compressed attributes.
+	 * Currently we can only expand the attribute or delete it,
+	 * and only for ATTR_IS_COMPRESSED. This is however possible
+	 * for resident attributes when there is no open fuse context
+	 * (important case : $INDEX_ROOT:$I30)
+	 */
+	compressed = (na->data_flags & ATTR_COMPRESSION_MASK)
+			 != const_cpu_to_le16(0);
+	if (compressed
+	   && NAttrNonResident(na)
+	   && ((na->data_flags & ATTR_COMPRESSION_MASK) != ATTR_IS_COMPRESSED)) {
+		errno = EOPNOTSUPP;
+		ntfs_log_perror("Failed to truncate compressed attribute");
+		goto out;
+	}
+	if (NAttrNonResident(na)) {
+		/*
+		 * For compressed data, the last block must be fully
+		 * allocated, and we do not know the size of compression
+		 * block until the attribute has been made non-resident.
+		 * Moreover we can only process a single compression
+		 * block at a time (from where we are about to write),
+		 * so we silently do not allocate more.
+		 *
+		 * Note : do not request upsizing of compressed files
+		 * unless being able to face the consequences !
+		 */
+		if (compressed && newsize && (newsize > na->data_size))
+			fullsize = (na->initialized_size
+				 | (na->compression_block_size - 1)) + 1;
+		else
+			fullsize = newsize;
+		if (fullsize > na->data_size)
+			ret = ntfs_non_resident_attr_expand(na, fullsize,
+								holes);
+		else
+			ret = ntfs_non_resident_attr_shrink(na, fullsize);
+	} else
+		ret = ntfs_resident_attr_resize_i(na, newsize, holes);
+out:	
+	ntfs_log_leave("Return status %d\n", ret);
+	return ret;
+}
+
+/*
+ *		Resize an attribute, creating a hole if relevant
+ */
+
+int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize)
+{
+	int r;
+
+	r = ntfs_attr_truncate_i(na, newsize, HOLES_OK);
+	NAttrClearDataAppending(na);
+	NAttrClearBeingNonResident(na);
+	return (r);
+}
+
+/*
+ *		Resize an attribute, avoiding hole creation
+ */
+
+int ntfs_attr_truncate_solid(ntfs_attr *na, const s64 newsize)
+{
+	return (ntfs_attr_truncate_i(na, newsize, HOLES_NO));
+}
+
+/*
+ *		Stuff a hole in a compressed file
+ *
+ *	An unallocated hole must be aligned on compression block size.
+ *	If needed current block and target block are stuffed with zeroes.
+ *
+ *	Returns 0 if succeeded,
+ *		-1 if it failed (as explained in errno)
+ */
+
+static int stuff_hole(ntfs_attr *na, const s64 pos)
+{
+	s64 size;
+	s64 begin_size;
+	s64 end_size;
+	char *buf;
+	int ret;
+
+	ret = 0;
+		/*
+		 * If the attribute is resident, the compression block size
+		 * is not defined yet and we can make no decision.
+		 * So we first try resizing to the target and if the
+		 * attribute is still resident, we're done
+		 */
+	if (!NAttrNonResident(na)) {
+		ret = ntfs_resident_attr_resize(na, pos);
+		if (!ret && !NAttrNonResident(na))
+			na->initialized_size = na->data_size = pos;
+	}
+	if (!ret && NAttrNonResident(na)) {
+			/* does the hole span over several compression block ? */
+		if ((pos ^ na->initialized_size)
+				& ~(na->compression_block_size - 1)) {
+			begin_size = ((na->initialized_size - 1)
+					| (na->compression_block_size - 1))
+					+ 1 - na->initialized_size;
+			end_size = pos & (na->compression_block_size - 1);
+			size = (begin_size > end_size ? begin_size : end_size);
+		} else {
+			/* short stuffing in a single compression block */
+			begin_size = size = pos - na->initialized_size;
+			end_size = 0;
+		}
+		if (size)
+			buf = (char*)ntfs_malloc(size);
+		else
+			buf = (char*)NULL;
+		if (buf || !size) {
+			memset(buf,0,size);
+				/* stuff into current block */
+			if (begin_size
+			    && (ntfs_attr_pwrite(na,
+				na->initialized_size, begin_size, buf)
+				   != begin_size))
+				ret = -1;
+				/* create an unstuffed hole */
+			if (!ret
+			    && ((na->initialized_size + end_size) < pos)
+			    && ntfs_non_resident_attr_expand(na,
+					pos - end_size, HOLES_OK))
+				ret = -1;
+			else 
+				na->initialized_size
+				    = na->data_size = pos - end_size;
+				/* stuff into the target block */
+			if (!ret && end_size
+			    && (ntfs_attr_pwrite(na, 
+				na->initialized_size, end_size, buf)
+				    != end_size))
+				ret = -1;
+			if (buf)
+				free(buf);
+		} else
+			ret = -1;
+	}
+		/* make absolutely sure we have reached the target */
+	if (!ret && (na->initialized_size != pos)) {
+		ntfs_log_error("Failed to stuff a compressed file"
+			"target %lld reached %lld\n",
+			(long long)pos, (long long)na->initialized_size);
+		errno = EIO;
+		ret = -1;
+	}
+	return (ret);
+}
+
+/**
+ * ntfs_attr_readall - read the entire data from an ntfs attribute
+ * @ni:		open ntfs inode in which the ntfs attribute resides
+ * @type:	attribute type
+ * @name:	attribute name in little endian Unicode or AT_UNNAMED or NULL
+ * @name_len:	length of attribute @name in Unicode characters (if @name given)
+ * @data_size:	if non-NULL then store here the data size 
+ *
+ * This function will read the entire content of an ntfs attribute.
+ * If @name is AT_UNNAMED then look specifically for an unnamed attribute.
+ * If @name is NULL then the attribute could be either named or not. 
+ * In both those cases @name_len is not used at all.
+ *
+ * On success a buffer is allocated with the content of the attribute 
+ * and which needs to be freed when it's not needed anymore. If the
+ * @data_size parameter is non-NULL then the data size is set there.
+ *
+ * On error NULL is returned with errno set to the error code.
+ */
+void *ntfs_attr_readall(ntfs_inode *ni, const ATTR_TYPES type,
+			ntfschar *name, u32 name_len, s64 *data_size)
+{
+	ntfs_attr *na;
+	void *data, *ret = NULL;
+	s64 size;
+	
+	ntfs_log_enter("Entering\n");
+	
+	na = ntfs_attr_open(ni, type, name, name_len);
+	if (!na) {
+		ntfs_log_perror("ntfs_attr_open failed, inode %lld attr 0x%lx",
+				(long long)ni->mft_no,(long)le32_to_cpu(type));
+		goto err_exit;
+	}
+	data = ntfs_malloc(na->data_size);
+	if (!data)
+		goto out;
+	
+	size = ntfs_attr_pread(na, 0, na->data_size, data);
+	if (size != na->data_size) {
+		ntfs_log_perror("ntfs_attr_pread failed");
+		free(data);
+		goto out;
+	}
+	ret = data;
+	if (data_size)
+		*data_size = size;
+out:
+	ntfs_attr_close(na);
+err_exit:
+	ntfs_log_leave("\n");
+	return ret;
+}
+
+/*
+ *		Read some data from a data attribute
+ *
+ *	Returns the amount of data read, negative if there was an error
+ */
+
+int ntfs_attr_data_read(ntfs_inode *ni,
+		ntfschar *stream_name, int stream_name_len,
+		char *buf, size_t size, off_t offset)
+{
+	ntfs_attr *na = NULL;
+	int res, total = 0;
+
+	na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);
+	if (!na) {
+		res = -errno;
+		goto exit;
+	}
+	if ((size_t)offset < (size_t)na->data_size) {
+		if (offset + size > (size_t)na->data_size)
+			size = na->data_size - offset;
+		while (size) {
+			res = ntfs_attr_pread(na, offset, size, buf + total);
+			if ((off_t)res < (off_t)size)
+				ntfs_log_perror("ntfs_attr_pread partial read "
+					"(%lld : %lld <> %d)",
+					(long long)offset,
+					(long long)size, res);
+			if (res <= 0) {
+				res = -errno;
+				goto exit;
+			}
+			size -= res;
+			offset += res;
+			total += res;
+		}
+	}
+	res = total;
+exit:
+	if (na)
+		ntfs_attr_close(na);
+	return res;
+}
+
+
+/*
+ *		Write some data into a data attribute
+ *
+ *	Returns the amount of data written, negative if there was an error
+ */
+
+int ntfs_attr_data_write(ntfs_inode *ni, ntfschar *stream_name,
+		int stream_name_len, const char *buf, size_t size, off_t offset)
+{
+	ntfs_attr *na = NULL;
+	int res, total = 0;
+
+	na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);
+	if (!na) {
+		res = -errno;
+		goto exit;
+	}
+	while (size) {
+		res = ntfs_attr_pwrite(na, offset, size, buf + total);
+		if (res < (s64)size)
+			ntfs_log_perror("ntfs_attr_pwrite partial write (%lld: "
+				"%lld <> %d)", (long long)offset,
+				(long long)size, res);
+		if (res <= 0) {
+			res = -errno;
+			goto exit;
+		}
+		size -= res;
+		offset += res;
+		total += res;
+	}
+	res = total;
+exit:
+	if (na)
+		ntfs_attr_close(na);
+	return res;
+}
+
+/*
+ *		Shrink the size of a data attribute if needed
+ *
+ *	For non-resident attributes only.
+ *	The space remains allocated.
+ *
+ *	Returns 0 if successful
+ *		-1 if failed, with errno telling why
+ */
+
+
+int ntfs_attr_shrink_size(ntfs_inode *ni, ntfschar *stream_name,
+		int stream_name_len, off_t offset)
+{
+	ntfs_attr_search_ctx *ctx;
+	ATTR_RECORD *a;
+	int res;
+
+	res = -1;
+	ctx = ntfs_attr_get_search_ctx(ni, NULL);
+	if (ctx) {
+		if (!ntfs_attr_lookup(AT_DATA, stream_name, stream_name_len,
+			CASE_SENSITIVE, 0, NULL, 0, ctx)) {
+			a = ctx->attr;
+
+			if (a->non_resident
+			    && (sle64_to_cpu(a->initialized_size) > offset)) {
+				a->initialized_size = cpu_to_le64(offset);
+				a->data_size = a->initialized_size;
+			}
+			res = 0;
+		}
+		ntfs_attr_put_search_ctx(ctx);
+	}
+	return (res);
+}
+
+int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type, const ntfschar *name,
+		    u32 name_len)
+{
+	ntfs_attr_search_ctx *ctx;
+	int ret;
+	
+	ntfs_log_trace("Entering\n");
+	
+	ctx = ntfs_attr_get_search_ctx(ni, NULL);
+	if (!ctx)
+		return 0;
+	
+	ret = ntfs_attr_lookup(type, name, name_len, CASE_SENSITIVE, 0, NULL, 0,
+			       ctx);
+
+	ntfs_attr_put_search_ctx(ctx);
+	
+	return !ret;
+}
+
+int ntfs_attr_remove(ntfs_inode *ni, const ATTR_TYPES type, ntfschar *name, 
+		     u32 name_len)
+{
+	ntfs_attr *na;
+	int ret;
+
+	ntfs_log_trace("Entering\n");
+	
+	if (!ni) {
+		ntfs_log_error("%s: NULL inode pointer", __FUNCTION__);
+		errno = EINVAL;
+		return -1;
+	}
+	
+	na = ntfs_attr_open(ni, type, name, name_len);
+	if (!na) {
+			/* do not log removal of non-existent stream */
+		if (type != AT_DATA) {
+			ntfs_log_perror("Failed to open attribute 0x%02x of inode "
+				"0x%llx", type, (unsigned long long)ni->mft_no);
+		}
+		return -1;
+	}
+	
+	ret = ntfs_attr_rm(na);
+	if (ret)
+		ntfs_log_perror("Failed to remove attribute 0x%02x of inode "
+				"0x%llx", type, (unsigned long long)ni->mft_no);
+	ntfs_attr_close(na);
+	
+	return ret;
+}
+
+/* Below macros are 32-bit ready. */
+#define BCX(x) ((x) - (((x) >> 1) & 0x77777777) - \
+		      (((x) >> 2) & 0x33333333) - \
+		      (((x) >> 3) & 0x11111111))
+#define BITCOUNT(x) (((BCX(x) + (BCX(x) >> 4)) & 0x0F0F0F0F) % 255)
+
+static u8 *ntfs_init_lut256(void)
+{
+	int i;
+	u8 *lut;
+	
+	lut = ntfs_malloc(256);
+	if (lut)
+		for(i = 0; i < 256; i++)
+			*(lut + i) = 8 - BITCOUNT(i);
+	return lut;
+}
+
+s64 ntfs_attr_get_free_bits(ntfs_attr *na)
+{
+	u8 *buf, *lut;
+	s64 br      = 0;
+	s64 total   = 0;
+	s64 nr_free = 0;
+
+	lut = ntfs_init_lut256();
+	if (!lut)
+		return -1;
+	
+	buf = ntfs_malloc(65536);
+	if (!buf)
+		goto out;
+
+	while (1) {
+		u32 *p;
+		br = ntfs_attr_pread(na, total, 65536, buf);
+		if (br <= 0)
+			break;
+		total += br;
+		p = (u32 *)buf + br / 4 - 1;
+		for (; (u8 *)p >= buf; p--) {
+			nr_free += lut[ *p        & 255] + 
+			           lut[(*p >>  8) & 255] + 
+			           lut[(*p >> 16) & 255] + 
+			           lut[(*p >> 24)      ];
+		}
+		switch (br % 4) {
+			case 3:  nr_free += lut[*(buf + br - 3)];
+			case 2:  nr_free += lut[*(buf + br - 2)];
+			case 1:  nr_free += lut[*(buf + br - 1)];
+		}
+	}
+	free(buf);
+out:
+	free(lut);
+	if (!total || br < 0)
+		return -1;
+	return nr_free;
+}
diff --git a/libntfs-3g/attrlist.c b/libntfs-3g/attrlist.c
new file mode 100755
index 0000000000000000000000000000000000000000..9c62f316146fb4e50b82879a0d5ca110e4dc0e03
--- /dev/null
+++ b/libntfs-3g/attrlist.c
@@ -0,0 +1,314 @@
+/**
+ * attrlist.c - Attribute list attribute handling code.  Originated from the Linux-NTFS
+ *		project.
+ *
+ * Copyright (c) 2004-2005 Anton Altaparmakov
+ * Copyright (c) 2004-2005 Yura Pakhuchiy
+ * 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
+ * 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_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "types.h"
+#include "layout.h"
+#include "attrib.h"
+#include "attrlist.h"
+#include "debug.h"
+#include "unistr.h"
+#include "logging.h"
+#include "misc.h"
+
+/**
+ * ntfs_attrlist_need - check whether inode need attribute list
+ * @ni:		opened ntfs inode for which perform check
+ *
+ * Check whether all are attributes belong to one MFT record, in that case
+ * attribute list is not needed.
+ *
+ * Return 1 if inode need attribute list, 0 if not, -1 on error with errno set
+ * to the error code. If function succeed errno set to 0. The following error
+ * codes are defined:
+ *	EINVAL	- Invalid arguments passed to function or attribute haven't got
+ *		  attribute list.
+ */
+int ntfs_attrlist_need(ntfs_inode *ni)
+{
+	ATTR_LIST_ENTRY *ale;
+
+	if (!ni) {
+		ntfs_log_trace("Invalid arguments.\n");
+		errno = EINVAL;
+		return -1;
+	}
+
+	ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no);
+
+	if (!NInoAttrList(ni)) {
+		ntfs_log_trace("Inode haven't got attribute list.\n");
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (!ni->attr_list) {
+		ntfs_log_trace("Corrupt in-memory struct.\n");
+		errno = EINVAL;
+		return -1;
+	}
+
+	errno = 0;
+	ale = (ATTR_LIST_ENTRY *)ni->attr_list;
+	while ((u8*)ale < ni->attr_list + ni->attr_list_size) {
+		if (MREF_LE(ale->mft_reference) != ni->mft_no)
+			return 1;
+		ale = (ATTR_LIST_ENTRY *)((u8*)ale + le16_to_cpu(ale->length));
+	}
+	return 0;
+}
+
+/**
+ * ntfs_attrlist_entry_add - add an attribute list attribute entry
+ * @ni:		opened ntfs inode, which contains that attribute
+ * @attr:	attribute record to add to attribute list
+ *
+ * Return 0 on success and -1 on error with errno set to the error code. The
+ * following error codes are defined:
+ *	EINVAL	- Invalid arguments passed to function.
+ *	ENOMEM	- Not enough memory to allocate necessary buffers.
+ *	EIO	- I/O error occurred or damaged filesystem.
+ *	EEXIST	- Such attribute already present in attribute list.
+ */
+int ntfs_attrlist_entry_add(ntfs_inode *ni, ATTR_RECORD *attr)
+{
+	ATTR_LIST_ENTRY *ale;
+	MFT_REF mref;
+	ntfs_attr *na = NULL;
+	ntfs_attr_search_ctx *ctx;
+	u8 *new_al;
+	int entry_len, entry_offset, err;
+
+	ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n",
+			(long long) ni->mft_no,
+			(unsigned) le32_to_cpu(attr->type));
+
+	if (!ni || !attr) {
+		ntfs_log_trace("Invalid arguments.\n");
+		errno = EINVAL;
+		return -1;
+	}
+
+	mref = MK_LE_MREF(ni->mft_no, le16_to_cpu(ni->mrec->sequence_number));
+
+	if (ni->nr_extents == -1)
+		ni = ni->base_ni;
+
+	if (!NInoAttrList(ni)) {
+		ntfs_log_trace("Attribute list isn't present.\n");
+		errno = ENOENT;
+		return -1;
+	}
+
+	/* Determine size and allocate memory for new attribute list. */
+	entry_len = (sizeof(ATTR_LIST_ENTRY) + sizeof(ntfschar) *
+			attr->name_length + 7) & ~7;
+	new_al = ntfs_calloc(ni->attr_list_size + entry_len);
+	if (!new_al)
+		return -1;
+
+	/* Find place for the new entry. */
+	ctx = ntfs_attr_get_search_ctx(ni, NULL);
+	if (!ctx) {
+		err = errno;
+		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) ? 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)) {
+		/* Found some extent, check it to be before new extent. */
+		if (ctx->al_entry->lowest_vcn == attr->lowest_vcn) {
+			err = EEXIST;
+			ntfs_log_trace("Such attribute already present in the "
+					"attribute list.\n");
+			ntfs_attr_put_search_ctx(ctx);
+			goto err_out;
+		}
+		/* Add new entry after this extent. */
+		ale = (ATTR_LIST_ENTRY*)((u8*)ctx->al_entry +
+				le16_to_cpu(ctx->al_entry->length));
+	} else {
+		/* Check for real errors. */
+		if (errno != ENOENT) {
+			err = errno;
+			ntfs_log_trace("Attribute lookup failed.\n");
+			ntfs_attr_put_search_ctx(ctx);
+			goto err_out;
+		}
+		/* No previous extents found. */
+		ale = ctx->al_entry;
+	}
+	/* Don't need it anymore, @ctx->al_entry points to @ni->attr_list. */
+	ntfs_attr_put_search_ctx(ctx);
+
+	/* Determine new entry offset. */
+	entry_offset = ((u8 *)ale - ni->attr_list);
+	/* Set pointer to new entry. */
+	ale = (ATTR_LIST_ENTRY *)(new_al + entry_offset);
+	/* Zero it to fix valgrind warning. */
+	memset(ale, 0, entry_len);
+	/* Form new entry. */
+	ale->type = attr->type;
+	ale->length = cpu_to_le16(entry_len);
+	ale->name_length = attr->name_length;
+	ale->name_offset = offsetof(ATTR_LIST_ENTRY, name);
+	if (attr->non_resident)
+		ale->lowest_vcn = attr->lowest_vcn;
+	else
+		ale->lowest_vcn = 0;
+	ale->mft_reference = mref;
+	ale->instance = attr->instance;
+	memcpy(ale->name, (u8 *)attr + le16_to_cpu(attr->name_offset),
+			attr->name_length * sizeof(ntfschar));
+
+	/* Resize $ATTRIBUTE_LIST to new length. */
+	na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0);
+	if (!na) {
+		err = errno;
+		ntfs_log_trace("Failed to open $ATTRIBUTE_LIST attribute.\n");
+		goto err_out;
+	}
+	if (ntfs_attr_truncate(na, ni->attr_list_size + entry_len)) {
+		err = errno;
+		ntfs_log_trace("$ATTRIBUTE_LIST resize failed.\n");
+		goto err_out;
+	}
+
+	/* Copy entries from old attribute list to new. */
+	memcpy(new_al, ni->attr_list, entry_offset);
+	memcpy(new_al + entry_offset + entry_len, ni->attr_list +
+			entry_offset, ni->attr_list_size - entry_offset);
+
+	/* Set new runlist. */
+	free(ni->attr_list);
+	ni->attr_list = new_al;
+	ni->attr_list_size = ni->attr_list_size + entry_len;
+	NInoAttrListSetDirty(ni);
+	/* Done! */
+	ntfs_attr_close(na);
+	return 0;
+err_out:
+	if (na)
+		ntfs_attr_close(na);
+	free(new_al);
+	errno = err;
+	return -1;
+}
+
+/**
+ * ntfs_attrlist_entry_rm - remove an attribute list attribute entry
+ * @ctx:	attribute search context describing the attribute list entry
+ *
+ * Remove the attribute list entry @ctx->al_entry from the attribute list.
+ *
+ * Return 0 on success and -1 on error with errno set to the error code.
+ */
+int ntfs_attrlist_entry_rm(ntfs_attr_search_ctx *ctx)
+{
+	u8 *new_al;
+	int new_al_len;
+	ntfs_inode *base_ni;
+	ntfs_attr *na;
+	ATTR_LIST_ENTRY *ale;
+	int err;
+
+	if (!ctx || !ctx->ntfs_ino || !ctx->al_entry) {
+		ntfs_log_trace("Invalid arguments.\n");
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (ctx->base_ntfs_ino)
+		base_ni = ctx->base_ntfs_ino;
+	else
+		base_ni = ctx->ntfs_ino;
+	ale = ctx->al_entry;
+
+	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) le64_to_cpu(ctx->al_entry->lowest_vcn));
+
+	if (!NInoAttrList(base_ni)) {
+		ntfs_log_trace("Attribute list isn't present.\n");
+		errno = ENOENT;
+		return -1;
+	}
+
+	/* Allocate memory for new attribute list. */
+	new_al_len = base_ni->attr_list_size - le16_to_cpu(ale->length);
+	new_al = ntfs_calloc(new_al_len);
+	if (!new_al)
+		return -1;
+
+	/* Reisze $ATTRIBUTE_LIST to new length. */
+	na = ntfs_attr_open(base_ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0);
+	if (!na) {
+		err = errno;
+		ntfs_log_trace("Failed to open $ATTRIBUTE_LIST attribute.\n");
+		goto err_out;
+	}
+	if (ntfs_attr_truncate(na, new_al_len)) {
+		err = errno;
+		ntfs_log_trace("$ATTRIBUTE_LIST resize failed.\n");
+		goto err_out;
+	}
+
+	/* Copy entries from old attribute list to new. */
+	memcpy(new_al, base_ni->attr_list, (u8*)ale - base_ni->attr_list);
+	memcpy(new_al + ((u8*)ale - base_ni->attr_list), (u8*)ale + le16_to_cpu(
+		ale->length), new_al_len - ((u8*)ale - base_ni->attr_list));
+
+	/* Set new runlist. */
+	free(base_ni->attr_list);
+	base_ni->attr_list = new_al;
+	base_ni->attr_list_size = new_al_len;
+	NInoAttrListSetDirty(base_ni);
+	/* Done! */
+	ntfs_attr_close(na);
+	return 0;
+err_out:
+	if (na)
+		ntfs_attr_close(na);
+	free(new_al);
+	errno = err;
+	return -1;
+}
diff --git a/libntfs-3g/bitmap.c b/libntfs-3g/bitmap.c
new file mode 100755
index 0000000000000000000000000000000000000000..65162a2946003ee63805d906625023eecd53052a
--- /dev/null
+++ b/libntfs-3g/bitmap.c
@@ -0,0 +1,300 @@
+/**
+ * bitmap.c - Bitmap handling code. Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2002-2006 Anton Altaparmakov
+ * Copyright (c) 2004-2005 Richard Russon
+ * Copyright (c) 2004-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
+ * 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_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "types.h"
+#include "attrib.h"
+#include "bitmap.h"
+#include "debug.h"
+#include "logging.h"
+#include "misc.h"
+
+/**
+ * ntfs_bit_set - set a bit in a field of bits
+ * @bitmap:	field of bits
+ * @bit:	bit to set
+ * @new_value:	value to set bit to (0 or 1)
+ *
+ * Set the bit @bit in the @bitmap to @new_value. Ignore all errors.
+ */
+void ntfs_bit_set(u8 *bitmap, const u64 bit, const u8 new_value)
+{
+	if (!bitmap || new_value > 1)
+		return;
+	if (!new_value)
+		bitmap[bit >> 3] &= ~(1 << (bit & 7));
+	else
+		bitmap[bit >> 3] |= (1 << (bit & 7));
+}
+
+/**
+ * ntfs_bit_get - get value of a bit in a field of bits
+ * @bitmap:	field of bits
+ * @bit:	bit to get
+ *
+ * Get and return the value of the bit @bit in @bitmap (0 or 1).
+ * Return -1 on error.
+ */
+char ntfs_bit_get(const u8 *bitmap, const u64 bit)
+{
+	if (!bitmap)
+		return -1;
+	return (bitmap[bit >> 3] >> (bit & 7)) & 1;
+}
+
+/**
+ * ntfs_bit_get_and_set - get value of a bit in a field of bits and set it
+ * @bitmap:	field of bits
+ * @bit:	bit to get/set
+ * @new_value:	value to set bit to (0 or 1)
+ *
+ * Return the value of the bit @bit and set it to @new_value (0 or 1).
+ * Return -1 on error.
+ */
+char ntfs_bit_get_and_set(u8 *bitmap, const u64 bit, const u8 new_value)
+{
+	register u8 old_bit, shift;
+
+	if (!bitmap || new_value > 1)
+		return -1;
+	shift = bit & 7;
+	old_bit = (bitmap[bit >> 3] >> shift) & 1;
+	if (new_value != old_bit)
+		bitmap[bit >> 3] ^= 1 << shift;
+	return old_bit;
+}
+
+/**
+ * ntfs_bitmap_set_bits_in_run - set a run of bits in a bitmap to a value
+ * @na:		attribute containing the bitmap
+ * @start_bit:	first bit to set
+ * @count:	number of bits to set
+ * @value:	value to set the bits to (i.e. 0 or 1)
+ *
+ * Set @count bits starting at bit @start_bit in the bitmap described by the
+ * attribute @na to @value, where @value is either 0 or 1.
+ *
+ * On success return 0 and on error return -1 with errno set to the error code.
+ */
+static int ntfs_bitmap_set_bits_in_run(ntfs_attr *na, s64 start_bit,
+				       s64 count, int value)
+{
+	s64 bufsize, br;
+	u8 *buf, *lastbyte_buf;
+	int bit, firstbyte, lastbyte, lastbyte_pos, tmp, ret = -1;
+
+	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;
+	}
+
+	bit = start_bit & 7;
+	if (bit)
+		firstbyte = 1;
+	else
+		firstbyte = 0;
+
+	/* Calculate the required buffer size in bytes, capping it at 8kiB. */
+	bufsize = ((count - (bit ? 8 - bit : 0) + 7) >> 3) + firstbyte;
+	if (bufsize > 8192)
+		bufsize = 8192;
+
+	buf = ntfs_malloc(bufsize);
+	if (!buf)
+		return -1;
+	
+	/* Depending on @value, zero or set all bits in the allocated buffer. */
+	memset(buf, value ? 0xff : 0, bufsize);
+
+	/* If there is a first partial byte... */
+	if (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;
+		}
+		/* and set or clear the appropriate bits in it. */
+		while ((bit & 7) && count--) {
+			if (value)
+				*buf |= 1 << bit++;
+			else
+				*buf &= ~(1 << bit++);
+		}
+		/* Update @start_bit to the new position. */
+		start_bit = (start_bit + 7) & ~7;
+	}
+
+	/* Loop until @count reaches zero. */
+	lastbyte = 0;
+	lastbyte_buf = NULL;
+	bit = count & 7;
+	do {
+		/* If there is a last partial byte... */
+		if (count > 0 && bit) {
+			lastbyte_pos = ((count + 7) >> 3) + firstbyte;
+			if (!lastbyte_pos) {
+				// FIXME: Eeek! BUG!
+				ntfs_log_error("Lastbyte is zero. Leaving "
+						"inconsistent metadata.\n");
+				errno = EIO;
+				goto free_err_out;
+			}
+			/* and it is in the currently loaded bitmap window... */
+			if (lastbyte_pos <= bufsize) {
+				lastbyte_buf = buf + lastbyte_pos - 1;
+
+				/* read the byte in... */
+				br = ntfs_attr_pread(na, (start_bit + count) >>
+						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);
+					goto free_err_out;
+				}
+				/* and set/clear the appropriate bits in it. */
+				while (bit && count--) {
+					if (value)
+						*lastbyte_buf |= 1 << --bit;
+					else
+						*lastbyte_buf &= ~(1 << --bit);
+				}
+				/* We don't want to come back here... */
+				bit = 0;
+				/* We have a last byte that we have handled. */
+				lastbyte = 1;
+			}
+		}
+
+		/* Write the prepared buffer to disk. */
+		tmp = (start_bit >> 3) - firstbyte;
+		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);
+			goto free_err_out;
+		}
+
+		/* Update counters. */
+		tmp = (bufsize - firstbyte - lastbyte) << 3;
+		if (firstbyte) {
+			firstbyte = 0;
+			/*
+			 * Re-set the partial first byte so a subsequent write
+			 * of the buffer does not have stale, incorrect bits.
+			 */
+			*buf = value ? 0xff : 0;
+		}
+		start_bit += tmp;
+		count -= tmp;
+		if (bufsize > (tmp = (count + 7) >> 3))
+			bufsize = tmp;
+
+		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;
+			goto free_err_out;
+		}
+	} while (count > 0);
+	
+	ret = 0;
+	
+free_err_out:
+	free(buf);
+	return ret;
+}
+
+/**
+ * ntfs_bitmap_set_run - set a run of bits in a bitmap
+ * @na:		attribute containing the bitmap
+ * @start_bit:	first bit to set
+ * @count:	number of bits to set
+ *
+ * Set @count bits starting at bit @start_bit in the bitmap described by the
+ * attribute @na.
+ *
+ * On success return 0 and on error return -1 with errno set to the error code.
+ */
+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;
+}
+
+/**
+ * ntfs_bitmap_clear_run - clear a run of bits in a bitmap
+ * @na:		attribute containing the bitmap
+ * @start_bit:	first bit to clear
+ * @count:	number of bits to clear
+ *
+ * Clear @count bits starting at bit @start_bit in the bitmap described by the
+ * attribute @na.
+ *
+ * On success return 0 and on error return -1 with errno set to the error code.
+ */
+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",
+		       (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;
+}
+
diff --git a/libntfs-3g/bootsect.c b/libntfs-3g/bootsect.c
new file mode 100755
index 0000000000000000000000000000000000000000..92c8505df90cd7fe13d4ef1a82a3f1f1adb00a12
--- /dev/null
+++ b/libntfs-3g/bootsect.c
@@ -0,0 +1,285 @@
+/**
+ * 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)      2005 Yura Pakhuchiy
+ *
+ * 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_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "compat.h"
+#include "bootsect.h"
+#include "debug.h"
+#include "logging.h"
+
+/**
+ * ntfs_boot_sector_is_ntfs - check if buffer contains a valid ntfs boot sector
+ * @b:		buffer containing putative boot sector to analyze
+ * @silent:	if zero, output progress messages to stderr
+ *
+ * Check if the buffer @b contains a valid ntfs boot sector. The buffer @b
+ * must be at least 512 bytes in size.
+ *
+ * If @silent is zero, output progress messages to stderr. Otherwise, do not
+ * output any messages (except when configured with --enable-debug in which
+ * case warning/debug messages may be displayed).
+ *
+ * Return TRUE if @b contains a valid ntfs boot sector and FALSE if not.
+ */
+BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b)
+{
+	u32 i;
+	BOOL ret = FALSE;
+
+	ntfs_log_debug("Beginning bootsector check.\n");
+
+	ntfs_log_debug("Checking OEMid, NTFS signature.\n");
+	if (b->oem_id != cpu_to_le64(0x202020205346544eULL)) { /* "NTFS    " */
+		ntfs_log_error("NTFS signature is missing.\n");
+		goto not_ntfs;
+	}
+
+	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));
+		goto not_ntfs;
+	}
+
+	ntfs_log_debug("Checking sectors per cluster.\n");
+	switch (b->bpb.sectors_per_cluster) {
+	case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128:
+		break;
+	default:
+		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");
+	i = (u32)le16_to_cpu(b->bpb.bytes_per_sector) * 
+		b->bpb.sectors_per_cluster;
+	if (i > 65536) {
+		ntfs_log_error("Unexpected cluster size (%d).\n", i);
+		goto not_ntfs;
+	}
+
+	ntfs_log_debug("Checking reserved fields are zero.\n");
+	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);
+		goto not_ntfs;
+	}
+
+	ntfs_log_debug("Checking clusters per mft record.\n");
+	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("Checking clusters per index block.\n");
+	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;
+		}
+	}
+
+	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;
+not_ntfs:
+	return ret;
+}
+
+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
+ * @bs:		buffer containing ntfs boot sector to parse
+ *
+ * Parse the ntfs bootsector @bs and setup the ntfs volume @vol with the
+ * obtained values.
+ *
+ * Return 0 on success or -1 on error with errno set to the error code EINVAL.
+ */
+int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs)
+{
+	s64 sectors;
+	u8  sectors_per_cluster;
+	s8  c;
+
+	/* We return -1 with errno = EINVAL on error. */
+	errno = EINVAL;
+
+	vol->sector_size = le16_to_cpu(bs->bpb.bytes_per_sector);
+	vol->sector_size_bits = ffs(vol->sector_size) - 1;
+	ntfs_log_debug("SectorSize = 0x%x\n", vol->sector_size);
+	ntfs_log_debug("SectorSizeBits = %u\n", vol->sector_size_bits);
+	/*
+	 * The bounds checks on mft_lcn and mft_mirr_lcn (i.e. them being
+	 * 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.
+	 */
+	sectors_per_cluster = bs->bpb.sectors_per_cluster;
+	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);
+		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->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);
+		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);
+		return -1;
+	}
+	vol->cluster_size_bits = ffs(vol->cluster_size) - 1;
+	/*
+	 * Need to get the clusters per mft record and handle it if it is
+	 * negative. Then calculate the mft_record_size. A value of 0x80 is
+	 * illegal, thus signed char is actually ok!
+	 */
+	c = bs->clusters_per_mft_record;
+	ntfs_log_debug("ClusterSize = 0x%x\n", (unsigned)vol->cluster_size);
+	ntfs_log_debug("ClusterSizeBits = %u\n", vol->cluster_size_bits);
+	ntfs_log_debug("ClustersPerMftRecord = 0x%x\n", c);
+	/*
+	 * When clusters_per_mft_record is negative, it means that it is to
+	 * be taken to be the negative base 2 logarithm of the mft_record_size
+	 * min bytes. Then:
+	 *	 mft_record_size = 2^(-clusters_per_mft_record) bytes.
+	 */
+	if (c < 0)
+		vol->mft_record_size = 1 << -c;
+	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);
+		return -1;
+	}
+	vol->mft_record_size_bits = ffs(vol->mft_record_size) - 1;
+	ntfs_log_debug("MftRecordSize = 0x%x\n", (unsigned)vol->mft_record_size);
+	ntfs_log_debug("MftRecordSizeBits = %u\n", vol->mft_record_size_bits);
+	/* Same as above for INDX record. */
+	c = bs->clusters_per_index_record;
+	ntfs_log_debug("ClustersPerINDXRecord = 0x%x\n", c);
+	if (c < 0)
+		vol->indx_record_size = 1 << -c;
+	else
+		vol->indx_record_size = c << vol->cluster_size_bits;
+	vol->indx_record_size_bits = ffs(vol->indx_record_size) - 1;
+	ntfs_log_debug("INDXRecordSize = 0x%x\n", (unsigned)vol->indx_record_size);
+	ntfs_log_debug("INDXRecordSizeBits = %u\n", vol->indx_record_size_bits);
+	/*
+	 * Work out the size of the MFT mirror in number of mft records. If the
+	 * cluster size is less than or equal to the size taken by four mft
+	 * records, the mft mirror stores the first four mft records. If the
+	 * cluster size is bigger than the size taken by four mft records, the
+	 * mft mirror contains as many mft records as will fit into one
+	 * cluster.
+	 */
+	if (vol->cluster_size <= 4 * vol->mft_record_size)
+		vol->mftmirr_size = 4;
+	else
+		vol->mftmirr_size = vol->cluster_size / vol->mft_record_size;
+	return 0;
+}
+
diff --git a/libntfs-3g/cache.c b/libntfs-3g/cache.c
new file mode 100755
index 0000000000000000000000000000000000000000..2ad8d359e101f341bada80836b858f8ea3885b16
--- /dev/null
+++ b/libntfs-3g/cache.c
@@ -0,0 +1,606 @@
+/**
+ * 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
+}
diff --git a/libntfs-3g/collate.c b/libntfs-3g/collate.c
new file mode 100755
index 0000000000000000000000000000000000000000..5f7a015a14963c190a8ab06a2bd070d809f5e7de
--- /dev/null
+++ b/libntfs-3g/collate.c
@@ -0,0 +1,271 @@
+/**
+ * collate.c - NTFS collation handling.  Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2004 Anton Altaparmakov
+ * Copyright (c) 2005 Yura Pakhuchiy
+ *
+ * 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
+#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"
+
+/**
+ * ntfs_collate_binary - Which of two binary objects should be listed first
+ * @vol: unused
+ * @data1:
+ * @data1_len:
+ * @data2:
+ * @data2_len:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static int ntfs_collate_binary(ntfs_volume *vol __attribute__((unused)),
+		const void *data1, const int data1_len,
+		const void *data2, const int data2_len)
+{
+	int rc;
+
+	ntfs_log_trace("Entering.\n");
+	rc = memcmp(data1, data2, min(data1_len, data2_len));
+	if (!rc && (data1_len != data2_len)) {
+		if (data1_len < data2_len)
+			rc = -1;
+		else
+			rc = 1;
+	}
+	ntfs_log_trace("Done, returning %i.\n", rc);
+	return rc;
+}
+
+/**
+ * ntfs_collate_ntofs_ulong - Which of two long ints should be listed first
+ * @vol: unused
+ * @data1:
+ * @data1_len:
+ * @data2:
+ * @data2_len:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static int ntfs_collate_ntofs_ulong(ntfs_volume *vol __attribute__((unused)),
+		const void *data1, const int data1_len,
+		const void *data2, const int data2_len)
+{
+	int rc;
+	u32 d1, d2;
+
+	ntfs_log_trace("Entering.\n");
+	if (data1_len != data2_len || data1_len != 4) {
+		ntfs_log_error("data1_len or/and data2_len not equal to 4.\n");
+		return NTFS_COLLATION_ERROR;
+	}
+	d1 = le32_to_cpup(data1);
+	d2 = le32_to_cpup(data2);
+	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_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:
+ * @data1:
+ * @data1_len: unused
+ * @data2:
+ * @data2_len: unused
+ *
+ * Description...
+ *
+ * Returns:
+ */
+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);
+	ntfs_log_trace("Done, returning %i.\n", rc);
+	return rc;
+}
+
+/*
+ *		Get a pointer to appropriate collation function.
+ *
+ *	Returns NULL if the needed function is not implemented
+ */
+
+COLLATE ntfs_get_collate_function(COLLATION_RULES cr)
+{
+	COLLATE collate;
+
+	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;
+	}
+	return (collate);
+}
diff --git a/libntfs-3g/compat.c b/libntfs-3g/compat.c
new file mode 100755
index 0000000000000000000000000000000000000000..63114a48707886ed5836ceb6b0e1d7d3b6432776
--- /dev/null
+++ b/libntfs-3g/compat.c
@@ -0,0 +1,250 @@
+/**
+ * compat.c - Tweaks for Windows compatibility
+ *
+ * Copyright (c) 2002 Richard Russon
+ * Copyright (c) 2002-2004 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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "compat.h"
+
+#ifndef HAVE_FFS
+/**
+ * ffs - Find the first set bit in an int
+ * @x:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+int ffs(int x)
+{
+	int r = 1;
+
+	if (!x)
+		return 0;
+	if (!(x & 0xffff)) {
+		x >>= 16;
+		r += 16;
+	}
+	if (!(x & 0xff)) {
+		x >>= 8;
+		r += 8;
+	}
+	if (!(x & 0xf)) {
+		x >>= 4;
+		r += 4;
+	}
+	if (!(x & 3)) {
+		x >>= 2;
+		r += 2;
+	}
+	if (!(x & 1)) {
+		x >>= 1;
+		r += 1;
+	}
+	return r;
+}
+#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 */
+
diff --git a/libntfs-3g/compress.c b/libntfs-3g/compress.c
new file mode 100755
index 0000000000000000000000000000000000000000..f1070aa273d390eb493b482160a4333b492cf5d9
--- /dev/null
+++ b/libntfs-3g/compress.c
@@ -0,0 +1,1938 @@
+/**
+ * compress.c - Compressed attribute handling code.  Originated from the Linux-NTFS
+ *		project.
+ *
+ * Copyright (c) 2004-2005 Anton Altaparmakov
+ * Copyright (c) 2004-2006 Szabolcs Szakacsits
+ * Copyright (c)      2005 Yura Pakhuchiy
+ * Copyright (c) 2009-2014 Jean-Pierre Andre
+ * Copyright (c)      2014 Eric Biggers
+ *
+ * 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_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "attrib.h"
+#include "debug.h"
+#include "volume.h"
+#include "types.h"
+#include "layout.h"
+#include "runlist.h"
+#include "compress.h"
+#include "lcnalloc.h"
+#include "logging.h"
+#include "misc.h"
+
+#undef le16_to_cpup 
+/* the standard le16_to_cpup() crashes for unaligned data on some processors */ 
+#define le16_to_cpup(p) (*(u8*)(p) + (((u8*)(p))[1] << 8))
+
+/**
+ * enum ntfs_compression_constants - constants used in the compression code
+ */
+typedef enum {
+	/* Token types and access mask. */
+	NTFS_SYMBOL_TOKEN	=	0,
+	NTFS_PHRASE_TOKEN	=	1,
+	NTFS_TOKEN_MASK		=	1,
+
+	/* Compression sub-block constants. */
+	NTFS_SB_SIZE_MASK	=	0x0fff,
+	NTFS_SB_SIZE		=	0x1000,
+	NTFS_SB_IS_COMPRESSED	=	0x8000,
+} ntfs_compression_constants;
+
+/* Match length at or above which ntfs_best_match() will stop searching for
+ * longer matches.  */
+#define NICE_MATCH_LEN 18
+
+/* Maximum number of potential matches that ntfs_best_match() will consider at
+ * each position.  */
+#define MAX_SEARCH_DEPTH 24
+
+/* log base 2 of the number of entries in the hash table for match-finding.  */
+#define HASH_SHIFT 14
+
+/* Constant for the multiplicative hash function.  */
+#define HASH_MULTIPLIER 0x1E35A7BD
+
+struct COMPRESS_CONTEXT {
+	const unsigned char *inbuf;
+	int bufsize;
+	int size;
+	int rel;
+	int mxsz;
+	s16 head[1 << HASH_SHIFT];
+	s16 prev[NTFS_SB_SIZE];
+} ;
+
+/*
+ *		Hash the next 3-byte sequence in the input buffer
+ */
+static inline unsigned int ntfs_hash(const u8 *p)
+{
+	u32 str;
+	u32 hash;
+
+#if defined(__i386__) || defined(__x86_64__)
+	/* Unaligned access allowed, and little endian CPU.
+	 * Callers ensure that at least 4 (not 3) bytes are remaining.  */
+	str = *(const u32 *)p & 0xFFFFFF;
+#else
+	str = ((u32)p[0] << 0) | ((u32)p[1] << 8) | ((u32)p[2] << 16);
+#endif
+
+	hash = str * HASH_MULTIPLIER;
+
+	/* High bits are more random than the low bits.  */
+	return hash >> (32 - HASH_SHIFT);
+}
+
+/*
+ *		Search for the longest sequence matching current position
+ *
+ *	A hash table, each entry of which points to a chain of sequence
+ *	positions sharing the corresponding hash code, is maintained to speed up
+ *	searching for matches.  To maintain the hash table, either
+ *	ntfs_best_match() or ntfs_skip_position() has to be called for each
+ *	consecutive position.
+ *
+ *	This function is heavily used; it has to be optimized carefully.
+ *
+ *	This function sets pctx->size and pctx->rel to the length and offset,
+ *	respectively, of the longest match found.
+ *
+ *	The minimum match length is assumed to be 3, and the maximum match
+ *	length is assumed to be pctx->mxsz.  If this function produces
+ *	pctx->size < 3, then no match was found.
+ *
+ *	Note: for the following reasons, this function is not guaranteed to find
+ *	*the* longest match up to pctx->mxsz:
+ *
+ *	(1) If this function finds a match of NICE_MATCH_LEN bytes or greater,
+ *	    it ends early because a match this long is good enough and it's not
+ *	    worth spending more time searching.
+ *
+ *	(2) If this function considers MAX_SEARCH_DEPTH matches with a single
+ *	    position, it ends early and returns the longest match found so far.
+ *	    This saves a lot of time on degenerate inputs.
+ */
+static void ntfs_best_match(struct COMPRESS_CONTEXT *pctx, const int i,
+			    int best_len)
+{
+	const u8 * const inbuf = pctx->inbuf;
+	const u8 * const strptr = &inbuf[i]; /* String we're matching against */
+	s16 * const prev = pctx->prev;
+	const int max_len = min(pctx->bufsize - i, pctx->mxsz);
+	const int nice_len = min(NICE_MATCH_LEN, max_len);
+	int depth_remaining = MAX_SEARCH_DEPTH;
+	const u8 *best_matchptr = strptr;
+	unsigned int hash;
+	s16 cur_match;
+	const u8 *matchptr;
+	int len;
+
+	if (max_len < 4)
+		goto out;
+
+	/* Insert the current sequence into the appropriate hash chain.  */
+	hash = ntfs_hash(strptr);
+	cur_match = pctx->head[hash];
+	prev[i] = cur_match;
+	pctx->head[hash] = i;
+
+	if (best_len >= max_len) {
+		/* Lazy match is being attempted, but there aren't enough length
+		 * bits remaining to code a longer match.  */
+		goto out;
+	}
+
+	/* Search the appropriate hash chain for matches.  */
+
+	for (; cur_match >= 0 && depth_remaining--;
+		cur_match = prev[cur_match])
+	{
+
+		matchptr = &inbuf[cur_match];
+
+		/* Considering the potential match at 'matchptr':  is it longer
+		 * than 'best_len'?
+		 *
+		 * The bytes at index 'best_len' are the most likely to differ,
+		 * so check them first.
+		 *
+		 * The bytes at indices 'best_len - 1' and '0' are less
+		 * important to check separately.  But doing so still gives a
+		 * slight performance improvement, at least on x86_64, probably
+		 * because they create separate branches for the CPU to predict
+		 * independently of the branches in the main comparison loops.
+		 */
+		if (matchptr[best_len] != strptr[best_len] ||
+		    matchptr[best_len - 1] != strptr[best_len - 1] ||
+		    matchptr[0] != strptr[0])
+			goto next_match;
+
+		for (len = 1; len < best_len - 1; len++)
+			if (matchptr[len] != strptr[len])
+				goto next_match;
+
+		/* The match is the longest found so far ---
+		 * at least 'best_len' + 1 bytes.  Continue extending it.  */
+
+		best_matchptr = matchptr;
+
+		do {
+			if (++best_len >= nice_len) {
+				/* 'nice_len' reached; don't waste time
+				 * searching for longer matches.  Extend the
+				 * match as far as possible and terminate the
+				 * search.  */
+				while (best_len < max_len &&
+					(best_matchptr[best_len] ==
+						strptr[best_len]))
+				{
+					best_len++;
+				}
+				goto out;
+			}
+		} while (best_matchptr[best_len] == strptr[best_len]);
+
+		/* Found a longer match, but 'nice_len' not yet reached.  */
+
+	next_match:
+		/* Continue to next match in the chain.  */
+		;
+	}
+
+	/* Reached end of chain, or ended early due to reaching the maximum
+	 * search depth.  */
+
+out:
+	/* Return the longest match we were able to find.  */
+	pctx->size = best_len;
+	pctx->rel = best_matchptr - strptr; /* given as a negative number! */
+}
+
+/*
+ *		Advance the match-finder, but don't search for matches.
+ */
+static void ntfs_skip_position(struct COMPRESS_CONTEXT *pctx, const int i)
+{
+	unsigned int hash;
+
+	if (pctx->bufsize - i < 4)
+		return;
+
+	/* Insert the current sequence into the appropriate hash chain.  */
+	hash = ntfs_hash(pctx->inbuf + i);
+	pctx->prev[i] = pctx->head[hash];
+	pctx->head[hash] = i;
+}
+
+/*
+ *		Compress a 4096-byte block
+ *
+ *	Returns a header of two bytes followed by the compressed data.
+ *	If compression is not effective, the header and an uncompressed
+ *	block is returned.
+ *
+ *	Note : two bytes may be output before output buffer overflow
+ *	is detected, so a 4100-bytes output buffer must be reserved.
+ *
+ *	Returns the size of the compressed block, including the
+ *			header (minimal size is 2, maximum size is 4098)
+ *		0 if an error has been met. 
+ */
+
+static unsigned int ntfs_compress_block(const char *inbuf, const int bufsize,
+				char *outbuf)
+{
+	struct COMPRESS_CONTEXT *pctx;
+	int i; /* current position */
+	int j; /* end of best match from current position */
+	int k; /* end of best match from next position */
+	int offs; /* offset to best match */
+	int bp; /* bits to store offset */
+	int bp_cur; /* saved bits to store offset at current position */
+	int mxoff; /* max match offset : 1 << bp */
+	unsigned int xout;
+	unsigned int q; /* aggregated offset and size */
+	int have_match; /* do we have a match at the current position? */
+	char *ptag; /* location reserved for a tag */
+	int tag;    /* current value of tag */
+	int ntag;   /* count of bits still undefined in tag */
+
+	pctx = ntfs_malloc(sizeof(struct COMPRESS_CONTEXT));
+	if (!pctx) {
+		errno = ENOMEM;
+		return 0;
+	}
+
+	/* All hash chains start as empty.  The special value '-1' indicates the
+	 * end of each hash chain.  */
+	memset(pctx->head, 0xFF, sizeof(pctx->head));
+
+	pctx->inbuf = (const unsigned char*)inbuf;
+	pctx->bufsize = bufsize;
+	xout = 2;
+	i = 0;
+	bp = 4;
+	mxoff = 1 << bp;
+	pctx->mxsz = (1 << (16 - bp)) + 2;
+	have_match = 0;
+	tag = 0;
+	ntag = 8;
+	ptag = &outbuf[xout++];
+
+	while ((i < bufsize) && (xout < (NTFS_SB_SIZE + 2))) {
+
+		/* This implementation uses "lazy" parsing: it always chooses
+		 * the longest match, unless the match at the next position is
+		 * longer.  This is the same strategy used by the high
+		 * compression modes of zlib.  */
+
+		if (!have_match) {
+			/* Find the longest match at the current position.  But
+			 * first adjust the maximum match length if needed.
+			 * (This loop might need to run more than one time in
+			 * the case that we just output a long match.)  */
+			while (mxoff < i) {
+				bp++;
+				mxoff <<= 1;
+				pctx->mxsz = (pctx->mxsz + 2) >> 1;
+			}
+			ntfs_best_match(pctx, i, 2);
+		}
+
+		if (pctx->size >= 3) {
+
+			/* Found a match at the current position.  */
+
+			j = i + pctx->size;
+			bp_cur = bp;
+			offs = pctx->rel;
+
+			if (pctx->size >= NICE_MATCH_LEN) {
+
+				/* Choose long matches immediately.  */
+
+				q = (~offs << (16 - bp_cur)) + (j - i - 3);
+				outbuf[xout++] = q & 255;
+				outbuf[xout++] = (q >> 8) & 255;
+				tag |= (1 << (8 - ntag));
+
+				if (j == bufsize) {
+					/* Shortcut if the match extends to the
+					 * end of the buffer.  */
+					i = j;
+					--ntag;
+					break;
+				}
+				i += 1;
+				do {
+					ntfs_skip_position(pctx, i);
+				} while (++i != j);
+				have_match = 0;
+			} else {
+				/* Check for a longer match at the next
+				 * position.  */
+
+				/* Doesn't need to be while() since we just
+				 * adjusted the maximum match length at the
+				 * previous position.  */
+				if (mxoff < i + 1) {
+					bp++;
+					mxoff <<= 1;
+					pctx->mxsz = (pctx->mxsz + 2) >> 1;
+				}
+				ntfs_best_match(pctx, i + 1, pctx->size);
+				k = i + 1 + pctx->size;
+
+				if (k > (j + 1)) {
+					/* Next match is longer.
+					 * Output a literal.  */
+					outbuf[xout++] = inbuf[i++];
+					have_match = 1;
+				} else {
+					/* Next match isn't longer.
+					 * Output the current match.  */
+					q = (~offs << (16 - bp_cur)) +
+							(j - i - 3);
+					outbuf[xout++] = q & 255;
+					outbuf[xout++] = (q >> 8) & 255;
+					tag |= (1 << (8 - ntag));
+
+					/* The minimum match length is 3, and
+					 * we've run two bytes through the
+					 * matchfinder already.  So the minimum
+					 * number of positions we need to skip
+					 * is 1.  */
+					i += 2;
+					do {
+						ntfs_skip_position(pctx, i);
+					} while (++i != j);
+					have_match = 0;
+				}
+			}
+		} else {
+			/* No match at current position.  Output a literal.  */
+			outbuf[xout++] = inbuf[i++];
+			have_match = 0;
+		}
+
+		/* Store the tag if fully used.  */
+		if (!--ntag) {
+			*ptag = tag;
+			ntag = 8;
+			ptag = &outbuf[xout++];
+			tag = 0;
+		}
+	}
+
+	/* Store the last tag if partially used.  */
+	if (ntag == 8)
+		xout--;
+	else
+		*ptag = tag;
+
+	/* Determine whether to store the data compressed or uncompressed.  */
+
+	if ((i >= bufsize) && (xout < (NTFS_SB_SIZE + 2))) {
+		/* Compressed.  */
+		outbuf[0] = (xout - 3) & 255;
+		outbuf[1] = 0xb0 + (((xout - 3) >> 8) & 15);
+	} else {
+		/* Uncompressed.  */
+		memcpy(&outbuf[2], inbuf, bufsize);
+		if (bufsize < NTFS_SB_SIZE)
+			memset(&outbuf[bufsize + 2], 0, NTFS_SB_SIZE - bufsize);
+		outbuf[0] = 0xff;
+		outbuf[1] = 0x3f;
+		xout = NTFS_SB_SIZE + 2;
+	}
+
+	/* Free the compression context and return the total number of bytes
+	 * written to 'outbuf'.  */
+	free(pctx);
+	return (xout);
+}
+
+/**
+ * ntfs_decompress - decompress a compression block into an array of pages
+ * @dest:	buffer to which to write the decompressed data
+ * @dest_size:	size of buffer @dest in bytes
+ * @cb_start:	compression block to decompress
+ * @cb_size:	size of compression block @cb_start in bytes
+ *
+ * This decompresses the compression block @cb_start into the destination
+ * buffer @dest.
+ *
+ * @cb_start is a pointer to the compression block which needs decompressing
+ * and @cb_size is the size of @cb_start in bytes (8-64kiB).
+ *
+ * Return 0 if success or -EOVERFLOW on error in the compressed stream.
+ */
+static int ntfs_decompress(u8 *dest, const u32 dest_size,
+		u8 *const cb_start, const u32 cb_size)
+{
+	/*
+	 * Pointers into the compressed data, i.e. the compression block (cb),
+	 * and the therein contained sub-blocks (sb).
+	 */
+	u8 *cb_end = cb_start + cb_size; /* End of cb. */
+	u8 *cb = cb_start;	/* Current position in cb. */
+	u8 *cb_sb_start = cb;	/* Beginning of the current sb in the cb. */
+	u8 *cb_sb_end;		/* End of current sb / beginning of next sb. */
+	/* Variables for uncompressed data / destination. */
+	u8 *dest_end = dest + dest_size;	/* End of dest buffer. */
+	u8 *dest_sb_start;	/* Start of current sub-block in dest. */
+	u8 *dest_sb_end;	/* End of current sb in dest. */
+	/* Variables for tag and token parsing. */
+	u8 tag;			/* Current tag. */
+	int token;		/* Loop counter for the eight tokens in tag. */
+
+	ntfs_log_trace("Entering, cb_size = 0x%x.\n", (unsigned)cb_size);
+do_next_sb:
+	ntfs_log_debug("Beginning sub-block at offset = %d in the cb.\n",
+			(int)(cb - cb_start));
+	/*
+	 * Have we reached the end of the compression block or the end of the
+	 * decompressed data?  The latter can happen for example if the current
+	 * position in the compression block is one byte before its end so the
+	 * first two checks do not detect it.
+	 */
+	if (cb == cb_end || !le16_to_cpup((le16*)cb) || dest == dest_end) {
+		ntfs_log_debug("Completed. Returning success (0).\n");
+		return 0;
+	}
+	/* Setup offset for the current sub-block destination. */
+	dest_sb_start = dest;
+	dest_sb_end = dest + NTFS_SB_SIZE;
+	/* Check that we are still within allowed boundaries. */
+	if (dest_sb_end > dest_end)
+		goto return_overflow;
+	/* Does the minimum size of a compressed sb overflow valid range? */
+	if (cb + 6 > cb_end)
+		goto return_overflow;
+	/* Setup the current sub-block source pointers and validate range. */
+	cb_sb_start = cb;
+	cb_sb_end = cb_sb_start + (le16_to_cpup((le16*)cb) & NTFS_SB_SIZE_MASK)
+			+ 3;
+	if (cb_sb_end > cb_end)
+		goto return_overflow;
+	/* Now, we are ready to process the current sub-block (sb). */
+	if (!(le16_to_cpup((le16*)cb) & NTFS_SB_IS_COMPRESSED)) {
+		ntfs_log_debug("Found uncompressed sub-block.\n");
+		/* This sb is not compressed, just copy it into destination. */
+		/* Advance source position to first data byte. */
+		cb += 2;
+		/* An uncompressed sb must be full size. */
+		if (cb_sb_end - cb != NTFS_SB_SIZE)
+			goto return_overflow;
+		/* Copy the block and advance the source position. */
+		memcpy(dest, cb, NTFS_SB_SIZE);
+		cb += NTFS_SB_SIZE;
+		/* Advance destination position to next sub-block. */
+		dest += NTFS_SB_SIZE;
+		goto do_next_sb;
+	}
+	ntfs_log_debug("Found compressed sub-block.\n");
+	/* This sb is compressed, decompress it into destination. */
+	/* Forward to the first tag in the sub-block. */
+	cb += 2;
+do_next_tag:
+	if (cb == cb_sb_end) {
+		/* Check if the decompressed sub-block was not full-length. */
+		if (dest < dest_sb_end) {
+			int nr_bytes = dest_sb_end - dest;
+
+			ntfs_log_debug("Filling incomplete sub-block with zeroes.\n");
+			/* Zero remainder and update destination position. */
+			memset(dest, 0, nr_bytes);
+			dest += nr_bytes;
+		}
+		/* We have finished the current sub-block. */
+		goto do_next_sb;
+	}
+	/* Check we are still in range. */
+	if (cb > cb_sb_end || dest > dest_sb_end)
+		goto return_overflow;
+	/* Get the next tag and advance to first token. */
+	tag = *cb++;
+	/* Parse the eight tokens described by the tag. */
+	for (token = 0; token < 8; token++, tag >>= 1) {
+		u16 lg, pt, length, max_non_overlap;
+		register u16 i;
+		u8 *dest_back_addr;
+
+		/* Check if we are done / still in range. */
+		if (cb >= cb_sb_end || dest > dest_sb_end)
+			break;
+		/* Determine token type and parse appropriately.*/
+		if ((tag & NTFS_TOKEN_MASK) == NTFS_SYMBOL_TOKEN) {
+			/*
+			 * We have a symbol token, copy the symbol across, and
+			 * advance the source and destination positions.
+			 */
+			*dest++ = *cb++;
+			/* Continue with the next token. */
+			continue;
+		}
+		/*
+		 * We have a phrase token. Make sure it is not the first tag in
+		 * the sb as this is illegal and would confuse the code below.
+		 */
+		if (dest == dest_sb_start)
+			goto return_overflow;
+		/*
+		 * Determine the number of bytes to go back (p) and the number
+		 * of bytes to copy (l). We use an optimized algorithm in which
+		 * we first calculate log2(current destination position in sb),
+		 * which allows determination of l and p in O(1) rather than
+		 * O(n). We just need an arch-optimized log2() function now.
+		 */
+		lg = 0;
+		for (i = dest - dest_sb_start - 1; i >= 0x10; i >>= 1)
+			lg++;
+		/* Get the phrase token into i. */
+		pt = le16_to_cpup((le16*)cb);
+		/*
+		 * Calculate starting position of the byte sequence in
+		 * the destination using the fact that p = (pt >> (12 - lg)) + 1
+		 * and make sure we don't go too far back.
+		 */
+		dest_back_addr = dest - (pt >> (12 - lg)) - 1;
+		if (dest_back_addr < dest_sb_start)
+			goto return_overflow;
+		/* Now calculate the length of the byte sequence. */
+		length = (pt & (0xfff >> lg)) + 3;
+		/* Verify destination is in range. */
+		if (dest + length > dest_sb_end)
+			goto return_overflow;
+		/* The number of non-overlapping bytes. */
+		max_non_overlap = dest - dest_back_addr;
+		if (length <= max_non_overlap) {
+			/* The byte sequence doesn't overlap, just copy it. */
+			memcpy(dest, dest_back_addr, length);
+			/* Advance destination pointer. */
+			dest += length;
+		} else {
+			/*
+			 * The byte sequence does overlap, copy non-overlapping
+			 * part and then do a slow byte by byte copy for the
+			 * overlapping part. Also, advance the destination
+			 * pointer.
+			 */
+			memcpy(dest, dest_back_addr, max_non_overlap);
+			dest += max_non_overlap;
+			dest_back_addr += max_non_overlap;
+			length -= max_non_overlap;
+			while (length--)
+				*dest++ = *dest_back_addr++;
+		}
+		/* Advance source position and continue with the next token. */
+		cb += 2;
+	}
+	/* No tokens left in the current tag. Continue with the next tag. */
+	goto do_next_tag;
+return_overflow:
+	errno = EOVERFLOW;
+	ntfs_log_perror("Failed to decompress file");
+	return -1;
+}
+
+/**
+ * ntfs_is_cb_compressed - internal function, do not use
+ *
+ * This is a very specialised function determining if a cb is compressed or
+ * uncompressed.  It is assumed that checking for a sparse cb has already been
+ * performed and that the cb is not sparse.  It makes all sorts of other
+ * assumptions as well and hence it is not useful anywhere other than where it
+ * is used at the moment.  Please, do not make this function available for use
+ * outside of compress.c as it is bound to confuse people and not do what they
+ * want.
+ *
+ * Return TRUE on errors so that the error will be detected later on in the
+ * code.  Might be a bit confusing to debug but there really should never be
+ * errors coming from here.
+ */
+static BOOL ntfs_is_cb_compressed(ntfs_attr *na, runlist_element *rl, 
+				  VCN cb_start_vcn, int cb_clusters)
+{
+	/*
+	 * The simplest case: the run starting at @cb_start_vcn contains
+	 * @cb_clusters clusters which are all not sparse, thus the cb is not
+	 * compressed.
+	 */
+restart:
+	cb_clusters -= rl->length - (cb_start_vcn - rl->vcn);
+	while (cb_clusters > 0) {
+		/* Go to the next run. */
+		rl++;
+		/* Map the next runlist fragment if it is not mapped. */
+		if (rl->lcn < LCN_HOLE || !rl->length) {
+			cb_start_vcn = rl->vcn;
+			rl = ntfs_attr_find_vcn(na, rl->vcn);
+			if (!rl || rl->lcn < LCN_HOLE || !rl->length)
+				return TRUE;
+			/*
+			 * If the runs were merged need to deal with the
+			 * resulting partial run so simply restart.
+			 */
+			if (rl->vcn < cb_start_vcn)
+				goto restart;
+		}
+		/* If the current run is sparse, the cb is compressed. */
+		if (rl->lcn == LCN_HOLE)
+			return TRUE;
+		/* If the whole cb is not sparse, it is not compressed. */
+		if (rl->length >= cb_clusters)
+			return FALSE;
+		cb_clusters -= rl->length;
+	};
+	/* All cb_clusters were not sparse thus the cb is not compressed. */
+	return FALSE;
+}
+
+/**
+ * ntfs_compressed_attr_pread - read from a compressed attribute
+ * @na:		ntfs attribute to read from
+ * @pos:	byte position in the attribute to begin reading from
+ * @count:	number of bytes to read
+ * @b:		output data buffer
+ *
+ * NOTE:  You probably want to be using attrib.c::ntfs_attr_pread() instead.
+ *
+ * This function will read @count bytes starting at offset @pos from the
+ * compressed ntfs attribute @na into the data buffer @b.
+ *
+ * On success, return the number of successfully read bytes.  If this number
+ * is lower than @count this means that the read reached end of file or that
+ * an error was encountered during the read so that the read is partial.
+ * 0 means end of file or nothing was read (also return 0 when @count is 0).
+ *
+ * On error and nothing has been read, return -1 with errno set appropriately
+ * to the return code of ntfs_pread(), or to EINVAL in case of invalid
+ * arguments.
+ */
+s64 ntfs_compressed_attr_pread(ntfs_attr *na, s64 pos, s64 count, void *b)
+{
+	s64 br, to_read, ofs, total, total2;
+	u64 cb_size_mask;
+	VCN start_vcn, vcn, end_vcn;
+	ntfs_volume *vol;
+	runlist_element *rl;
+	u8 *dest, *cb, *cb_pos, *cb_end;
+	u32 cb_size;
+	int err;
+	ATTR_FLAGS data_flags;
+	FILE_ATTR_FLAGS compression;
+	unsigned int nr_cbs, cb_clusters;
+
+	ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, pos 0x%llx, count 0x%llx.\n",
+			(unsigned long long)na->ni->mft_no, na->type,
+			(long long)pos, (long long)count);
+	data_flags = na->data_flags;
+	compression = na->ni->flags & FILE_ATTR_COMPRESSED;
+	if (!na || !na->ni || !na->ni->vol || !b
+			|| ((data_flags & ATTR_COMPRESSION_MASK)
+				!= ATTR_IS_COMPRESSED)
+			|| pos < 0 || count < 0) {
+		errno = EINVAL;
+		return -1;
+	}
+	/*
+	 * Encrypted attributes are not supported.  We return access denied,
+	 * which is what Windows NT4 does, too.
+	 */
+	if (NAttrEncrypted(na)) {
+		errno = EACCES;
+		return -1;
+	}
+	if (!count)
+		return 0;
+	/* Truncate reads beyond end of attribute. */
+	if (pos + count > na->data_size) {
+		if (pos >= na->data_size) {
+			return 0;
+		}
+		count = na->data_size - pos;
+	}
+	/* If it is a resident attribute, simply use ntfs_attr_pread(). */
+	if (!NAttrNonResident(na))
+		return ntfs_attr_pread(na, pos, count, b);
+	total = total2 = 0;
+	/* Zero out reads beyond initialized size. */
+	if (pos + count > na->initialized_size) {
+		if (pos >= na->initialized_size) {
+			memset(b, 0, count);
+			return count;
+		}
+		total2 = pos + count - na->initialized_size;
+		count -= total2;
+		memset((u8*)b + count, 0, total2);
+	}
+	vol = na->ni->vol;
+	cb_size = na->compression_block_size;
+	cb_size_mask = cb_size - 1UL;
+	cb_clusters = na->compression_block_clusters;
+	
+	/* Need a temporary buffer for each loaded compression block. */
+	cb = (u8*)ntfs_malloc(cb_size);
+	if (!cb)
+		return -1;
+	
+	/* Need a temporary buffer for each uncompressed block. */
+	dest = (u8*)ntfs_malloc(cb_size);
+	if (!dest) {
+		free(cb);
+		return -1;
+	}
+	/*
+	 * The first vcn in the first compression block (cb) which we need to
+	 * decompress.
+	 */
+	start_vcn = (pos & ~cb_size_mask) >> vol->cluster_size_bits;
+	/* Offset in the uncompressed cb at which to start reading data. */
+	ofs = pos & cb_size_mask;
+	/*
+	 * The first vcn in the cb after the last cb which we need to
+	 * decompress.
+	 */
+	end_vcn = ((pos + count + cb_size - 1) & ~cb_size_mask) >>
+			vol->cluster_size_bits;
+	/* Number of compression blocks (cbs) in the wanted vcn range. */
+	nr_cbs = (end_vcn - start_vcn) << vol->cluster_size_bits >>
+			na->compression_block_size_bits;
+	cb_end = cb + cb_size;
+do_next_cb:
+	nr_cbs--;
+	cb_pos = cb;
+	vcn = start_vcn;
+	start_vcn += cb_clusters;
+
+	/* Check whether the compression block is sparse. */
+	rl = ntfs_attr_find_vcn(na, vcn);
+	if (!rl || rl->lcn < LCN_HOLE) {
+		free(cb);
+		free(dest);
+		if (total)
+			return total;
+		/* FIXME: Do we want EIO or the error code? (AIA) */
+		errno = EIO;
+		return -1;
+	}
+	if (rl->lcn == LCN_HOLE) {
+		/* Sparse cb, zero out destination range overlapping the cb. */
+		ntfs_log_debug("Found sparse compression block.\n");
+		to_read = min(count, cb_size - ofs);
+		memset(b, 0, to_read);
+		ofs = 0;
+		total += to_read;
+		count -= to_read;
+		b = (u8*)b + to_read;
+	} else if (!ntfs_is_cb_compressed(na, rl, vcn, cb_clusters)) {
+		s64 tdata_size, tinitialized_size;
+		/*
+		 * Uncompressed cb, read it straight into the destination range
+		 * overlapping the cb.
+		 */
+		ntfs_log_debug("Found uncompressed compression block.\n");
+		/*
+		 * Read the uncompressed data into the destination buffer.
+		 * NOTE: We cheat a little bit here by marking the attribute as
+		 * not compressed in the ntfs_attr structure so that we can
+		 * read the data by simply using ntfs_attr_pread().  (-8
+		 * NOTE: we have to modify data_size and initialized_size
+		 * temporarily as well...
+		 */
+		to_read = min(count, cb_size - ofs);
+		ofs += vcn << vol->cluster_size_bits;
+		NAttrClearCompressed(na);
+		na->data_flags &= ~ATTR_COMPRESSION_MASK;
+		tdata_size = na->data_size;
+		tinitialized_size = na->initialized_size;
+		na->data_size = na->initialized_size = na->allocated_size;
+		do {
+			br = ntfs_attr_pread(na, ofs, to_read, b);
+			if (br <= 0) {
+				if (!br) {
+					ntfs_log_error("Failed to read an"
+						" uncompressed cluster,"
+						" inode %lld offs 0x%llx\n",
+						(long long)na->ni->mft_no,
+						(long long)ofs);
+					errno = EIO;
+				}
+				err = errno;
+				na->data_size = tdata_size;
+				na->initialized_size = tinitialized_size;
+				na->ni->flags |= compression;
+				na->data_flags = data_flags;
+				free(cb);
+				free(dest);
+				if (total)
+					return total;
+				errno = err;
+				return br;
+			}
+			total += br;
+			count -= br;
+			b = (u8*)b + br;
+			to_read -= br;
+			ofs += br;
+		} while (to_read > 0);
+		na->data_size = tdata_size;
+		na->initialized_size = tinitialized_size;
+		na->ni->flags |= compression;
+		na->data_flags = data_flags;
+		ofs = 0;
+	} else {
+		s64 tdata_size, tinitialized_size;
+		u32 decompsz;
+
+		/*
+		 * Compressed cb, decompress it into the temporary buffer, then
+		 * copy the data to the destination range overlapping the cb.
+		 */
+		ntfs_log_debug("Found compressed compression block.\n");
+		/*
+		 * Read the compressed data into the temporary buffer.
+		 * NOTE: We cheat a little bit here by marking the attribute as
+		 * not compressed in the ntfs_attr structure so that we can
+		 * read the raw, compressed data by simply using
+		 * ntfs_attr_pread().  (-8
+		 * NOTE: We have to modify data_size and initialized_size
+		 * temporarily as well...
+		 */
+		to_read = cb_size;
+		NAttrClearCompressed(na);
+		na->data_flags &= ~ATTR_COMPRESSION_MASK;
+		tdata_size = na->data_size;
+		tinitialized_size = na->initialized_size;
+		na->data_size = na->initialized_size = na->allocated_size;
+		do {
+			br = ntfs_attr_pread(na,
+					(vcn << vol->cluster_size_bits) +
+					(cb_pos - cb), to_read, cb_pos);
+			if (br <= 0) {
+				if (!br) {
+					ntfs_log_error("Failed to read a"
+						" compressed cluster, "
+						" inode %lld offs 0x%llx\n",
+						(long long)na->ni->mft_no,
+						(long long)(vcn << vol->cluster_size_bits));
+					errno = EIO;
+				}
+				err = errno;
+				na->data_size = tdata_size;
+				na->initialized_size = tinitialized_size;
+				na->ni->flags |= compression;
+				na->data_flags = data_flags;
+				free(cb);
+				free(dest);
+				if (total)
+					return total;
+				errno = err;
+				return br;
+			}
+			cb_pos += br;
+			to_read -= br;
+		} while (to_read > 0);
+		na->data_size = tdata_size;
+		na->initialized_size = tinitialized_size;
+		na->ni->flags |= compression;
+		na->data_flags = data_flags;
+		/* Just a precaution. */
+		if (cb_pos + 2 <= cb_end)
+			*(u16*)cb_pos = 0;
+		ntfs_log_debug("Successfully read the compression block.\n");
+		/* Do not decompress beyond the requested block */
+		to_read = min(count, cb_size - ofs);
+		decompsz = ((ofs + to_read - 1) | (NTFS_SB_SIZE - 1)) + 1;
+		if (ntfs_decompress(dest, decompsz, cb, cb_size) < 0) {
+			err = errno;
+			free(cb);
+			free(dest);
+			if (total)
+				return total;
+			errno = err;
+			return -1;
+		}
+		memcpy(b, dest + ofs, to_read);
+		total += to_read;
+		count -= to_read;
+		b = (u8*)b + to_read;
+		ofs = 0;
+	}
+	/* Do we have more work to do? */
+	if (nr_cbs)
+		goto do_next_cb;
+	/* We no longer need the buffers. */
+	free(cb);
+	free(dest);
+	/* Return number of bytes read. */
+	return total + total2;
+}
+
+/*
+ *		Read data from a set of clusters
+ *
+ *	Returns the amount of data read
+ */
+
+static u32 read_clusters(ntfs_volume *vol, const runlist_element *rl,
+			s64 offs, u32 to_read, char *inbuf)
+{
+	u32 count;
+	int xgot;
+	u32 got;
+	s64 xpos;
+	BOOL first;
+	char *xinbuf;
+	const runlist_element *xrl;
+
+	got = 0;
+	xrl = rl;
+	xinbuf = inbuf;
+	first = TRUE;
+	do {
+		count = xrl->length << vol->cluster_size_bits;
+		xpos = xrl->lcn << vol->cluster_size_bits;
+		if (first) {
+			count -= offs;
+			xpos += offs;
+		}
+		if ((to_read - got) < count)
+			count = to_read - got;
+		xgot = ntfs_pread(vol->dev, xpos, count, xinbuf);
+		if (xgot == (int)count) {
+			got += count;
+			xpos += count;
+			xinbuf += count;
+			xrl++;
+		}
+		first = FALSE;
+	} while ((xgot == (int)count) && (got < to_read));
+	return (got);
+}
+
+/*
+ *		Write data to a set of clusters
+ *
+ *	Returns the amount of data written
+ */
+
+static s32 write_clusters(ntfs_volume *vol, const runlist_element *rl,
+			s64 offs, s32 to_write, const char *outbuf)
+{
+	s32 count;
+	s32 put, xput;
+	s64 xpos;
+	BOOL first;
+	const char *xoutbuf;
+	const runlist_element *xrl;
+
+	put = 0;
+	xrl = rl;
+	xoutbuf = outbuf;
+	first = TRUE;
+	do {
+		count = xrl->length << vol->cluster_size_bits;
+		xpos = xrl->lcn << vol->cluster_size_bits;
+		if (first) {
+			count -= offs;
+			xpos += offs;
+		}
+		if ((to_write - put) < count)
+			count = to_write - put;
+		xput = ntfs_pwrite(vol->dev, xpos, count, xoutbuf);
+		if (xput == count) {
+			put += count;
+			xpos += count;
+			xoutbuf += count;
+			xrl++;
+		}
+		first = FALSE;
+	} while ((xput == count) && (put < to_write));
+	return (put);
+}
+
+
+/*
+ *		Compress and write a set of blocks
+ *
+ *	returns the size actually written (rounded to a full cluster)
+ *		or 0 if all zeroes (nothing is written)
+ *		or -1 if could not compress (nothing is written)
+ *		or -2 if there were an irrecoverable error (errno set)
+ */
+
+static s32 ntfs_comp_set(ntfs_attr *na, runlist_element *rl,
+			s64 offs, u32 insz, const char *inbuf)
+{
+	ntfs_volume *vol;
+	char *outbuf;
+	char *pbuf;
+	u32 compsz;
+	s32 written;
+	s32 rounded;
+	unsigned int clsz;
+	u32 p;
+	unsigned int sz;
+	unsigned int bsz;
+	BOOL fail;
+	BOOL allzeroes;
+		/* a single compressed zero */
+	static char onezero[] = { 0x01, 0xb0, 0x00, 0x00 } ;
+		/* a couple of compressed zeroes */
+	static char twozeroes[] = { 0x02, 0xb0, 0x00, 0x00, 0x00 } ;
+		/* more compressed zeroes, to be followed by some count */
+	static char morezeroes[] = { 0x03, 0xb0, 0x02, 0x00 } ;
+
+	vol = na->ni->vol;
+	written = -1; /* default return */
+	clsz = 1 << vol->cluster_size_bits;
+		/* may need 2 extra bytes per block and 2 more bytes */
+	outbuf = (char*)ntfs_malloc(na->compression_block_size
+			+ 2*(na->compression_block_size/NTFS_SB_SIZE)
+			+ 2);
+	if (outbuf) {
+		fail = FALSE;
+		compsz = 0;
+		allzeroes = TRUE;
+		for (p=0; (p<insz) && !fail; p+=NTFS_SB_SIZE) {
+			if ((p + NTFS_SB_SIZE) < insz)
+				bsz = NTFS_SB_SIZE;
+			else
+				bsz = insz - p;
+			pbuf = &outbuf[compsz];
+			sz = ntfs_compress_block(&inbuf[p],bsz,pbuf);
+			/* fail if all the clusters (or more) are needed */
+			if (!sz || ((compsz + sz + clsz + 2)
+					 > na->compression_block_size))
+				fail = TRUE;
+			else {
+				if (allzeroes) {
+				/* check whether this is all zeroes */
+					switch (sz) {
+					case 4 :
+						allzeroes = !memcmp(
+							pbuf,onezero,4);
+						break;
+					case 5 :
+						allzeroes = !memcmp(
+							pbuf,twozeroes,5);
+						break;
+					case 6 :
+						allzeroes = !memcmp(
+							pbuf,morezeroes,4);
+						break;
+					default :
+						allzeroes = FALSE;
+						break;
+					}
+				}
+			compsz += sz;
+			}
+		}
+		if (!fail && !allzeroes) {
+			/* add a couple of null bytes, space has been checked */
+			outbuf[compsz++] = 0;
+			outbuf[compsz++] = 0;
+			/* write a full cluster, to avoid partial reading */
+			rounded = ((compsz - 1) | (clsz - 1)) + 1;
+			written = write_clusters(vol, rl, offs, rounded, outbuf);
+			if (written != rounded) {
+				/*
+				 * TODO : previously written text has been
+				 * spoilt, should return a specific error
+				 */
+				ntfs_log_error("error writing compressed data\n");
+				errno = EIO;
+				written = -2;
+			}
+		} else
+			if (!fail)
+				written = 0;
+		free(outbuf);
+	}
+	return (written);
+}
+
+/*
+ *		Check the validity of a compressed runlist
+ *	The check starts at the beginning of current run and ends
+ *	at the end of runlist
+ *	errno is set if the runlist is not valid
+ */
+
+static BOOL valid_compressed_run(ntfs_attr *na, runlist_element *rl,
+			BOOL fullcheck, const char *text)
+{
+	runlist_element *xrl;
+	const char *err;
+	BOOL ok = TRUE;
+
+	xrl = rl;
+	while (xrl->vcn & (na->compression_block_clusters - 1))
+		xrl--;
+	err = (const char*)NULL;
+	while (xrl->length) {
+		if ((xrl->vcn + xrl->length) != xrl[1].vcn)
+			err = "Runs not adjacent";
+		if (xrl->lcn == LCN_HOLE) {
+			if ((xrl->vcn + xrl->length)
+			    & (na->compression_block_clusters - 1)) {
+				err = "Invalid hole";
+			}
+			if (fullcheck && (xrl[1].lcn == LCN_HOLE)) {
+				err = "Adjacent holes";
+			}
+		}
+		if (err) {
+			ntfs_log_error("%s at %s index %ld inode %lld\n",
+				err, text, (long)(xrl - na->rl),
+				(long long)na->ni->mft_no);
+			errno = EIO;
+			ok = FALSE;
+			err = (const char*)NULL;
+		}
+		xrl++;
+	}
+	return (ok);
+}
+
+/*
+ *		Free unneeded clusters after overwriting compressed data
+ *
+ *	This generally requires one or two empty slots at the end of runlist,
+ *	but we do not want to reallocate the runlist here because
+ *	there are many pointers to it.
+ *	So the empty slots have to be reserved beforehand
+ *
+ *	Returns zero unless some error occurred (described by errno)
+ *
+ *         +======= start of block =====+
+ *      0  |A     chunk may overflow    | <-- rl         usedcnt : A + B
+ *         |A     on previous block     |                        then B
+ *         |A                           |
+ *         +-- end of allocated chunk --+                freelength : C
+ *         |B                           |                      (incl overflow)
+ *         +== end of compressed data ==+
+ *         |C                           | <-- freerl     freecnt : C + D
+ *         |C     chunk may overflow    |
+ *         |C     on next block         |
+ *         +-- end of allocated chunk --+
+ *         |D                           |
+ *         |D     chunk may overflow    |
+ *     15  |D     on next block         |
+ *         +======== end of block ======+
+ *
+ */
+
+static int ntfs_compress_overwr_free(ntfs_attr *na, runlist_element *rl,
+			s32 usedcnt, s32 freecnt, VCN *update_from)
+{
+	BOOL beginhole;
+	BOOL mergeholes;
+	s32 oldlength;
+	s32 freelength;
+	s64 freelcn;
+	s64 freevcn;
+	runlist_element *freerl;
+	ntfs_volume *vol;
+	s32 carry;
+	int res;
+
+	vol = na->ni->vol;
+	res = 0;
+	freelcn = rl->lcn + usedcnt;
+	freevcn = rl->vcn + usedcnt;
+	freelength = rl->length - usedcnt;
+	beginhole = !usedcnt && !rl->vcn;
+		/* can merge with hole before ? */
+	mergeholes = !usedcnt
+			&& rl[0].vcn
+			&& (rl[-1].lcn == LCN_HOLE);
+		/* truncate current run, carry to subsequent hole */
+	carry = freelength;
+	oldlength = rl->length;
+	if (mergeholes) {
+			/* merging with a hole before */
+		freerl = rl;
+	} else {
+		rl->length -= freelength; /* warning : can be zero */
+		freerl = ++rl;
+	}
+	if (!mergeholes && (usedcnt || beginhole)) {
+		s32 freed;
+		runlist_element *frl;
+		runlist_element *erl;
+		int holes = 0;
+		BOOL threeparts;
+
+		/* free the unneeded clusters from initial run, then freerl */
+		threeparts = (freelength > freecnt);
+		freed = 0;
+		frl = freerl;
+		if (freelength) {
+      			res = ntfs_cluster_free_basic(vol,freelcn,
+				(threeparts ? freecnt : freelength));
+			if (!res)
+				freed += (threeparts ? freecnt : freelength);
+			if (!usedcnt) {
+				holes++;
+				freerl--;
+				freerl->length += (threeparts
+						? freecnt : freelength);
+				if (freerl->vcn < *update_from)
+					*update_from = freerl->vcn;
+			}
+   		}
+   		while (!res && frl->length && (freed < freecnt)) {
+      			if (frl->length <= (freecnt - freed)) {
+         			res = ntfs_cluster_free_basic(vol, frl->lcn,
+						frl->length);
+				if (!res) {
+         				freed += frl->length;
+         				frl->lcn = LCN_HOLE;
+					frl->length += carry;
+					carry = 0;
+         				holes++;
+				}
+      			} else {
+         			res = ntfs_cluster_free_basic(vol, frl->lcn,
+						freecnt - freed);
+				if (!res) {
+         				frl->lcn += freecnt - freed;
+         				frl->vcn += freecnt - freed;
+         				frl->length -= freecnt - freed;
+         				freed = freecnt;
+				}
+      			}
+      			frl++;
+   		}
+		na->compressed_size -= freed << vol->cluster_size_bits;
+		switch (holes) {
+		case 0 :
+			/* there are no hole, must insert one */
+			/* space for hole has been prereserved */
+			if (freerl->lcn == LCN_HOLE) {
+				if (threeparts) {
+					erl = freerl;
+					while (erl->length)
+						erl++;
+					do {
+						erl[2] = *erl;
+					} while (erl-- != freerl);
+
+					freerl[1].length = freelength - freecnt;
+					freerl->length = freecnt;
+					freerl[1].lcn = freelcn + freecnt;
+					freerl[1].vcn = freevcn + freecnt;
+					freerl[2].lcn = LCN_HOLE;
+					freerl[2].vcn = freerl[1].vcn
+							+ freerl[1].length;
+					freerl->vcn = freevcn;
+				} else {
+					freerl->vcn = freevcn;
+					freerl->length += freelength;
+				}
+			} else {
+				erl = freerl;
+				while (erl->length)
+					erl++;
+				if (threeparts) {
+					do {
+						erl[2] = *erl;
+					} while (erl-- != freerl);
+					freerl[1].lcn = freelcn + freecnt;
+					freerl[1].vcn = freevcn + freecnt;
+					freerl[1].length = oldlength - usedcnt - freecnt;
+				} else {
+					do {
+						erl[1] = *erl;
+					} while (erl-- != freerl);
+				}
+				freerl->lcn = LCN_HOLE;
+				freerl->vcn = freevcn;
+				freerl->length = freecnt;
+			}
+			break;
+		case 1 :
+			/* there is a single hole, may have to merge */
+			freerl->vcn = freevcn;
+			freerl->length = freecnt;
+			if (freerl[1].lcn == LCN_HOLE) {
+				freerl->length += freerl[1].length;
+				erl = freerl;
+				do {
+					erl++;
+					*erl = erl[1];
+				} while (erl->length);
+			}
+			break;
+		default :
+			/* there were several holes, must merge them */
+			freerl->lcn = LCN_HOLE;
+			freerl->vcn = freevcn;
+			freerl->length = freecnt;
+			if (freerl[holes].lcn == LCN_HOLE) {
+				freerl->length += freerl[holes].length;
+				holes++;
+			}
+			erl = freerl;
+			do {
+				erl++;
+				*erl = erl[holes - 1];
+			} while (erl->length);
+			break;
+		}
+	} else {
+		s32 freed;
+		runlist_element *frl;
+		runlist_element *xrl;
+
+		freed = 0;
+		frl = freerl--;
+		if (freerl->vcn < *update_from)
+			*update_from = freerl->vcn;
+		while (!res && frl->length && (freed < freecnt)) {
+			if (frl->length <= (freecnt - freed)) {
+				freerl->length += frl->length;
+				freed += frl->length;
+				res = ntfs_cluster_free_basic(vol, frl->lcn,
+						frl->length);
+				frl++;
+			} else {
+				freerl->length += freecnt - freed;
+				res = ntfs_cluster_free_basic(vol, frl->lcn,
+						freecnt - freed);
+				frl->lcn += freecnt - freed;
+				frl->vcn += freecnt - freed;
+				frl->length -= freecnt - freed;
+				freed = freecnt;
+			}
+		}
+			/* remove unneded runlist entries */
+		xrl = freerl;
+			/* group with next run if also a hole */
+		if (frl->length && (frl->lcn == LCN_HOLE)) {
+			xrl->length += frl->length;
+			frl++;
+		}
+		while (frl->length) {
+			*++xrl = *frl++;
+		}
+		*++xrl = *frl; /* terminator */
+	na->compressed_size -= freed << vol->cluster_size_bits;
+	}
+	return (res);
+}
+
+
+/*
+ *		Free unneeded clusters after compression
+ *
+ *	This generally requires one or two empty slots at the end of runlist,
+ *	but we do not want to reallocate the runlist here because
+ *	there are many pointers to it.
+ *	So the empty slots have to be reserved beforehand
+ *
+ *	Returns zero unless some error occurred (described by errno)
+ */
+
+static int ntfs_compress_free(ntfs_attr *na, runlist_element *rl,
+				s64 used, s64 reserved, BOOL appending,
+				VCN *update_from)
+{
+	s32 freecnt;
+	s32 usedcnt;
+	int res;
+	s64 freelcn;
+	s64 freevcn;
+	s32 freelength;
+	BOOL mergeholes;
+	BOOL beginhole;
+	ntfs_volume *vol;
+	runlist_element *freerl;
+
+	res = -1; /* default return */
+	vol = na->ni->vol;
+	freecnt = (reserved - used) >> vol->cluster_size_bits;
+	usedcnt = (reserved >> vol->cluster_size_bits) - freecnt;
+	if (rl->vcn < *update_from)
+		*update_from = rl->vcn;
+		/* skip entries fully used, if any */
+	while (rl->length && (rl->length < usedcnt)) {
+		usedcnt -= rl->length; /* must be > 0 */
+		rl++;
+	}
+	if (rl->length) {
+		/*
+		 * Splitting the current allocation block requires
+		 * an extra runlist element to create the hole.
+		 * The required entry has been prereserved when
+		 * mapping the runlist.
+		 */
+			/* get the free part in initial run */
+		freelcn = rl->lcn + usedcnt;
+		freevcn = rl->vcn + usedcnt;
+			/* new count of allocated clusters */
+		if (!((freevcn + freecnt)
+			    & (na->compression_block_clusters - 1))) {
+			if (!appending)
+				res = ntfs_compress_overwr_free(na,rl,
+						usedcnt,freecnt,update_from);
+			else {
+				freelength = rl->length - usedcnt;
+				beginhole = !usedcnt && !rl->vcn;
+				mergeholes = !usedcnt
+						&& rl[0].vcn
+						&& (rl[-1].lcn == LCN_HOLE);
+				if (mergeholes) {
+					s32 carry;
+
+				/* shorten the runs which have free space */
+					carry = freecnt;
+					freerl = rl;
+					while (freerl->length < carry) {
+						carry -= freerl->length;
+						freerl++;
+					}
+					freerl->length = carry;
+					freerl = rl;
+				} else {
+					rl->length = usedcnt; /* can be zero ? */
+					freerl = ++rl;
+				}
+				if ((freelength > 0)
+				    && !mergeholes
+				    && (usedcnt || beginhole)) {
+				/*
+				 * move the unused part to the end. Doing so,
+				 * the vcn will be out of order. This does
+				 * not harm, the vcn are meaningless now, and
+				 * only the lcn are meaningful for freeing.
+				 */
+					/* locate current end */
+					while (rl->length)
+						rl++;
+					/* new terminator relocated */
+					rl[1].vcn = rl->vcn;
+					rl[1].lcn = LCN_ENOENT;
+					rl[1].length = 0;
+					/* hole, currently allocated */
+					rl->vcn = freevcn;
+					rl->lcn = freelcn;
+					rl->length = freelength;
+				} else {
+	/* why is this different from the begin hole case ? */
+					if ((freelength > 0)
+					    && !mergeholes
+					    && !usedcnt) {
+						freerl--;
+						freerl->length = freelength;
+						if (freerl->vcn < *update_from)
+							*update_from
+								= freerl->vcn;
+					}
+				}
+				/* free the hole */
+				res = ntfs_cluster_free_from_rl(vol,freerl);
+				if (!res) {
+					na->compressed_size -= freecnt
+						<< vol->cluster_size_bits;
+					if (mergeholes) {
+						/* merge with adjacent hole */
+						freerl--;
+						freerl->length += freecnt;
+					} else {
+						if (beginhole)
+							freerl--;
+						/* mark hole as free */
+						freerl->lcn = LCN_HOLE;
+						freerl->vcn = freevcn;
+						freerl->length = freecnt;
+					}
+					if (freerl->vcn < *update_from)
+						*update_from = freerl->vcn;
+						/* and set up the new end */
+					freerl[1].lcn = LCN_ENOENT;
+					freerl[1].vcn = freevcn + freecnt;
+					freerl[1].length = 0;
+				}
+			}
+		} else {
+			ntfs_log_error("Bad end of a compression block set\n");
+			errno = EIO;
+		}
+	} else {
+		ntfs_log_error("No cluster to free after compression\n");
+		errno = EIO;
+	}
+	NAttrSetRunlistDirty(na);
+	return (res);
+}
+
+/*
+ *		Read existing data, decompress and append buffer
+ *	Do nothing if something fails
+ */
+
+static int ntfs_read_append(ntfs_attr *na, const runlist_element *rl,
+			s64 offs, u32 compsz, s32 pos, BOOL appending,
+			char *outbuf, s64 to_write, const void *b)
+{
+	int fail = 1;
+	char *compbuf;
+	u32 decompsz;
+	u32 got;
+
+	if (compsz == na->compression_block_size) {
+			/* if the full block was requested, it was a hole */
+		memset(outbuf,0,compsz);
+		memcpy(&outbuf[pos],b,to_write);
+		fail = 0;
+	} else {
+		compbuf = (char*)ntfs_malloc(compsz);
+		if (compbuf) {
+			/* must align to full block for decompression */
+			if (appending)
+				decompsz = ((pos - 1) | (NTFS_SB_SIZE - 1)) + 1;
+			else
+				decompsz = na->compression_block_size;
+			got = read_clusters(na->ni->vol, rl, offs,
+					compsz, compbuf);
+			if ((got == compsz)
+			    && !ntfs_decompress((u8*)outbuf,decompsz,
+					(u8*)compbuf,compsz)) {
+				memcpy(&outbuf[pos],b,to_write);
+				fail = 0;
+			}
+			free(compbuf);
+		}
+	}
+	return (fail);
+}
+
+/*
+ *		Flush a full compression block
+ *
+ *	returns the size actually written (rounded to a full cluster)
+ *		or 0 if could not compress (and written uncompressed)
+ *		or -1 if there were an irrecoverable error (errno set)
+ */
+
+static s32 ntfs_flush(ntfs_attr *na, runlist_element *rl, s64 offs,
+			const char *outbuf, s32 count, BOOL compress,
+			BOOL appending, VCN *update_from)
+{
+	s32 rounded;
+	s32 written;
+	int clsz;
+
+	if (compress) {
+		written = ntfs_comp_set(na, rl, offs, count, outbuf);
+		if (written == -1)
+			compress = FALSE;
+		if ((written >= 0)
+		   && ntfs_compress_free(na,rl,offs + written,
+				offs + na->compression_block_size, appending,
+				update_from))
+			written = -1;
+	} else
+		written = 0;
+	if (!compress) {
+		clsz = 1 << na->ni->vol->cluster_size_bits;
+		rounded = ((count - 1) | (clsz - 1)) + 1;
+		written = write_clusters(na->ni->vol, rl,
+				offs, rounded, outbuf);
+		if (written != rounded)
+			written = -1;
+	}
+	return (written);
+}
+
+/*
+ *		Write some data to be compressed.
+ *	Compression only occurs when a few clusters (usually 16) are
+ *	full. When this occurs an extra runlist slot may be needed, so
+ *	it has to be reserved beforehand.
+ *
+ *	Returns the size of uncompressed data written,
+ *		or negative if an error occurred.
+ *	When the returned size is less than requested, new clusters have
+ *	to be allocated before the function is called again.
+ */
+
+s64 ntfs_compressed_pwrite(ntfs_attr *na, runlist_element *wrl, s64 wpos,
+				s64 offs, s64 to_write, s64 rounded,
+				const void *b, int compressed_part,
+				VCN *update_from)
+{
+	ntfs_volume *vol;
+	runlist_element *brl; /* entry containing the beginning of block */
+	int compression_length;
+	s64 written;
+	s64 to_read;
+	s64 to_flush;
+	s64 roffs;
+	s64 got;
+	s64 start_vcn;
+	s64 nextblock;
+	s64 endwrite;
+	u32 compsz;
+	char *inbuf;
+	char *outbuf;
+	BOOL fail;
+	BOOL done;
+	BOOL compress;
+	BOOL appending;
+
+	if (!valid_compressed_run(na,wrl,FALSE,"begin compressed write")) {
+		return (-1);
+	}
+	if ((*update_from < 0)
+	    || (compressed_part < 0)
+	    || (compressed_part > (int)na->compression_block_clusters)) {
+		ntfs_log_error("Bad update vcn or compressed_part %d for compressed write\n",
+			compressed_part);
+		errno = EIO;
+		return (-1);
+	}
+		/* make sure there are two unused entries in runlist */
+	if (na->unused_runs < 2) {
+		ntfs_log_error("No unused runs for compressed write\n");
+		errno = EIO;
+		return (-1);
+	}
+	if (wrl->vcn < *update_from)
+		*update_from = wrl->vcn;
+	written = -1; /* default return */
+	vol = na->ni->vol;
+	compression_length = na->compression_block_clusters;
+	compress = FALSE;
+	done = FALSE;
+		/*
+		 * Cannot accept writing beyond the current compression set
+		 * because when compression occurs, clusters are freed
+		 * and have to be reallocated.
+		 * (cannot happen with standard fuse 4K buffers)
+		 * Caller has to avoid this situation, or face consequences.
+		 */
+	nextblock = ((offs + (wrl->vcn << vol->cluster_size_bits))
+			| (na->compression_block_size - 1)) + 1;
+		/* determine whether we are appending to file */
+	endwrite = offs + to_write + (wrl->vcn << vol->cluster_size_bits);
+	appending = endwrite >= na->initialized_size;
+	if (endwrite >= nextblock) {
+			/* it is time to compress */
+		compress = TRUE;
+			/* only process what we can */
+		to_write = rounded = nextblock
+			- (offs + (wrl->vcn << vol->cluster_size_bits));
+	}
+	start_vcn = 0;
+	fail = FALSE;
+	brl = wrl;
+	roffs = 0;
+		/*
+		 * If we are about to compress or we need to decompress
+		 * existing data, we have to process a full set of blocks.
+		 * So relocate the parameters to the beginning of allocation
+		 * containing the first byte of the set of blocks.
+		 */
+	if (compress || compressed_part) {
+		/* find the beginning of block */
+		start_vcn = (wrl->vcn + (offs >> vol->cluster_size_bits))
+				& -compression_length;
+		if (start_vcn < *update_from)
+			*update_from = start_vcn;
+		while (brl->vcn && (brl->vcn > start_vcn)) {
+			/* jumping back a hole means big trouble */
+			if (brl->lcn == (LCN)LCN_HOLE) {
+				ntfs_log_error("jump back over a hole when appending\n");
+				fail = TRUE;
+				errno = EIO;
+			}
+			brl--;
+			offs += brl->length << vol->cluster_size_bits;
+		}
+		roffs = (start_vcn - brl->vcn) << vol->cluster_size_bits;
+	}
+	if (compressed_part && !fail) {
+		/*
+		 * The set of compression blocks contains compressed data
+		 * (we are reopening an existing file to append to it)
+		 * Decompress the data and append
+		 */
+		compsz = (s32)compressed_part << vol->cluster_size_bits;
+		outbuf = (char*)ntfs_malloc(na->compression_block_size);
+		if (outbuf) {
+			if (appending) {
+				to_read = offs - roffs;
+				to_flush = to_read + to_write;
+			} else {
+				to_read = na->data_size
+					- (brl->vcn << vol->cluster_size_bits);
+				if (to_read > na->compression_block_size)
+					to_read = na->compression_block_size;
+				to_flush = to_read;
+			}
+			if (!ntfs_read_append(na, brl, roffs, compsz,
+					(s32)(offs - roffs), appending,
+					outbuf, to_write, b)) {
+				written = ntfs_flush(na, brl, roffs,
+					outbuf, to_flush, compress, appending,
+					update_from);
+				if (written >= 0) {
+					written = to_write;
+					done = TRUE;
+				}
+			}
+		free(outbuf);
+		}
+	} else {
+		if (compress && !fail) {
+			/*
+			 * we are filling up a block, read the full set
+			 * of blocks and compress it
+		 	 */
+			inbuf = (char*)ntfs_malloc(na->compression_block_size);
+			if (inbuf) {
+				to_read = offs - roffs;
+				if (to_read)
+					got = read_clusters(vol, brl, roffs,
+							to_read, inbuf);
+				else
+					got = 0;
+				if (got == to_read) {
+					memcpy(&inbuf[to_read],b,to_write);
+					written = ntfs_comp_set(na, brl, roffs,
+						to_read + to_write, inbuf);
+				/*
+				 * if compression was not successful,
+				 * only write the part which was requested
+				 */
+					if ((written >= 0)
+						/* free the unused clusters */
+				  	  && !ntfs_compress_free(na,brl,
+						    written + roffs,
+						    na->compression_block_size
+						         + roffs,
+						    appending, update_from)) {
+						done = TRUE;
+						written = to_write;
+					}
+				}
+				free(inbuf);
+			}
+		}
+		if (!done) {
+			/*
+			 * if the compression block is not full, or
+			 * if compression failed for whatever reason,
+		 	 * write uncompressed
+			 */
+			/* check we are not overflowing current allocation */
+			if ((wpos + rounded)
+			    > ((wrl->lcn + wrl->length)
+				 << vol->cluster_size_bits)) {
+				ntfs_log_error("writing on unallocated clusters\n");
+				errno = EIO;
+			} else {
+				written = ntfs_pwrite(vol->dev, wpos,
+					rounded, b);
+				if (written == rounded)
+					written = to_write;
+			}
+		}
+	}
+	if ((written >= 0)
+	    && !valid_compressed_run(na,wrl,TRUE,"end compressed write"))
+		written = -1;
+	return (written);
+}
+
+/*
+ *		Close a file written compressed.
+ *	This compresses the last partial compression block of the file.
+ *	Two empty runlist slots have to be reserved beforehand.
+ *
+ *	Returns zero if closing is successful.
+ */
+
+int ntfs_compressed_close(ntfs_attr *na, runlist_element *wrl, s64 offs,
+			VCN *update_from)
+{
+	ntfs_volume *vol;
+	runlist_element *brl; /* entry containing the beginning of block */
+	int compression_length;
+	s64 written;
+	s64 to_read;
+	s64 roffs;
+	s64 got;
+	s64 start_vcn;
+	char *inbuf;
+	BOOL fail;
+	BOOL done;
+
+	if (na->unused_runs < 2) {
+		ntfs_log_error("No unused runs for compressed close\n");
+		errno = EIO;
+		return (-1);
+	}
+	if (*update_from < 0) {
+		ntfs_log_error("Bad update vcn for compressed close\n");
+		errno = EIO;
+		return (-1);
+	}
+	if (wrl->vcn < *update_from)
+		*update_from = wrl->vcn;
+	vol = na->ni->vol;
+	compression_length = na->compression_block_clusters;
+	done = FALSE;
+		/*
+		 * There generally is an uncompressed block at end of file,
+		 * read the full block and compress it
+		 */
+	inbuf = (char*)ntfs_malloc(na->compression_block_size);
+	if (inbuf) {
+		start_vcn = (wrl->vcn + (offs >> vol->cluster_size_bits))
+				& -compression_length;
+		if (start_vcn < *update_from)
+			*update_from = start_vcn;
+		to_read = offs + ((wrl->vcn - start_vcn)
+					<< vol->cluster_size_bits);
+		brl = wrl;
+		fail = FALSE;
+		while (brl->vcn && (brl->vcn > start_vcn)) {
+			if (brl->lcn == (LCN)LCN_HOLE) {
+				ntfs_log_error("jump back over a hole when closing\n");
+				fail = TRUE;
+				errno = EIO;
+			}
+			brl--;
+		}
+		if (!fail) {
+			/* roffs can be an offset from another uncomp block */
+			roffs = (start_vcn - brl->vcn)
+						<< vol->cluster_size_bits;
+			if (to_read) {
+				got = read_clusters(vol, brl, roffs, to_read,
+						 inbuf);
+				if (got == to_read) {
+					written = ntfs_comp_set(na, brl, roffs,
+							to_read, inbuf);
+					if ((written >= 0)
+					/* free the unused clusters */
+					    && !ntfs_compress_free(na,brl,
+							written + roffs,
+							na->compression_block_size + roffs,
+							TRUE, update_from)) {
+						done = TRUE;
+					} else
+				/* if compression failed, leave uncompressed */
+						if (written == -1)
+							done = TRUE;
+				}
+			} else
+				done = TRUE;
+			free(inbuf);
+		}
+	}
+	if (done && !valid_compressed_run(na,wrl,TRUE,"end compressed close"))
+		done = FALSE;
+	return (!done);
+}
diff --git a/libntfs-3g/debug.c b/libntfs-3g/debug.c
new file mode 100755
index 0000000000000000000000000000000000000000..f19348330955ea7f47b2718e494c8b5340bfea13
--- /dev/null
+++ b/libntfs-3g/debug.c
@@ -0,0 +1,79 @@
+/**
+ * debug.c - Debugging output functions. Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2002-2004 Anton Altaparmakov
+ * 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
+ * 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_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "types.h"
+#include "runlist.h"
+#include "debug.h"
+#include "logging.h"
+
+#ifdef DEBUG
+/**
+ * ntfs_debug_runlist_dump - Dump a runlist.
+ * @rl:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+void ntfs_debug_runlist_dump(const runlist_element *rl)
+{
+	int i = 0;
+	const char *lcn_str[5] = { "LCN_HOLE         ", "LCN_RL_NOT_MAPPED",
+				   "LCN_ENOENT       ", "LCN_EINVAL       ",
+				   "LCN_unknown      " };
+
+	ntfs_log_debug("NTFS-fs DEBUG: Dumping runlist (values in hex):\n");
+	if (!rl) {
+		ntfs_log_debug("Run list not present.\n");
+		return;
+	}
+	ntfs_log_debug("VCN              LCN               Run length\n");
+	do {
+		LCN lcn = (rl + i)->lcn;
+
+		if (lcn < (LCN)0) {
+			int idx = -lcn - 1;
+
+			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)");
+		} 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)");
+	} while (rl[i++].length);
+}
+
+#endif
+
diff --git a/libntfs-3g/device.c b/libntfs-3g/device.c
new file mode 100755
index 0000000000000000000000000000000000000000..a5c32f4227caaeac5ac62d83fb94a48f254c4f81
--- /dev/null
+++ b/libntfs-3g/device.c
@@ -0,0 +1,932 @@
+/**
+ * device.c - Low level device io functions. Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2004-2013 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
+ * 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_UNISTD_H
+#include <unistd.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
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#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"
+#include "debug.h"
+#include "device.h"
+#include "logging.h"
+#include "misc.h"
+
+#if defined(linux) && defined(_IO) && !defined(BLKGETSIZE)
+#define BLKGETSIZE	_IO(0x12,96)  /* Get device size in 512-byte blocks. */
+#endif
+#if defined(linux) && defined(_IOR) && !defined(BLKGETSIZE64)
+#define BLKGETSIZE64	_IOR(0x12,114,size_t)	/* Get device size in bytes. */
+#endif
+#if defined(linux) && !defined(HDIO_GETGEO)
+#define HDIO_GETGEO	0x0301	/* Get device geometry. */
+#endif
+#if defined(linux) && defined(_IO) && !defined(BLKSSZGET)
+#	define BLKSSZGET _IO(0x12,104) /* Get device sector size in bytes. */
+#endif
+#if defined(linux) && defined(_IO) && !defined(BLKBSZSET)
+#	define BLKBSZSET _IOW(0x12,113,size_t) /* Set device block size in bytes. */
+#endif
+
+/**
+ * ntfs_device_alloc - allocate an ntfs device structure and pre-initialize it
+ * @name:	name of the device (must be present)
+ * @state:	initial device state (usually zero)
+ * @dops:	ntfs device operations to use with the device (must be present)
+ * @priv_data:	pointer to private data (optional)
+ *
+ * Allocate an ntfs device structure and pre-initialize it with the user-
+ * specified device operations @dops, device state @state, device name @name,
+ * and optional private data @priv_data.
+ *
+ * Note, @name is copied and can hence be freed after this functions returns.
+ *
+ * On success return a pointer to the allocated ntfs device structure and on
+ * error return NULL with errno set to the error code returned by ntfs_malloc().
+ */
+struct ntfs_device *ntfs_device_alloc(const char *name, const long state,
+		struct ntfs_device_operations *dops, void *priv_data)
+{
+	struct ntfs_device *dev;
+
+	if (!name) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	dev = ntfs_malloc(sizeof(struct ntfs_device));
+	if (dev) {
+		if (!(dev->d_name = strdup(name))) {
+			int eo = errno;
+			free(dev);
+			errno = eo;
+			return NULL;
+		}
+		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;
+}
+
+/**
+ * ntfs_device_free - free an ntfs device structure
+ * @dev:	ntfs device structure to free
+ *
+ * Free the ntfs device structure @dev.
+ *
+ * Return 0 on success or -1 on error with errno set to the error code. The
+ * following error codes are defined:
+ *	EINVAL		Invalid pointer @dev.
+ *	EBUSY		Device is still open. Close it before freeing it!
+ */
+int ntfs_device_free(struct ntfs_device *dev)
+{
+	if (!dev) {
+		errno = EINVAL;
+		return -1;
+	}
+	if (NDevOpen(dev)) {
+		errno = EBUSY;
+		return -1;
+	}
+	free(dev->d_name);
+	free(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
+ * @pos:	position in device to read from
+ * @count:	number of bytes to read
+ * @b:		output data buffer
+ *
+ * This function will read @count bytes from device @dev at position @pos into
+ * the data buffer @b.
+ *
+ * On success, return the number of successfully read bytes. If this number is
+ * lower than @count this means that we have either reached end of file or
+ * encountered an error during the read so that the read is partial. 0 means
+ * end of file or nothing to read (@count is 0).
+ *
+ * On error and nothing has been read, return -1 with errno set appropriately
+ * to the return code of either seek, read, or set to EINVAL in case of
+ * invalid arguments.
+ */
+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);
+	
+	if (!b || count < 0 || pos < 0) {
+		errno = EINVAL;
+		return -1;
+	}
+	if (!count)
+		return 0;
+	
+	dops = dev->d_ops;
+
+	for (total = 0; count; count -= br, total += br) {
+		br = dops->pread(dev, (char*)b + total, count, pos + total);
+		/* If everything ok, continue. */
+		if (br > 0)
+			continue;
+		/* If EOF or error return number of bytes read. */
+		if (!br || total)
+			return total;
+		/* Nothing read and error, return error status. */
+		return br;
+	}
+	/* Finally, return the number of bytes read. */
+	return total;
+}
+
+/**
+ * ntfs_pwrite - positioned write to disk
+ * @dev:	device to write to
+ * @pos:	position in file descriptor to write to
+ * @count:	number of bytes to write
+ * @b:		data buffer to write to disk
+ *
+ * This function will write @count bytes from data buffer @b to the device @dev
+ * at position @pos.
+ *
+ * On success, return the number of successfully written bytes. If this number
+ * is lower than @count this means that the write has been interrupted in
+ * flight or that an error was encountered during the write so that the write
+ * is partial. 0 means nothing was written (also return 0 when @count is 0).
+ *
+ * On error and nothing has been written, return -1 with errno set
+ * appropriately to the return code of either seek, write, or set
+ * to EINVAL in case of invalid arguments.
+ */
+s64 ntfs_pwrite(struct ntfs_device *dev, const s64 pos, s64 count,
+		const void *b)
+{
+	s64 written, total, ret = -1;
+	struct ntfs_device_operations *dops;
+
+	ntfs_log_trace("pos %lld, count %lld\n",(long long)pos,(long long)count);
+
+	if (!b || count < 0 || pos < 0) {
+		errno = EINVAL;
+		goto out;
+	}
+	if (!count)
+		return 0;
+	if (NDevReadOnly(dev)) {
+		errno = EROFS;
+		goto out;
+	}
+	
+	dops = dev->d_ops;
+
+	NDevSetDirty(dev);
+	for (total = 0; count; count -= written, total += written) {
+		written = dops->pwrite(dev, (const char*)b + total, count,
+				       pos + total);
+		/* If everything ok, continue. */
+		if (written > 0)
+			continue;
+		/*
+		 * If nothing written or error return number of bytes written.
+		 */
+		if (!written || total)
+			break;
+		/* Nothing written and error, return error status. */
+		total = written;
+		break;
+	}
+	if (NDevSync(dev) && total && dops->sync(dev)) {
+		total--; /* on sync error, return partially written */
+	}
+	ret = total;
+out:	
+	return ret;
+}
+
+/**
+ * ntfs_mst_pread - multi sector transfer (mst) positioned read
+ * @dev:	device to read from
+ * @pos:	position in file descriptor to read from
+ * @count:	number of blocks to read
+ * @bksize:	size of each block that needs mst deprotecting
+ * @b:		output data buffer
+ *
+ * Multi sector transfer (mst) positioned read. This function will read @count
+ * blocks of size @bksize bytes each from device @dev at position @pos into the
+ * the data buffer @b.
+ *
+ * On success, return the number of successfully read blocks. If this number is
+ * lower than @count this means that we have reached end of file, that the read
+ * was interrupted, or that an error was encountered during the read so that
+ * the read is partial. 0 means end of file or nothing was read (also return 0
+ * when @count or @bksize are 0).
+ *
+ * On error and nothing was read, return -1 with errno set appropriately to the
+ * return code of either seek, read, or set to EINVAL in case of invalid
+ * arguments.
+ *
+ * NOTE: If an incomplete multi sector transfer has been detected the magic
+ * will have been changed to magic_BAAD but no error will be returned. Thus it
+ * is possible that we return count blocks as being read but that any number
+ * (between zero and count!) of these blocks is actually subject to a multi
+ * sector transfer error. This should be detected by the caller by checking for
+ * the magic being "BAAD".
+ */
+s64 ntfs_mst_pread(struct ntfs_device *dev, const s64 pos, s64 count,
+		const u32 bksize, void *b)
+{
+	s64 br, i;
+
+	if (bksize & (bksize - 1) || bksize % NTFS_BLOCK_SIZE) {
+		errno = EINVAL;
+		return -1;
+	}
+	/* Do the read. */
+	br = ntfs_pread(dev, pos, count * bksize, b);
+	if (br < 0)
+		return br;
+	/*
+	 * Apply fixups to successfully read data, disregarding any errors
+	 * returned from the MST fixup function. This is because we want to
+	 * fixup everything possible and we rely on the fact that the "BAAD"
+	 * magic will be detected later on.
+	 */
+	count = br / bksize;
+	for (i = 0; i < count; ++i)
+		ntfs_mst_post_read_fixup((NTFS_RECORD*)
+				((u8*)b + i * bksize), bksize);
+	/* Finally, return the number of complete blocks read. */
+	return count;
+}
+
+/**
+ * ntfs_mst_pwrite - multi sector transfer (mst) positioned write
+ * @dev:	device to write to
+ * @pos:	position in file descriptor to write to
+ * @count:	number of blocks to write
+ * @bksize:	size of each block that needs mst protecting
+ * @b:		data buffer to write to disk
+ *
+ * Multi sector transfer (mst) positioned write. This function will write
+ * @count blocks of size @bksize bytes each from data buffer @b to the device
+ * @dev at position @pos.
+ *
+ * On success, return the number of successfully written blocks. If this number
+ * is lower than @count this means that the write has been interrupted or that
+ * an error was encountered during the write so that the write is partial. 0
+ * means nothing was written (also return 0 when @count or @bksize are 0).
+ *
+ * On error and nothing has been written, return -1 with errno set
+ * appropriately to the return code of either seek, write, or set
+ * to EINVAL in case of invalid arguments.
+ *
+ * NOTE: We mst protect the data, write it, then mst deprotect it using a quick
+ * deprotect algorithm (no checking). This saves us from making a copy before
+ * the write and at the same time causes the usn to be incremented in the
+ * buffer. This conceptually fits in better with the idea that cached data is
+ * always deprotected and protection is performed when the data is actually
+ * going to hit the disk and the cache is immediately deprotected again
+ * simulating an mst read on the written data. This way cache coherency is
+ * achieved.
+ */
+s64 ntfs_mst_pwrite(struct ntfs_device *dev, const s64 pos, s64 count,
+		const u32 bksize, void *b)
+{
+	s64 written, i;
+
+	if (count < 0 || bksize % NTFS_BLOCK_SIZE) {
+		errno = EINVAL;
+		return -1;
+	}
+	if (!count)
+		return 0;
+	/* Prepare data for writing. */
+	for (i = 0; i < count; ++i) {
+		int err;
+
+		err = ntfs_mst_pre_write_fixup((NTFS_RECORD*)
+				((u8*)b + i * bksize), bksize);
+		if (err < 0) {
+			/* Abort write at this position. */
+			if (!i)
+				return err;
+			count = i;
+			break;
+		}
+	}
+	/* Write the prepared data. */
+	written = ntfs_pwrite(dev, pos, count * bksize, b);
+	/* Quickly deprotect the data again. */
+	for (i = 0; i < count; ++i)
+		ntfs_mst_post_write_fixup((NTFS_RECORD*)((u8*)b + i * bksize));
+	if (written <= 0)
+		return written;
+	/* Finally, return the number of complete blocks written. */
+	return written / bksize;
+}
+
+/**
+ * ntfs_cluster_read - read ntfs clusters
+ * @vol:	volume to read from
+ * @lcn:	starting logical cluster number
+ * @count:	number of clusters to read
+ * @b:		output data buffer
+ *
+ * Read @count ntfs clusters starting at logical cluster number @lcn from
+ * volume @vol into buffer @b. Return number of clusters read or -1 on error,
+ * with errno set to the error code.
+ */
+s64 ntfs_cluster_read(const ntfs_volume *vol, const s64 lcn, const s64 count,
+		void *b)
+{
+	s64 br;
+
+	if (!vol || lcn < 0 || count < 0) {
+		errno = EINVAL;
+		return -1;
+	}
+	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);
+		return -1;
+	}
+	br = ntfs_pread(vol->dev, lcn << vol->cluster_size_bits,
+			count << vol->cluster_size_bits, b);
+	if (br < 0) {
+		ntfs_log_perror("Error reading cluster(s)");
+		return br;
+	}
+	return br >> vol->cluster_size_bits;
+}
+
+/**
+ * ntfs_cluster_write - write ntfs clusters
+ * @vol:	volume to write to
+ * @lcn:	starting logical cluster number
+ * @count:	number of clusters to write
+ * @b:		data buffer to write to disk
+ *
+ * Write @count ntfs clusters starting at logical cluster number @lcn from
+ * buffer @b to volume @vol. Return the number of clusters written or -1 on
+ * error, with errno set to the error code.
+ */
+s64 ntfs_cluster_write(const ntfs_volume *vol, const s64 lcn,
+		const s64 count, const void *b)
+{
+	s64 bw;
+
+	if (!vol || lcn < 0 || count < 0) {
+		errno = EINVAL;
+		return -1;
+	}
+	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);
+		return -1;
+	}
+	if (!NVolReadOnly(vol))
+		bw = ntfs_pwrite(vol->dev, lcn << vol->cluster_size_bits,
+				count << vol->cluster_size_bits, b);
+	else
+		bw = count << vol->cluster_size_bits;
+	if (bw < 0) {
+		ntfs_log_perror("Error writing cluster(s)");
+		return bw;
+	}
+	return bw >> vol->cluster_size_bits;
+}
+
+/**
+ * ntfs_device_offset_valid - test if a device offset is valid
+ * @dev:	open device
+ * @ofs:	offset to test for validity
+ *
+ * Test if the offset @ofs is an existing location on the device described
+ * by the open device structure @dev.
+ *
+ * Return 0 if it is valid and -1 if it is not valid.
+ */
+static int ntfs_device_offset_valid(struct ntfs_device *dev, s64 ofs)
+{
+	char ch;
+
+	if (dev->d_ops->seek(dev, ofs, SEEK_SET) >= 0 &&
+			dev->d_ops->read(dev, &ch, 1) == 1)
+		return 0;
+	return -1;
+}
+
+/**
+ * ntfs_device_size_get - return the size of a device in blocks
+ * @dev:	open device
+ * @block_size:	block size in bytes in which to return the result
+ *
+ * Return the number of @block_size sized blocks in the device described by the
+ * open device @dev.
+ *
+ * Adapted from e2fsutils-1.19, Copyright (C) 1995 Theodore Ts'o.
+ *
+ * On error return -1 with errno set to the error code.
+ */
+s64 ntfs_device_size_get(struct ntfs_device *dev, int block_size)
+{
+	s64 high, low;
+
+	if (!dev || block_size <= 0 || (block_size - 1) & block_size) {
+		errno = EINVAL;
+		return -1;
+	}
+#ifdef BLKGETSIZE64
+	{	u64 size;
+
+		if (dev->d_ops->ioctl(dev, BLKGETSIZE64, &size) >= 0) {
+			ntfs_log_debug("BLKGETSIZE64 nr bytes = %llu (0x%llx)\n",
+					(unsigned long long)size,
+					(unsigned long long)size);
+			return (s64)size / block_size;
+		}
+	}
+#endif
+#ifdef BLKGETSIZE
+	{	unsigned long size;
+
+		if (dev->d_ops->ioctl(dev, BLKGETSIZE, &size) >= 0) {
+			ntfs_log_debug("BLKGETSIZE nr 512 byte blocks = %lu (0x%lx)\n",
+					size, size);
+			return (s64)size * 512 / block_size;
+		}
+	}
+#endif
+#ifdef FDGETPRM
+	{       struct floppy_struct this_floppy;
+
+		if (dev->d_ops->ioctl(dev, FDGETPRM, &this_floppy) >= 0) {
+			ntfs_log_debug("FDGETPRM nr 512 byte blocks = %lu (0x%lx)\n",
+					(unsigned long)this_floppy.size,
+					(unsigned long)this_floppy.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,
+	 * so do binary search to find the size of the device.
+	 */
+	low = 0LL;
+	for (high = 1024LL; !ntfs_device_offset_valid(dev, high); high <<= 1)
+		low = high;
+	while (low < high - 1LL) {
+		const s64 mid = (low + high) / 2;
+
+		if (!ntfs_device_offset_valid(dev, mid))
+			low = mid;
+		else
+			high = mid;
+	}
+	dev->d_ops->seek(dev, 0LL, SEEK_SET);
+	return (low + 1LL) / block_size;
+}
+
+/**
+ * ntfs_device_partition_start_sector_get - get starting sector of a partition
+ * @dev:	open device
+ *
+ * On success, return the starting sector of the partition @dev in the parent
+ * block device of @dev.  On error return -1 with errno set to the error code.
+ *
+ * The following error codes are defined:
+ *	EINVAL		Input parameter error
+ *	EOPNOTSUPP	System does not support HDIO_GETGEO ioctl
+ *	ENOTTY		@dev is a file or a device not supporting HDIO_GETGEO
+ */
+s64 ntfs_device_partition_start_sector_get(struct ntfs_device *dev)
+{
+	if (!dev) {
+		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 start_sect = %lu (0x%lx)\n",
+					geo.start, geo.start);
+			return geo.start;
+		}
+	}
+#else
+	errno = EOPNOTSUPP;
+#endif
+	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
+ *
+ * On success, return the number of heads on the device @dev.  On error return
+ * -1 with errno set to the error code.
+ *
+ * The following error codes are defined:
+ *	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)
+{
+	if (!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;
+		}
+	}
+	return dev->d_heads;
+}
+
+/**
+ * ntfs_device_sectors_per_track_get - get number of sectors per track of device
+ * @dev:		open device
+ *
+ * On success, return the number of sectors per track on the device @dev.  On
+ * error return -1 with errno set to the error code.
+ *
+ * The following error codes are defined:
+ *	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)
+{
+	if (!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;
+		}
+	}
+	return dev->d_sectors_per_track;
+}
+
+/**
+ * ntfs_device_sector_size_get - get sector size of a device
+ * @dev:	open device
+ *
+ * On success, return the sector size in bytes of the device @dev.
+ * On error return -1 with errno set to the error code.
+ *
+ * The following error codes are defined:
+ *	EINVAL		Input parameter error
+ *	EOPNOTSUPP	System does not support BLKSSZGET ioctl
+ *	ENOTTY		@dev is a file or a device not supporting BLKSSZGET
+ */
+int ntfs_device_sector_size_get(struct ntfs_device *dev)
+{
+	if (!dev) {
+		errno = EINVAL;
+		return -1;
+	}
+#ifdef BLKSSZGET
+	{
+		int sect_size = 0;
+
+		if (!dev->d_ops->ioctl(dev, BLKSSZGET, &sect_size)) {
+			ntfs_log_debug("BLKSSZGET sector size = %d bytes\n",
+					sect_size);
+			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
+	return -1;
+}
+
+/**
+ * ntfs_device_block_size_set - set block size of a device
+ * @dev:	open device
+ * @block_size: block size to set @dev to
+ *
+ * On success, return 0.
+ * On error return -1 with errno set to the error code.
+ *
+ * The following error codes are defined:
+ *	EINVAL		Input parameter error
+ *	EOPNOTSUPP	System does not support BLKBSZSET ioctl
+ *	ENOTTY		@dev is a file or a device not supporting BLKBSZSET
+ */
+int ntfs_device_block_size_set(struct ntfs_device *dev,
+		int block_size __attribute__((unused)))
+{
+	if (!dev) {
+		errno = EINVAL;
+		return -1;
+	}
+#ifdef BLKBSZSET
+	{
+		size_t s_block_size = block_size;
+		if (!dev->d_ops->ioctl(dev, BLKBSZSET, &s_block_size)) {
+			ntfs_log_debug("Used BLKBSZSET to set block size to "
+					"%d bytes.\n", block_size);
+			return 0;
+		}
+		/* If not a block device, pretend it was successful. */
+		if (!NDevBlock(dev))
+			return 0;
+	}
+#else
+	/* If not a block device, pretend it was successful. */
+	if (!NDevBlock(dev))
+		return 0;
+	errno = EOPNOTSUPP;
+#endif
+	return -1;
+}
diff --git a/libntfs-3g/dir.c b/libntfs-3g/dir.c
new file mode 100755
index 0000000000000000000000000000000000000000..8633c7d9b13f550ac109654e79838c75cb0a5981
--- /dev/null
+++ b/libntfs-3g/dir.c
@@ -0,0 +1,2787 @@
+/**
+ * dir.c - Directory handling code. Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2002-2005 Anton Altaparmakov
+ * Copyright (c) 2004-2005 Richard Russon
+ * Copyright (c) 2004-2008 Szabolcs Szakacsits
+ * Copyright (c) 2005-2007 Yura Pakhuchiy
+ * Copyright (c) 2008-2014 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 "param.h"
+#include "types.h"
+#include "debug.h"
+#include "attrib.h"
+#include "inode.h"
+#include "dir.h"
+#include "volume.h"
+#include "mft.h"
+#include "index.h"
+#include "ntfstime.h"
+#include "lcnalloc.h"
+#include "logging.h"
+#include "cache.h"
+#include "misc.h"
+#include "security.h"
+#include "reparse.h"
+#include "object_id.h"
+
+#ifdef HAVE_SETXATTR
+#include <sys/xattr.h>
+#endif
+
+/*
+ * The little endian Unicode strings "$I30", "$SII", "$SDH", "$O"
+ *  and "$Q" as global constants.
+ */
+ntfschar NTFS_INDEX_I30[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('I'),
+		const_cpu_to_le16('3'), const_cpu_to_le16('0'),
+		const_cpu_to_le16('\0') };
+ntfschar NTFS_INDEX_SII[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('S'),
+		const_cpu_to_le16('I'), const_cpu_to_le16('I'),
+		const_cpu_to_le16('\0') };
+ntfschar NTFS_INDEX_SDH[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('S'),
+		const_cpu_to_le16('D'), const_cpu_to_le16('H'),
+		const_cpu_to_le16('\0') };
+ntfschar NTFS_INDEX_O[3] = { const_cpu_to_le16('$'), const_cpu_to_le16('O'),
+		const_cpu_to_le16('\0') };
+ntfschar NTFS_INDEX_Q[3] = { const_cpu_to_le16('$'), const_cpu_to_le16('Q'),
+		const_cpu_to_le16('\0') };
+ntfschar NTFS_INDEX_R[3] = { const_cpu_to_le16('$'), const_cpu_to_le16('R'),
+		const_cpu_to_le16('\0') };
+
+#if CACHE_INODE_SIZE
+
+/*
+ *		Pathname hashing
+ *
+ *	Based on first char and second char (which may be '\0')
+ */
+
+int ntfs_dir_inode_hash(const struct CACHED_GENERIC *cached)
+{
+	const char *path;
+	const unsigned char *name;
+
+	path = (const char*)cached->variable;
+	if (!path) {
+		ntfs_log_error("Bad inode cache entry\n");
+		return (-1);
+	}
+	name = (const unsigned char*)strrchr(path,'/');
+	if (!name)
+		name = (const unsigned char*)path;
+	return (((name[0] << 1) + name[1] + strlen((const char*)name))
+				% (2*CACHE_INODE_SIZE));
+}
+
+/*
+ *		Pathname comparing for entering/fetching from cache
+ */
+
+static int inode_cache_compare(const struct CACHED_GENERIC *cached,
+			const struct CACHED_GENERIC *wanted)
+{
+	return (!cached->variable
+		    || strcmp(cached->variable, wanted->variable));
+}
+
+/*
+ *		Pathname comparing for invalidating entries in cache
+ *
+ *	A partial path is compared in order to invalidate all paths
+ *	related to a renamed directory
+ *	inode numbers are also checked, as deleting a long name may
+ *	imply deleting a short name and conversely
+ *
+ *	Only use associated with a CACHE_NOHASH flag
+ */
+
+static int inode_cache_inv_compare(const struct CACHED_GENERIC *cached,
+			const struct CACHED_GENERIC *wanted)
+{
+	int len;
+	BOOL different;
+	const struct CACHED_INODE *w;
+	const struct CACHED_INODE *c;
+
+	w = (const struct CACHED_INODE*)wanted;
+	c = (const struct CACHED_INODE*)cached;
+	if (w->pathname) {
+		len = strlen(w->pathname);
+		different = !cached->variable
+			|| ((w->inum != MREF(c->inum))
+			   && (strncmp(c->pathname, w->pathname, len)
+				|| ((c->pathname[len] != '\0')
+				   && (c->pathname[len] != '/'))));
+	} else
+		different = !c->pathname
+			|| (w->inum != MREF(c->inum));
+	return (different);
+}
+
+#endif
+
+#if CACHE_LOOKUP_SIZE
+
+/*
+ *		File name comparing for entering/fetching from lookup cache
+ */
+
+static int lookup_cache_compare(const struct CACHED_GENERIC *cached,
+			const struct CACHED_GENERIC *wanted)
+{
+	const struct CACHED_LOOKUP *c = (const struct CACHED_LOOKUP*) cached;
+	const struct CACHED_LOOKUP *w = (const struct CACHED_LOOKUP*) wanted;
+	return (!c->name
+		    || (c->parent != w->parent)
+		    || (c->namesize != w->namesize)
+		    || memcmp(c->name, w->name, c->namesize));
+}
+
+/*
+ *		Inode number comparing for invalidating lookup cache
+ *
+ *	All entries with designated inode number are invalidated
+ *
+ *	Only use associated with a CACHE_NOHASH flag
+ */
+
+static int lookup_cache_inv_compare(const struct CACHED_GENERIC *cached,
+			const struct CACHED_GENERIC *wanted)
+{
+	const struct CACHED_LOOKUP *c = (const struct CACHED_LOOKUP*) cached;
+	const struct CACHED_LOOKUP *w = (const struct CACHED_LOOKUP*) wanted;
+	return (!c->name
+		    || (c->parent != w->parent)
+		    || (MREF(c->inum) != MREF(w->inum)));
+}
+
+/*
+ *		Lookup hashing
+ *
+ *	Based on first, second and and last char
+ */
+
+int ntfs_dir_lookup_hash(const struct CACHED_GENERIC *cached)
+{
+	const unsigned char *name;
+	int count;
+	unsigned int val;
+
+	name = (const unsigned char*)cached->variable;
+	count = cached->varsize;
+	if (!name || !count) {
+		ntfs_log_error("Bad lookup cache entry\n");
+		return (-1);
+	}
+	val = (name[0] << 2) + (name[1] << 1) + name[count - 1] + count;
+	return (val % (2*CACHE_LOOKUP_SIZE));
+}
+
+#endif
+
+/**
+ * ntfs_inode_lookup_by_name - find an inode in a directory given its name
+ * @dir_ni:	ntfs inode of the directory in which to search for the name
+ * @uname:	Unicode name for which to search in the directory
+ * @uname_len:	length of the name @uname in Unicode characters
+ *
+ * Look for an inode with name @uname in the directory with inode @dir_ni.
+ * ntfs_inode_lookup_by_name() walks the contents of the directory looking for
+ * the Unicode name. If the name is found in the directory, the corresponding
+ * inode number (>= 0) is returned as a mft reference in cpu format, i.e. it
+ * is a 64-bit number containing the sequence number.
+ *
+ * On error, return -1 with errno set to the error code. If the inode is is not
+ * found errno is ENOENT.
+ *
+ * Note, @uname_len does not include the (optional) terminating NULL character.
+ *
+ * Note, we look for a case sensitive match first but we also look for a case
+ * insensitive match at the same time. If we find a case insensitive match, we
+ * save that for the case that we don't find an exact match, where we return
+ * the mft reference of the case insensitive match.
+ *
+ * If the volume is mounted with the case sensitive flag set, then we only
+ * allow exact matches.
+ */
+u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni,
+		const ntfschar *uname, const int uname_len)
+{
+	VCN vcn;
+	u64 mref = 0;
+	s64 br;
+	ntfs_volume *vol = dir_ni->vol;
+	ntfs_attr_search_ctx *ctx;
+	INDEX_ROOT *ir;
+	INDEX_ENTRY *ie;
+	INDEX_ALLOCATION *ia;
+	IGNORE_CASE_BOOL case_sensitivity;
+	u8 *index_end;
+	ntfs_attr *ia_na;
+	int eo, rc;
+	u32 index_block_size;
+	u8 index_vcn_size_bits;
+
+	ntfs_log_trace("Entering\n");
+
+	if (!dir_ni || !dir_ni->mrec || !uname || uname_len <= 0) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	ctx = ntfs_attr_get_search_ctx(dir_ni, NULL);
+	if (!ctx)
+		return -1;
+
+	/* Find the index root attribute in the mft record. */
+	if (ntfs_attr_lookup(AT_INDEX_ROOT, NTFS_INDEX_I30, 4, CASE_SENSITIVE, 0, NULL,
+			0, ctx)) {
+		ntfs_log_perror("Index root attribute missing in directory inode "
+				"%lld", (unsigned long long)dir_ni->mft_no);
+		goto put_err_out;
+	}
+	case_sensitivity = (NVolCaseSensitive(vol) ? CASE_SENSITIVE : IGNORE_CASE);
+	/* Get to the index root value. */
+	ir = (INDEX_ROOT*)((u8*)ctx->attr +
+			le16_to_cpu(ctx->attr->value_offset));
+	index_block_size = le32_to_cpu(ir->index_block_size);
+	if (index_block_size < NTFS_BLOCK_SIZE ||
+			index_block_size & (index_block_size - 1)) {
+		ntfs_log_error("Index block size %u is invalid.\n",
+				(unsigned)index_block_size);
+		goto put_err_out;
+	}
+	index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length);
+	/* The first index entry. */
+	ie = (INDEX_ENTRY*)((u8*)&ir->index +
+			le32_to_cpu(ir->index.entries_offset));
+	/*
+	 * Loop until we exceed valid memory (corruption case) or until we
+	 * reach the last entry.
+	 */
+	for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {
+		/* Bounds checks. */
+		if ((u8*)ie < (u8*)ctx->mrec || (u8*)ie +
+				sizeof(INDEX_ENTRY_HEADER) > index_end ||
+				(u8*)ie + le16_to_cpu(ie->key_length) >
+				index_end) {
+			ntfs_log_error("Index entry out of bounds in inode %lld"
+				       "\n", (unsigned long long)dir_ni->mft_no);
+			goto put_err_out;
+		}
+		/*
+		 * The last entry cannot contain a name. It can however contain
+		 * a pointer to a child node in the B+tree so we just break out.
+		 */
+		if (ie->ie_flags & INDEX_ENTRY_END)
+			break;
+		
+		if (!le16_to_cpu(ie->length)) {
+			ntfs_log_error("Zero length index entry in inode %lld"
+				       "\n", (unsigned long long)dir_ni->mft_no);
+			goto put_err_out;
+		}
+		/*
+		 * Not a perfect match, need to do full blown collation so we
+		 * know which way in the B+tree we have to go.
+		 */
+		rc = ntfs_names_full_collate(uname, uname_len,
+				(ntfschar*)&ie->key.file_name.file_name,
+				ie->key.file_name.file_name_length,
+				case_sensitivity, vol->upcase, vol->upcase_len);
+		/*
+		 * If uname collates before the name of the current entry, there
+		 * is definitely no such name in this index but we might need to
+		 * descend into the B+tree so we just break out of the loop.
+		 */
+		if (rc == -1)
+			break;
+		/* The names are not equal, continue the search. */
+		if (rc)
+			continue;
+		/*
+		 * Perfect match, this will never happen as the
+		 * ntfs_are_names_equal() call will have gotten a match but we
+		 * still treat it correctly.
+		 */
+		mref = le64_to_cpu(ie->indexed_file);
+		ntfs_attr_put_search_ctx(ctx);
+		return mref;
+	}
+	/*
+	 * We have finished with this index without success. Check for the
+	 * presence of a child node and if not present return error code
+	 * ENOENT, unless we have got the mft reference of a matching name
+	 * cached in mref in which case return mref.
+	 */
+	if (!(ie->ie_flags & INDEX_ENTRY_NODE)) {
+		ntfs_attr_put_search_ctx(ctx);
+		if (mref)
+			return mref;
+		ntfs_log_debug("Entry not found - between root entries.\n");
+		errno = ENOENT;
+		return -1;
+	} /* Child node present, descend into it. */
+
+	/* Open the index allocation attribute. */
+	ia_na = ntfs_attr_open(dir_ni, AT_INDEX_ALLOCATION, NTFS_INDEX_I30, 4);
+	if (!ia_na) {
+		ntfs_log_perror("Failed to open index allocation (inode %lld)",
+				(unsigned long long)dir_ni->mft_no);
+		goto put_err_out;
+	}
+
+	/* Allocate a buffer for the current index block. */
+	ia = ntfs_malloc(index_block_size);
+	if (!ia) {
+		ntfs_attr_close(ia_na);
+		goto put_err_out;
+	}
+
+	/* Determine the size of a vcn in the directory index. */
+	if (vol->cluster_size <= index_block_size) {
+		index_vcn_size_bits = vol->cluster_size_bits;
+	} else {
+		index_vcn_size_bits = NTFS_BLOCK_SIZE_BITS;
+	}
+
+	/* Get the starting vcn of the index_block holding the child node. */
+	vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8);
+
+descend_into_child_node:
+
+	/* Read the index block starting at vcn. */
+	br = ntfs_attr_mst_pread(ia_na, vcn << index_vcn_size_bits, 1,
+			index_block_size, ia);
+	if (br != 1) {
+		if (br != -1)
+			errno = EIO;
+		ntfs_log_perror("Failed to read vcn 0x%llx",
+			       	(unsigned long long)vcn);
+		goto close_err_out;
+	}
+
+	if (sle64_to_cpu(ia->index_block_vcn) != vcn) {
+		ntfs_log_error("Actual VCN (0x%llx) of index buffer is different "
+				"from expected VCN (0x%llx).\n",
+				(long long)sle64_to_cpu(ia->index_block_vcn),
+				(long long)vcn);
+		errno = EIO;
+		goto close_err_out;
+	}
+	if (le32_to_cpu(ia->index.allocated_size) + 0x18 != index_block_size) {
+		ntfs_log_error("Index buffer (VCN 0x%llx) of directory inode 0x%llx "
+				"has a size (%u) differing from the directory "
+				"specified size (%u).\n", (long long)vcn,
+				(unsigned long long)dir_ni->mft_no,
+				(unsigned) le32_to_cpu(ia->index.allocated_size) + 0x18,
+				(unsigned)index_block_size);
+		errno = EIO;
+		goto close_err_out;
+	}
+	index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length);
+	if (index_end > (u8*)ia + index_block_size) {
+		ntfs_log_error("Size of index buffer (VCN 0x%llx) of directory inode "
+				"0x%llx exceeds maximum size.\n",
+				(long long)vcn, (unsigned long long)dir_ni->mft_no);
+		errno = EIO;
+		goto close_err_out;
+	}
+
+	/* The first index entry. */
+	ie = (INDEX_ENTRY*)((u8*)&ia->index +
+			le32_to_cpu(ia->index.entries_offset));
+	/*
+	 * Iterate similar to above big loop but applied to index buffer, thus
+	 * loop until we exceed valid memory (corruption case) or until we
+	 * reach the last entry.
+	 */
+	for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {
+		/* Bounds check. */
+		if ((u8*)ie < (u8*)ia || (u8*)ie +
+				sizeof(INDEX_ENTRY_HEADER) > index_end ||
+				(u8*)ie + le16_to_cpu(ie->key_length) >
+				index_end) {
+			ntfs_log_error("Index entry out of bounds in directory "
+				       "inode %lld.\n", 
+				       (unsigned long long)dir_ni->mft_no);
+			errno = EIO;
+			goto close_err_out;
+		}
+		/*
+		 * The last entry cannot contain a name. It can however contain
+		 * a pointer to a child node in the B+tree so we just break out.
+		 */
+		if (ie->ie_flags & INDEX_ENTRY_END)
+			break;
+		
+		if (!le16_to_cpu(ie->length)) {
+			errno = EIO;
+			ntfs_log_error("Zero length index entry in inode %lld"
+				       "\n", (unsigned long long)dir_ni->mft_no);
+			goto close_err_out;
+		}
+		/*
+		 * Not a perfect match, need to do full blown collation so we
+		 * know which way in the B+tree we have to go.
+		 */
+		rc = ntfs_names_full_collate(uname, uname_len,
+				(ntfschar*)&ie->key.file_name.file_name,
+				ie->key.file_name.file_name_length,
+				case_sensitivity, vol->upcase, vol->upcase_len);
+		/*
+		 * If uname collates before the name of the current entry, there
+		 * is definitely no such name in this index but we might need to
+		 * descend into the B+tree so we just break out of the loop.
+		 */
+		if (rc == -1)
+			break;
+		/* The names are not equal, continue the search. */
+		if (rc)
+			continue;
+		mref = le64_to_cpu(ie->indexed_file);
+		free(ia);
+		ntfs_attr_close(ia_na);
+		ntfs_attr_put_search_ctx(ctx);
+		return mref;
+	}
+	/*
+	 * We have finished with this index buffer without success. Check for
+	 * the presence of a child node.
+	 */
+	if (ie->ie_flags & INDEX_ENTRY_NODE) {
+		if ((ia->index.ih_flags & NODE_MASK) == LEAF_NODE) {
+			ntfs_log_error("Index entry with child node found in a leaf "
+					"node in directory inode %lld.\n",
+					(unsigned long long)dir_ni->mft_no);
+			errno = EIO;
+			goto close_err_out;
+		}
+		/* Child node present, descend into it. */
+		vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8);
+		if (vcn >= 0)
+			goto descend_into_child_node;
+		ntfs_log_error("Negative child node vcn in directory inode "
+			       "0x%llx.\n", (unsigned long long)dir_ni->mft_no);
+		errno = EIO;
+		goto close_err_out;
+	}
+	free(ia);
+	ntfs_attr_close(ia_na);
+	ntfs_attr_put_search_ctx(ctx);
+	/*
+	 * No child node present, return error code ENOENT, unless we have got
+	 * the mft reference of a matching name cached in mref in which case
+	 * return mref.
+	 */
+	if (mref)
+		return mref;
+	ntfs_log_debug("Entry not found.\n");
+	errno = ENOENT;
+	return -1;
+put_err_out:
+	eo = EIO;
+	ntfs_log_debug("Corrupt directory. Aborting lookup.\n");
+eo_put_err_out:
+	ntfs_attr_put_search_ctx(ctx);
+	errno = eo;
+	return -1;
+close_err_out:
+	eo = errno;
+	free(ia);
+	ntfs_attr_close(ia_na);
+	goto eo_put_err_out;
+}
+
+/*
+ *		Lookup a file in a directory from its UTF-8 name
+ *
+ *	The name is first fetched from cache if one is defined
+ *
+ *	Returns the inode number
+ *		or -1 if not possible (errno tells why)
+ */
+
+u64 ntfs_inode_lookup_by_mbsname(ntfs_inode *dir_ni, const char *name)
+{
+	int uname_len;
+	ntfschar *uname = (ntfschar*)NULL;
+	u64 inum;
+	char *cached_name;
+	const char *const_name;
+
+	if (!NVolCaseSensitive(dir_ni->vol)) {
+		cached_name = ntfs_uppercase_mbs(name,
+			dir_ni->vol->upcase, dir_ni->vol->upcase_len);
+		const_name = cached_name;
+	} else {
+		cached_name = (char*)NULL;
+		const_name = name;
+	}
+	if (const_name) {
+#if CACHE_LOOKUP_SIZE
+
+		/*
+		 * fetch inode from cache
+		 */
+
+		if (dir_ni->vol->lookup_cache) {
+			struct CACHED_LOOKUP item;
+			struct CACHED_LOOKUP *cached;
+
+			item.name = const_name;
+			item.namesize = strlen(const_name) + 1;
+			item.parent = dir_ni->mft_no;
+			cached = (struct CACHED_LOOKUP*)ntfs_fetch_cache(
+					dir_ni->vol->lookup_cache,
+					GENERIC(&item), lookup_cache_compare);
+			if (cached) {
+				inum = cached->inum;
+				if (inum == (u64)-1)
+					errno = ENOENT;
+			} else {
+				/* Generate unicode name. */
+				uname_len = ntfs_mbstoucs(name, &uname);
+				if (uname_len >= 0) {
+					inum = ntfs_inode_lookup_by_name(dir_ni,
+							uname, uname_len);
+					item.inum = inum;
+				/* enter into cache, even if not found */
+					ntfs_enter_cache(dir_ni->vol->lookup_cache,
+							GENERIC(&item),
+							lookup_cache_compare);
+					free(uname);
+				} else
+					inum = (s64)-1;
+			}
+		} else
+#endif
+			{
+				/* Generate unicode name. */
+			uname_len = ntfs_mbstoucs(cached_name, &uname);
+			if (uname_len >= 0)
+				inum = ntfs_inode_lookup_by_name(dir_ni,
+						uname, uname_len);
+			else
+				inum = (s64)-1;
+		}
+		if (cached_name)
+			free(cached_name);
+	} else
+		inum = (s64)-1;
+	return (inum);
+}
+
+/*
+ *		Update a cache lookup record when a name has been defined
+ *
+ *	The UTF-8 name is required
+ */
+
+void ntfs_inode_update_mbsname(ntfs_inode *dir_ni, const char *name, u64 inum)
+{
+#if CACHE_LOOKUP_SIZE
+	struct CACHED_LOOKUP item;
+	struct CACHED_LOOKUP *cached;
+	char *cached_name;
+
+	if (dir_ni->vol->lookup_cache) {
+		if (!NVolCaseSensitive(dir_ni->vol)) {
+			cached_name = ntfs_uppercase_mbs(name,
+				dir_ni->vol->upcase, dir_ni->vol->upcase_len);
+			item.name = cached_name;
+		} else {
+			cached_name = (char*)NULL;
+			item.name = name;
+		}
+		if (item.name) {
+			item.namesize = strlen(item.name) + 1;
+			item.parent = dir_ni->mft_no;
+			item.inum = inum;
+			cached = (struct CACHED_LOOKUP*)ntfs_enter_cache(
+					dir_ni->vol->lookup_cache,
+					GENERIC(&item), lookup_cache_compare);
+			if (cached)
+				cached->inum = inum;
+			if (cached_name)
+				free(cached_name);
+		}
+	}
+#endif
+}
+
+/**
+ * ntfs_pathname_to_inode - Find the inode which represents the given pathname
+ * @vol:       An ntfs volume obtained from ntfs_mount
+ * @parent:    A directory inode to begin the search (may be NULL)
+ * @pathname:  Pathname to be located
+ *
+ * Take an ASCII pathname and find the inode that represents it.  The function
+ * splits the path and then descends the directory tree.  If @parent is NULL,
+ * then the root directory '.' will be used as the base for the search.
+ *
+ * Return:  inode  Success, the pathname was valid
+ *	    NULL   Error, the pathname was invalid, or some other error occurred
+ */
+ntfs_inode *ntfs_pathname_to_inode(ntfs_volume *vol, ntfs_inode *parent,
+		const char *pathname)
+{
+	u64 inum;
+	int len, err = 0;
+	char *p, *q;
+	ntfs_inode *ni;
+	ntfs_inode *result = NULL;
+	ntfschar *unicode = NULL;
+	char *ascii = NULL;
+#if CACHE_INODE_SIZE
+	struct CACHED_INODE item;
+	struct CACHED_INODE *cached;
+	char *fullname;
+#endif
+
+	if (!vol || !pathname) {
+		errno = EINVAL;
+		return NULL;
+	}
+	
+	ntfs_log_trace("path: '%s'\n", pathname);
+	
+	ascii = strdup(pathname);
+	if (!ascii) {
+		ntfs_log_error("Out of memory.\n");
+		err = ENOMEM;
+		goto out;
+	}
+
+	p = ascii;
+	/* Remove leading /'s. */
+	while (p && *p && *p == PATH_SEP)
+		p++;
+#if CACHE_INODE_SIZE
+	fullname = p;
+	if (p[0] && (p[strlen(p)-1] == PATH_SEP))
+		ntfs_log_error("Unnormalized path %s\n",ascii);
+#endif
+	if (parent) {
+		ni = parent;
+	} else {
+#if CACHE_INODE_SIZE
+			/*
+			 * fetch inode for full path from cache
+			 */
+		if (*fullname) {
+			item.pathname = fullname;
+			item.varsize = strlen(fullname) + 1;
+			cached = (struct CACHED_INODE*)ntfs_fetch_cache(
+				vol->xinode_cache, GENERIC(&item),
+				inode_cache_compare);
+		} else
+			cached = (struct CACHED_INODE*)NULL;
+		if (cached) {
+			/*
+			 * return opened inode if found in cache
+			 */
+			inum = MREF(cached->inum);
+			ni = ntfs_inode_open(vol, inum);
+			if (!ni) {
+				ntfs_log_debug("Cannot open inode %llu: %s.\n",
+						(unsigned long long)inum, p);
+				err = EIO;
+			}
+			result = ni;
+			goto out;
+		}
+#endif
+		ni = ntfs_inode_open(vol, FILE_root);
+		if (!ni) {
+			ntfs_log_debug("Couldn't open the inode of the root "
+					"directory.\n");
+			err = EIO;
+			result = (ntfs_inode*)NULL;
+			goto out;
+		}
+	}
+
+	while (p && *p) {
+		/* Find the end of the first token. */
+		q = strchr(p, PATH_SEP);
+		if (q != NULL) {
+			*q = '\0';
+		}
+#if CACHE_INODE_SIZE
+			/*
+			 * fetch inode for partial path from cache
+			 */
+		cached = (struct CACHED_INODE*)NULL;
+		if (!parent) {
+			item.pathname = fullname;
+			item.varsize = strlen(fullname) + 1;
+			cached = (struct CACHED_INODE*)ntfs_fetch_cache(
+					vol->xinode_cache, GENERIC(&item),
+					inode_cache_compare);
+			if (cached) {
+				inum = cached->inum;
+			}
+		}
+			/*
+			 * if not in cache, translate, search, then
+			 * insert into cache if found
+			 */
+		if (!cached) {
+			len = ntfs_mbstoucs(p, &unicode);
+			if (len < 0) {
+				ntfs_log_perror("Could not convert filename to Unicode:"
+					" '%s'", p);
+				err = errno;
+				goto close;
+			} else if (len > NTFS_MAX_NAME_LEN) {
+				err = ENAMETOOLONG;
+				goto close;
+			}
+			inum = ntfs_inode_lookup_by_name(ni, unicode, len);
+			if (!parent && (inum != (u64) -1)) {
+				item.inum = inum;
+				ntfs_enter_cache(vol->xinode_cache,
+						GENERIC(&item),
+						inode_cache_compare);
+			}
+		}
+#else
+		len = ntfs_mbstoucs(p, &unicode);
+		if (len < 0) {
+			ntfs_log_perror("Could not convert filename to Unicode:"
+					" '%s'", p);
+			err = errno;
+			goto close;
+		} else if (len > NTFS_MAX_NAME_LEN) {
+			err = ENAMETOOLONG;
+			goto close;
+		}
+		inum = ntfs_inode_lookup_by_name(ni, unicode, len);
+#endif
+		if (inum == (u64) -1) {
+			ntfs_log_debug("Couldn't find name '%s' in pathname "
+					"'%s'.\n", p, pathname);
+			err = ENOENT;
+			goto close;
+		}
+
+		if (ni != parent)
+			if (ntfs_inode_close(ni)) {
+				err = errno;
+				goto out;
+			}
+
+		inum = MREF(inum);
+		ni = ntfs_inode_open(vol, inum);
+		if (!ni) {
+			ntfs_log_debug("Cannot open inode %llu: %s.\n",
+					(unsigned long long)inum, p);
+			err = EIO;
+			goto close;
+		}
+	
+		free(unicode);
+		unicode = NULL;
+
+		if (q) *q++ = PATH_SEP; /* JPA */
+		p = q;
+		while (p && *p && *p == PATH_SEP)
+			p++;
+	}
+
+	result = ni;
+	ni = NULL;
+close:
+	if (ni && (ni != parent))
+		if (ntfs_inode_close(ni) && !err)
+			err = errno;
+out:
+	free(ascii);
+	free(unicode);
+	if (err)
+		errno = err;
+	return result;
+}
+
+/*
+ * The little endian Unicode string ".." for ntfs_readdir().
+ */
+static const ntfschar dotdot[3] = { const_cpu_to_le16('.'),
+				   const_cpu_to_le16('.'),
+				   const_cpu_to_le16('\0') };
+
+/*
+ * union index_union -
+ * More helpers for ntfs_readdir().
+ */
+typedef union {
+	INDEX_ROOT *ir;
+	INDEX_ALLOCATION *ia;
+} index_union __attribute__((__transparent_union__));
+
+/**
+ * enum INDEX_TYPE -
+ * More helpers for ntfs_readdir().
+ */
+typedef enum {
+	INDEX_TYPE_ROOT,	/* index root */
+	INDEX_TYPE_ALLOCATION,	/* index allocation */
+} INDEX_TYPE;
+
+/*
+ *		Decode Interix file types
+ *
+ *	Non-Interix types are returned as plain files, because a
+ *	Windows user may force patterns very similar to Interix,
+ *	and most metadata files have such similar patters.
+ */
+
+static u32 ntfs_interix_types(ntfs_inode *ni)
+{
+	ntfs_attr *na;
+	u32 dt_type;
+	le64 magic;
+
+	dt_type = NTFS_DT_UNKNOWN;
+	na = ntfs_attr_open(ni, AT_DATA, NULL, 0);
+	if (na) {
+		/* Unrecognized patterns (eg HID + SYST) are plain files */
+		dt_type = NTFS_DT_REG;
+		if (na->data_size <= 1) {
+			if (!(ni->flags & FILE_ATTR_HIDDEN))
+				dt_type = (na->data_size ?
+						NTFS_DT_SOCK : NTFS_DT_FIFO);
+		} else {
+			if ((na->data_size >= (s64)sizeof(magic))
+			    && (ntfs_attr_pread(na, 0, sizeof(magic), &magic)
+				== sizeof(magic))) {
+				if (magic == INTX_SYMBOLIC_LINK)
+					dt_type = NTFS_DT_LNK;
+				else if (magic == INTX_BLOCK_DEVICE)
+					dt_type = NTFS_DT_BLK;
+				else if (magic == INTX_CHARACTER_DEVICE)
+					dt_type = NTFS_DT_CHR;
+			}
+		}
+		ntfs_attr_close(na);
+	}
+	return (dt_type);
+}
+
+/*
+ *		Decode file types
+ *
+ *	Better only use for Interix types and junctions,
+ *	unneeded complexity when used for plain files or directories
+ *
+ *	Error cases are logged and returned as unknown.
+ */
+
+static u32 ntfs_dir_entry_type(ntfs_inode *dir_ni, MFT_REF mref,
+					FILE_ATTR_FLAGS attributes)
+{
+	ntfs_inode *ni;
+	u32 dt_type;
+
+	dt_type = NTFS_DT_UNKNOWN;
+	ni = ntfs_inode_open(dir_ni->vol, mref);
+	if (ni) {
+		if ((attributes & FILE_ATTR_REPARSE_POINT)
+		    && ntfs_possible_symlink(ni))
+			dt_type = NTFS_DT_LNK;
+		else
+			if ((attributes & FILE_ATTR_SYSTEM)
+			   && !(attributes & FILE_ATTR_I30_INDEX_PRESENT))
+				dt_type = ntfs_interix_types(ni);
+			else
+				dt_type = (attributes
+						& FILE_ATTR_I30_INDEX_PRESENT
+					? NTFS_DT_DIR : NTFS_DT_REG);
+		if (ntfs_inode_close(ni)) {
+				 /* anything special worth doing ? */
+			ntfs_log_error("Failed to close inode %lld\n",
+				(long long)MREF(mref));
+		}
+	}
+	if (dt_type == NTFS_DT_UNKNOWN)
+		ntfs_log_error("Could not decode the type of inode %lld\n",
+				(long long)MREF(mref));
+	return (dt_type);
+}
+
+/**
+ * ntfs_filldir - ntfs specific filldir method
+ * @dir_ni:	ntfs inode of current directory
+ * @pos:	current position in directory
+ * @ivcn_bits:	log(2) of index vcn size
+ * @index_type:	specifies whether @iu is an index root or an index allocation
+ * @iu:		index root or index block to which @ie belongs
+ * @ie:		current index entry
+ * @dirent:	context for filldir callback supplied by the caller
+ * @filldir:	filldir callback supplied by the caller
+ *
+ * Pass information specifying the current directory entry @ie to the @filldir
+ * callback.
+ */
+static int ntfs_filldir(ntfs_inode *dir_ni, s64 *pos, u8 ivcn_bits,
+		const INDEX_TYPE index_type, index_union iu, INDEX_ENTRY *ie,
+		void *dirent, ntfs_filldir_t filldir)
+{
+	FILE_NAME_ATTR *fn = &ie->key.file_name;
+	unsigned dt_type;
+	BOOL metadata;
+	ntfschar *loname;
+	int res;
+	MFT_REF mref;
+
+	ntfs_log_trace("Entering.\n");
+	
+	/* Advance the position even if going to skip the entry. */
+	if (index_type == INDEX_TYPE_ALLOCATION)
+		*pos = (u8*)ie - (u8*)iu.ia + (sle64_to_cpu(
+				iu.ia->index_block_vcn) << ivcn_bits) +
+				dir_ni->vol->mft_record_size;
+	else /* if (index_type == INDEX_TYPE_ROOT) */
+		*pos = (u8*)ie - (u8*)iu.ir;
+	mref = le64_to_cpu(ie->indexed_file);
+	metadata = (MREF(mref) != FILE_root) && (MREF(mref) < FILE_first_user);
+	/* Skip root directory self reference entry. */
+	if (MREF_LE(ie->indexed_file) == FILE_root)
+		return 0;
+	if ((ie->key.file_name.file_attributes
+		     & (FILE_ATTR_REPARSE_POINT | FILE_ATTR_SYSTEM))
+	    && !metadata)
+		dt_type = ntfs_dir_entry_type(dir_ni, mref,
+					ie->key.file_name.file_attributes);
+	else if (ie->key.file_name.file_attributes
+		     & FILE_ATTR_I30_INDEX_PRESENT)
+		dt_type = NTFS_DT_DIR;
+	else
+		dt_type = NTFS_DT_REG;
+
+		/* return metadata files and hidden files if requested */
+        if ((!metadata && (NVolShowHidFiles(dir_ni->vol)
+				|| !(fn->file_attributes & FILE_ATTR_HIDDEN)))
+            || (NVolShowSysFiles(dir_ni->vol) && (NVolShowHidFiles(dir_ni->vol)
+				|| metadata))) {
+		if (NVolCaseSensitive(dir_ni->vol)) {
+			res = filldir(dirent, fn->file_name,
+					fn->file_name_length,
+					fn->file_name_type, *pos,
+					mref, dt_type);
+		} else {
+			loname = (ntfschar*)ntfs_malloc(2*fn->file_name_length);
+			if (loname) {
+				memcpy(loname, fn->file_name,
+					2*fn->file_name_length);
+				ntfs_name_locase(loname, fn->file_name_length,
+					dir_ni->vol->locase,
+					dir_ni->vol->upcase_len);
+				res = filldir(dirent, loname,
+					fn->file_name_length,
+					fn->file_name_type, *pos,
+					mref, dt_type);
+				free(loname);
+			} else
+				res = -1;
+		}
+	} else
+		res = 0;
+	return (res);
+}
+
+/**
+ * ntfs_mft_get_parent_ref - find mft reference of parent directory of an inode
+ * @ni:		ntfs inode whose parent directory to find
+ *
+ * Find the parent directory of the ntfs inode @ni. To do this, find the first
+ * file name attribute in the mft record of @ni and return the parent mft
+ * reference from that.
+ *
+ * Note this only makes sense for directories, since files can be hard linked
+ * from multiple directories and there is no way for us to tell which one is
+ * being looked for.
+ *
+ * Technically directories can have hard links, too, but we consider that as
+ * illegal as Linux/UNIX do not support directory hard links.
+ *
+ * Return the mft reference of the parent directory on success or -1 on error
+ * with errno set to the error code.
+ */
+static MFT_REF ntfs_mft_get_parent_ref(ntfs_inode *ni)
+{
+	MFT_REF mref;
+	ntfs_attr_search_ctx *ctx;
+	FILE_NAME_ATTR *fn;
+	int eo;
+
+	ntfs_log_trace("Entering.\n");
+	
+	if (!ni) {
+		errno = EINVAL;
+		return ERR_MREF(-1);
+	}
+
+	ctx = ntfs_attr_get_search_ctx(ni, NULL);
+	if (!ctx)
+		return ERR_MREF(-1);
+	if (ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) {
+		ntfs_log_error("No file name found in inode %lld\n", 
+			       (unsigned long long)ni->mft_no);
+		goto err_out;
+	}
+	if (ctx->attr->non_resident) {
+		ntfs_log_error("File name attribute must be resident (inode "
+			       "%lld)\n", (unsigned long long)ni->mft_no);
+		goto io_err_out;
+	}
+	fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
+			le16_to_cpu(ctx->attr->value_offset));
+	if ((u8*)fn +	le32_to_cpu(ctx->attr->value_length) >
+			(u8*)ctx->attr + le32_to_cpu(ctx->attr->length)) {
+		ntfs_log_error("Corrupt file name attribute in inode %lld.\n",
+			       (unsigned long long)ni->mft_no);
+		goto io_err_out;
+	}
+	mref = le64_to_cpu(fn->parent_directory);
+	ntfs_attr_put_search_ctx(ctx);
+	return mref;
+io_err_out:
+	errno = EIO;
+err_out:
+	eo = errno;
+	ntfs_attr_put_search_ctx(ctx);
+	errno = eo;
+	return ERR_MREF(-1);
+}
+
+/**
+ * ntfs_readdir - read the contents of an ntfs directory
+ * @dir_ni:	ntfs inode of current directory
+ * @pos:	current position in directory
+ * @dirent:	context for filldir callback supplied by the caller
+ * @filldir:	filldir callback supplied by the caller
+ *
+ * Parse the index root and the index blocks that are marked in use in the
+ * index bitmap and hand each found directory entry to the @filldir callback
+ * supplied by the caller.
+ *
+ * Return 0 on success or -1 on error with errno set to the error code.
+ *
+ * Note: Index blocks are parsed in ascending vcn order, from which follows
+ * that the directory entries are not returned sorted.
+ */
+int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos,
+		void *dirent, ntfs_filldir_t filldir)
+{
+	s64 i_size, br, ia_pos, bmp_pos, ia_start;
+	ntfs_volume *vol;
+	ntfs_attr *ia_na, *bmp_na = NULL;
+	ntfs_attr_search_ctx *ctx = NULL;
+	u8 *index_end, *bmp = NULL;
+	INDEX_ROOT *ir;
+	INDEX_ENTRY *ie;
+	INDEX_ALLOCATION *ia = NULL;
+	int rc, ir_pos, bmp_buf_size, bmp_buf_pos, eo;
+	u32 index_block_size;
+	u8 index_block_size_bits, index_vcn_size_bits;
+
+	ntfs_log_trace("Entering.\n");
+	
+	if (!dir_ni || !pos || !filldir) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (!(dir_ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
+		errno = ENOTDIR;
+		return -1;
+	}
+
+	vol = dir_ni->vol;
+
+	ntfs_log_trace("Entering for inode %lld, *pos 0x%llx.\n",
+			(unsigned long long)dir_ni->mft_no, (long long)*pos);
+
+	/* Open the index allocation attribute. */
+	ia_na = ntfs_attr_open(dir_ni, AT_INDEX_ALLOCATION, NTFS_INDEX_I30, 4);
+	if (!ia_na) {
+		if (errno != ENOENT) {
+			ntfs_log_perror("Failed to open index allocation attribute. "
+				"Directory inode %lld is corrupt or bug",
+				(unsigned long long)dir_ni->mft_no);
+			return -1;
+		}
+		i_size = 0;
+	} else
+		i_size = ia_na->data_size;
+
+	rc = 0;
+
+	/* Are we at end of dir yet? */
+	if (*pos >= i_size + vol->mft_record_size)
+		goto done;
+
+	/* Emulate . and .. for all directories. */
+	if (!*pos) {
+		rc = filldir(dirent, dotdot, 1, FILE_NAME_POSIX, *pos,
+				MK_MREF(dir_ni->mft_no,
+				le16_to_cpu(dir_ni->mrec->sequence_number)),
+				NTFS_DT_DIR);
+		if (rc)
+			goto err_out;
+		++*pos;
+	}
+	if (*pos == 1) {
+		MFT_REF parent_mref;
+
+		parent_mref = ntfs_mft_get_parent_ref(dir_ni);
+		if (parent_mref == ERR_MREF(-1)) {
+			ntfs_log_perror("Parent directory not found");
+			goto dir_err_out;
+		}
+
+		rc = filldir(dirent, dotdot, 2, FILE_NAME_POSIX, *pos,
+				parent_mref, NTFS_DT_DIR);
+		if (rc)
+			goto err_out;
+		++*pos;
+	}
+
+	ctx = ntfs_attr_get_search_ctx(dir_ni, NULL);
+	if (!ctx)
+		goto err_out;
+
+	/* Get the offset into the index root attribute. */
+	ir_pos = (int)*pos;
+	/* Find the index root attribute in the mft record. */
+	if (ntfs_attr_lookup(AT_INDEX_ROOT, NTFS_INDEX_I30, 4, CASE_SENSITIVE, 0, NULL,
+			0, ctx)) {
+		ntfs_log_perror("Index root attribute missing in directory inode "
+				"%lld", (unsigned long long)dir_ni->mft_no);
+		goto dir_err_out;
+	}
+	/* Get to the index root value. */
+	ir = (INDEX_ROOT*)((u8*)ctx->attr +
+			le16_to_cpu(ctx->attr->value_offset));
+
+	/* Determine the size of a vcn in the directory index. */
+	index_block_size = le32_to_cpu(ir->index_block_size);
+	if (index_block_size < NTFS_BLOCK_SIZE ||
+			index_block_size & (index_block_size - 1)) {
+		ntfs_log_error("Index block size %u is invalid.\n",
+				(unsigned)index_block_size);
+		goto dir_err_out;
+	}
+	index_block_size_bits = ffs(index_block_size) - 1;
+	if (vol->cluster_size <= index_block_size) {
+		index_vcn_size_bits = vol->cluster_size_bits;
+	} else {
+		index_vcn_size_bits = NTFS_BLOCK_SIZE_BITS;
+	}
+
+	/* Are we jumping straight into the index allocation attribute? */
+	if (*pos >= vol->mft_record_size) {
+		ntfs_attr_put_search_ctx(ctx);
+		ctx = NULL;
+		goto skip_index_root;
+	}
+
+	index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length);
+	/* The first index entry. */
+	ie = (INDEX_ENTRY*)((u8*)&ir->index +
+			le32_to_cpu(ir->index.entries_offset));
+	/*
+	 * Loop until we exceed valid memory (corruption case) or until we
+	 * reach the last entry or until filldir tells us it has had enough
+	 * or signals an error (both covered by the rc test).
+	 */
+	for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {
+		ntfs_log_debug("In index root, offset %d.\n", (int)((u8*)ie - (u8*)ir));
+		/* Bounds checks. */
+		if ((u8*)ie < (u8*)ctx->mrec || (u8*)ie +
+				sizeof(INDEX_ENTRY_HEADER) > index_end ||
+				(u8*)ie + le16_to_cpu(ie->key_length) >
+				index_end)
+			goto dir_err_out;
+		/* The last entry cannot contain a name. */
+		if (ie->ie_flags & INDEX_ENTRY_END)
+			break;
+		
+		if (!le16_to_cpu(ie->length))
+			goto dir_err_out;
+		
+		/* Skip index root entry if continuing previous readdir. */
+		if (ir_pos > (u8*)ie - (u8*)ir)
+			continue;
+		/*
+		 * Submit the directory entry to ntfs_filldir(), which will
+		 * invoke the filldir() callback as appropriate.
+		 */
+		rc = ntfs_filldir(dir_ni, pos, index_vcn_size_bits,
+				INDEX_TYPE_ROOT, ir, ie, dirent, filldir);
+		if (rc) {
+			ntfs_attr_put_search_ctx(ctx);
+			ctx = NULL;
+			goto err_out;
+		}
+	}
+	ntfs_attr_put_search_ctx(ctx);
+	ctx = NULL;
+
+	/* If there is no index allocation attribute we are finished. */
+	if (!ia_na)
+		goto EOD;
+
+	/* Advance *pos to the beginning of the index allocation. */
+	*pos = vol->mft_record_size;
+
+skip_index_root:
+
+	if (!ia_na)
+		goto done;
+
+	/* Allocate a buffer for the current index block. */
+	ia = ntfs_malloc(index_block_size);
+	if (!ia)
+		goto err_out;
+
+	bmp_na = ntfs_attr_open(dir_ni, AT_BITMAP, NTFS_INDEX_I30, 4);
+	if (!bmp_na) {
+		ntfs_log_perror("Failed to open index bitmap attribute");
+		goto dir_err_out;
+	}
+
+	/* Get the offset into the index allocation attribute. */
+	ia_pos = *pos - vol->mft_record_size;
+
+	bmp_pos = ia_pos >> index_block_size_bits;
+	if (bmp_pos >> 3 >= bmp_na->data_size) {
+		ntfs_log_error("Current index position exceeds index bitmap "
+				"size.\n");
+		goto dir_err_out;
+	}
+
+	bmp_buf_size = min(bmp_na->data_size - (bmp_pos >> 3), 4096);
+	bmp = ntfs_malloc(bmp_buf_size);
+	if (!bmp)
+		goto err_out;
+
+	br = ntfs_attr_pread(bmp_na, bmp_pos >> 3, bmp_buf_size, bmp);
+	if (br != bmp_buf_size) {
+		if (br != -1)
+			errno = EIO;
+		ntfs_log_perror("Failed to read from index bitmap attribute");
+		goto err_out;
+	}
+
+	bmp_buf_pos = 0;
+	/* If the index block is not in use find the next one that is. */
+	while (!(bmp[bmp_buf_pos >> 3] & (1 << (bmp_buf_pos & 7)))) {
+find_next_index_buffer:
+		bmp_pos++;
+		bmp_buf_pos++;
+		/* If we have reached the end of the bitmap, we are done. */
+		if (bmp_pos >> 3 >= bmp_na->data_size)
+			goto EOD;
+		ia_pos = bmp_pos << index_block_size_bits;
+		if (bmp_buf_pos >> 3 < bmp_buf_size)
+			continue;
+		/* Read next chunk from the index bitmap. */
+		bmp_buf_pos = 0;
+		if ((bmp_pos >> 3) + bmp_buf_size > bmp_na->data_size)
+			bmp_buf_size = bmp_na->data_size - (bmp_pos >> 3);
+		br = ntfs_attr_pread(bmp_na, bmp_pos >> 3, bmp_buf_size, bmp);
+		if (br != bmp_buf_size) {
+			if (br != -1)
+				errno = EIO;
+			ntfs_log_perror("Failed to read from index bitmap attribute");
+			goto err_out;
+		}
+	}
+
+	ntfs_log_debug("Handling index block 0x%llx.\n", (long long)bmp_pos);
+
+	/* Read the index block starting at bmp_pos. */
+	br = ntfs_attr_mst_pread(ia_na, bmp_pos << index_block_size_bits, 1,
+			index_block_size, ia);
+	if (br != 1) {
+		if (br != -1)
+			errno = EIO;
+		ntfs_log_perror("Failed to read index block");
+		goto err_out;
+	}
+
+	ia_start = ia_pos & ~(s64)(index_block_size - 1);
+	if (sle64_to_cpu(ia->index_block_vcn) != ia_start >>
+			index_vcn_size_bits) {
+		ntfs_log_error("Actual VCN (0x%llx) of index buffer is different "
+				"from expected VCN (0x%llx) in inode 0x%llx.\n",
+				(long long)sle64_to_cpu(ia->index_block_vcn),
+				(long long)ia_start >> index_vcn_size_bits,
+				(unsigned long long)dir_ni->mft_no);
+		goto dir_err_out;
+	}
+	if (le32_to_cpu(ia->index.allocated_size) + 0x18 != index_block_size) {
+		ntfs_log_error("Index buffer (VCN 0x%llx) of directory inode %lld "
+				"has a size (%u) differing from the directory "
+				"specified size (%u).\n", (long long)ia_start >>
+				index_vcn_size_bits,
+				(unsigned long long)dir_ni->mft_no,
+				(unsigned) le32_to_cpu(ia->index.allocated_size)
+				+ 0x18, (unsigned)index_block_size);
+		goto dir_err_out;
+	}
+	index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length);
+	if (index_end > (u8*)ia + index_block_size) {
+		ntfs_log_error("Size of index buffer (VCN 0x%llx) of directory inode "
+				"%lld exceeds maximum size.\n",
+				(long long)ia_start >> index_vcn_size_bits,
+				(unsigned long long)dir_ni->mft_no);
+		goto dir_err_out;
+	}
+	/* The first index entry. */
+	ie = (INDEX_ENTRY*)((u8*)&ia->index +
+			le32_to_cpu(ia->index.entries_offset));
+	/*
+	 * Loop until we exceed valid memory (corruption case) or until we
+	 * reach the last entry or until ntfs_filldir tells us it has had
+	 * enough or signals an error (both covered by the rc test).
+	 */
+	for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {
+		ntfs_log_debug("In index allocation, offset 0x%llx.\n",
+				(long long)ia_start + ((u8*)ie - (u8*)ia));
+		/* Bounds checks. */
+		if ((u8*)ie < (u8*)ia || (u8*)ie +
+				sizeof(INDEX_ENTRY_HEADER) > index_end ||
+				(u8*)ie + le16_to_cpu(ie->key_length) >
+				index_end) {
+			ntfs_log_error("Index entry out of bounds in directory inode "
+				"%lld.\n", (unsigned long long)dir_ni->mft_no);
+			goto dir_err_out;
+		}
+		/* The last entry cannot contain a name. */
+		if (ie->ie_flags & INDEX_ENTRY_END)
+			break;
+		
+		if (!le16_to_cpu(ie->length))
+			goto dir_err_out;
+		
+		/* Skip index entry if continuing previous readdir. */
+		if (ia_pos - ia_start > (u8*)ie - (u8*)ia)
+			continue;
+		/*
+		 * Submit the directory entry to ntfs_filldir(), which will
+		 * invoke the filldir() callback as appropriate.
+		 */
+		rc = ntfs_filldir(dir_ni, pos, index_vcn_size_bits,
+				INDEX_TYPE_ALLOCATION, ia, ie, dirent, filldir);
+		if (rc)
+			goto err_out;
+	}
+	goto find_next_index_buffer;
+EOD:
+	/* We are finished, set *pos to EOD. */
+	*pos = i_size + vol->mft_record_size;
+done:
+	free(ia);
+	free(bmp);
+	if (bmp_na)
+		ntfs_attr_close(bmp_na);
+	if (ia_na)
+		ntfs_attr_close(ia_na);
+	ntfs_log_debug("EOD, *pos 0x%llx, returning 0.\n", (long long)*pos);
+	return 0;
+dir_err_out:
+	errno = EIO;
+err_out:
+	eo = errno;
+	ntfs_log_trace("failed.\n");
+	if (ctx)
+		ntfs_attr_put_search_ctx(ctx);
+	free(ia);
+	free(bmp);
+	if (bmp_na)
+		ntfs_attr_close(bmp_na);
+	if (ia_na)
+		ntfs_attr_close(ia_na);
+	errno = eo;
+	return -1;
+}
+
+
+/**
+ * __ntfs_create - create object on ntfs volume
+ * @dir_ni:	ntfs inode for directory in which create new object
+ * @securid:	id of inheritable security descriptor, 0 if none
+ * @name:	unicode name of new object
+ * @name_len:	length of the name in unicode characters
+ * @type:	type of the object to create
+ * @dev:	major and minor device numbers (obtained from makedev())
+ * @target:	target in unicode (only for symlinks)
+ * @target_len:	length of target in unicode characters
+ *
+ * Internal, use ntfs_create{,_device,_symlink} wrappers instead.
+ *
+ * @type can be:
+ *	S_IFREG		to create regular file
+ *	S_IFDIR		to create directory
+ *	S_IFBLK		to create block device
+ *	S_IFCHR		to create character device
+ *	S_IFLNK		to create symbolic link
+ *	S_IFIFO		to create FIFO
+ *	S_IFSOCK	to create socket
+ * other values are invalid.
+ *
+ * @dev is used only if @type is S_IFBLK or S_IFCHR, in other cases its value
+ * ignored.
+ *
+ * @target and @target_len are used only if @type is S_IFLNK, in other cases
+ * their value ignored.
+ *
+ * Return opened ntfs inode that describes created object on success or NULL
+ * on error with errno set to the error code.
+ */
+static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, le32 securid,
+		const ntfschar *name, u8 name_len, mode_t type, dev_t dev,
+		const ntfschar *target, int target_len)
+{
+	ntfs_inode *ni;
+	int rollback_data = 0, rollback_sd = 0;
+	FILE_NAME_ATTR *fn = NULL;
+	STANDARD_INFORMATION *si = NULL;
+	int err, fn_len, si_len;
+
+	ntfs_log_trace("Entering.\n");
+	
+	/* Sanity checks. */
+	if (!dir_ni || !name || !name_len) {
+		ntfs_log_error("Invalid arguments.\n");
+		errno = EINVAL;
+		return NULL;
+	}
+	
+	if (dir_ni->flags & FILE_ATTR_REPARSE_POINT) {
+		errno = EOPNOTSUPP;
+		return NULL;
+	}
+	
+	ni = ntfs_mft_record_alloc(dir_ni->vol, NULL);
+	if (!ni)
+		return NULL;
+#if CACHE_NIDATA_SIZE
+	ntfs_inode_invalidate(dir_ni->vol, ni->mft_no);
+#endif
+	/*
+	 * Create STANDARD_INFORMATION attribute.
+	 * JPA Depending on available inherited security descriptor,
+	 * Write STANDARD_INFORMATION v1.2 (no inheritance) or v3
+	 */
+	if (securid)
+		si_len = sizeof(STANDARD_INFORMATION);
+	else
+		si_len = offsetof(STANDARD_INFORMATION, v1_end);
+	si = ntfs_calloc(si_len);
+	if (!si) {
+		err = errno;
+		goto err_out;
+	}
+	si->creation_time = ni->creation_time;
+	si->last_data_change_time = ni->last_data_change_time;
+	si->last_mft_change_time = ni->last_mft_change_time;
+	si->last_access_time = ni->last_access_time;
+	if (securid) {
+		set_nino_flag(ni, v3_Extensions);
+		ni->owner_id = si->owner_id = 0;
+		ni->security_id = si->security_id = securid;
+		ni->quota_charged = si->quota_charged = const_cpu_to_le64(0);
+		ni->usn = si->usn = const_cpu_to_le64(0);
+	} else
+		clear_nino_flag(ni, v3_Extensions);
+	if (!S_ISREG(type) && !S_ISDIR(type)) {
+		si->file_attributes = FILE_ATTR_SYSTEM;
+		ni->flags = FILE_ATTR_SYSTEM;
+	}
+	ni->flags |= FILE_ATTR_ARCHIVE;
+	if (NVolHideDotFiles(dir_ni->vol)
+	    && (name_len > 1)
+	    && (name[0] == const_cpu_to_le16('.'))
+	    && (name[1] != const_cpu_to_le16('.')))
+		ni->flags |= FILE_ATTR_HIDDEN;
+		/*
+		 * Set compression flag according to parent directory
+		 * unless NTFS version < 3.0 or cluster size > 4K
+		 * or compression has been disabled
+		 */
+	if ((dir_ni->flags & FILE_ATTR_COMPRESSED)
+	   && (dir_ni->vol->major_ver >= 3)
+	   && NVolCompression(dir_ni->vol)
+	   && (dir_ni->vol->cluster_size <= MAX_COMPRESSION_CLUSTER_SIZE)
+	   && (S_ISREG(type) || S_ISDIR(type)))
+		ni->flags |= FILE_ATTR_COMPRESSED;
+	/* Add STANDARD_INFORMATION to inode. */
+	if (ntfs_attr_add(ni, AT_STANDARD_INFORMATION, AT_UNNAMED, 0,
+			(u8*)si, si_len)) {
+		err = errno;
+		ntfs_log_error("Failed to add STANDARD_INFORMATION "
+				"attribute.\n");
+		goto err_out;
+	}
+
+	if (!securid) {
+		if (ntfs_sd_add_everyone(ni)) {
+			err = errno;
+			goto err_out;
+		}
+	}
+	rollback_sd = 1;
+
+	if (S_ISDIR(type)) {
+		INDEX_ROOT *ir = NULL;
+		INDEX_ENTRY *ie;
+		int ir_len, index_len;
+
+		/* Create INDEX_ROOT attribute. */
+		index_len = sizeof(INDEX_HEADER) + sizeof(INDEX_ENTRY_HEADER);
+		ir_len = offsetof(INDEX_ROOT, index) + index_len;
+		ir = ntfs_calloc(ir_len);
+		if (!ir) {
+			err = errno;
+			goto err_out;
+		}
+		ir->type = AT_FILE_NAME;
+		ir->collation_rule = COLLATION_FILE_NAME;
+		ir->index_block_size = cpu_to_le32(ni->vol->indx_record_size);
+		if (ni->vol->cluster_size <= ni->vol->indx_record_size)
+			ir->clusters_per_index_block =
+					ni->vol->indx_record_size >>
+					ni->vol->cluster_size_bits;
+		else
+			ir->clusters_per_index_block = 
+					ni->vol->indx_record_size >>
+					NTFS_BLOCK_SIZE_BITS;
+		ir->index.entries_offset = cpu_to_le32(sizeof(INDEX_HEADER));
+		ir->index.index_length = cpu_to_le32(index_len);
+		ir->index.allocated_size = cpu_to_le32(index_len);
+		ie = (INDEX_ENTRY*)((u8*)ir + sizeof(INDEX_ROOT));
+		ie->length = cpu_to_le16(sizeof(INDEX_ENTRY_HEADER));
+		ie->key_length = 0;
+		ie->ie_flags = INDEX_ENTRY_END;
+		/* Add INDEX_ROOT attribute to inode. */
+		if (ntfs_attr_add(ni, AT_INDEX_ROOT, NTFS_INDEX_I30, 4,
+				(u8*)ir, ir_len)) {
+			err = errno;
+			free(ir);
+			ntfs_log_error("Failed to add INDEX_ROOT attribute.\n");
+			goto err_out;
+		}
+		free(ir);
+	} else {
+		INTX_FILE *data;
+		int data_len;
+
+		switch (type) {
+			case S_IFBLK:
+			case S_IFCHR:
+				data_len = offsetof(INTX_FILE, device_end);
+				data = ntfs_malloc(data_len);
+				if (!data) {
+					err = errno;
+					goto err_out;
+				}
+				data->major = cpu_to_le64(major(dev));
+				data->minor = cpu_to_le64(minor(dev));
+				if (type == S_IFBLK)
+					data->magic = INTX_BLOCK_DEVICE;
+				if (type == S_IFCHR)
+					data->magic = INTX_CHARACTER_DEVICE;
+				break;
+			case S_IFLNK:
+				data_len = sizeof(INTX_FILE_TYPES) +
+						target_len * sizeof(ntfschar);
+				data = ntfs_malloc(data_len);
+				if (!data) {
+					err = errno;
+					goto err_out;
+				}
+				data->magic = INTX_SYMBOLIC_LINK;
+				memcpy(data->target, target,
+						target_len * sizeof(ntfschar));
+				break;
+			case S_IFSOCK:
+				data = NULL;
+				data_len = 1;
+				break;
+			default: /* FIFO or regular file. */
+				data = NULL;
+				data_len = 0;
+				break;
+		}
+		/* Add DATA attribute to inode. */
+		if (ntfs_attr_add(ni, AT_DATA, AT_UNNAMED, 0, (u8*)data,
+				data_len)) {
+			err = errno;
+			ntfs_log_error("Failed to add DATA attribute.\n");
+			free(data);
+			goto err_out;
+		}
+		rollback_data = 1;
+		free(data);
+	}
+	/* Create FILE_NAME attribute. */
+	fn_len = sizeof(FILE_NAME_ATTR) + name_len * sizeof(ntfschar);
+	fn = ntfs_calloc(fn_len);
+	if (!fn) {
+		err = errno;
+		goto err_out;
+	}
+	fn->parent_directory = MK_LE_MREF(dir_ni->mft_no,
+			le16_to_cpu(dir_ni->mrec->sequence_number));
+	fn->file_name_length = name_len;
+	fn->file_name_type = FILE_NAME_POSIX;
+	if (S_ISDIR(type))
+		fn->file_attributes = FILE_ATTR_I30_INDEX_PRESENT;
+	if (!S_ISREG(type) && !S_ISDIR(type))
+		fn->file_attributes = FILE_ATTR_SYSTEM;
+	else
+		fn->file_attributes |= ni->flags & FILE_ATTR_COMPRESSED;
+	fn->file_attributes |= FILE_ATTR_ARCHIVE;
+	fn->file_attributes |= ni->flags & FILE_ATTR_HIDDEN;
+	fn->creation_time = ni->creation_time;
+	fn->last_data_change_time = ni->last_data_change_time;
+	fn->last_mft_change_time = ni->last_mft_change_time;
+	fn->last_access_time = ni->last_access_time;
+	if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
+		fn->data_size = fn->allocated_size = const_cpu_to_le64(0);
+	else {
+		fn->data_size = cpu_to_sle64(ni->data_size);
+		fn->allocated_size = cpu_to_sle64(ni->allocated_size);
+	}
+	memcpy(fn->file_name, name, name_len * sizeof(ntfschar));
+	/* Add FILE_NAME attribute to inode. */
+	if (ntfs_attr_add(ni, AT_FILE_NAME, AT_UNNAMED, 0, (u8*)fn, fn_len)) {
+		err = errno;
+		ntfs_log_error("Failed to add FILE_NAME attribute.\n");
+		goto err_out;
+	}
+	/* Add FILE_NAME attribute to index. */
+	if (ntfs_index_add_filename(dir_ni, fn, MK_MREF(ni->mft_no,
+			le16_to_cpu(ni->mrec->sequence_number)))) {
+		err = errno;
+		ntfs_log_perror("Failed to add entry to the index");
+		goto err_out;
+	}
+	/* Set hard links count and directory flag. */
+	ni->mrec->link_count = cpu_to_le16(1);
+	if (S_ISDIR(type))
+		ni->mrec->flags |= MFT_RECORD_IS_DIRECTORY;
+	ntfs_inode_mark_dirty(ni);
+	/* Done! */
+	free(fn);
+	free(si);
+	ntfs_log_trace("Done.\n");
+	return ni;
+err_out:
+	ntfs_log_trace("Failed.\n");
+
+	if (rollback_sd)
+		ntfs_attr_remove(ni, AT_SECURITY_DESCRIPTOR, AT_UNNAMED, 0);
+	
+	if (rollback_data)
+		ntfs_attr_remove(ni, AT_DATA, AT_UNNAMED, 0);
+	/*
+	 * Free extent MFT records (should not exist any with current
+	 * ntfs_create implementation, but for any case if something will be
+	 * changed in the future).
+	 */
+	while (ni->nr_extents)
+		if (ntfs_mft_record_free(ni->vol, *(ni->extent_nis))) {
+			err = errno;
+			ntfs_log_error("Failed to free extent MFT record.  "
+					"Leaving inconsistent metadata.\n");
+		}
+	if (ntfs_mft_record_free(ni->vol, ni))
+		ntfs_log_error("Failed to free MFT record.  "
+				"Leaving inconsistent metadata. Run chkdsk.\n");
+	free(fn);
+	free(si);
+	errno = err;
+	return NULL;
+}
+
+/**
+ * Some wrappers around __ntfs_create() ...
+ */
+
+ntfs_inode *ntfs_create(ntfs_inode *dir_ni, le32 securid, const ntfschar *name,
+		u8 name_len, mode_t type)
+{
+	if (type != S_IFREG && type != S_IFDIR && type != S_IFIFO &&
+			type != S_IFSOCK) {
+		ntfs_log_error("Invalid arguments.\n");
+		return NULL;
+	}
+	return __ntfs_create(dir_ni, securid, name, name_len, type, 0, NULL, 0);
+}
+
+ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, le32 securid,
+		const ntfschar *name, u8 name_len, mode_t type, dev_t dev)
+{
+	if (type != S_IFCHR && type != S_IFBLK) {
+		ntfs_log_error("Invalid arguments.\n");
+		return NULL;
+	}
+	return __ntfs_create(dir_ni, securid, name, name_len, type, dev, NULL, 0);
+}
+
+ntfs_inode *ntfs_create_symlink(ntfs_inode *dir_ni, le32 securid,
+		const ntfschar *name, u8 name_len, const ntfschar *target,
+		int target_len)
+{
+	if (!target || !target_len) {
+		ntfs_log_error("%s: Invalid argument (%p, %d)\n", __FUNCTION__,
+			       target, target_len);
+		return NULL;
+	}
+	return __ntfs_create(dir_ni, securid, name, name_len, S_IFLNK, 0,
+			target, target_len);
+}
+
+int ntfs_check_empty_dir(ntfs_inode *ni)
+{
+	ntfs_attr *na;
+	int ret = 0;
+	
+	if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY))
+		return 0;
+
+	na = ntfs_attr_open(ni, AT_INDEX_ROOT, NTFS_INDEX_I30, 4);
+	if (!na) {
+		errno = EIO;
+		ntfs_log_perror("Failed to open directory");
+		return -1;
+	}
+	
+	/* Non-empty directory? */
+	if ((na->data_size != sizeof(INDEX_ROOT) + sizeof(INDEX_ENTRY_HEADER))){
+		/* Both ENOTEMPTY and EEXIST are ok. We use the more common. */
+		errno = ENOTEMPTY;
+		ntfs_log_debug("Directory is not empty\n");
+		ret = -1;
+	}
+	
+	ntfs_attr_close(na);
+	return ret;
+}
+
+static int ntfs_check_unlinkable_dir(ntfs_inode *ni, FILE_NAME_ATTR *fn)
+{
+	int link_count = le16_to_cpu(ni->mrec->link_count);
+	int ret;
+	
+	ret = ntfs_check_empty_dir(ni);
+	if (!ret || errno != ENOTEMPTY)
+		return ret;
+	/* 
+	 * Directory is non-empty, so we can unlink only if there is more than
+	 * one "real" hard link, i.e. links aren't different DOS and WIN32 names
+	 */
+	if ((link_count == 1) || 
+	    (link_count == 2 && fn->file_name_type == FILE_NAME_DOS)) {
+		errno = ENOTEMPTY;
+		ntfs_log_debug("Non-empty directory without hard links\n");
+		goto no_hardlink;
+	}
+	
+	ret = 0;
+no_hardlink:	
+	return ret;
+}
+
+/**
+ * ntfs_delete - delete file or directory from ntfs volume
+ * @ni:		ntfs inode for object to delte
+ * @dir_ni:	ntfs inode for directory in which delete object
+ * @name:	unicode name of the object to delete
+ * @name_len:	length of the name in unicode characters
+ *
+ * @ni is always closed after the call to this function (even if it failed),
+ * user does not need to call ntfs_inode_close himself.
+ *
+ * Return 0 on success or -1 on error with errno set to the error code.
+ */
+int ntfs_delete(ntfs_volume *vol, const char *pathname,
+		ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
+		u8 name_len)
+{
+	ntfs_attr_search_ctx *actx = NULL;
+	FILE_NAME_ATTR *fn = NULL;
+	BOOL looking_for_dos_name = FALSE, looking_for_win32_name = FALSE;
+	BOOL case_sensitive_match = TRUE;
+	int err = 0;
+#if CACHE_NIDATA_SIZE
+	int i;
+#endif
+#if CACHE_INODE_SIZE
+	struct CACHED_INODE item;
+	const char *p;
+	u64 inum = (u64)-1;
+	int count;
+#endif
+#if CACHE_LOOKUP_SIZE
+	struct CACHED_LOOKUP lkitem;
+#endif
+
+	ntfs_log_trace("Entering.\n");
+	
+	if (!ni || !dir_ni || !name || !name_len) {
+		ntfs_log_error("Invalid arguments.\n");
+		errno = EINVAL;
+		goto err_out;
+	}
+	if (ni->nr_extents == -1)
+		ni = ni->base_ni;
+	if (dir_ni->nr_extents == -1)
+		dir_ni = dir_ni->base_ni;
+	/*
+	 * Search for FILE_NAME attribute with such name. If it's in POSIX or
+	 * WIN32_AND_DOS namespace, then simply remove it from index and inode.
+	 * If filename in DOS or in WIN32 namespace, then remove DOS name first,
+	 * only then remove WIN32 name.
+	 */
+	actx = ntfs_attr_get_search_ctx(ni, NULL);
+	if (!actx)
+		goto err_out;
+search:
+	while (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, CASE_SENSITIVE,
+			0, NULL, 0, actx)) {
+		char *s;
+		IGNORE_CASE_BOOL case_sensitive = IGNORE_CASE;
+
+		errno = 0;
+		fn = (FILE_NAME_ATTR*)((u8*)actx->attr +
+				le16_to_cpu(actx->attr->value_offset));
+		s = ntfs_attr_name_get(fn->file_name, fn->file_name_length);
+		ntfs_log_trace("name: '%s'  type: %d  dos: %d  win32: %d  "
+			       "case: %d\n", s, fn->file_name_type,
+			       looking_for_dos_name, looking_for_win32_name,
+			       case_sensitive_match);
+		ntfs_attr_name_free(&s);
+		if (looking_for_dos_name) {
+			if (fn->file_name_type == FILE_NAME_DOS)
+				break;
+			else
+				continue;
+		}
+		if (looking_for_win32_name) {
+			if  (fn->file_name_type == FILE_NAME_WIN32)
+				break;
+			else
+				continue;
+		}
+		
+		/* Ignore hard links from other directories */
+		if (dir_ni->mft_no != MREF_LE(fn->parent_directory)) {
+			ntfs_log_debug("MFT record numbers don't match "
+				       "(%llu != %llu)\n", 
+				       (long long unsigned)dir_ni->mft_no, 
+				       (long long unsigned)MREF_LE(fn->parent_directory));
+			continue;
+		}
+		if (case_sensitive_match
+		    || ((fn->file_name_type == FILE_NAME_POSIX)
+			&& NVolCaseSensitive(ni->vol)))
+			case_sensitive = CASE_SENSITIVE;
+		
+		if (ntfs_names_are_equal(fn->file_name, fn->file_name_length,
+					 name, name_len, case_sensitive, 
+					 ni->vol->upcase, ni->vol->upcase_len)){
+			
+			if (fn->file_name_type == FILE_NAME_WIN32) {
+				looking_for_dos_name = TRUE;
+				ntfs_attr_reinit_search_ctx(actx);
+				continue;
+			}
+			if (fn->file_name_type == FILE_NAME_DOS)
+				looking_for_dos_name = TRUE;
+			break;
+		}
+	}
+	if (errno) {
+		/*
+		 * If case sensitive search failed, then try once again
+		 * ignoring case.
+		 */
+		if (errno == ENOENT && case_sensitive_match) {
+			case_sensitive_match = FALSE;
+			ntfs_attr_reinit_search_ctx(actx);
+			goto search;
+		}
+		goto err_out;
+	}
+	
+	if (ntfs_check_unlinkable_dir(ni, fn) < 0)
+		goto err_out;
+		
+	if (ntfs_index_remove(dir_ni, ni, fn, le32_to_cpu(actx->attr->value_length)))
+		goto err_out;
+	
+	/*
+	 * Keep the last name in place, this is useful for undeletion
+	 * (Windows also does so), however delete the name if it were
+	 * in an extent, to avoid leaving an attribute list.
+	 */
+	if ((ni->mrec->link_count == cpu_to_le16(1)) && !actx->base_ntfs_ino) {
+			/* make sure to not loop to another search */
+		looking_for_dos_name = FALSE;
+	} else {
+		if (ntfs_attr_record_rm(actx))
+			goto err_out;
+	}
+	
+	ni->mrec->link_count = cpu_to_le16(le16_to_cpu(
+			ni->mrec->link_count) - 1);
+	
+	ntfs_inode_mark_dirty(ni);
+	if (looking_for_dos_name) {
+		looking_for_dos_name = FALSE;
+		looking_for_win32_name = TRUE;
+		ntfs_attr_reinit_search_ctx(actx);
+		goto search;
+	}
+	/* TODO: Update object id, quota and securiry indexes if required. */
+	/*
+	 * If hard link count is not equal to zero then we are done. In other
+	 * case there are no reference to this inode left, so we should free all
+	 * non-resident attributes and mark all MFT record as not in use.
+	 */
+#if CACHE_LOOKUP_SIZE
+			/* invalidate entry in lookup cache */
+	lkitem.name = (const char*)NULL;
+	lkitem.namesize = 0;
+	lkitem.inum = ni->mft_no;
+	lkitem.parent = dir_ni->mft_no;
+	ntfs_invalidate_cache(vol->lookup_cache, GENERIC(&lkitem),
+			lookup_cache_inv_compare, CACHE_NOHASH);
+#endif
+#if CACHE_INODE_SIZE
+	inum = ni->mft_no;
+	if (pathname) {
+			/* invalide cache entry, even if there was an error */
+		/* Remove leading /'s. */
+		p = pathname;
+		while (*p == PATH_SEP)
+			p++;
+		if (p[0] && (p[strlen(p)-1] == PATH_SEP))
+			ntfs_log_error("Unnormalized path %s\n",pathname);
+		item.pathname = p;
+		item.varsize = strlen(p);
+	} else {
+		item.pathname = (const char*)NULL;
+		item.varsize = 0;
+	}
+	item.inum = inum;
+	count = ntfs_invalidate_cache(vol->xinode_cache, GENERIC(&item),
+				inode_cache_inv_compare, CACHE_NOHASH);
+	if (pathname && !count)
+		ntfs_log_error("Could not delete inode cache entry for %s\n",
+			pathname);
+#endif
+	if (ni->mrec->link_count) {
+		ntfs_inode_update_times(ni, NTFS_UPDATE_CTIME);
+		goto ok;
+	}
+	if (ntfs_delete_reparse_index(ni)) {
+		/*
+		 * Failed to remove the reparse index : proceed anyway
+		 * This is not a critical error, the entry is useless
+		 * because of sequence_number, and stopping file deletion
+		 * would be much worse as the file is not referenced now.
+		 */
+		err = errno;
+	}
+	if (ntfs_delete_object_id_index(ni)) {
+		/*
+		 * Failed to remove the object id index : proceed anyway
+		 * This is not a critical error.
+		 */
+		err = errno;
+	}
+	ntfs_attr_reinit_search_ctx(actx);
+	while (!ntfs_attrs_walk(actx)) {
+		if (actx->attr->non_resident) {
+			runlist *rl;
+
+			rl = ntfs_mapping_pairs_decompress(ni->vol, actx->attr,
+					NULL);
+			if (!rl) {
+				err = errno;
+				ntfs_log_error("Failed to decompress runlist.  "
+						"Leaving inconsistent metadata.\n");
+				continue;
+			}
+			if (ntfs_cluster_free_from_rl(ni->vol, rl)) {
+				err = errno;
+				ntfs_log_error("Failed to free clusters.  "
+						"Leaving inconsistent metadata.\n");
+				continue;
+			}
+			free(rl);
+		}
+	}
+	if (errno != ENOENT) {
+		err = errno;
+		ntfs_log_error("Attribute enumeration failed.  "
+				"Probably leaving inconsistent metadata.\n");
+	}
+	/* All extents should be attached after attribute walk. */
+#if CACHE_NIDATA_SIZE
+		/*
+		 * Disconnect extents before deleting them, so they are
+		 * not wrongly moved to cache through the chainings
+		 */
+	for (i=ni->nr_extents-1; i>=0; i--) {
+		ni->extent_nis[i]->base_ni = (ntfs_inode*)NULL;
+		ni->extent_nis[i]->nr_extents = 0;
+		if (ntfs_mft_record_free(ni->vol, ni->extent_nis[i])) {
+			err = errno;
+			ntfs_log_error("Failed to free extent MFT record.  "
+					"Leaving inconsistent metadata.\n");
+		}
+	}
+	free(ni->extent_nis);
+	ni->nr_extents = 0;
+	ni->extent_nis = (ntfs_inode**)NULL;
+#else
+	while (ni->nr_extents)
+		if (ntfs_mft_record_free(ni->vol, *(ni->extent_nis))) {
+			err = errno;
+			ntfs_log_error("Failed to free extent MFT record.  "
+					"Leaving inconsistent metadata.\n");
+		}
+#endif
+	debug_double_inode(ni->mft_no,0);
+	if (ntfs_mft_record_free(ni->vol, ni)) {
+		err = errno;
+		ntfs_log_error("Failed to free base MFT record.  "
+				"Leaving inconsistent metadata.\n");
+	}
+	ni = NULL;
+ok:	
+	ntfs_inode_update_times(dir_ni, NTFS_UPDATE_MCTIME);
+out:
+	if (actx)
+		ntfs_attr_put_search_ctx(actx);
+	if (ntfs_inode_close(dir_ni) && !err)
+		err = errno;
+	if (ntfs_inode_close(ni) && !err)
+		err = errno;
+	if (err) {
+		errno = err;
+		ntfs_log_debug("Could not delete file: %s\n", strerror(errno));
+		return -1;
+	}
+	ntfs_log_trace("Done.\n");
+	return 0;
+err_out:
+	err = errno;
+	goto out;
+}
+
+/**
+ * ntfs_link - create hard link for file or directory
+ * @ni:		ntfs inode for object to create hard link
+ * @dir_ni:	ntfs inode for directory in which new link should be placed
+ * @name:	unicode name of the new link
+ * @name_len:	length of the name in unicode characters
+ *
+ * NOTE: At present we allow creating hardlinks to directories, we use them
+ * in a temporary state during rename. But it's defenitely bad idea to have
+ * hard links to directories as a result of operation.
+ * FIXME: Create internal  __ntfs_link that allows hard links to a directories
+ * and external ntfs_link that do not. Write ntfs_rename that uses __ntfs_link.
+ *
+ * Return 0 on success or -1 on error with errno set to the error code.
+ */
+static int ntfs_link_i(ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
+			 u8 name_len, FILE_NAME_TYPE_FLAGS nametype)
+{
+	FILE_NAME_ATTR *fn = NULL;
+	int fn_len, err;
+
+	ntfs_log_trace("Entering.\n");
+	
+	if (!ni || !dir_ni || !name || !name_len || 
+			ni->mft_no == dir_ni->mft_no) {
+		err = EINVAL;
+		ntfs_log_perror("ntfs_link wrong arguments");
+		goto err_out;
+	}
+	
+	if ((ni->flags & FILE_ATTR_REPARSE_POINT)
+	   && !ntfs_possible_symlink(ni)) {
+		err = EOPNOTSUPP;
+		goto err_out;
+	}
+	if (NVolHideDotFiles(dir_ni->vol)) {
+		/* Set hidden flag according to the latest name */
+		if ((name_len > 1)
+		    && (name[0] == const_cpu_to_le16('.'))
+		    && (name[1] != const_cpu_to_le16('.')))
+			ni->flags |= FILE_ATTR_HIDDEN;
+		else
+			ni->flags &= ~FILE_ATTR_HIDDEN;
+	}
+	
+	/* Create FILE_NAME attribute. */
+	fn_len = sizeof(FILE_NAME_ATTR) + name_len * sizeof(ntfschar);
+	fn = ntfs_calloc(fn_len);
+	if (!fn) {
+		err = errno;
+		goto err_out;
+	}
+	fn->parent_directory = MK_LE_MREF(dir_ni->mft_no,
+			le16_to_cpu(dir_ni->mrec->sequence_number));
+	fn->file_name_length = name_len;
+	fn->file_name_type = nametype;
+	fn->file_attributes = ni->flags;
+	if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
+		fn->file_attributes |= FILE_ATTR_I30_INDEX_PRESENT;
+		fn->data_size = fn->allocated_size = const_cpu_to_le64(0);
+	} else {
+		fn->allocated_size = cpu_to_sle64(ni->allocated_size);
+		fn->data_size = cpu_to_sle64(ni->data_size);
+	}
+	fn->creation_time = ni->creation_time;
+	fn->last_data_change_time = ni->last_data_change_time;
+	fn->last_mft_change_time = ni->last_mft_change_time;
+	fn->last_access_time = ni->last_access_time;
+	memcpy(fn->file_name, name, name_len * sizeof(ntfschar));
+	/* Add FILE_NAME attribute to index. */
+	if (ntfs_index_add_filename(dir_ni, fn, MK_MREF(ni->mft_no,
+			le16_to_cpu(ni->mrec->sequence_number)))) {
+		err = errno;
+		ntfs_log_perror("Failed to add filename to the index");
+		goto err_out;
+	}
+	/* Add FILE_NAME attribute to inode. */
+	if (ntfs_attr_add(ni, AT_FILE_NAME, AT_UNNAMED, 0, (u8*)fn, fn_len)) {
+		ntfs_log_error("Failed to add FILE_NAME attribute.\n");
+		err = errno;
+		/* Try to remove just added attribute from index. */
+		if (ntfs_index_remove(dir_ni, ni, fn, fn_len))
+			goto rollback_failed;
+		goto err_out;
+	}
+	/* Increment hard links count. */
+	ni->mrec->link_count = cpu_to_le16(le16_to_cpu(
+			ni->mrec->link_count) + 1);
+	/* Done! */
+	ntfs_inode_mark_dirty(ni);
+	free(fn);
+	ntfs_log_trace("Done.\n");
+	return 0;
+rollback_failed:
+	ntfs_log_error("Rollback failed. Leaving inconsistent metadata.\n");
+err_out:
+	free(fn);
+	errno = err;
+	return -1;
+}
+
+int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
+		u8 name_len)
+{
+	return (ntfs_link_i(ni, dir_ni, name, name_len, FILE_NAME_POSIX));
+}
+
+/*
+ *		Get a parent directory from an inode entry
+ *
+ *	This is only used in situations where the path used to access
+ *	the current file is not known for sure. The result may be different
+ *	from the path when the file is linked in several parent directories.
+ *
+ *	Currently this is only used for translating ".." in the target
+ *	of a Vista relative symbolic link
+ */
+
+ntfs_inode *ntfs_dir_parent_inode(ntfs_inode *ni)
+{
+	ntfs_inode *dir_ni = (ntfs_inode*)NULL;
+	u64 inum;
+	FILE_NAME_ATTR *fn;
+	ntfs_attr_search_ctx *ctx;
+
+	if (ni->mft_no != FILE_root) {
+			/* find the name in the attributes */
+		ctx = ntfs_attr_get_search_ctx(ni, NULL);
+		if (!ctx)
+			return ((ntfs_inode*)NULL);
+
+		if (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0,
+				CASE_SENSITIVE,	0, NULL, 0, ctx)) {
+			/* We know this will always be resident. */
+			fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
+					le16_to_cpu(ctx->attr->value_offset));
+			inum = le64_to_cpu(fn->parent_directory);
+			if (inum != (u64)-1) {
+				dir_ni = ntfs_inode_open(ni->vol, MREF(inum));
+			}
+		}
+		ntfs_attr_put_search_ctx(ctx);
+	}
+	return (dir_ni);
+}
+
+#ifdef HAVE_SETXATTR
+
+#define MAX_DOS_NAME_LENGTH	 12
+
+/*
+ *		Get a DOS name for a file in designated directory
+ *
+ *	Not allowed if there are several non-dos names (EMLINK)
+ *
+ *	Returns size if found
+ *		0 if not found
+ *		-1 if there was an error (described by errno)
+ */
+
+static int get_dos_name(ntfs_inode *ni, u64 dnum, ntfschar *dosname)
+{
+	size_t outsize = 0;
+	int namecount = 0;
+	FILE_NAME_ATTR *fn;
+	ntfs_attr_search_ctx *ctx;
+
+		/* find the name in the attributes */
+	ctx = ntfs_attr_get_search_ctx(ni, NULL);
+	if (!ctx)
+		return -1;
+
+	while (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, CASE_SENSITIVE,
+			0, NULL, 0, ctx)) {
+		/* We know this will always be resident. */
+		fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
+				le16_to_cpu(ctx->attr->value_offset));
+
+		if (fn->file_name_type != FILE_NAME_DOS)
+			namecount++;
+		if ((fn->file_name_type & FILE_NAME_DOS)
+		    && (MREF_LE(fn->parent_directory) == dnum)) {
+				/*
+				 * Found a DOS or WIN32+DOS name for the entry
+				 * copy name, after truncation for safety
+				 */
+			outsize = fn->file_name_length;
+/* TODO : reject if name is too long ? */
+			if (outsize > MAX_DOS_NAME_LENGTH)
+				outsize = MAX_DOS_NAME_LENGTH;
+			memcpy(dosname,fn->file_name,outsize*sizeof(ntfschar));
+		}
+	}
+	ntfs_attr_put_search_ctx(ctx);
+	if ((outsize > 0) && (namecount > 1)) {
+		outsize = -1;
+		errno = EMLINK; /* this error implies there is a dos name */
+	}
+	return (outsize);
+}
+
+
+/*
+ *		Get a long name for a file in designated directory
+ *
+ *	Not allowed if there are several non-dos names (EMLINK)
+ *
+ *	Returns size if found
+ *		0 if not found
+ *		-1 if there was an error (described by errno)
+ */
+
+static int get_long_name(ntfs_inode *ni, u64 dnum, ntfschar *longname)
+{
+	size_t outsize = 0;
+	int namecount = 0;
+	FILE_NAME_ATTR *fn;
+	ntfs_attr_search_ctx *ctx;
+
+		/* find the name in the attributes */
+	ctx = ntfs_attr_get_search_ctx(ni, NULL);
+	if (!ctx)
+		return -1;
+
+		/* first search for WIN32 or DOS+WIN32 names */
+	while (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, CASE_SENSITIVE,
+			0, NULL, 0, ctx)) {
+		/* We know this will always be resident. */
+		fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
+				le16_to_cpu(ctx->attr->value_offset));
+
+		if (fn->file_name_type != FILE_NAME_DOS)
+			namecount++;
+		if ((fn->file_name_type & FILE_NAME_WIN32)
+		    && (MREF_LE(fn->parent_directory) == dnum)) {
+				/*
+				 * Found a WIN32 or WIN32+DOS name for the entry
+				 * copy name
+				 */
+			outsize = fn->file_name_length;
+			memcpy(longname,fn->file_name,outsize*sizeof(ntfschar));
+		}
+	}
+	if (namecount > 1) {
+		ntfs_attr_put_search_ctx(ctx);
+		errno = EMLINK;
+		return -1;
+	}
+		/* if not found search for POSIX names */
+	if (!outsize) {
+		ntfs_attr_reinit_search_ctx(ctx);
+	while (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, CASE_SENSITIVE,
+			0, NULL, 0, ctx)) {
+		/* We know this will always be resident. */
+		fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
+				le16_to_cpu(ctx->attr->value_offset));
+
+		if ((fn->file_name_type == FILE_NAME_POSIX)
+		    && (MREF_LE(fn->parent_directory) == dnum)) {
+				/*
+				 * Found a POSIX name for the entry
+				 * copy name
+				 */
+			outsize = fn->file_name_length;
+			memcpy(longname,fn->file_name,outsize*sizeof(ntfschar));
+		}
+	}
+	}
+	ntfs_attr_put_search_ctx(ctx);
+	return (outsize);
+}
+
+
+/*
+ *		Get the ntfs DOS name into an extended attribute
+ */
+
+int ntfs_get_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
+			char *value, size_t size)
+{
+	int outsize = 0;
+	char *outname = (char*)NULL;
+	u64 dnum;
+	int doslen;
+	ntfschar dosname[MAX_DOS_NAME_LENGTH];
+
+	dnum = dir_ni->mft_no;
+	doslen = get_dos_name(ni, dnum, dosname);
+	if (doslen > 0) {
+			/*
+			 * Found a DOS name for the entry, make
+			 * uppercase and encode into the buffer
+			 * if there is enough space
+			 */
+		ntfs_name_upcase(dosname, doslen,
+				ni->vol->upcase, ni->vol->upcase_len);
+		if (ntfs_ucstombs(dosname, doslen, &outname, size) < 0) {
+			ntfs_log_error("Cannot represent dosname in current locale.\n");
+			outsize = -errno;
+		} else {
+			outsize = strlen(outname);
+			if (value && (outsize <= (int)size))
+				memcpy(value, outname, outsize);
+			else
+				if (size && (outsize > (int)size))
+					outsize = -ERANGE;
+			free(outname);
+		}
+	} else {
+		if (doslen == 0)
+			errno = ENODATA;
+		outsize = -errno;
+	}
+	return (outsize);
+}
+
+/*
+ *		Change the name space of an existing file or directory
+ *
+ *	Returns the old namespace if successful
+ *		-1 if an error occurred (described by errno)
+ */
+
+static int set_namespace(ntfs_inode *ni, ntfs_inode *dir_ni,
+			const ntfschar *name, int len,
+			FILE_NAME_TYPE_FLAGS nametype)
+{
+	ntfs_attr_search_ctx *actx;
+	ntfs_index_context *icx;
+	FILE_NAME_ATTR *fnx;
+	FILE_NAME_ATTR *fn = NULL;
+	BOOL found;
+	int lkup;
+	int ret;
+
+	ret = -1;
+	actx = ntfs_attr_get_search_ctx(ni, NULL);
+	if (actx) {
+		found = FALSE;
+		do {
+			lkup = ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0,
+	                        CASE_SENSITIVE, 0, NULL, 0, actx);
+			if (!lkup) {
+				fn = (FILE_NAME_ATTR*)((u8*)actx->attr +
+				     le16_to_cpu(actx->attr->value_offset));
+				found = (MREF_LE(fn->parent_directory)
+						== dir_ni->mft_no)
+					&& !memcmp(fn->file_name, name,
+						len*sizeof(ntfschar));
+			}
+		} while (!lkup && !found);
+		if (found) {
+			icx = ntfs_index_ctx_get(dir_ni, NTFS_INDEX_I30, 4);
+			if (icx) {
+				lkup = ntfs_index_lookup((char*)fn, len, icx);
+				if (!lkup && icx->data && icx->data_len) {
+					fnx = (FILE_NAME_ATTR*)icx->data;
+					ret = fn->file_name_type;
+					fn->file_name_type = nametype;
+					fnx->file_name_type = nametype;
+					ntfs_inode_mark_dirty(ni);
+					ntfs_index_entry_mark_dirty(icx);
+				}
+			ntfs_index_ctx_put(icx);
+			}
+		}
+		ntfs_attr_put_search_ctx(actx);
+	}
+	return (ret);
+}
+
+/*
+ *		Set a DOS name to a file and adjust name spaces
+ *
+ *	If the new names are collapsible (same uppercased chars) :
+ *
+ * - the existing DOS name or DOS+Win32 name is made Posix
+ * - if it was a real DOS name, the existing long name is made DOS+Win32
+ *        and the existing DOS name is deleted
+ * - finally the existing long name is made DOS+Win32 unless already done
+ *
+ *	If the new names are not collapsible :
+ *
+ * - insert the short name as a DOS name
+ * - delete the old long name or existing short name
+ * - insert the new long name (as a Win32 or DOS+Win32 name)
+ *
+ * Deleting the old long name will not delete the file
+ * provided the old name was in the Posix name space,
+ * because the alternate name has been set before.
+ *
+ * The inodes of file and parent directory are always closed
+ *
+ * Returns 0 if successful
+ *	   -1 if failed
+ */
+
+static int set_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
+			const ntfschar *shortname, int shortlen,
+			const ntfschar *longname, int longlen,
+			const ntfschar *deletename, int deletelen, BOOL existed)
+{
+	unsigned int linkcount;
+	ntfs_volume *vol;
+	BOOL collapsible;
+	BOOL deleted;
+	BOOL done;
+	FILE_NAME_TYPE_FLAGS oldnametype;
+	u64 dnum;
+	u64 fnum;
+	int res;
+
+	res = -1;
+	vol = ni->vol;
+	dnum = dir_ni->mft_no;
+	fnum = ni->mft_no;
+				/* save initial link count */
+	linkcount = le16_to_cpu(ni->mrec->link_count);
+
+		/* check whether the same name may be used as DOS and WIN32 */
+	collapsible = ntfs_collapsible_chars(ni->vol, shortname, shortlen,
+						longname, longlen);
+	if (collapsible) {
+		deleted = FALSE;
+		done = FALSE;
+		if (existed) {
+			oldnametype = set_namespace(ni, dir_ni, deletename,
+					deletelen, FILE_NAME_POSIX);
+			if (oldnametype == FILE_NAME_DOS) {
+				if (set_namespace(ni, dir_ni, longname, longlen,
+						FILE_NAME_WIN32_AND_DOS) >= 0) {
+					if (!ntfs_delete(vol,
+						(const char*)NULL, ni, dir_ni,  
+						deletename, deletelen))
+						res = 0;
+					deleted = TRUE;
+				} else
+					done = TRUE;
+			}
+		}
+		if (!deleted) {
+			if (!done && (set_namespace(ni, dir_ni,
+					longname, longlen,
+					FILE_NAME_WIN32_AND_DOS) >= 0))
+				res = 0;
+			ntfs_inode_update_times(ni, NTFS_UPDATE_CTIME);
+			ntfs_inode_update_times(dir_ni, NTFS_UPDATE_MCTIME);
+			if (ntfs_inode_close_in_dir(ni,dir_ni) && !res)
+				res = -1;
+			if (ntfs_inode_close(dir_ni) && !res)
+				res = -1;
+		}
+	} else {
+		if (!ntfs_link_i(ni, dir_ni, shortname, shortlen, 
+				FILE_NAME_DOS)
+			/* make sure a new link was recorded */
+		    && (le16_to_cpu(ni->mrec->link_count) > linkcount)) {
+			/* delete the existing long name or short name */
+// is it ok to not provide the path ?
+			if (!ntfs_delete(vol, (char*)NULL, ni, dir_ni,
+				 deletename, deletelen)) {
+			/* delete closes the inodes, so have to open again */
+				dir_ni = ntfs_inode_open(vol, dnum);
+				if (dir_ni) {
+					ni = ntfs_inode_open(vol, fnum);
+					if (ni) {
+						if (!ntfs_link_i(ni, dir_ni,
+							longname, longlen,
+							FILE_NAME_WIN32))
+							res = 0;
+						if (ntfs_inode_close_in_dir(ni,
+							dir_ni)
+						    && !res)
+							res = -1;
+					}
+				if (ntfs_inode_close(dir_ni) && !res)
+					res = -1;
+				}
+			}
+		} else {
+			ntfs_inode_close_in_dir(ni,dir_ni);
+			ntfs_inode_close(dir_ni);
+		}
+	}
+	return (res);
+}
+
+
+/*
+ *		Set the ntfs DOS name into an extended attribute
+ *
+ *  The DOS name will be added as another file name attribute
+ *  using the existing file name information from the original
+ *  name or overwriting the DOS Name if one exists.
+ *
+ *  	The inode of the file is always closed
+ */
+
+int ntfs_set_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
+			const char *value, size_t size,	int flags)
+{
+	int res = 0;
+	int longlen = 0;
+	int shortlen = 0;
+	char newname[3*MAX_DOS_NAME_LENGTH + 1];
+	ntfschar oldname[MAX_DOS_NAME_LENGTH];
+	int oldlen;
+	u64 dnum;
+	BOOL closed = FALSE;
+	ntfschar *shortname = NULL;
+	ntfschar longname[NTFS_MAX_NAME_LEN];
+
+		/* copy the string to insert a null char, and truncate */
+	if (size > 3*MAX_DOS_NAME_LENGTH)
+		size = 3*MAX_DOS_NAME_LENGTH;
+	strncpy(newname, value, size);
+		/* a long name may be truncated badly and be untranslatable */
+	newname[size] = 0;
+		/* convert the string to the NTFS wide chars, and truncate */
+	shortlen = ntfs_mbstoucs(newname, &shortname);
+	if (shortlen > MAX_DOS_NAME_LENGTH)
+		shortlen = MAX_DOS_NAME_LENGTH;
+			/* make sure the short name has valid chars */
+	if ((shortlen < 0)
+	    || ntfs_forbidden_names(ni->vol,shortname,shortlen)) {
+		ntfs_inode_close_in_dir(ni,dir_ni);
+		ntfs_inode_close(dir_ni);
+		res = -errno;
+		return res;
+	}
+	dnum = dir_ni->mft_no;
+	longlen = get_long_name(ni, dnum, longname);
+	if (longlen > 0) {
+		oldlen = get_dos_name(ni, dnum, oldname);
+		if ((oldlen >= 0)
+		    && !ntfs_forbidden_names(ni->vol, longname, longlen)) {
+			if (oldlen > 0) {
+				if (flags & XATTR_CREATE) {
+					res = -1;
+					errno = EEXIST;
+				} else
+					if ((shortlen == oldlen)
+					    && !memcmp(shortname,oldname,
+						     oldlen*sizeof(ntfschar)))
+						/* already set, done */
+						res = 0;
+					else {
+						res = set_dos_name(ni, dir_ni,
+							shortname, shortlen,
+							longname, longlen,
+							oldname, oldlen, TRUE);
+						closed = TRUE;
+					}
+			} else {
+				if (flags & XATTR_REPLACE) {
+					res = -1;
+					errno = ENODATA;
+				} else {
+					res = set_dos_name(ni, dir_ni,
+						shortname, shortlen,
+						longname, longlen,
+						longname, longlen, FALSE);
+					closed = TRUE;
+				}
+			}
+		} else
+			res = -1;
+	} else {
+		res = -1;
+		if (!longlen)
+			errno = ENOENT;
+	}
+	free(shortname);
+	if (!closed) {
+		ntfs_inode_close_in_dir(ni,dir_ni);
+		ntfs_inode_close(dir_ni);
+	}
+	return (res ? -1 : 0);
+}
+
+/*
+ *		Delete the ntfs DOS name
+ */
+
+int ntfs_remove_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni)
+{
+	int res;
+	int oldnametype;
+	int longlen = 0;
+	int shortlen;
+	u64 dnum;
+	ntfs_volume *vol;
+	BOOL deleted = FALSE;
+	ntfschar shortname[MAX_DOS_NAME_LENGTH];
+	ntfschar longname[NTFS_MAX_NAME_LEN];
+
+	res = -1;
+	vol = ni->vol;
+	dnum = dir_ni->mft_no;
+	longlen = get_long_name(ni, dnum, longname);
+	if (longlen > 0) {
+		shortlen = get_dos_name(ni, dnum, shortname);
+		if (shortlen >= 0) {
+				/* migrate the long name as Posix */
+			oldnametype = set_namespace(ni,dir_ni,longname,longlen,
+					FILE_NAME_POSIX);
+			switch (oldnametype) {
+			case FILE_NAME_WIN32_AND_DOS :
+				/* name was Win32+DOS : done */
+				res = 0;
+				break;
+			case FILE_NAME_DOS :
+				/* name was DOS, make it back to DOS */
+				set_namespace(ni,dir_ni,longname,longlen,
+						FILE_NAME_DOS);
+				errno = ENOENT;
+				break;
+			case FILE_NAME_WIN32 :
+				/* name was Win32, make it Posix and delete */
+				if (set_namespace(ni,dir_ni,shortname,shortlen,
+						FILE_NAME_POSIX) >= 0) {
+					if (!ntfs_delete(vol,
+							(const char*)NULL, ni,
+							dir_ni, shortname,
+							shortlen))
+						res = 0;
+					deleted = TRUE;
+				} else {
+					/*
+					 * DOS name has been found, but cannot
+					 * migrate to Posix : something bad 
+					 * has happened
+					 */
+					errno = EIO;
+					ntfs_log_error("Could not change"
+						" DOS name of inode %lld to Posix\n",
+						(long long)ni->mft_no);
+				}
+				break;
+			default :
+				/* name was Posix or not found : error */
+				errno = ENOENT;
+				break;
+			}
+		}
+	} else {
+		if (!longlen)
+			errno = ENOENT;
+		res = -1;
+	}
+	if (!deleted) {
+		ntfs_inode_close_in_dir(ni,dir_ni);
+		ntfs_inode_close(dir_ni);
+	}
+	return (res);
+}
+
+#endif
diff --git a/libntfs-3g/ea.c b/libntfs-3g/ea.c
new file mode 100755
index 0000000000000000000000000000000000000000..d07e111b843b809f53e7d91f78a3a7d632bf8ff5
--- /dev/null
+++ b/libntfs-3g/ea.c
@@ -0,0 +1,402 @@
+/**
+ * ea.c - Processing of EA's
+ *
+ *      This module is part of ntfs-3g library
+ *
+ * Copyright (c) 2014 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_SETXATTR /* extended attributes support required */
+
+#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 HAVE_SETXATTR
+#include <sys/xattr.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"
+
+/*
+ *		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 exclude each other
+		 * see http://msdn.microsoft.com/en-us/library/windows/desktop/aa364404(v=vs.85).aspx
+		 * Also return EINVAL if REPARSE_POINT is present.
+		 */
+		if (ok
+		    && !ntfs_attr_exist(ni, AT_REPARSE_POINT, AT_UNNAMED,0)) {
+			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);
+}
+
+#endif  /* HAVE_SETXATTR */
diff --git a/libntfs-3g/efs.c b/libntfs-3g/efs.c
new file mode 100755
index 0000000000000000000000000000000000000000..7957005b6b629d619b3ecdf5ac69cbdb749d710f
--- /dev/null
+++ b/libntfs-3g/efs.c
@@ -0,0 +1,437 @@
+/**
+ * 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_SETXATTR
+#include <sys/xattr.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"
+
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+
+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) 
+{
+	u64 newsize;
+	u64 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_le64(newsize);
+	if (le64_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);
+}
+
+#endif /* HAVE_SETXATTR */
diff --git a/libntfs-3g/index.c b/libntfs-3g/index.c
new file mode 100755
index 0000000000000000000000000000000000000000..d498dde4b6b4e554ebe76108ee3cf117a7115969
--- /dev/null
+++ b/libntfs-3g/index.c
@@ -0,0 +1,2085 @@
+/**
+ * index.c - NTFS index handling.  Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2004-2005 Anton Altaparmakov
+ * Copyright (c) 2004-2005 Richard Russon
+ * Copyright (c) 2005-2006 Yura Pakhuchiy
+ * Copyright (c) 2005-2008 Szabolcs Szakacsits
+ * Copyright (c) 2007 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
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "attrib.h"
+#include "debug.h"
+#include "index.h"
+#include "collate.h"
+#include "mst.h"
+#include "dir.h"
+#include "logging.h"
+#include "bitmap.h"
+#include "reparse.h"
+#include "misc.h"
+
+/**
+ * ntfs_index_entry_mark_dirty - mark an index entry dirty
+ * @ictx:	ntfs index context describing the index entry
+ *
+ * Mark the index entry described by the index entry context @ictx dirty.
+ *
+ * If the index entry is in the index root attribute, simply mark the inode
+ * containing the index root attribute dirty.  This ensures the mftrecord, and
+ * hence the index root attribute, will be written out to disk later.
+ *
+ * If the index entry is in an index block belonging to the index allocation
+ * attribute, set ib_dirty to TRUE, thus index block will be updated during
+ * ntfs_index_ctx_put.
+ */
+void ntfs_index_entry_mark_dirty(ntfs_index_context *ictx)
+{
+	if (ictx->is_in_root)
+		ntfs_inode_mark_dirty(ictx->actx->ntfs_ino);
+	else
+		ictx->ib_dirty = TRUE;
+}
+
+static s64 ntfs_ib_vcn_to_pos(ntfs_index_context *icx, VCN vcn)
+{
+	return vcn << icx->vcn_size_bits;
+}
+
+static VCN ntfs_ib_pos_to_vcn(ntfs_index_context *icx, s64 pos)
+{
+	return pos >> icx->vcn_size_bits;
+}
+
+static int ntfs_ib_write(ntfs_index_context *icx, INDEX_BLOCK *ib)
+{
+	s64 ret, vcn = sle64_to_cpu(ib->index_block_vcn);
+	
+	ntfs_log_trace("vcn: %lld\n", (long long)vcn);
+	
+	ret = ntfs_attr_mst_pwrite(icx->ia_na, ntfs_ib_vcn_to_pos(icx, vcn),
+				   1, icx->block_size, ib);
+	if (ret != 1) {
+		ntfs_log_perror("Failed to write index block %lld, inode %llu",
+			(long long)vcn, (unsigned long long)icx->ni->mft_no);
+		return STATUS_ERROR;
+	}
+	
+	return STATUS_OK;
+}
+
+static int ntfs_icx_ib_write(ntfs_index_context *icx)
+{
+		if (ntfs_ib_write(icx, icx->ib))
+			return STATUS_ERROR;
+		
+		icx->ib_dirty = FALSE;
+		
+		return STATUS_OK;
+}
+
+/**
+ * ntfs_index_ctx_get - allocate and initialize a new index context
+ * @ni:		ntfs inode with which to initialize the context
+ * @name:	name of the which context describes
+ * @name_len:	length of the index name
+ *
+ * Allocate a new index context, initialize it with @ni and return it.
+ * Return NULL if allocation failed.
+ */
+ntfs_index_context *ntfs_index_ctx_get(ntfs_inode *ni,
+				       ntfschar *name, u32 name_len)
+{
+	ntfs_index_context *icx;
+
+	ntfs_log_trace("Entering\n");
+	
+	if (!ni) {
+		errno = EINVAL;
+		return NULL;
+	}
+	if (ni->nr_extents == -1)
+		ni = ni->base_ni;
+	icx = ntfs_calloc(sizeof(ntfs_index_context));
+	if (icx)
+		*icx = (ntfs_index_context) {
+			.ni = ni,
+			.name = name,
+			.name_len = name_len,
+		};
+	return icx;
+}
+
+static void ntfs_index_ctx_free(ntfs_index_context *icx)
+{
+	ntfs_log_trace("Entering\n");
+	
+	if (!icx->entry)
+		return;
+
+	if (icx->actx)
+		ntfs_attr_put_search_ctx(icx->actx);
+
+	if (!icx->is_in_root) {
+		if (icx->ib_dirty) {
+			/* FIXME: Error handling!!! */
+			ntfs_ib_write(icx, icx->ib);
+		}
+		free(icx->ib);
+	}
+	
+	ntfs_attr_close(icx->ia_na);
+}
+
+/**
+ * ntfs_index_ctx_put - release an index context
+ * @icx:	index context to free
+ *
+ * Release the index context @icx, releasing all associated resources.
+ */
+void ntfs_index_ctx_put(ntfs_index_context *icx)
+{
+	ntfs_index_ctx_free(icx);
+	free(icx);
+}
+
+/**
+ * ntfs_index_ctx_reinit - reinitialize an index context
+ * @icx:	index context to reinitialize
+ *
+ * Reinitialize the index context @icx so it can be used for ntfs_index_lookup.
+ */
+void ntfs_index_ctx_reinit(ntfs_index_context *icx)
+{
+	ntfs_log_trace("Entering\n");
+	
+	ntfs_index_ctx_free(icx);
+	
+	*icx = (ntfs_index_context) {
+		.ni = icx->ni,
+		.name = icx->name,
+		.name_len = icx->name_len,
+	};
+}
+
+static VCN *ntfs_ie_get_vcn_addr(INDEX_ENTRY *ie)
+{
+	return (VCN *)((u8 *)ie + le16_to_cpu(ie->length) - sizeof(VCN));
+}
+
+/**
+ *  Get the subnode vcn to which the index entry refers.
+ */
+VCN ntfs_ie_get_vcn(INDEX_ENTRY *ie)
+{
+	return sle64_to_cpup(ntfs_ie_get_vcn_addr(ie));
+}
+
+static INDEX_ENTRY *ntfs_ie_get_first(INDEX_HEADER *ih)
+{
+	return (INDEX_ENTRY *)((u8 *)ih + le32_to_cpu(ih->entries_offset));
+}
+
+static INDEX_ENTRY *ntfs_ie_get_next(INDEX_ENTRY *ie)
+{
+	return (INDEX_ENTRY *)((char *)ie + le16_to_cpu(ie->length));
+}
+
+static u8 *ntfs_ie_get_end(INDEX_HEADER *ih)
+{
+	/* FIXME: check if it isn't overflowing the index block size */
+	return (u8 *)ih + le32_to_cpu(ih->index_length);
+}
+
+static int ntfs_ie_end(INDEX_ENTRY *ie)
+{
+	return ie->ie_flags & INDEX_ENTRY_END || !ie->length;
+}
+
+/** 
+ *  Find the last entry in the index block
+ */
+static INDEX_ENTRY *ntfs_ie_get_last(INDEX_ENTRY *ie, char *ies_end)
+{
+	ntfs_log_trace("Entering\n");
+	
+	while ((char *)ie < ies_end && !ntfs_ie_end(ie))
+		ie = ntfs_ie_get_next(ie);
+	
+	return ie;
+}
+
+static INDEX_ENTRY *ntfs_ie_get_by_pos(INDEX_HEADER *ih, int pos)
+{
+	INDEX_ENTRY *ie;
+	
+	ntfs_log_trace("pos: %d\n", pos);
+	
+	ie = ntfs_ie_get_first(ih);
+	
+	while (pos-- > 0)
+		ie = ntfs_ie_get_next(ie);
+	
+	return ie;
+}
+
+static INDEX_ENTRY *ntfs_ie_prev(INDEX_HEADER *ih, INDEX_ENTRY *ie)
+{
+	INDEX_ENTRY *ie_prev = NULL;
+	INDEX_ENTRY *tmp;
+	
+	ntfs_log_trace("Entering\n");
+	
+	tmp = ntfs_ie_get_first(ih);
+	
+	while (tmp != ie) {
+		ie_prev = tmp;
+		tmp = ntfs_ie_get_next(tmp);
+	}
+	
+	return ie_prev;
+}
+
+char *ntfs_ie_filename_get(INDEX_ENTRY *ie)
+{
+	FILE_NAME_ATTR *fn;
+
+	fn = (FILE_NAME_ATTR *)&ie->key;
+	return ntfs_attr_name_get(fn->file_name, fn->file_name_length);
+}
+
+void ntfs_ie_filename_dump(INDEX_ENTRY *ie)
+{
+	char *s;
+
+	s = ntfs_ie_filename_get(ie);
+	ntfs_log_debug("'%s' ", s);
+	ntfs_attr_name_free(&s);
+}
+
+void ntfs_ih_filename_dump(INDEX_HEADER *ih)
+{
+	INDEX_ENTRY *ie;
+	
+	ntfs_log_trace("Entering\n");
+	
+	ie = ntfs_ie_get_first(ih);
+	while (!ntfs_ie_end(ie)) {
+		ntfs_ie_filename_dump(ie);
+		ie = ntfs_ie_get_next(ie);
+	}
+}
+
+static int ntfs_ih_numof_entries(INDEX_HEADER *ih)
+{
+	int n;
+	INDEX_ENTRY *ie;
+	u8 *end;
+	
+	ntfs_log_trace("Entering\n");
+	
+	end = ntfs_ie_get_end(ih);
+	ie = ntfs_ie_get_first(ih);
+	for (n = 0; !ntfs_ie_end(ie) && (u8 *)ie < end; n++)
+		ie = ntfs_ie_get_next(ie);
+	return n;
+}
+
+static int ntfs_ih_one_entry(INDEX_HEADER *ih)
+{
+	return (ntfs_ih_numof_entries(ih) == 1);
+}
+
+static int ntfs_ih_zero_entry(INDEX_HEADER *ih)
+{
+	return (ntfs_ih_numof_entries(ih) == 0);
+}
+
+static void ntfs_ie_delete(INDEX_HEADER *ih, INDEX_ENTRY *ie)
+{
+	u32 new_size;
+	
+	ntfs_log_trace("Entering\n");
+	
+	new_size = le32_to_cpu(ih->index_length) - le16_to_cpu(ie->length);
+	ih->index_length = cpu_to_le32(new_size);
+	memmove(ie, (u8 *)ie + le16_to_cpu(ie->length),
+		new_size - ((u8 *)ie - (u8 *)ih));
+}
+
+static void ntfs_ie_set_vcn(INDEX_ENTRY *ie, VCN vcn)
+{
+	*ntfs_ie_get_vcn_addr(ie) = cpu_to_le64(vcn);
+}
+
+/**
+ *  Insert @ie index entry at @pos entry. Used @ih values should be ok already.
+ */
+static void ntfs_ie_insert(INDEX_HEADER *ih, INDEX_ENTRY *ie, INDEX_ENTRY *pos)
+{
+	int ie_size = le16_to_cpu(ie->length);
+	
+	ntfs_log_trace("Entering\n");
+	
+	ih->index_length = cpu_to_le32(le32_to_cpu(ih->index_length) + ie_size);
+	memmove((u8 *)pos + ie_size, pos,
+		le32_to_cpu(ih->index_length) - ((u8 *)pos - (u8 *)ih) - ie_size);
+	memcpy(pos, ie, ie_size);
+}
+
+static INDEX_ENTRY *ntfs_ie_dup(INDEX_ENTRY *ie)
+{
+	INDEX_ENTRY *dup;
+	
+	ntfs_log_trace("Entering\n");
+	
+	dup = ntfs_malloc(le16_to_cpu(ie->length));
+	if (dup)
+		memcpy(dup, ie, le16_to_cpu(ie->length));
+	
+	return dup;
+}
+
+static INDEX_ENTRY *ntfs_ie_dup_novcn(INDEX_ENTRY *ie)
+{
+	INDEX_ENTRY *dup;
+	int size = le16_to_cpu(ie->length);
+	
+	ntfs_log_trace("Entering\n");
+	
+	if (ie->ie_flags & INDEX_ENTRY_NODE)
+		size -= sizeof(VCN);
+	
+	dup = ntfs_malloc(size);
+	if (dup) {
+		memcpy(dup, ie, size);
+		dup->ie_flags &= ~INDEX_ENTRY_NODE;
+		dup->length = cpu_to_le16(size);
+	}
+	return dup;
+}
+
+static int ntfs_ia_check(ntfs_index_context *icx, INDEX_BLOCK *ib, VCN vcn)
+{
+	u32 ib_size = (unsigned)le32_to_cpu(ib->index.allocated_size) + 0x18;
+	
+	ntfs_log_trace("Entering\n");
+	
+	if (!ntfs_is_indx_record(ib->magic)) {
+		
+		ntfs_log_error("Corrupt index block signature: vcn %lld inode "
+			       "%llu\n", (long long)vcn,
+			       (unsigned long long)icx->ni->mft_no);
+		return -1;
+	}
+	
+	if (sle64_to_cpu(ib->index_block_vcn) != vcn) {
+		
+		ntfs_log_error("Corrupt index block: VCN (%lld) is different "
+			       "from expected VCN (%lld) in inode %llu\n",
+			       (long long)sle64_to_cpu(ib->index_block_vcn),
+			       (long long)vcn,
+			       (unsigned long long)icx->ni->mft_no);
+		return -1;
+	}
+	
+	if (ib_size != icx->block_size) {
+		
+		ntfs_log_error("Corrupt index block : VCN (%lld) of inode %llu "
+			       "has a size (%u) differing from the index "
+			       "specified size (%u)\n", (long long)vcn, 
+			       (unsigned long long)icx->ni->mft_no, ib_size,
+			       icx->block_size);
+		return -1;
+	}
+	return 0;
+}
+
+static INDEX_ROOT *ntfs_ir_lookup(ntfs_inode *ni, ntfschar *name,
+				  u32 name_len, ntfs_attr_search_ctx **ctx)
+{
+	ATTR_RECORD *a;
+	INDEX_ROOT *ir = NULL;
+
+	ntfs_log_trace("Entering\n");
+	
+	*ctx = ntfs_attr_get_search_ctx(ni, NULL);
+	if (!*ctx)
+		return NULL;
+	
+	if (ntfs_attr_lookup(AT_INDEX_ROOT, name, name_len, CASE_SENSITIVE, 
+			     0, NULL, 0, *ctx)) {
+		ntfs_log_perror("Failed to lookup $INDEX_ROOT");
+		goto err_out;
+	}
+	
+	a = (*ctx)->attr;
+	if (a->non_resident) {
+		errno = EINVAL;
+		ntfs_log_perror("Non-resident $INDEX_ROOT detected");
+		goto err_out;
+	}
+	
+	ir = (INDEX_ROOT *)((char *)a + le16_to_cpu(a->value_offset));
+err_out:
+	if (!ir) {
+		ntfs_attr_put_search_ctx(*ctx);
+		*ctx = NULL;
+	}
+	return ir;
+}
+
+static INDEX_ROOT *ntfs_ir_lookup2(ntfs_inode *ni, ntfschar *name, u32 len)
+{
+	ntfs_attr_search_ctx *ctx;
+	INDEX_ROOT *ir;
+
+	ir = ntfs_ir_lookup(ni, name, len, &ctx);
+	if (ir)
+		ntfs_attr_put_search_ctx(ctx);
+	return ir;
+}
+
+/** 
+ * Find a key in the index block.
+ * 
+ * Return values:
+ *   STATUS_OK with errno set to ESUCCESS if we know for sure that the 
+ *             entry exists and @ie_out points to this entry.
+ *   STATUS_NOT_FOUND with errno set to ENOENT if we know for sure the
+ *                    entry doesn't exist and @ie_out is the insertion point.
+ *   STATUS_KEEP_SEARCHING if we can't answer the above question and
+ *                         @vcn will contain the node index block.
+ *   STATUS_ERROR with errno set if on unexpected error during lookup.
+ */
+static int ntfs_ie_lookup(const void *key, const int key_len,
+			  ntfs_index_context *icx, INDEX_HEADER *ih,
+			  VCN *vcn, INDEX_ENTRY **ie_out)
+{
+	INDEX_ENTRY *ie;
+	u8 *index_end;
+	int rc, item = 0;
+	 
+	ntfs_log_trace("Entering\n");
+	
+	index_end = ntfs_ie_get_end(ih);
+	
+	/*
+	 * Loop until we exceed valid memory (corruption case) or until we
+	 * reach the last entry.
+	 */
+	for (ie = ntfs_ie_get_first(ih); ; ie = ntfs_ie_get_next(ie)) {
+		/* Bounds checks. */
+		if ((u8 *)ie + sizeof(INDEX_ENTRY_HEADER) > index_end ||
+		    (u8 *)ie + le16_to_cpu(ie->length) > index_end) {
+			errno = ERANGE;
+			ntfs_log_error("Index entry out of bounds in inode "
+				       "%llu.\n",
+				       (unsigned long long)icx->ni->mft_no);
+			return STATUS_ERROR;
+		}
+		/*
+		 * The last entry cannot contain a key.  It can however contain
+		 * a pointer to a child node in the B+tree so we just break out.
+		 */
+		if (ntfs_ie_end(ie))
+			break;
+		/*
+		 * Not a perfect match, need to do full blown collation so we
+		 * know which way in the B+tree we have to go.
+		 */
+		if (!icx->collate) {
+			ntfs_log_error("Collation function not defined\n");
+			errno = EOPNOTSUPP;
+			return STATUS_ERROR;
+		}
+		rc = icx->collate(icx->ni->vol, key, key_len,
+					&ie->key, le16_to_cpu(ie->key_length));
+		if (rc == NTFS_COLLATION_ERROR) {
+			ntfs_log_error("Collation error. Perhaps a filename "
+				       "contains invalid characters?\n");
+			errno = ERANGE;
+			return STATUS_ERROR;
+		}
+		/*
+		 * If @key collates before the key of the current entry, there
+		 * is definitely no such key in this index but we might need to
+		 * descend into the B+tree so we just break out of the loop.
+		 */
+		if (rc == -1)
+			break;
+		
+		if (!rc) {
+			*ie_out = ie;
+			errno = 0;
+			icx->parent_pos[icx->pindex] = item;
+			return STATUS_OK;
+		}
+		
+		item++;
+	}
+	/*
+	 * We have finished with this index block without success. Check for the
+	 * presence of a child node and if not present return with errno ENOENT,
+	 * otherwise we will keep searching in another index block.
+	 */
+	if (!(ie->ie_flags & INDEX_ENTRY_NODE)) {
+		ntfs_log_debug("Index entry wasn't found.\n");
+		*ie_out = ie;
+		errno = ENOENT;
+		return STATUS_NOT_FOUND;
+	}
+	
+	/* Get the starting vcn of the index_block holding the child node. */
+	*vcn = ntfs_ie_get_vcn(ie);
+	if (*vcn < 0) {
+		errno = EINVAL;
+		ntfs_log_perror("Negative vcn in inode %llu",
+			       	(unsigned long long)icx->ni->mft_no);
+		return STATUS_ERROR;
+	}
+
+	ntfs_log_trace("Parent entry number %d\n", item);
+	icx->parent_pos[icx->pindex] = item;
+	
+	return STATUS_KEEP_SEARCHING;
+}
+
+static ntfs_attr *ntfs_ia_open(ntfs_index_context *icx, ntfs_inode *ni)
+{
+	ntfs_attr *na;
+	
+	na = ntfs_attr_open(ni, AT_INDEX_ALLOCATION, icx->name, icx->name_len);
+	if (!na) {
+		ntfs_log_perror("Failed to open index allocation of inode "
+				"%llu", (unsigned long long)ni->mft_no);
+		return NULL;
+	}
+	
+	return na;
+}
+
+static int ntfs_ib_read(ntfs_index_context *icx, VCN vcn, INDEX_BLOCK *dst)
+{
+	s64 pos, ret;
+
+	ntfs_log_trace("vcn: %lld\n", (long long)vcn);
+	
+	pos = ntfs_ib_vcn_to_pos(icx, vcn);
+
+	ret = ntfs_attr_mst_pread(icx->ia_na, pos, 1, icx->block_size, (u8 *)dst);
+	if (ret != 1) {
+		if (ret == -1)
+			ntfs_log_perror("Failed to read index block");
+		else 
+			ntfs_log_error("Failed to read full index block at "
+				       "%lld\n", (long long)pos);
+		return -1;
+	}
+	
+	if (ntfs_ia_check(icx, dst, vcn))
+		return -1;
+	
+	return 0;
+}
+
+static int ntfs_icx_parent_inc(ntfs_index_context *icx)
+{
+	icx->pindex++;
+	if (icx->pindex >= MAX_PARENT_VCN) {
+		errno = EOPNOTSUPP;
+		ntfs_log_perror("Index is over %d level deep", MAX_PARENT_VCN);
+		return STATUS_ERROR;
+	}
+	return STATUS_OK;
+}
+
+static int ntfs_icx_parent_dec(ntfs_index_context *icx)
+{
+	icx->pindex--;
+	if (icx->pindex < 0) {
+		errno = EINVAL;
+		ntfs_log_perror("Corrupt index pointer (%d)", icx->pindex);
+		return STATUS_ERROR;
+	}
+	return STATUS_OK;
+}
+	
+/**
+ * ntfs_index_lookup - find a key in an index and return its index entry
+ * @key:	[IN] key for which to search in the index
+ * @key_len:	[IN] length of @key in bytes
+ * @icx:	[IN/OUT] context describing the index and the returned entry
+ *
+ * Before calling ntfs_index_lookup(), @icx must have been obtained from a
+ * call to ntfs_index_ctx_get().
+ *
+ * Look for the @key in the index specified by the index lookup context @icx.
+ * ntfs_index_lookup() walks the contents of the index looking for the @key.
+ *
+ * If the @key is found in the index, 0 is returned and @icx is setup to
+ * describe the index entry containing the matching @key.  @icx->entry is the
+ * index entry and @icx->data and @icx->data_len are the index entry data and
+ * its length in bytes, respectively.
+ *
+ * If the @key is not found in the index, -1 is returned, errno = ENOENT and
+ * @icx is setup to describe the index entry whose key collates immediately
+ * after the search @key, i.e. this is the position in the index at which
+ * an index entry with a key of @key would need to be inserted.
+ *
+ * If an error occurs return -1, set errno to error code and @icx is left
+ * untouched.
+ *
+ * When finished with the entry and its data, call ntfs_index_ctx_put() to free
+ * the context and other associated resources.
+ *
+ * If the index entry was modified, call ntfs_index_entry_mark_dirty() before
+ * the call to ntfs_index_ctx_put() to ensure that the changes are written
+ * to disk.
+ */
+int ntfs_index_lookup(const void *key, const int key_len, ntfs_index_context *icx)
+{
+	VCN old_vcn, vcn;
+	ntfs_inode *ni = icx->ni;
+	INDEX_ROOT *ir;
+	INDEX_ENTRY *ie;
+	INDEX_BLOCK *ib = NULL;
+	int ret, err = 0;
+
+	ntfs_log_trace("Entering\n");
+	
+	if (!key || key_len <= 0) {
+		errno = EINVAL;
+		ntfs_log_perror("key: %p  key_len: %d", key, key_len);
+		return -1;
+	}
+
+	ir = ntfs_ir_lookup(ni, icx->name, icx->name_len, &icx->actx);
+	if (!ir) {
+		if (errno == ENOENT)
+			errno = EIO;
+		return -1;
+	}
+	
+	icx->block_size = le32_to_cpu(ir->index_block_size);
+	if (icx->block_size < NTFS_BLOCK_SIZE) {
+		errno = EINVAL;
+		ntfs_log_perror("Index block size (%d) is smaller than the "
+				"sector size (%d)", icx->block_size, NTFS_BLOCK_SIZE);
+		goto err_out;
+	}
+
+	if (ni->vol->cluster_size <= icx->block_size)
+		icx->vcn_size_bits = ni->vol->cluster_size_bits;
+	else
+		icx->vcn_size_bits = NTFS_BLOCK_SIZE_BITS;
+			/* get the appropriate collation function */
+	icx->collate = ntfs_get_collate_function(ir->collation_rule);
+	if (!icx->collate) {
+		err = errno = EOPNOTSUPP;
+		ntfs_log_perror("Unknown collation rule 0x%x", 
+				(unsigned)le32_to_cpu(ir->collation_rule));
+		goto err_out;
+	}
+	
+	old_vcn = VCN_INDEX_ROOT_PARENT;
+	/* 
+	 * FIXME: check for both ir and ib that the first index entry is
+	 * within the index block.
+	 */
+	ret = ntfs_ie_lookup(key, key_len, icx, &ir->index, &vcn, &ie);
+	if (ret == STATUS_ERROR) {
+		err = errno;
+		goto err_out;
+	}
+	
+	icx->ir = ir;
+	
+	if (ret != STATUS_KEEP_SEARCHING) {
+		/* STATUS_OK or STATUS_NOT_FOUND */
+		err = errno;
+		icx->is_in_root = TRUE;
+		icx->parent_vcn[icx->pindex] = old_vcn;
+		goto done;
+	}
+	
+	/* Child node present, descend into it. */
+	
+	icx->ia_na = ntfs_ia_open(icx, ni);
+	if (!icx->ia_na)
+		goto err_out;
+	
+	ib = ntfs_malloc(icx->block_size);
+	if (!ib) {
+		err = errno;
+		goto err_out;
+	}
+	
+descend_into_child_node:
+
+	icx->parent_vcn[icx->pindex] = old_vcn;
+	if (ntfs_icx_parent_inc(icx)) {
+		err = errno;
+		goto err_out;
+	}
+	old_vcn = vcn;
+
+	ntfs_log_debug("Descend into node with VCN %lld\n", (long long)vcn);
+	
+	if (ntfs_ib_read(icx, vcn, ib))
+		goto err_out;
+	
+	ret = ntfs_ie_lookup(key, key_len, icx, &ib->index, &vcn, &ie);
+	if (ret != STATUS_KEEP_SEARCHING) {
+		err = errno;
+		if (ret == STATUS_ERROR)
+			goto err_out;
+		
+		/* STATUS_OK or STATUS_NOT_FOUND */
+		icx->is_in_root = FALSE;
+		icx->ib = ib;
+		icx->parent_vcn[icx->pindex] = vcn;
+		goto done;
+	}
+
+	if ((ib->index.ih_flags & NODE_MASK) == LEAF_NODE) {
+		ntfs_log_error("Index entry with child node found in a leaf "
+			       "node in inode 0x%llx.\n",
+			       (unsigned long long)ni->mft_no);
+		goto err_out;
+	}
+	
+	goto descend_into_child_node;
+err_out:
+	free(ib);
+	if (!err)
+		err = EIO;
+	errno = err;
+	return -1;
+done:
+	icx->entry = ie;
+	icx->data = (u8 *)ie + offsetof(INDEX_ENTRY, key);
+	icx->data_len = le16_to_cpu(ie->key_length);
+	ntfs_log_trace("Done.\n");
+	if (err) {
+		errno = err;
+		return -1;
+	}
+	return 0;
+
+}
+
+static INDEX_BLOCK *ntfs_ib_alloc(VCN ib_vcn, u32 ib_size, 
+				  INDEX_HEADER_FLAGS node_type)
+{
+	INDEX_BLOCK *ib;
+	int ih_size = sizeof(INDEX_HEADER);
+	
+	ntfs_log_trace("ib_vcn: %lld ib_size: %u\n", (long long)ib_vcn, ib_size);
+	
+	ib = ntfs_calloc(ib_size);
+	if (!ib)
+		return NULL;
+	
+	ib->magic = magic_INDX;
+	ib->usa_ofs = cpu_to_le16(sizeof(INDEX_BLOCK));
+	ib->usa_count = cpu_to_le16(ib_size / NTFS_BLOCK_SIZE + 1);
+	/* Set USN to 1 */
+	*(u16 *)((char *)ib + le16_to_cpu(ib->usa_ofs)) = cpu_to_le16(1);
+	ib->lsn = cpu_to_le64(0);
+	
+	ib->index_block_vcn = cpu_to_sle64(ib_vcn);
+	
+	ib->index.entries_offset = cpu_to_le32((ih_size +
+			le16_to_cpu(ib->usa_count) * 2 + 7) & ~7);
+	ib->index.index_length = 0;
+	ib->index.allocated_size = cpu_to_le32(ib_size - 
+					       (sizeof(INDEX_BLOCK) - ih_size));
+	ib->index.ih_flags = node_type;
+	
+	return ib;
+}	
+
+/** 
+ *  Find the median by going through all the entries
+ */
+static INDEX_ENTRY *ntfs_ie_get_median(INDEX_HEADER *ih)
+{
+	INDEX_ENTRY *ie, *ie_start;
+	u8 *ie_end;
+	int i = 0, median;
+	
+	ntfs_log_trace("Entering\n");
+	
+	ie = ie_start = ntfs_ie_get_first(ih);
+	ie_end   = (u8 *)ntfs_ie_get_end(ih);
+	
+	while ((u8 *)ie < ie_end && !ntfs_ie_end(ie)) {
+		ie = ntfs_ie_get_next(ie);
+		i++;
+	}
+	/*
+	 * NOTE: this could be also the entry at the half of the index block.
+	 */
+	median = i / 2 - 1;
+	
+	ntfs_log_trace("Entries: %d  median: %d\n", i, median);
+	
+	for (i = 0, ie = ie_start; i <= median; i++)
+		ie = ntfs_ie_get_next(ie);
+	
+	return ie;
+}
+
+static s64 ntfs_ibm_vcn_to_pos(ntfs_index_context *icx, VCN vcn)
+{
+	return ntfs_ib_vcn_to_pos(icx, vcn) / icx->block_size;
+}
+
+static s64 ntfs_ibm_pos_to_vcn(ntfs_index_context *icx, s64 pos)
+{
+	return ntfs_ib_pos_to_vcn(icx, pos * icx->block_size);
+}
+
+static int ntfs_ibm_add(ntfs_index_context *icx)
+{
+	u8 bmp[8];
+
+	ntfs_log_trace("Entering\n");
+	
+	if (ntfs_attr_exist(icx->ni, AT_BITMAP, icx->name, icx->name_len))
+		return STATUS_OK;
+	/*
+	 * AT_BITMAP must be at least 8 bytes.
+	 */
+	memset(bmp, 0, sizeof(bmp));
+	if (ntfs_attr_add(icx->ni, AT_BITMAP, icx->name, icx->name_len,
+			  bmp, sizeof(bmp))) {
+		ntfs_log_perror("Failed to add AT_BITMAP");
+		return STATUS_ERROR;
+	}
+	
+	return STATUS_OK;
+}
+
+static int ntfs_ibm_modify(ntfs_index_context *icx, VCN vcn, int set)
+{
+	u8 byte;
+	s64 pos = ntfs_ibm_vcn_to_pos(icx, vcn);
+	u32 bpos = pos / 8;
+	u32 bit = 1 << (pos % 8);
+	ntfs_attr *na;
+	int ret = STATUS_ERROR;
+
+	ntfs_log_trace("%s vcn: %lld\n", set ? "set" : "clear", (long long)vcn);
+	
+	na = ntfs_attr_open(icx->ni, AT_BITMAP,  icx->name, icx->name_len);
+	if (!na) {
+		ntfs_log_perror("Failed to open $BITMAP attribute");
+		return -1;
+	}
+
+	if (set) {
+		if (na->data_size < bpos + 1) {
+			if (ntfs_attr_truncate(na, (na->data_size + 8) & ~7)) {
+				ntfs_log_perror("Failed to truncate AT_BITMAP");
+				goto err_na;
+			}
+		}
+	}
+	
+	if (ntfs_attr_pread(na, bpos, 1, &byte) != 1) {
+		ntfs_log_perror("Failed to read $BITMAP");
+		goto err_na;
+	}
+
+	if (set) 
+		byte |= bit;
+	else
+		byte &= ~bit;
+		
+	if (ntfs_attr_pwrite(na, bpos, 1, &byte) != 1) {
+		ntfs_log_perror("Failed to write $Bitmap");
+		goto err_na;
+	}
+
+	ret = STATUS_OK;
+err_na:
+	ntfs_attr_close(na);
+	return ret;
+}
+
+
+static int ntfs_ibm_set(ntfs_index_context *icx, VCN vcn)
+{
+	return ntfs_ibm_modify(icx, vcn, 1);
+}
+
+static int ntfs_ibm_clear(ntfs_index_context *icx, VCN vcn)
+{
+	return ntfs_ibm_modify(icx, vcn, 0);
+}
+
+static VCN ntfs_ibm_get_free(ntfs_index_context *icx)
+{
+	u8 *bm;
+	int bit;
+	s64 vcn, byte, size;
+
+	ntfs_log_trace("Entering\n");
+	
+	bm = ntfs_attr_readall(icx->ni, AT_BITMAP,  icx->name, icx->name_len,
+			       &size);
+	if (!bm)
+		return (VCN)-1;
+	
+	for (byte = 0; byte < size; byte++) {
+		
+		if (bm[byte] == 255)
+			continue;
+		
+		for (bit = 0; bit < 8; bit++) {
+			if (!(bm[byte] & (1 << bit))) {
+				vcn = ntfs_ibm_pos_to_vcn(icx, byte * 8 + bit);
+				goto out;
+			}
+		}
+	}
+	
+	vcn = ntfs_ibm_pos_to_vcn(icx, size * 8);
+out:	
+	ntfs_log_trace("allocated vcn: %lld\n", (long long)vcn);
+
+	if (ntfs_ibm_set(icx, vcn))
+		vcn = (VCN)-1;
+	
+	free(bm);
+	return vcn;
+}
+
+static INDEX_BLOCK *ntfs_ir_to_ib(INDEX_ROOT *ir, VCN ib_vcn)
+{
+	INDEX_BLOCK *ib;
+	INDEX_ENTRY *ie_last;
+	char *ies_start, *ies_end;
+	int i;
+	
+	ntfs_log_trace("Entering\n");
+	
+	ib = ntfs_ib_alloc(ib_vcn, le32_to_cpu(ir->index_block_size), LEAF_NODE);
+	if (!ib)
+		return NULL;
+	
+	ies_start = (char *)ntfs_ie_get_first(&ir->index);
+	ies_end   = (char *)ntfs_ie_get_end(&ir->index);
+	ie_last   = ntfs_ie_get_last((INDEX_ENTRY *)ies_start, ies_end);
+	/* 
+	 * Copy all entries, including the termination entry
+	 * as well, which can never have any data.
+	 */
+	i = (char *)ie_last - ies_start + le16_to_cpu(ie_last->length);
+	memcpy(ntfs_ie_get_first(&ib->index), ies_start, i);
+	
+	ib->index.ih_flags = ir->index.ih_flags;
+	ib->index.index_length = cpu_to_le32(i +
+			le32_to_cpu(ib->index.entries_offset));
+	return ib;
+}
+
+static void ntfs_ir_nill(INDEX_ROOT *ir)
+{
+	INDEX_ENTRY *ie_last;
+	char *ies_start, *ies_end;
+	
+	ntfs_log_trace("Entering\n");
+	/*
+	 * TODO: This function could be much simpler.
+	 */
+	ies_start = (char *)ntfs_ie_get_first(&ir->index);
+	ies_end   = (char *)ntfs_ie_get_end(&ir->index);
+	ie_last   = ntfs_ie_get_last((INDEX_ENTRY *)ies_start, ies_end);
+	/* 
+	 * Move the index root termination entry forward
+	 */
+	if ((char *)ie_last > ies_start) {
+		memmove(ies_start, (char *)ie_last, le16_to_cpu(ie_last->length));
+		ie_last = (INDEX_ENTRY *)ies_start;
+	}
+}
+
+static int ntfs_ib_copy_tail(ntfs_index_context *icx, INDEX_BLOCK *src,
+			     INDEX_ENTRY *median, VCN new_vcn)
+{
+	u8 *ies_end;
+	INDEX_ENTRY *ie_head;		/* first entry after the median */
+	int tail_size, ret;
+	INDEX_BLOCK *dst;
+	
+	ntfs_log_trace("Entering\n");
+	
+	dst = ntfs_ib_alloc(new_vcn, icx->block_size, 
+			    src->index.ih_flags & NODE_MASK);
+	if (!dst)
+		return STATUS_ERROR;
+	
+	ie_head = ntfs_ie_get_next(median);
+	
+	ies_end = (u8 *)ntfs_ie_get_end(&src->index);
+	tail_size = ies_end - (u8 *)ie_head;
+	memcpy(ntfs_ie_get_first(&dst->index), ie_head, tail_size);
+	
+	dst->index.index_length = cpu_to_le32(tail_size + 
+					      le32_to_cpu(dst->index.entries_offset));
+	ret = ntfs_ib_write(icx, dst);
+
+	free(dst);
+	return ret;
+}
+
+static int ntfs_ib_cut_tail(ntfs_index_context *icx, INDEX_BLOCK *ib,
+			    INDEX_ENTRY *ie)
+{
+	char *ies_start, *ies_end;
+	INDEX_ENTRY *ie_last;
+	
+	ntfs_log_trace("Entering\n");
+	
+	ies_start = (char *)ntfs_ie_get_first(&ib->index);
+	ies_end   = (char *)ntfs_ie_get_end(&ib->index);
+	
+	ie_last   = ntfs_ie_get_last((INDEX_ENTRY *)ies_start, ies_end);
+	if (ie_last->ie_flags & INDEX_ENTRY_NODE)
+		ntfs_ie_set_vcn(ie_last, ntfs_ie_get_vcn(ie));
+	
+	memcpy(ie, ie_last, le16_to_cpu(ie_last->length));
+	
+	ib->index.index_length = cpu_to_le32(((char *)ie - ies_start) + 
+		le16_to_cpu(ie->length) + le32_to_cpu(ib->index.entries_offset));
+	
+	if (ntfs_ib_write(icx, ib))
+		return STATUS_ERROR;
+	
+	return STATUS_OK;
+}
+	
+static int ntfs_ia_add(ntfs_index_context *icx)
+{
+	ntfs_log_trace("Entering\n");
+
+	if (ntfs_ibm_add(icx))
+		return -1;
+	
+	if (!ntfs_attr_exist(icx->ni, AT_INDEX_ALLOCATION, icx->name, icx->name_len)) {
+	
+		if (ntfs_attr_add(icx->ni, AT_INDEX_ALLOCATION, icx->name,
+				  icx->name_len, NULL, 0)) {
+			ntfs_log_perror("Failed to add AT_INDEX_ALLOCATION");
+			return -1;
+		}
+	}
+	
+	icx->ia_na = ntfs_ia_open(icx, icx->ni);
+	if (!icx->ia_na)
+		return -1;
+
+	return 0;
+}
+
+static int ntfs_ir_reparent(ntfs_index_context *icx)
+{
+	ntfs_attr_search_ctx *ctx = NULL;
+	INDEX_ROOT *ir;
+	INDEX_ENTRY *ie;
+	INDEX_BLOCK *ib = NULL;
+	VCN new_ib_vcn;
+	int ix_root_size;
+	int ret = STATUS_ERROR;
+
+	ntfs_log_trace("Entering\n");
+	
+	ir = ntfs_ir_lookup2(icx->ni, icx->name, icx->name_len);
+	if (!ir)
+		goto out;
+	
+	if ((ir->index.ih_flags & NODE_MASK) == SMALL_INDEX)
+		if (ntfs_ia_add(icx))
+			goto out;
+	
+	new_ib_vcn = ntfs_ibm_get_free(icx);
+	if (new_ib_vcn == -1)
+		goto out;
+		
+	ir = ntfs_ir_lookup2(icx->ni, icx->name, icx->name_len);
+	if (!ir)
+		goto clear_bmp;
+	
+	ib = ntfs_ir_to_ib(ir, new_ib_vcn);
+	if (ib == NULL) {
+		ntfs_log_perror("Failed to move index root to index block");
+		goto clear_bmp;
+	}
+		
+	if (ntfs_ib_write(icx, ib))
+		goto clear_bmp;
+	
+retry :
+	ir = ntfs_ir_lookup(icx->ni, icx->name, icx->name_len, &ctx);
+	if (!ir)
+		goto clear_bmp;
+	
+	ntfs_ir_nill(ir);
+	
+	ie = ntfs_ie_get_first(&ir->index);
+	ie->ie_flags |= INDEX_ENTRY_NODE;
+	ie->length = cpu_to_le16(sizeof(INDEX_ENTRY_HEADER) + sizeof(VCN));
+	
+	ir->index.ih_flags = LARGE_INDEX;
+	ir->index.index_length = cpu_to_le32(le32_to_cpu(ir->index.entries_offset)
+					     + le16_to_cpu(ie->length));
+	ir->index.allocated_size = ir->index.index_length;
+	ix_root_size = sizeof(INDEX_ROOT) - sizeof(INDEX_HEADER)
+			+ le32_to_cpu(ir->index.allocated_size);
+	if (ntfs_resident_attr_value_resize(ctx->mrec, ctx->attr,
+					ix_root_size)) {
+			/*
+			 * When there is no space to build a non-resident
+			 * index, we may have to move the root to an extent
+			 */
+		if ((errno == ENOSPC)
+		    && !ctx->al_entry
+		    && !ntfs_inode_add_attrlist(icx->ni)) {
+			ntfs_attr_put_search_ctx(ctx);
+			ctx = (ntfs_attr_search_ctx*)NULL;
+			ir = ntfs_ir_lookup(icx->ni, icx->name, icx->name_len,
+							&ctx);
+			if (ir
+			    && !ntfs_attr_record_move_away(ctx, ix_root_size
+				    - le32_to_cpu(ctx->attr->value_length))) {
+				ntfs_attr_put_search_ctx(ctx);
+				ctx = (ntfs_attr_search_ctx*)NULL;
+				goto retry;
+			}
+		}
+		/* FIXME: revert index root */
+		goto clear_bmp;
+	}
+	/*
+	 *  FIXME: do it earlier if we have enough space in IR (should always),
+	 *  so in error case we wouldn't lose the IB.
+	 */
+	ntfs_ie_set_vcn(ie, new_ib_vcn);
+	
+	ret = STATUS_OK;
+err_out:
+	free(ib);
+	ntfs_attr_put_search_ctx(ctx);
+out:
+	return ret;
+clear_bmp:
+	ntfs_ibm_clear(icx, new_ib_vcn);
+	goto err_out;
+}
+
+/**
+ * ntfs_ir_truncate - Truncate index root attribute
+ * 
+ * Returns STATUS_OK, STATUS_RESIDENT_ATTRIBUTE_FILLED_MFT or STATUS_ERROR.
+ */
+static int ntfs_ir_truncate(ntfs_index_context *icx, int data_size)
+{			  
+	ntfs_attr *na;
+	int ret;
+
+	ntfs_log_trace("Entering\n");
+	
+	na = ntfs_attr_open(icx->ni, AT_INDEX_ROOT, icx->name, icx->name_len);
+	if (!na) {
+		ntfs_log_perror("Failed to open INDEX_ROOT");
+		return STATUS_ERROR;
+	}
+	/*
+	 *  INDEX_ROOT must be resident and its entries can be moved to 
+	 *  INDEX_BLOCK, so ENOSPC isn't a real error.
+	 */
+	ret = ntfs_attr_truncate(na, data_size + offsetof(INDEX_ROOT, index));
+	if (ret == STATUS_OK) {
+		
+		icx->ir = ntfs_ir_lookup2(icx->ni, icx->name, icx->name_len);
+		if (!icx->ir)
+			return STATUS_ERROR;
+	
+		icx->ir->index.allocated_size = cpu_to_le32(data_size);
+		
+	} else if (ret == STATUS_ERROR)
+		ntfs_log_perror("Failed to truncate INDEX_ROOT");
+	
+	ntfs_attr_close(na);
+	return ret;
+}
+		
+/**
+ * ntfs_ir_make_space - Make more space for the index root attribute
+ * 
+ * On success return STATUS_OK or STATUS_KEEP_SEARCHING.
+ * On error return STATUS_ERROR.
+ */
+static int ntfs_ir_make_space(ntfs_index_context *icx, int data_size)
+{			  
+	int ret;
+
+	ntfs_log_trace("Entering\n");
+
+	ret = ntfs_ir_truncate(icx, data_size);
+	if (ret == STATUS_RESIDENT_ATTRIBUTE_FILLED_MFT) {
+	
+		ret = ntfs_ir_reparent(icx);
+		if (ret == STATUS_OK)
+			ret = STATUS_KEEP_SEARCHING;
+		else
+			ntfs_log_perror("Failed to nodify INDEX_ROOT");
+	}
+
+	return ret;
+}
+
+/*
+ * NOTE: 'ie' must be a copy of a real index entry.
+ */
+static int ntfs_ie_add_vcn(INDEX_ENTRY **ie)
+{
+	INDEX_ENTRY *p, *old = *ie;
+	 
+	old->length = cpu_to_le16(le16_to_cpu(old->length) + sizeof(VCN));
+	p = realloc(old, le16_to_cpu(old->length));
+	if (!p)
+		return STATUS_ERROR;
+	
+	p->ie_flags |= INDEX_ENTRY_NODE;
+	*ie = p;
+
+	return STATUS_OK;
+}
+
+static int ntfs_ih_insert(INDEX_HEADER *ih, INDEX_ENTRY *orig_ie, VCN new_vcn, 
+			  int pos)
+{
+	INDEX_ENTRY *ie_node, *ie;
+	int ret = STATUS_ERROR;
+	VCN old_vcn;
+	
+	ntfs_log_trace("Entering\n");
+	
+	ie = ntfs_ie_dup(orig_ie);
+	if (!ie)
+		return STATUS_ERROR;
+	
+	if (!(ie->ie_flags & INDEX_ENTRY_NODE))
+		if (ntfs_ie_add_vcn(&ie))
+			goto out;
+
+	ie_node = ntfs_ie_get_by_pos(ih, pos);
+	old_vcn = ntfs_ie_get_vcn(ie_node);
+	ntfs_ie_set_vcn(ie_node, new_vcn);
+	
+	ntfs_ie_insert(ih, ie, ie_node);
+	ntfs_ie_set_vcn(ie_node, old_vcn);
+	ret = STATUS_OK;
+out:	
+	free(ie);
+	
+	return ret;
+}
+
+static VCN ntfs_icx_parent_vcn(ntfs_index_context *icx)
+{
+	return icx->parent_vcn[icx->pindex];
+}
+
+static VCN ntfs_icx_parent_pos(ntfs_index_context *icx)
+{
+	return icx->parent_pos[icx->pindex];
+}
+
+
+static int ntfs_ir_insert_median(ntfs_index_context *icx, INDEX_ENTRY *median,
+				 VCN new_vcn)
+{
+	u32 new_size;
+	int ret;
+	
+	ntfs_log_trace("Entering\n");
+	
+	icx->ir = ntfs_ir_lookup2(icx->ni, icx->name, icx->name_len);
+	if (!icx->ir)
+		return STATUS_ERROR;
+
+	new_size = le32_to_cpu(icx->ir->index.index_length) + 
+			le16_to_cpu(median->length);
+	if (!(median->ie_flags & INDEX_ENTRY_NODE))
+		new_size += sizeof(VCN);
+
+	ret = ntfs_ir_make_space(icx, new_size);
+	if (ret != STATUS_OK)
+		return ret;
+	
+	icx->ir = ntfs_ir_lookup2(icx->ni, icx->name, icx->name_len);
+	if (!icx->ir)
+		return STATUS_ERROR;
+
+	return ntfs_ih_insert(&icx->ir->index, median, new_vcn, 
+			      ntfs_icx_parent_pos(icx));
+}
+
+static int ntfs_ib_split(ntfs_index_context *icx, INDEX_BLOCK *ib);
+
+/**
+ * On success return STATUS_OK or STATUS_KEEP_SEARCHING.
+ * On error return STATUS_ERROR.
+ */
+static int ntfs_ib_insert(ntfs_index_context *icx, INDEX_ENTRY *ie, VCN new_vcn)
+{			  
+	INDEX_BLOCK *ib;
+	u32 idx_size, allocated_size;
+	int err = STATUS_ERROR;
+	VCN old_vcn;
+
+	ntfs_log_trace("Entering\n");
+	
+	ib = ntfs_malloc(icx->block_size);
+	if (!ib)
+		return -1;
+	
+	old_vcn = ntfs_icx_parent_vcn(icx);
+	
+	if (ntfs_ib_read(icx, old_vcn, ib))
+		goto err_out;
+
+	idx_size       = le32_to_cpu(ib->index.index_length);
+	allocated_size = le32_to_cpu(ib->index.allocated_size);
+	/* FIXME: sizeof(VCN) should be included only if ie has no VCN */
+	if (idx_size + le16_to_cpu(ie->length) + sizeof(VCN) > allocated_size) {
+		err = ntfs_ib_split(icx, ib);
+		if (err == STATUS_OK)
+			err = STATUS_KEEP_SEARCHING;
+		goto err_out;
+	}
+	
+	if (ntfs_ih_insert(&ib->index, ie, new_vcn, ntfs_icx_parent_pos(icx)))
+		goto err_out;
+	
+	if (ntfs_ib_write(icx, ib))
+		goto err_out;
+	
+	err = STATUS_OK;
+err_out:	
+	free(ib);
+	return err;
+}
+
+/**
+ * ntfs_ib_split - Split an index block
+ * 
+ * On success return STATUS_OK or STATUS_KEEP_SEARCHING.
+ * On error return is STATUS_ERROR.
+ */
+static int ntfs_ib_split(ntfs_index_context *icx, INDEX_BLOCK *ib)
+{			  
+	INDEX_ENTRY *median;
+	VCN new_vcn;
+	int ret;
+
+	ntfs_log_trace("Entering\n");
+	
+	if (ntfs_icx_parent_dec(icx))
+		return STATUS_ERROR;
+	
+	median  = ntfs_ie_get_median(&ib->index);
+	new_vcn = ntfs_ibm_get_free(icx);
+	if (new_vcn == -1)
+		return STATUS_ERROR;
+	
+	if (ntfs_ib_copy_tail(icx, ib, median, new_vcn)) {
+		ntfs_ibm_clear(icx, new_vcn);
+		return STATUS_ERROR;
+	}
+	
+	if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT)
+		ret = ntfs_ir_insert_median(icx, median, new_vcn);
+	else
+		ret = ntfs_ib_insert(icx, median, new_vcn);
+	
+	if (ret != STATUS_OK) {
+		ntfs_ibm_clear(icx, new_vcn);
+		return ret;
+	}
+	
+	ret = ntfs_ib_cut_tail(icx, ib, median);
+	
+	return ret;
+}
+
+/* JPA static */
+int ntfs_ie_add(ntfs_index_context *icx, INDEX_ENTRY *ie)
+{
+	INDEX_HEADER *ih;
+	int allocated_size, new_size;
+	int ret = STATUS_ERROR;
+	
+#ifdef DEBUG
+/* removed by JPA to make function usable for security indexes
+	char *fn;
+	fn = ntfs_ie_filename_get(ie);
+	ntfs_log_trace("file: '%s'\n", fn);
+	ntfs_attr_name_free(&fn);
+*/
+#endif
+	
+	while (1) {
+				
+		if (!ntfs_index_lookup(&ie->key, le16_to_cpu(ie->key_length), icx)) {
+			errno = EEXIST;
+			ntfs_log_perror("Index already have such entry");
+			goto err_out;
+		}
+		if (errno != ENOENT) {
+			ntfs_log_perror("Failed to find place for new entry");
+			goto err_out;
+		}
+		
+		if (icx->is_in_root)
+			ih = &icx->ir->index;
+		else
+			ih = &icx->ib->index;
+		
+		allocated_size = le32_to_cpu(ih->allocated_size);
+		new_size = le32_to_cpu(ih->index_length) + le16_to_cpu(ie->length);
+	
+		if (new_size <= allocated_size)
+			break;
+		
+		ntfs_log_trace("index block sizes: allocated: %d  needed: %d\n",
+			       allocated_size, new_size);
+		
+		if (icx->is_in_root) {
+			if (ntfs_ir_make_space(icx, new_size) == STATUS_ERROR)
+				goto err_out;
+		} else {
+			if (ntfs_ib_split(icx, icx->ib) == STATUS_ERROR)
+				goto err_out;
+		}
+		
+		ntfs_inode_mark_dirty(icx->actx->ntfs_ino);
+		ntfs_index_ctx_reinit(icx);
+	}
+	
+	ntfs_ie_insert(ih, ie, icx->entry);
+	ntfs_index_entry_mark_dirty(icx);
+	
+	ret = STATUS_OK;
+err_out:
+	ntfs_log_trace("%s\n", ret ? "Failed" : "Done");
+	return ret;
+}
+
+/**
+ * ntfs_index_add_filename - add filename to directory index
+ * @ni:		ntfs inode describing directory to which index add filename
+ * @fn:		FILE_NAME attribute to add
+ * @mref:	reference of the inode which @fn describes
+ *
+ * Return 0 on success or -1 on error with errno set to the error code.
+ */
+int ntfs_index_add_filename(ntfs_inode *ni, FILE_NAME_ATTR *fn, MFT_REF mref)
+{
+	INDEX_ENTRY *ie;
+	ntfs_index_context *icx;
+	int fn_size, ie_size, err, ret = -1;
+
+	ntfs_log_trace("Entering\n");
+	
+	if (!ni || !fn) {
+		ntfs_log_error("Invalid arguments.\n");
+		errno = EINVAL;
+		return -1;
+	}
+	
+	fn_size = (fn->file_name_length * sizeof(ntfschar)) +
+			sizeof(FILE_NAME_ATTR);
+	ie_size = (sizeof(INDEX_ENTRY_HEADER) + fn_size + 7) & ~7;
+	
+	ie = ntfs_calloc(ie_size);
+	if (!ie)
+		return -1;
+
+	ie->indexed_file = cpu_to_le64(mref);
+	ie->length 	 = cpu_to_le16(ie_size);
+	ie->key_length 	 = cpu_to_le16(fn_size);
+	memcpy(&ie->key, fn, fn_size);
+	
+	icx = ntfs_index_ctx_get(ni, NTFS_INDEX_I30, 4);
+	if (!icx)
+		goto out;
+	
+	ret = ntfs_ie_add(icx, ie);
+	err = errno;
+	ntfs_index_ctx_put(icx);
+	errno = err;
+out:
+	free(ie);
+	return ret;
+}
+
+static int ntfs_ih_takeout(ntfs_index_context *icx, INDEX_HEADER *ih,
+			   INDEX_ENTRY *ie, INDEX_BLOCK *ib)
+{
+	INDEX_ENTRY *ie_roam;
+	int ret = STATUS_ERROR;
+	
+	ntfs_log_trace("Entering\n");
+	
+	ie_roam = ntfs_ie_dup_novcn(ie);
+	if (!ie_roam)
+		return STATUS_ERROR;
+
+	ntfs_ie_delete(ih, ie);
+
+	if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT)
+		ntfs_inode_mark_dirty(icx->actx->ntfs_ino);
+	else
+		if (ntfs_ib_write(icx, ib))
+			goto out;
+	
+	ntfs_index_ctx_reinit(icx);
+
+	ret = ntfs_ie_add(icx, ie_roam);
+out:
+	free(ie_roam);
+	return ret;
+}
+
+/**
+ *  Used if an empty index block to be deleted has END entry as the parent
+ *  in the INDEX_ROOT which is the only one there.
+ */
+static void ntfs_ir_leafify(ntfs_index_context *icx, INDEX_HEADER *ih)
+{
+	INDEX_ENTRY *ie;
+	
+	ntfs_log_trace("Entering\n");
+	
+	ie = ntfs_ie_get_first(ih);
+	ie->ie_flags &= ~INDEX_ENTRY_NODE;
+	ie->length = cpu_to_le16(le16_to_cpu(ie->length) - sizeof(VCN));
+	
+	ih->index_length = cpu_to_le32(le32_to_cpu(ih->index_length) - sizeof(VCN));
+	ih->ih_flags &= ~LARGE_INDEX;
+	
+	/* Not fatal error */
+	ntfs_ir_truncate(icx, le32_to_cpu(ih->index_length));
+}
+
+/**
+ *  Used if an empty index block to be deleted has END entry as the parent 
+ *  in the INDEX_ROOT which is not the only one there.
+ */
+static int ntfs_ih_reparent_end(ntfs_index_context *icx, INDEX_HEADER *ih,
+				INDEX_BLOCK *ib)
+{
+	INDEX_ENTRY *ie, *ie_prev;
+	
+	ntfs_log_trace("Entering\n");
+	
+	ie = ntfs_ie_get_by_pos(ih, ntfs_icx_parent_pos(icx));
+	ie_prev = ntfs_ie_prev(ih, ie);
+	
+	ntfs_ie_set_vcn(ie, ntfs_ie_get_vcn(ie_prev));
+	
+	return ntfs_ih_takeout(icx, ih, ie_prev, ib);
+}
+
+static int ntfs_index_rm_leaf(ntfs_index_context *icx)
+{
+	INDEX_BLOCK *ib = NULL;
+	INDEX_HEADER *parent_ih;
+	INDEX_ENTRY *ie;
+	int ret = STATUS_ERROR;
+	
+	ntfs_log_trace("pindex: %d\n", icx->pindex);
+	
+	if (ntfs_icx_parent_dec(icx))
+		return STATUS_ERROR;
+
+	if (ntfs_ibm_clear(icx, icx->parent_vcn[icx->pindex + 1]))
+		return STATUS_ERROR;
+	
+	if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT)
+		parent_ih = &icx->ir->index;
+	else {
+		ib = ntfs_malloc(icx->block_size);
+		if (!ib)
+			return STATUS_ERROR;
+		
+		if (ntfs_ib_read(icx, ntfs_icx_parent_vcn(icx), ib))
+			goto out;
+	
+		parent_ih = &ib->index;
+	}
+	
+	ie = ntfs_ie_get_by_pos(parent_ih, ntfs_icx_parent_pos(icx));
+	if (!ntfs_ie_end(ie)) {
+		ret = ntfs_ih_takeout(icx, parent_ih, ie, ib);
+		goto out;
+	}
+		
+	if (ntfs_ih_zero_entry(parent_ih)) {
+		
+		if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT) {
+			ntfs_ir_leafify(icx, parent_ih);
+			goto ok;
+		}
+		
+		ret = ntfs_index_rm_leaf(icx);
+		goto out;
+	}
+		
+	if (ntfs_ih_reparent_end(icx, parent_ih, ib))
+		goto out;
+ok:	
+	ret = STATUS_OK;
+out:
+	free(ib);
+	return ret;
+}
+
+static int ntfs_index_rm_node(ntfs_index_context *icx)
+{
+	int entry_pos, pindex;
+	VCN vcn;
+	INDEX_BLOCK *ib = NULL;
+	INDEX_ENTRY *ie_succ, *ie, *entry = icx->entry;
+	INDEX_HEADER *ih;
+	u32 new_size;
+	int delta, ret = STATUS_ERROR;
+
+	ntfs_log_trace("Entering\n");
+	
+	if (!icx->ia_na) {
+		icx->ia_na = ntfs_ia_open(icx, icx->ni);
+		if (!icx->ia_na)
+			return STATUS_ERROR;
+	}
+
+	ib = ntfs_malloc(icx->block_size);
+	if (!ib)
+		return STATUS_ERROR;
+	
+	ie_succ = ntfs_ie_get_next(icx->entry);
+	entry_pos = icx->parent_pos[icx->pindex]++;
+	pindex = icx->pindex;
+descend:
+	vcn = ntfs_ie_get_vcn(ie_succ);
+	if (ntfs_ib_read(icx, vcn, ib))
+		goto out;
+	
+	ie_succ = ntfs_ie_get_first(&ib->index);
+
+	if (ntfs_icx_parent_inc(icx))
+		goto out;
+	
+	icx->parent_vcn[icx->pindex] = vcn;
+	icx->parent_pos[icx->pindex] = 0;
+
+	if ((ib->index.ih_flags & NODE_MASK) == INDEX_NODE)
+		goto descend;
+
+	if (ntfs_ih_zero_entry(&ib->index)) {
+		errno = EIO;
+		ntfs_log_perror("Empty index block");
+		goto out;
+	}
+
+	ie = ntfs_ie_dup(ie_succ);
+	if (!ie)
+		goto out;
+	
+	if (ntfs_ie_add_vcn(&ie))
+		goto out2;
+
+	ntfs_ie_set_vcn(ie, ntfs_ie_get_vcn(icx->entry));
+
+	if (icx->is_in_root)
+		ih = &icx->ir->index;
+	else
+		ih = &icx->ib->index;
+
+	delta = le16_to_cpu(ie->length) - le16_to_cpu(icx->entry->length);
+	new_size = le32_to_cpu(ih->index_length) + delta;
+	if (delta > 0) {
+		if (icx->is_in_root) {
+			ret = ntfs_ir_make_space(icx, new_size);
+			if (ret != STATUS_OK)
+				goto out2;
+			
+			ih = &icx->ir->index;
+			entry = ntfs_ie_get_by_pos(ih, entry_pos);
+			
+		} else if (new_size > le32_to_cpu(ih->allocated_size)) {
+			icx->pindex = pindex;
+			ret = ntfs_ib_split(icx, icx->ib);
+			if (ret == STATUS_OK)
+				ret = STATUS_KEEP_SEARCHING;
+			goto out2;
+		}
+	}
+
+	ntfs_ie_delete(ih, entry);
+	ntfs_ie_insert(ih, ie, entry);
+	
+	if (icx->is_in_root) {
+		if (ntfs_ir_truncate(icx, new_size))
+			goto out2;
+	} else
+		if (ntfs_icx_ib_write(icx))
+			goto out2;
+	
+	ntfs_ie_delete(&ib->index, ie_succ);
+	
+	if (ntfs_ih_zero_entry(&ib->index)) {
+		if (ntfs_index_rm_leaf(icx))
+			goto out2;
+	} else 
+		if (ntfs_ib_write(icx, ib))
+			goto out2;
+
+	ret = STATUS_OK;
+out2:
+	free(ie);
+out:
+	free(ib);
+	return ret;
+}
+
+/**
+ * ntfs_index_rm - remove entry from the index
+ * @icx:	index context describing entry to delete
+ *
+ * Delete entry described by @icx from the index. Index context is always 
+ * reinitialized after use of this function, so it can be used for index 
+ * lookup once again.
+ *
+ * Return 0 on success or -1 on error with errno set to the error code.
+ */
+/*static JPA*/
+int ntfs_index_rm(ntfs_index_context *icx)
+{
+	INDEX_HEADER *ih;
+	int err, ret = STATUS_OK;
+
+	ntfs_log_trace("Entering\n");
+	
+	if (!icx || (!icx->ib && !icx->ir) || ntfs_ie_end(icx->entry)) {
+		ntfs_log_error("Invalid arguments.\n");
+		errno = EINVAL;
+		goto err_out;
+	}
+	if (icx->is_in_root)
+		ih = &icx->ir->index;
+	else
+		ih = &icx->ib->index;
+	
+	if (icx->entry->ie_flags & INDEX_ENTRY_NODE) {
+		
+		ret = ntfs_index_rm_node(icx);
+
+	} else if (icx->is_in_root || !ntfs_ih_one_entry(ih)) {
+		
+		ntfs_ie_delete(ih, icx->entry);
+		
+		if (icx->is_in_root) {
+			err = ntfs_ir_truncate(icx, le32_to_cpu(ih->index_length));
+			if (err != STATUS_OK)
+				goto err_out;
+		} else
+			if (ntfs_icx_ib_write(icx))
+				goto err_out;
+	} else {
+		if (ntfs_index_rm_leaf(icx))
+			goto err_out;
+	}
+out:
+	return ret;
+err_out:
+	ret = STATUS_ERROR;
+	goto out;
+}
+
+int ntfs_index_remove(ntfs_inode *dir_ni, ntfs_inode *ni,
+		const void *key, const int keylen)
+{
+	int ret = STATUS_ERROR;
+	ntfs_index_context *icx;
+
+	icx = ntfs_index_ctx_get(dir_ni, NTFS_INDEX_I30, 4);
+	if (!icx)
+		return -1;
+
+	while (1) {
+				
+		if (ntfs_index_lookup(key, keylen, icx))
+			goto err_out;
+
+		if ((((FILE_NAME_ATTR *)icx->data)->file_attributes &
+				FILE_ATTR_REPARSE_POINT)
+		   && !ntfs_possible_symlink(ni)) {
+			errno = EOPNOTSUPP;
+			goto err_out;
+		}
+
+		ret = ntfs_index_rm(icx);
+		if (ret == STATUS_ERROR)
+			goto err_out;
+		else if (ret == STATUS_OK)
+			break;
+		
+		ntfs_inode_mark_dirty(icx->actx->ntfs_ino);
+		ntfs_index_ctx_reinit(icx);
+	}
+
+	ntfs_inode_mark_dirty(icx->actx->ntfs_ino);
+out:	
+	ntfs_index_ctx_put(icx);
+	return ret;
+err_out:
+	ret = STATUS_ERROR;
+	ntfs_log_perror("Delete failed");
+	goto out;
+}
+
+/**
+ * ntfs_index_root_get - read the index root of an attribute
+ * @ni:		open ntfs inode in which the ntfs attribute resides
+ * @attr:	attribute for which we want its index root 
+ *
+ * This function will read the related index root an ntfs attribute.
+ *
+ * On success a buffer is allocated with the content of the index root
+ * and which needs to be freed when it's not needed anymore.
+ *
+ * On error NULL is returned with errno set to the error code.
+ */
+INDEX_ROOT *ntfs_index_root_get(ntfs_inode *ni, ATTR_RECORD *attr)
+{
+	ntfs_attr_search_ctx *ctx;
+	ntfschar *name;
+	INDEX_ROOT *root = NULL;
+
+	name = (ntfschar *)((u8 *)attr + le16_to_cpu(attr->name_offset));
+
+	if (!ntfs_ir_lookup(ni, name, attr->name_length, &ctx))
+		return NULL;
+	
+	root = ntfs_malloc(sizeof(INDEX_ROOT));
+	if (!root)
+		goto out;
+	
+	*root = *((INDEX_ROOT *)((u8 *)ctx->attr +
+				le16_to_cpu(ctx->attr->value_offset)));
+out:	
+	ntfs_attr_put_search_ctx(ctx);
+	return root;
+}
+
+
+/*
+ *		Walk down the index tree (leaf bound)
+ *	until there are no subnode in the first index entry
+ *	returns the entry at the bottom left in subnode
+ */
+
+static INDEX_ENTRY *ntfs_index_walk_down(INDEX_ENTRY *ie,
+			ntfs_index_context *ictx)
+{
+	INDEX_ENTRY *entry;
+	s64 vcn;
+
+	entry = ie;
+	do {
+		vcn = ntfs_ie_get_vcn(entry);
+		if (ictx->is_in_root) {
+
+			/* down from level zero */
+
+			ictx->ir = (INDEX_ROOT*)NULL;
+			ictx->ib = (INDEX_BLOCK*)ntfs_malloc(ictx->block_size);
+			ictx->pindex = 1;
+			ictx->is_in_root = FALSE;
+		} else {
+
+			/* down from non-zero level */
+			
+			ictx->pindex++;
+		}
+		ictx->parent_pos[ictx->pindex] = 0;
+		ictx->parent_vcn[ictx->pindex] = vcn;
+		if (!ntfs_ib_read(ictx,vcn,ictx->ib)) {
+			ictx->entry = ntfs_ie_get_first(&ictx->ib->index);
+			entry = ictx->entry;
+		} else
+			entry = (INDEX_ENTRY*)NULL;
+	} while (entry && (entry->ie_flags & INDEX_ENTRY_NODE));
+	return (entry);
+}
+
+/*
+ *		Walk up the index tree (root bound)
+ *	until there is a valid data entry in parent
+ *	returns the parent entry or NULL if no more parent
+ */
+
+static INDEX_ENTRY *ntfs_index_walk_up(INDEX_ENTRY *ie,
+			ntfs_index_context *ictx)
+{
+	INDEX_ENTRY *entry;
+	s64 vcn;
+
+	entry = ie;
+	if (ictx->pindex > 0) {
+		do {
+			ictx->pindex--;
+			if (!ictx->pindex) {
+
+					/* we have reached the root */
+
+				free(ictx->ib);
+				ictx->ib = (INDEX_BLOCK*)NULL;
+				ictx->is_in_root = TRUE;
+				/* a new search context is to be allocated */
+				if (ictx->actx)
+					free(ictx->actx);
+				ictx->ir = ntfs_ir_lookup(ictx->ni,
+					ictx->name, ictx->name_len,
+					&ictx->actx);
+				if (ictx->ir)
+					entry = ntfs_ie_get_by_pos(
+						&ictx->ir->index,
+						ictx->parent_pos[ictx->pindex]);
+				else
+					entry = (INDEX_ENTRY*)NULL;
+			} else {
+					/* up into non-root node */
+				vcn = ictx->parent_vcn[ictx->pindex];
+				if (!ntfs_ib_read(ictx,vcn,ictx->ib)) {
+					entry = ntfs_ie_get_by_pos(
+						&ictx->ib->index,
+						ictx->parent_pos[ictx->pindex]);
+				} else
+					entry = (INDEX_ENTRY*)NULL;
+			}
+		ictx->entry = entry;
+		} while (entry && (ictx->pindex > 0)
+			 && (entry->ie_flags & INDEX_ENTRY_END));
+	} else
+		entry = (INDEX_ENTRY*)NULL;
+	return (entry);
+}
+
+/*
+ *		Get next entry in an index according to collating sequence.
+ *	Must be initialized through a ntfs_index_lookup()
+ *
+ *	Returns next entry or NULL if none
+ *
+ *	Sample layout :
+ *
+ *                 +---+---+---+---+---+---+---+---+    n ptrs to subnodes
+ *                 |   |   | 10| 25| 33|   |   |   |    n-1 keys in between
+ *                 +---+---+---+---+---+---+---+---+    no key in last entry
+ *                              | A | A
+ *                              | | | +-------------------------------+
+ *   +--------------------------+ | +-----+                           |
+ *   |                            +--+    |                           |
+ *   V                               |    V                           |
+ * +---+---+---+---+---+---+---+---+ |  +---+---+---+---+---+---+---+---+
+ * | 11| 12| 13| 14| 15| 16| 17|   | |  | 26| 27| 28| 29| 30| 31| 32|   |
+ * +---+---+---+---+---+---+---+---+ |  +---+---+---+---+---+---+---+---+
+ *                               |   |
+ *       +-----------------------+   |
+ *       |                           |
+ *     +---+---+---+---+---+---+---+---+
+ *     | 18| 19| 20| 21| 22| 23| 24|   |
+ *     +---+---+---+---+---+---+---+---+
+ */
+
+INDEX_ENTRY *ntfs_index_next(INDEX_ENTRY *ie, ntfs_index_context *ictx)
+{
+	INDEX_ENTRY *next;
+	int flags;
+
+			/*
+                         * lookup() may have returned an invalid node
+			 * when searching for a partial key
+			 * if this happens, walk up
+			 */
+
+	if (ie->ie_flags & INDEX_ENTRY_END)
+		next = ntfs_index_walk_up(ie, ictx);
+	else {
+			/*
+			 * get next entry in same node
+                         * there is always one after any entry with data
+			 */
+
+		next = (INDEX_ENTRY*)((char*)ie + le16_to_cpu(ie->length));
+		++ictx->parent_pos[ictx->pindex];
+		flags = next->ie_flags;
+
+			/* walk down if it has a subnode */
+
+		if (flags & INDEX_ENTRY_NODE) {
+			next = ntfs_index_walk_down(next,ictx);
+		} else {
+
+				/* walk up it has no subnode, nor data */
+
+			if (flags & INDEX_ENTRY_END) {
+				next = ntfs_index_walk_up(next, ictx);
+			}
+		}
+	}
+		/* return NULL if stuck at end of a block */
+
+	if (next && (next->ie_flags & INDEX_ENTRY_END))
+		next = (INDEX_ENTRY*)NULL;
+	return (next);
+}
+
+
diff --git a/libntfs-3g/inode.c b/libntfs-3g/inode.c
new file mode 100755
index 0000000000000000000000000000000000000000..a4a01348be2620072ee6a6f5e9b78cc43ac177a6
--- /dev/null
+++ b/libntfs-3g/inode.c
@@ -0,0 +1,1608 @@
+/**
+ * inode.c - Inode handling code. Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2002-2005 Anton Altaparmakov
+ * Copyright (c) 2002-2008 Szabolcs Szakacsits
+ * Copyright (c) 2004-2007 Yura Pakhuchiy
+ * Copyright (c) 2004-2005 Richard Russon
+ * 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_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_SETXATTR
+#include <sys/xattr.h>
+#endif
+
+#include "param.h"
+#include "compat.h"
+#include "types.h"
+#include "volume.h"
+#include "cache.h"
+#include "inode.h"
+#include "attrib.h"
+#include "debug.h"
+#include "mft.h"
+#include "attrlist.h"
+#include "runlist.h"
+#include "lcnalloc.h"
+#include "index.h"
+#include "dir.h"
+#include "ntfstime.h"
+#include "logging.h"
+#include "misc.h"
+
+ntfs_inode *ntfs_inode_base(ntfs_inode *ni)
+{
+	if (ni->nr_extents == -1)
+		return ni->base_ni;
+	return ni;
+}
+
+/**
+ * ntfs_inode_mark_dirty - set the inode (and its base inode if it exists) dirty
+ * @ni:		ntfs inode to set dirty
+ *
+ * Set the inode @ni dirty so it is written out later (at the latest at
+ * ntfs_inode_close() time). If @ni is an extent inode, set the base inode
+ * dirty, too.
+ *
+ * This function cannot fail.
+ */
+void ntfs_inode_mark_dirty(ntfs_inode *ni)
+{
+	NInoSetDirty(ni);
+	if (ni->nr_extents == -1)
+		NInoSetDirty(ni->base_ni);
+}
+
+/**
+ * __ntfs_inode_allocate - Create and initialise an NTFS inode object
+ * @vol:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static ntfs_inode *__ntfs_inode_allocate(ntfs_volume *vol)
+{
+	ntfs_inode *ni;
+
+	ni = (ntfs_inode*)ntfs_calloc(sizeof(ntfs_inode));
+	if (ni)
+		ni->vol = vol;
+	return ni;
+}
+
+/**
+ * ntfs_inode_allocate - Create an NTFS inode object
+ * @vol:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+ntfs_inode *ntfs_inode_allocate(ntfs_volume *vol)
+{
+	return __ntfs_inode_allocate(vol);
+}
+
+/**
+ * __ntfs_inode_release - Destroy an NTFS inode object
+ * @ni:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static void __ntfs_inode_release(ntfs_inode *ni)
+{
+	if (NInoDirty(ni))
+		ntfs_log_error("Releasing dirty inode %lld!\n", 
+			       (long long)ni->mft_no);
+	if (NInoAttrList(ni) && ni->attr_list)
+		free(ni->attr_list);
+	free(ni->mrec);
+	free(ni);
+	return;
+}
+
+/**
+ * ntfs_inode_open - open an inode ready for access
+ * @vol:	volume to get the inode from
+ * @mref:	inode number / mft record number to open
+ *
+ * Allocate an ntfs_inode structure and initialize it for the given inode
+ * specified by @mref. @mref specifies the inode number / mft record to read,
+ * including the sequence number, which can be 0 if no sequence number checking
+ * is to be performed.
+ *
+ * Then, allocate a buffer for the mft record, read the mft record from the
+ * volume @vol, and attach it to the ntfs_inode structure (->mrec). The
+ * mft record is mst deprotected and sanity checked for validity and we abort
+ * if deprotection or checks fail.
+ *
+ * Finally, search for an attribute list attribute in the mft record and if one
+ * is found, load the attribute list attribute value and attach it to the
+ * ntfs_inode structure (->attr_list). Also set the NI_AttrList bit to indicate
+ * this.
+ *
+ * Return a pointer to the ntfs_inode structure on success or NULL on error,
+ * with errno set to the error code.
+ */
+static ntfs_inode *ntfs_inode_real_open(ntfs_volume *vol, const MFT_REF mref)
+{
+	s64 l;
+	ntfs_inode *ni = NULL;
+	ntfs_attr_search_ctx *ctx;
+	STANDARD_INFORMATION *std_info;
+	le32 lthle;
+	int olderrno;
+
+	ntfs_log_enter("Entering for inode %lld\n", (long long)MREF(mref));
+	if (!vol) {
+		errno = EINVAL;
+		goto out;
+	}
+	ni = __ntfs_inode_allocate(vol);
+	if (!ni)
+		goto out;
+	if (ntfs_file_record_read(vol, mref, &ni->mrec, NULL))
+		goto err_out;
+	if (!(ni->mrec->flags & MFT_RECORD_IN_USE)) {
+		errno = ENOENT;
+		goto err_out;
+	}
+	ni->mft_no = MREF(mref);
+	ctx = ntfs_attr_get_search_ctx(ni, NULL);
+	if (!ctx)
+		goto err_out;
+	/* Receive some basic information about inode. */
+	if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED,
+				0, CASE_SENSITIVE, 0, NULL, 0, ctx)) {
+		if (!ni->mrec->base_mft_record)
+			ntfs_log_perror("No STANDARD_INFORMATION in base record"
+					" %lld", (long long)MREF(mref));
+		goto put_err_out;
+	}
+	std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr +
+			le16_to_cpu(ctx->attr->value_offset));
+	ni->flags = std_info->file_attributes;
+	ni->creation_time = std_info->creation_time;
+	ni->last_data_change_time = std_info->last_data_change_time;
+	ni->last_mft_change_time = std_info->last_mft_change_time;
+	ni->last_access_time = std_info->last_access_time;
+  		/* JPA insert v3 extensions if present */
+                /* length may be seen as 72 (v1.x) or 96 (v3.x) */
+	lthle = ctx->attr->length;
+	if (le32_to_cpu(lthle) > sizeof(STANDARD_INFORMATION)) {
+		set_nino_flag(ni, v3_Extensions);
+		ni->owner_id = std_info->owner_id;
+		ni->security_id = std_info->security_id;
+		ni->quota_charged = std_info->quota_charged;
+		ni->usn = std_info->usn;
+	} else {
+		clear_nino_flag(ni, v3_Extensions);
+		ni->owner_id = const_cpu_to_le32(0);
+		ni->security_id = const_cpu_to_le32(0);
+	}
+	/* Set attribute list information. */
+	olderrno = errno;
+	if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0,
+			CASE_SENSITIVE, 0, NULL, 0, ctx)) {
+		if (errno != ENOENT)
+			goto put_err_out;
+		/* Attribute list attribute does not present. */
+		/* restore previous errno to avoid misinterpretation */
+		errno = olderrno;
+		goto get_size;
+	}
+	NInoSetAttrList(ni);
+	l = ntfs_get_attribute_value_length(ctx->attr);
+	if (!l)
+		goto put_err_out;
+	if (l > 0x40000) {
+		errno = EIO;
+		ntfs_log_perror("Too large attrlist attribute (%lld), inode "
+				"%lld", (long long)l, (long long)MREF(mref));
+		goto put_err_out;
+	}
+	ni->attr_list_size = l;
+	ni->attr_list = ntfs_malloc(ni->attr_list_size);
+	if (!ni->attr_list)
+		goto put_err_out;
+	l = ntfs_get_attribute_value(vol, ctx->attr, ni->attr_list);
+	if (!l)
+		goto put_err_out;
+	if (l != ni->attr_list_size) {
+		errno = EIO;
+		ntfs_log_perror("Unexpected attrlist size (%lld <> %u), inode "
+				"%lld", (long long)l, ni->attr_list_size, 
+				(long long)MREF(mref));
+		goto put_err_out;
+	}
+get_size:
+	olderrno = errno;
+	if (ntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) {
+		if (errno != ENOENT)
+			goto put_err_out;
+		/* Directory or special file. */
+		/* restore previous errno to avoid misinterpretation */
+		errno = olderrno;
+		ni->data_size = ni->allocated_size = 0;
+	} else {
+		if (ctx->attr->non_resident) {
+			ni->data_size = sle64_to_cpu(ctx->attr->data_size);
+			if (ctx->attr->flags &
+					(ATTR_IS_COMPRESSED | ATTR_IS_SPARSE))
+				ni->allocated_size = sle64_to_cpu(
+						ctx->attr->compressed_size);
+			else
+				ni->allocated_size = sle64_to_cpu(
+						ctx->attr->allocated_size);
+		} else {
+			ni->data_size = le32_to_cpu(ctx->attr->value_length);
+			ni->allocated_size = (ni->data_size + 7) & ~7;
+		}
+		set_nino_flag(ni,KnownSize);
+	}
+	ntfs_attr_put_search_ctx(ctx);
+out:	
+	ntfs_log_leave("\n");
+	return ni;
+
+put_err_out:
+	ntfs_attr_put_search_ctx(ctx);
+err_out:
+	__ntfs_inode_release(ni);
+	ni = NULL;
+	goto out;
+}
+
+/**
+ * ntfs_inode_close - close an ntfs inode and free all associated memory
+ * @ni:		ntfs inode to close
+ *
+ * Make sure the ntfs inode @ni is clean.
+ *
+ * If the ntfs inode @ni is a base inode, close all associated extent inodes,
+ * then deallocate all memory attached to it, and finally free the ntfs inode
+ * structure itself.
+ *
+ * If it is an extent inode, we disconnect it from its base inode before we
+ * destroy it.
+ *
+ * It is OK to pass NULL to this function, it is just noop in this case.
+ *
+ * Return 0 on success or -1 on error with errno set to the error code. On
+ * error, @ni has not been freed. The user should attempt to handle the error
+ * and call ntfs_inode_close() again. The following error codes are defined:
+ *
+ *	EBUSY	@ni and/or its attribute list runlist is/are dirty and the
+ *		attempt to write it/them to disk failed.
+ *	EINVAL	@ni is invalid (probably it is an extent inode).
+ *	EIO	I/O error while trying to write inode to disk.
+ */
+
+int ntfs_inode_real_close(ntfs_inode *ni)
+{
+	int ret = -1;
+	
+	if (!ni)
+		return 0;
+
+	ntfs_log_enter("Entering for inode %lld\n", (long long)ni->mft_no);
+
+	/* If we have dirty metadata, write it out. */
+	if (NInoDirty(ni) || NInoAttrListDirty(ni)) {
+		if (ntfs_inode_sync(ni)) {
+			if (errno != EIO)
+				errno = EBUSY;
+			goto err;
+		}
+	}
+	/* Is this a base inode with mapped extent inodes? */
+	if (ni->nr_extents > 0) {
+		while (ni->nr_extents > 0) {
+			if (ntfs_inode_real_close(ni->extent_nis[0])) {
+				if (errno != EIO)
+					errno = EBUSY;
+				goto err;
+			}
+		}
+	} else if (ni->nr_extents == -1) {
+		ntfs_inode **tmp_nis;
+		ntfs_inode *base_ni;
+		s32 i;
+
+		/*
+		 * If the inode is an extent inode, disconnect it from the
+		 * base inode before destroying it.
+		 */
+		base_ni = ni->base_ni;
+		for (i = 0; i < base_ni->nr_extents; ++i) {
+			tmp_nis = base_ni->extent_nis;
+			if (tmp_nis[i] != ni)
+				continue;
+			/* Found it. Disconnect. */
+			memmove(tmp_nis + i, tmp_nis + i + 1,
+					(base_ni->nr_extents - i - 1) *
+					sizeof(ntfs_inode *));
+			/* Buffer should be for multiple of four extents. */
+			if ((--base_ni->nr_extents) & 3) {
+				i = -1;
+				break;
+			}
+			/*
+			 * ElectricFence is unhappy with realloc(x,0) as free(x)
+			 * thus we explicitly separate these two cases.
+			 */
+			if (base_ni->nr_extents) {
+				/* Resize the memory buffer. */
+				tmp_nis = realloc(tmp_nis, base_ni->nr_extents *
+						  sizeof(ntfs_inode *));
+				/* Ignore errors, they don't really matter. */
+				if (tmp_nis)
+					base_ni->extent_nis = tmp_nis;
+			} else if (tmp_nis) {
+				free(tmp_nis);
+				base_ni->extent_nis = (ntfs_inode**)NULL;
+			}
+			/* Allow for error checking. */
+			i = -1;
+			break;
+		}
+		
+		/* 
+		 *  We could successfully sync, so only log this error
+		 *  and try to sync other inode extents too.
+		 */
+		if (i != -1)
+			ntfs_log_error("Extent inode %lld was not found\n",
+				       (long long)ni->mft_no);
+	}
+	
+	__ntfs_inode_release(ni);
+	ret = 0;
+err:
+	ntfs_log_leave("\n");
+	return ret;
+}
+
+#if CACHE_NIDATA_SIZE
+
+/*
+ *		Free an inode structure when there is not more space
+ *	in the cache
+ */
+
+void ntfs_inode_nidata_free(const struct CACHED_GENERIC *cached)
+{
+        ntfs_inode_real_close(((const struct CACHED_NIDATA*)cached)->ni);
+}
+
+/*
+ *		Compute a hash value for an inode entry
+ */
+
+int ntfs_inode_nidata_hash(const struct CACHED_GENERIC *item)
+{
+	return (((const struct CACHED_NIDATA*)item)->inum
+			% (2*CACHE_NIDATA_SIZE));
+}
+
+/*
+ *		inum comparing for entering/fetching from cache
+ */
+
+static int idata_cache_compare(const struct CACHED_GENERIC *cached,
+			const struct CACHED_GENERIC *wanted)
+{
+	return (((const struct CACHED_NIDATA*)cached)->inum
+			!= ((const struct CACHED_NIDATA*)wanted)->inum);
+}
+
+/*
+ *		Invalidate an inode entry when not needed anymore.
+ *	The entry should have been synced, it may be reused later,
+ *	if it is requested before it is dropped from cache.
+ */
+
+void ntfs_inode_invalidate(ntfs_volume *vol, const MFT_REF mref)
+{
+	struct CACHED_NIDATA item;
+
+	item.inum = MREF(mref);
+	item.ni = (ntfs_inode*)NULL;
+	item.pathname = (const char*)NULL;
+	item.varsize = 0;
+	ntfs_invalidate_cache(vol->nidata_cache,
+				GENERIC(&item),idata_cache_compare,CACHE_FREE);
+}
+
+#endif
+
+/*
+ *		Open an inode
+ *
+ *	When possible, an entry recorded in the cache is reused
+ *
+ *	**NEVER REOPEN** an inode, this can lead to a duplicated
+ * 	cache entry (hard to detect), and to an obsolete one being
+ *	reused. System files are however protected from being cached.
+ */
+
+ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref)
+{
+	ntfs_inode *ni;
+#if CACHE_NIDATA_SIZE
+	struct CACHED_NIDATA item;
+	struct CACHED_NIDATA *cached;
+
+		/* fetch idata from cache */
+	item.inum = MREF(mref);
+	debug_double_inode(item.inum,1);
+	item.pathname = (const char*)NULL;
+	item.varsize = 0;
+	cached = (struct CACHED_NIDATA*)ntfs_fetch_cache(vol->nidata_cache,
+				GENERIC(&item),idata_cache_compare);
+	if (cached) {
+		ni = cached->ni;
+		/* do not keep open entries in cache */
+		ntfs_remove_cache(vol->nidata_cache,
+				(struct CACHED_GENERIC*)cached,0);
+	} else {
+		ni = ntfs_inode_real_open(vol, mref);
+	}
+	if (!ni) {
+		debug_double_inode(item.inum, 0);
+	}
+#else
+	ni = ntfs_inode_real_open(vol, mref);
+#endif
+	return (ni);
+}
+
+/*
+ *		Close an inode entry
+ *
+ *	If cacheing is in use, the entry is synced and kept available
+ *	in cache for further use.
+ *
+ *	System files (inode < 16 or having the IS_4 flag) are protected
+ *	against being cached.
+ */
+
+int ntfs_inode_close(ntfs_inode *ni)
+{
+	int res;
+#if CACHE_NIDATA_SIZE
+	BOOL dirty;
+	struct CACHED_NIDATA item;
+
+	if (ni) {
+		debug_double_inode(ni->mft_no,0);
+		/* do not cache system files : could lead to double entries */
+		if (ni->vol && ni->vol->nidata_cache
+			&& ((ni->mft_no == FILE_root)
+			    || ((ni->mft_no >= FILE_first_user)
+				&& !(ni->mrec->flags & MFT_RECORD_IS_4)))) {
+			/* If we have dirty metadata, write it out. */
+			dirty = NInoDirty(ni) || NInoAttrListDirty(ni);
+			if (dirty) {
+				res = ntfs_inode_sync(ni);
+					/* do a real close if sync failed */
+				if (res)
+					ntfs_inode_real_close(ni);
+			} else
+				res = 0;
+
+			if (!res) {
+					/* feed idata into cache */
+				item.inum = ni->mft_no;
+				item.ni = ni;
+				item.pathname = (const char*)NULL;
+				item.varsize = 0;
+				debug_cached_inode(ni);
+				ntfs_enter_cache(ni->vol->nidata_cache,
+					GENERIC(&item), idata_cache_compare);
+			}
+		} else {
+			/* cache not ready or system file, really close */
+			res = ntfs_inode_real_close(ni);
+		}
+	} else
+		res = 0;
+#else
+	res = ntfs_inode_real_close(ni);
+#endif
+	return (res);
+}
+
+/**
+ * ntfs_extent_inode_open - load an extent inode and attach it to its base
+ * @base_ni:	base ntfs inode
+ * @mref:	mft reference of the extent inode to load (in little endian)
+ *
+ * First check if the extent inode @mref is already attached to the base ntfs
+ * inode @base_ni, and if so, return a pointer to the attached extent inode.
+ *
+ * If the extent inode is not already attached to the base inode, allocate an
+ * ntfs_inode structure and initialize it for the given inode @mref. @mref
+ * specifies the inode number / mft record to read, including the sequence
+ * number, which can be 0 if no sequence number checking is to be performed.
+ *
+ * Then, allocate a buffer for the mft record, read the mft record from the
+ * volume @base_ni->vol, and attach it to the ntfs_inode structure (->mrec).
+ * The mft record is mst deprotected and sanity checked for validity and we
+ * abort if deprotection or checks fail.
+ *
+ * Finally attach the ntfs inode to its base inode @base_ni and return a
+ * pointer to the ntfs_inode structure on success or NULL on error, with errno
+ * set to the error code.
+ *
+ * Note, extent inodes are never closed directly. They are automatically
+ * disposed off by the closing of the base inode.
+ */
+ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni, const MFT_REF mref)
+{
+	u64 mft_no = MREF_LE(mref);
+	VCN extent_vcn;
+	runlist_element *rl;
+	ntfs_volume *vol;
+	ntfs_inode *ni = NULL;
+	ntfs_inode **extent_nis;
+	int i;
+
+	if (!base_ni) {
+		errno = EINVAL;
+		ntfs_log_perror("%s", __FUNCTION__);
+		return NULL;
+	}
+	
+	ntfs_log_enter("Opening extent inode %lld (base mft record %lld).\n",
+			(unsigned long long)mft_no,
+			(unsigned long long)base_ni->mft_no);
+	
+	if (!base_ni->mft_no) {
+			/*
+			 * When getting extents of MFT, we must be sure
+			 * they are in the MFT part which has already
+			 * been mapped, otherwise we fall into an endless
+			 * recursion.
+			 * Situations have been met where extents locations
+			 * are described in themselves.
+			 * This is a severe error which chkdsk cannot fix.
+			 */
+		vol = base_ni->vol;
+		extent_vcn = mft_no << vol->mft_record_size_bits
+				>> vol->cluster_size_bits;
+		rl = vol->mft_na->rl;
+		if (rl) {
+			while (rl->length
+			    && ((rl->vcn + rl->length) <= extent_vcn))
+				rl++;
+		}
+		if (!rl || (rl->lcn < 0)) {
+			ntfs_log_error("MFT is corrupt, cannot read"
+				" its unmapped extent record %lld\n",
+					(long long)mft_no);
+			ntfs_log_error("Note : chkdsk cannot fix this,"
+				" try ntfsfix\n");
+			errno = EIO;
+			ni = (ntfs_inode*)NULL;
+			goto out;
+		}
+	}
+
+	/* Is the extent inode already open and attached to the base inode? */
+	if (base_ni->nr_extents > 0) {
+		extent_nis = base_ni->extent_nis;
+		for (i = 0; i < base_ni->nr_extents; i++) {
+			u16 seq_no;
+
+			ni = extent_nis[i];
+			if (mft_no != ni->mft_no)
+				continue;
+			/* Verify the sequence number if given. */
+			seq_no = MSEQNO_LE(mref);
+			if (seq_no && seq_no != le16_to_cpu(
+					ni->mrec->sequence_number)) {
+				errno = EIO;
+				ntfs_log_perror("Found stale extent mft "
+					"reference mft=%lld",
+					(long long)ni->mft_no);
+				goto out;
+			}
+			goto out;
+		}
+	}
+	/* Wasn't there, we need to load the extent inode. */
+	ni = __ntfs_inode_allocate(base_ni->vol);
+	if (!ni)
+		goto out;
+	if (ntfs_file_record_read(base_ni->vol, le64_to_cpu(mref), &ni->mrec, NULL))
+		goto err_out;
+	ni->mft_no = mft_no;
+	ni->nr_extents = -1;
+	ni->base_ni = base_ni;
+	/* Attach extent inode to base inode, reallocating memory if needed. */
+	if (!(base_ni->nr_extents & 3)) {
+		i = (base_ni->nr_extents + 4) * sizeof(ntfs_inode *);
+
+		extent_nis = ntfs_malloc(i);
+		if (!extent_nis)
+			goto err_out;
+		if (base_ni->nr_extents) {
+			memcpy(extent_nis, base_ni->extent_nis,
+					i - 4 * sizeof(ntfs_inode *));
+			free(base_ni->extent_nis);
+		}
+		base_ni->extent_nis = extent_nis;
+	}
+	base_ni->extent_nis[base_ni->nr_extents++] = ni;
+out:
+	ntfs_log_leave("\n");
+	return ni;
+err_out:
+	__ntfs_inode_release(ni);
+	ni = NULL;
+	goto out;
+}
+
+/**
+ * ntfs_inode_attach_all_extents - attach all extents for target inode
+ * @ni:		opened ntfs inode for which perform attach
+ *
+ * Return 0 on success and -1 on error with errno set to the error code.
+ */
+int ntfs_inode_attach_all_extents(ntfs_inode *ni)
+{
+	ATTR_LIST_ENTRY *ale;
+	u64 prev_attached = 0;
+
+	if (!ni) {
+		ntfs_log_trace("Invalid arguments.\n");
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (ni->nr_extents == -1)
+		ni = ni->base_ni;
+
+	ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no);
+
+	/* Inode haven't got attribute list, thus nothing to attach. */
+	if (!NInoAttrList(ni))
+		return 0;
+
+	if (!ni->attr_list) {
+		ntfs_log_trace("Corrupt in-memory struct.\n");
+		errno = EINVAL;
+		return -1;
+	}
+
+	/* Walk through attribute list and attach all extents. */
+	errno = 0;
+	ale = (ATTR_LIST_ENTRY *)ni->attr_list;
+	while ((u8*)ale < ni->attr_list + ni->attr_list_size) {
+		if (ni->mft_no != MREF_LE(ale->mft_reference) &&
+				prev_attached != MREF_LE(ale->mft_reference)) {
+			if (!ntfs_extent_inode_open(ni, ale->mft_reference)) {
+				ntfs_log_trace("Couldn't attach extent inode.\n");
+				return -1;
+			}
+			prev_attached = MREF_LE(ale->mft_reference);
+		}
+		ale = (ATTR_LIST_ENTRY *)((u8*)ale + le16_to_cpu(ale->length));
+	}
+	return 0;
+}
+
+/**
+ * ntfs_inode_sync_standard_information - update standard information attribute
+ * @ni:		ntfs inode to update standard information
+ *
+ * Return 0 on success or -1 on error with errno set to the error code.
+ */
+static int ntfs_inode_sync_standard_information(ntfs_inode *ni)
+{
+	ntfs_attr_search_ctx *ctx;
+	STANDARD_INFORMATION *std_info;
+	u32 lth;
+	le32 lthle;
+
+	ntfs_log_trace("Entering for inode %lld\n", (long long)ni->mft_no);
+
+	ctx = ntfs_attr_get_search_ctx(ni, NULL);
+	if (!ctx)
+		return -1;
+	if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED,
+			     0, CASE_SENSITIVE, 0, NULL, 0, ctx)) {
+		ntfs_log_perror("Failed to sync standard info (inode %lld)",
+				(long long)ni->mft_no);
+		ntfs_attr_put_search_ctx(ctx);
+		return -1;
+	}
+	std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr +
+			le16_to_cpu(ctx->attr->value_offset));
+	std_info->file_attributes = ni->flags;
+	if (!test_nino_flag(ni, TimesSet)) {
+		std_info->creation_time = ni->creation_time;
+		std_info->last_data_change_time = ni->last_data_change_time;
+		std_info->last_mft_change_time = ni->last_mft_change_time;
+		std_info->last_access_time = ni->last_access_time;
+	}
+
+		/* JPA update v3.x extensions, ensuring consistency */
+
+	lthle = ctx->attr->length;
+	lth = le32_to_cpu(lthle);
+	if (test_nino_flag(ni, v3_Extensions)
+	    && (lth <= sizeof(STANDARD_INFORMATION)))
+		ntfs_log_error("bad sync of standard information\n");
+
+	if (lth > sizeof(STANDARD_INFORMATION)) {
+		std_info->owner_id = ni->owner_id;
+		std_info->security_id = ni->security_id;
+		std_info->quota_charged = ni->quota_charged;
+		std_info->usn = ni->usn;
+	}
+	ntfs_inode_mark_dirty(ctx->ntfs_ino);
+	ntfs_attr_put_search_ctx(ctx);
+	return 0;
+}
+
+/**
+ * ntfs_inode_sync_file_name - update FILE_NAME attributes
+ * @ni:		ntfs inode to update FILE_NAME attributes
+ *
+ * Update all FILE_NAME attributes for inode @ni in the index.
+ *
+ * Return 0 on success or -1 on error with errno set to the error code.
+ */
+static int ntfs_inode_sync_file_name(ntfs_inode *ni, ntfs_inode *dir_ni)
+{
+	ntfs_attr_search_ctx *ctx = NULL;
+	ntfs_index_context *ictx;
+	ntfs_inode *index_ni;
+	FILE_NAME_ATTR *fn;
+	FILE_NAME_ATTR *fnx;
+	REPARSE_POINT *rpp;
+	le32 reparse_tag;
+	int err = 0;
+
+	ntfs_log_trace("Entering for inode %lld\n", (long long)ni->mft_no);
+
+	ctx = ntfs_attr_get_search_ctx(ni, NULL);
+	if (!ctx) {
+		err = errno;
+		goto err_out;
+	}
+	/* Collect the reparse tag, if any */
+	reparse_tag = cpu_to_le32(0);
+	if (ni->flags & FILE_ATTR_REPARSE_POINT) {
+		if (!ntfs_attr_lookup(AT_REPARSE_POINT, NULL,
+				0, CASE_SENSITIVE, 0, NULL, 0, ctx)) {
+			rpp = (REPARSE_POINT*)((u8 *)ctx->attr +
+					le16_to_cpu(ctx->attr->value_offset));
+			reparse_tag = rpp->reparse_tag;
+		}
+		ntfs_attr_reinit_search_ctx(ctx);
+	}
+	/* Walk through all FILE_NAME attributes and update them. */
+	while (!ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, 0, 0, NULL, 0, ctx)) {
+		fn = (FILE_NAME_ATTR *)((u8 *)ctx->attr +
+				le16_to_cpu(ctx->attr->value_offset));
+		if (MREF_LE(fn->parent_directory) == ni->mft_no) {
+			/*
+			 * WARNING: We cheat here and obtain 2 attribute
+			 * search contexts for one inode (first we obtained
+			 * above, second will be obtained inside
+			 * ntfs_index_lookup), it's acceptable for library,
+			 * but will deadlock in the kernel.
+			 */
+			index_ni = ni;
+		} else
+			if (dir_ni)
+				index_ni = dir_ni;
+			else
+				index_ni = ntfs_inode_open(ni->vol, 
+					le64_to_cpu(fn->parent_directory));
+		if (!index_ni) {
+			if (!err)
+				err = errno;
+			ntfs_log_perror("Failed to open inode %lld with index",
+				(long long)le64_to_cpu(fn->parent_directory));
+			continue;
+		}
+		ictx = ntfs_index_ctx_get(index_ni, NTFS_INDEX_I30, 4);
+		if (!ictx) {
+			if (!err)
+				err = errno;
+			ntfs_log_perror("Failed to get index ctx, inode %lld",
+					(long long)index_ni->mft_no);
+			if ((ni != index_ni) && !dir_ni
+			    && ntfs_inode_close(index_ni) && !err)
+				err = errno;
+			continue;
+		}
+		if (ntfs_index_lookup(fn, sizeof(FILE_NAME_ATTR), ictx)) {
+			if (!err) {
+				if (errno == ENOENT)
+					err = EIO;
+				else
+					err = errno;
+			}
+			ntfs_log_perror("Index lookup failed, inode %lld",
+					(long long)index_ni->mft_no);
+			ntfs_index_ctx_put(ictx);
+			if (ni != index_ni && ntfs_inode_close(index_ni) && !err)
+				err = errno;
+			continue;
+		}
+		/* Update flags and file size. */
+		fnx = (FILE_NAME_ATTR *)ictx->data;
+		fnx->file_attributes =
+				(fnx->file_attributes & ~FILE_ATTR_VALID_FLAGS) |
+				(ni->flags & FILE_ATTR_VALID_FLAGS);
+		if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
+			fnx->data_size = fnx->allocated_size
+				= const_cpu_to_le64(0);
+		else {
+			fnx->allocated_size = cpu_to_sle64(ni->allocated_size);
+			fnx->data_size = cpu_to_sle64(ni->data_size);
+			/*
+			 * The file name record has also to be fixed if some
+			 * attribute update implied the unnamed data to be
+			 * made non-resident
+			 */
+			fn->allocated_size = fnx->allocated_size;
+		}
+			/* update or clear the reparse tag in the index */
+		fnx->reparse_point_tag = reparse_tag;
+		if (!test_nino_flag(ni, TimesSet)) {
+			fnx->creation_time = ni->creation_time;
+			fnx->last_data_change_time = ni->last_data_change_time;
+			fnx->last_mft_change_time = ni->last_mft_change_time;
+			fnx->last_access_time = ni->last_access_time;
+		} else {
+			fnx->creation_time = fn->creation_time;
+			fnx->last_data_change_time = fn->last_data_change_time;
+			fnx->last_mft_change_time = fn->last_mft_change_time;
+			fnx->last_access_time = fn->last_access_time;
+		}
+		ntfs_index_entry_mark_dirty(ictx);
+		ntfs_index_ctx_put(ictx);
+		if ((ni != index_ni) && !dir_ni
+		    && ntfs_inode_close(index_ni) && !err)
+			err = errno;
+	}
+	/* Check for real error occurred. */
+	if (errno != ENOENT) {
+		err = errno;
+		ntfs_log_perror("Attribute lookup failed, inode %lld",
+				(long long)ni->mft_no);
+		goto err_out;
+	}
+	ntfs_attr_put_search_ctx(ctx);
+	if (err) {
+		errno = err;
+		return -1;
+	}
+	return 0;
+err_out:
+	if (ctx)
+		ntfs_attr_put_search_ctx(ctx);
+	errno = err;
+	return -1;
+}
+
+/**
+ * ntfs_inode_sync - write the inode (and its dirty extents) to disk
+ * @ni:		ntfs inode to write
+ *
+ * Write the inode @ni to disk as well as its dirty extent inodes if such
+ * exist and @ni is a base inode. If @ni is an extent inode, only @ni is
+ * written completely disregarding its base inode and any other extent inodes.
+ *
+ * For a base inode with dirty extent inodes if any writes fail for whatever
+ * reason, the failing inode is skipped and the sync process is continued. At
+ * the end the error condition that brought about the failure is returned. Thus
+ * the smallest amount of data loss possible occurs.
+ *
+ * Return 0 on success or -1 on error with errno set to the error code.
+ * The following error codes are defined:
+ *	EINVAL	- Invalid arguments were passed to the function.
+ *	EBUSY	- Inode and/or one of its extents is busy, try again later.
+ *	EIO	- I/O error while writing the inode (or one of its extents).
+ */
+static int ntfs_inode_sync_in_dir(ntfs_inode *ni, ntfs_inode *dir_ni)
+{
+	int ret = 0;
+	int err = 0;
+	if (!ni) {
+		errno = EINVAL;
+		ntfs_log_error("Failed to sync NULL inode\n");
+		return -1;
+	}
+
+	ntfs_log_enter("Entering for inode %lld\n", (long long)ni->mft_no);
+
+	/* Update STANDARD_INFORMATION. */
+	if ((ni->mrec->flags & MFT_RECORD_IN_USE) && ni->nr_extents != -1 &&
+			ntfs_inode_sync_standard_information(ni)) {
+		if (!err || errno == EIO) {
+			err = errno;
+			if (err != EIO)
+				err = EBUSY;
+		}
+	}
+
+	/* Update FILE_NAME's in the index. */
+	if ((ni->mrec->flags & MFT_RECORD_IN_USE) && ni->nr_extents != -1 &&
+			NInoFileNameTestAndClearDirty(ni) &&
+			ntfs_inode_sync_file_name(ni, dir_ni)) {
+		if (!err || errno == EIO) {
+			err = errno;
+			if (err != EIO)
+				err = EBUSY;
+		}
+		ntfs_log_perror("Failed to sync FILE_NAME (inode %lld)",
+				(long long)ni->mft_no);
+		NInoFileNameSetDirty(ni);
+	}
+
+	/* Write out attribute list from cache to disk. */
+	if ((ni->mrec->flags & MFT_RECORD_IN_USE) && ni->nr_extents != -1 &&
+			NInoAttrList(ni) && NInoAttrListTestAndClearDirty(ni)) {
+		ntfs_attr *na;
+
+		na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0);
+		if (!na) {
+			if (!err || errno == EIO) {
+				err = errno;
+				if (err != EIO)
+					err = EBUSY;
+				ntfs_log_perror("Attribute list sync failed "
+						"(open, inode %lld)",
+						(long long)ni->mft_no);
+			}
+			NInoAttrListSetDirty(ni);
+			goto sync_inode;
+		} 
+		
+		if (na->data_size == ni->attr_list_size) {
+			if (ntfs_attr_pwrite(na, 0, ni->attr_list_size,
+				        ni->attr_list) != ni->attr_list_size) {
+				if (!err || errno == EIO) {
+					err = errno;
+					if (err != EIO)
+						err = EBUSY;
+					ntfs_log_perror("Attribute list sync "
+						"failed (write, inode %lld)",
+						(long long)ni->mft_no);
+				}
+				NInoAttrListSetDirty(ni);
+			}
+		} else {
+			err = EIO;
+			ntfs_log_error("Attribute list sync failed (bad size, "
+				       "inode %lld)\n", (long long)ni->mft_no);
+			NInoAttrListSetDirty(ni);
+		}
+		ntfs_attr_close(na);
+	}
+	
+sync_inode:
+	/* Write this inode out to the $MFT (and $MFTMirr if applicable). */
+	if (NInoTestAndClearDirty(ni)) {
+		if (ntfs_mft_record_write(ni->vol, ni->mft_no, ni->mrec)) {
+			if (!err || errno == EIO) {
+				err = errno;
+				if (err != EIO)
+					err = EBUSY;
+			}
+			NInoSetDirty(ni);
+			ntfs_log_perror("MFT record sync failed, inode %lld",
+					(long long)ni->mft_no);
+		}
+	}
+
+	/* If this is a base inode with extents write all dirty extents, too. */
+	if (ni->nr_extents > 0) {
+		s32 i;
+
+		for (i = 0; i < ni->nr_extents; ++i) {
+			ntfs_inode *eni;
+
+			eni = ni->extent_nis[i];
+			if (!NInoTestAndClearDirty(eni))
+				continue;
+			
+			if (ntfs_mft_record_write(eni->vol, eni->mft_no, 
+						  eni->mrec)) {
+				if (!err || errno == EIO) {
+					err = errno;
+					if (err != EIO)
+						err = EBUSY;
+				}
+				NInoSetDirty(eni);
+				ntfs_log_perror("Extent MFT record sync failed,"
+						" inode %lld/%lld",
+						(long long)ni->mft_no,
+						(long long)eni->mft_no);
+			}
+		}
+	}
+
+	if (err) {
+		errno = err;
+		ret = -1;
+	}
+	
+	ntfs_log_leave("\n");
+	return ret;
+}
+
+int ntfs_inode_sync(ntfs_inode *ni)
+{
+	return (ntfs_inode_sync_in_dir(ni, (ntfs_inode*)NULL));
+}
+
+/*
+ *		Close an inode with an open parent inode
+ */
+
+int ntfs_inode_close_in_dir(ntfs_inode *ni, ntfs_inode *dir_ni)
+{
+	int res;
+
+	res = ntfs_inode_sync_in_dir(ni, dir_ni);
+	if (res) {
+		if (errno != EIO)
+			errno = EBUSY;
+	} else
+		res = ntfs_inode_close(ni);
+	return (res);
+}
+
+/**
+ * ntfs_inode_add_attrlist - add attribute list to inode and fill it
+ * @ni: opened ntfs inode to which add attribute list
+ *
+ * Return 0 on success or -1 on error with errno set to the error code.
+ * The following error codes are defined:
+ *	EINVAL	- Invalid arguments were passed to the function.
+ *	EEXIST	- Attribute list already exist.
+ *	EIO	- Input/Ouput error occurred.
+ *	ENOMEM	- Not enough memory to perform add.
+ */
+int ntfs_inode_add_attrlist(ntfs_inode *ni)
+{
+	int err;
+	ntfs_attr_search_ctx *ctx;
+	u8 *al = NULL, *aln;
+	int al_len = 0;
+	ATTR_LIST_ENTRY *ale = NULL;
+	ntfs_attr *na;
+
+	if (!ni) {
+		errno = EINVAL;
+		ntfs_log_perror("%s", __FUNCTION__);
+		return -1;
+	}
+
+	ntfs_log_trace("inode %llu\n", (unsigned long long) ni->mft_no);
+
+	if (NInoAttrList(ni) || ni->nr_extents) {
+		errno = EEXIST;
+		ntfs_log_perror("Inode already has attribute list");
+		return -1;
+	}
+
+	/* Form attribute list. */
+	ctx = ntfs_attr_get_search_ctx(ni, NULL);
+	if (!ctx) {
+		err = errno;
+		goto err_out;
+	}
+	/* Walk through all attributes. */
+	while (!ntfs_attr_lookup(AT_UNUSED, NULL, 0, 0, 0, NULL, 0, ctx)) {
+		
+		int ale_size;
+		
+		if (ctx->attr->type == AT_ATTRIBUTE_LIST) {
+			err = EIO;
+			ntfs_log_perror("Attribute list already present");
+			goto put_err_out;
+		}
+		
+		ale_size = (sizeof(ATTR_LIST_ENTRY) + sizeof(ntfschar) *
+					ctx->attr->name_length + 7) & ~7;
+		al_len += ale_size;
+		
+		aln = realloc(al, al_len);
+		if (!aln) {
+			err = errno;
+			ntfs_log_perror("Failed to realloc %d bytes", al_len);
+			goto put_err_out;
+		}
+		ale = (ATTR_LIST_ENTRY *)(aln + ((u8 *)ale - al));
+		al = aln;
+		
+		memset(ale, 0, ale_size);
+		
+		/* Add attribute to attribute list. */
+		ale->type = ctx->attr->type;
+		ale->length = cpu_to_le16((sizeof(ATTR_LIST_ENTRY) +
+			sizeof(ntfschar) * ctx->attr->name_length + 7) & ~7);
+		ale->name_length = ctx->attr->name_length;
+		ale->name_offset = (u8 *)ale->name - (u8 *)ale;
+		if (ctx->attr->non_resident)
+			ale->lowest_vcn = ctx->attr->lowest_vcn;
+		else
+			ale->lowest_vcn = 0;
+		ale->mft_reference = MK_LE_MREF(ni->mft_no,
+			le16_to_cpu(ni->mrec->sequence_number));
+		ale->instance = ctx->attr->instance;
+		memcpy(ale->name, (u8 *)ctx->attr +
+				le16_to_cpu(ctx->attr->name_offset),
+				ctx->attr->name_length * sizeof(ntfschar));
+		ale = (ATTR_LIST_ENTRY *)(al + al_len);
+	}
+	/* Check for real error occurred. */
+	if (errno != ENOENT) {
+		err = errno;
+		ntfs_log_perror("%s: Attribute lookup failed, inode %lld",
+				__FUNCTION__, (long long)ni->mft_no);
+		goto put_err_out;
+	}
+
+	/* Set in-memory attribute list. */
+	ni->attr_list = al;
+	ni->attr_list_size = al_len;
+	NInoSetAttrList(ni);
+	NInoAttrListSetDirty(ni);
+
+	/* Free space if there is not enough it for $ATTRIBUTE_LIST. */
+	if (le32_to_cpu(ni->mrec->bytes_allocated) -
+			le32_to_cpu(ni->mrec->bytes_in_use) <
+			offsetof(ATTR_RECORD, resident_end)) {
+		if (ntfs_inode_free_space(ni,
+				offsetof(ATTR_RECORD, resident_end))) {
+			/* Failed to free space. */
+			err = errno;
+			ntfs_log_perror("Failed to free space for attrlist");
+			goto rollback;
+		}
+	}
+
+	/* Add $ATTRIBUTE_LIST to mft record. */
+	if (ntfs_resident_attr_record_add(ni,
+				AT_ATTRIBUTE_LIST, NULL, 0, NULL, 0, 0) < 0) {
+		err = errno;
+		ntfs_log_perror("Couldn't add $ATTRIBUTE_LIST to MFT");
+		goto rollback;
+	}
+
+	/* Resize it. */
+	na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0);
+	if (!na) {
+		err = errno;
+		ntfs_log_perror("Failed to open just added $ATTRIBUTE_LIST");
+		goto remove_attrlist_record;
+	}
+	if (ntfs_attr_truncate(na, al_len)) {
+		err = errno;
+		ntfs_log_perror("Failed to resize just added $ATTRIBUTE_LIST");
+		ntfs_attr_close(na);
+		goto remove_attrlist_record;;
+	}
+	
+	ntfs_attr_put_search_ctx(ctx);
+	ntfs_attr_close(na);
+	return 0;
+
+remove_attrlist_record:
+	/* Prevent ntfs_attr_recorm_rm from freeing attribute list. */
+	ni->attr_list = NULL;
+	NInoClearAttrList(ni);
+	/* Remove $ATTRIBUTE_LIST record. */
+	ntfs_attr_reinit_search_ctx(ctx);
+	if (!ntfs_attr_lookup(AT_ATTRIBUTE_LIST, NULL, 0,
+				CASE_SENSITIVE, 0, NULL, 0, ctx)) {
+		if (ntfs_attr_record_rm(ctx))
+			ntfs_log_perror("Rollback failed to remove attrlist");
+	} else
+		ntfs_log_perror("Rollback failed to find attrlist");
+	/* Setup back in-memory runlist. */
+	ni->attr_list = al;
+	ni->attr_list_size = al_len;
+	NInoSetAttrList(ni);
+rollback:
+	/*
+	 * Scan attribute list for attributes that placed not in the base MFT
+	 * record and move them to it.
+	 */
+	ntfs_attr_reinit_search_ctx(ctx);
+	ale = (ATTR_LIST_ENTRY*)al;
+	while ((u8*)ale < al + al_len) {
+		if (MREF_LE(ale->mft_reference) != ni->mft_no) {
+			if (!ntfs_attr_lookup(ale->type, ale->name,
+						ale->name_length,
+						CASE_SENSITIVE,
+						sle64_to_cpu(ale->lowest_vcn),
+						NULL, 0, ctx)) {
+				if (ntfs_attr_record_move_to(ctx, ni))
+					ntfs_log_perror("Rollback failed to "
+							"move attribute");
+			} else
+				ntfs_log_perror("Rollback failed to find attr");
+			ntfs_attr_reinit_search_ctx(ctx);
+		}
+		ale = (ATTR_LIST_ENTRY*)((u8*)ale + le16_to_cpu(ale->length));
+	}
+	/* Remove in-memory attribute list. */
+	ni->attr_list = NULL;
+	ni->attr_list_size = 0;
+	NInoClearAttrList(ni);
+	NInoAttrListClearDirty(ni);
+put_err_out:
+	ntfs_attr_put_search_ctx(ctx);
+err_out:
+	free(al);
+	errno = err;
+	return -1;
+}
+
+/**
+ * ntfs_inode_free_space - free space in the MFT record of an inode
+ * @ni:		ntfs inode in which MFT record needs more free space
+ * @size:	amount of space needed to free
+ *
+ * Return 0 on success or -1 on error with errno set to the error code.
+ */
+int ntfs_inode_free_space(ntfs_inode *ni, int size)
+{
+	ntfs_attr_search_ctx *ctx;
+	int freed;
+
+	if (!ni || size < 0) {
+		errno = EINVAL;
+		ntfs_log_perror("%s: ni=%p size=%d", __FUNCTION__, ni, size);
+		return -1;
+	}
+
+	ntfs_log_trace("Entering for inode %lld, size %d\n",
+		       (unsigned long long)ni->mft_no, size);
+
+	freed = (le32_to_cpu(ni->mrec->bytes_allocated) -
+				le32_to_cpu(ni->mrec->bytes_in_use));
+
+	if (size <= freed)
+		return 0;
+
+	ctx = ntfs_attr_get_search_ctx(ni, NULL);
+	if (!ctx)
+		return -1;
+	/*
+	 * $STANDARD_INFORMATION and $ATTRIBUTE_LIST must stay in the base MFT
+	 * record, so position search context on the first attribute after them.
+	 */
+	if (ntfs_attr_position(AT_FILE_NAME, ctx))
+		goto put_err_out;
+
+	while (1) {
+		int record_size;
+		/*
+		 * Check whether attribute is from different MFT record. If so,
+		 * find next, because we don't need such.
+		 */
+		while (ctx->ntfs_ino->mft_no != ni->mft_no) {
+retry:			
+			if (ntfs_attr_position(AT_UNUSED, ctx))
+				goto put_err_out;
+		}
+
+		if (ntfs_inode_base(ctx->ntfs_ino)->mft_no == FILE_MFT && 
+		    ctx->attr->type == AT_DATA)
+			goto retry;
+
+		if (ctx->attr->type == AT_INDEX_ROOT)
+			goto retry;
+
+		record_size = le32_to_cpu(ctx->attr->length);
+
+		if (ntfs_attr_record_move_away(ctx, 0)) {
+			ntfs_log_perror("Failed to move out attribute #2");
+			break;
+		}
+		freed += record_size;
+
+		/* Check whether we are done. */
+		if (size <= freed) {
+			ntfs_attr_put_search_ctx(ctx);
+			return 0;
+		}
+		/*
+		 * Reposition to first attribute after $STANDARD_INFORMATION 
+		 * and $ATTRIBUTE_LIST instead of simply skipping this attribute 
+		 * because in the case when we have got only in-memory attribute 
+		 * list then ntfs_attr_lookup will fail when it tries to find 
+		 * $ATTRIBUTE_LIST.
+		 */
+		ntfs_attr_reinit_search_ctx(ctx);
+		if (ntfs_attr_position(AT_FILE_NAME, ctx))
+			break;
+	}
+put_err_out:
+	ntfs_attr_put_search_ctx(ctx);
+	if (errno == ENOSPC)
+		ntfs_log_trace("No attributes left that could be moved out.\n");
+	return -1;
+}
+
+/**
+ * ntfs_inode_update_times - update selected time fields for ntfs inode
+ * @ni:		ntfs inode for which update time fields
+ * @mask:	select which time fields should be updated
+ *
+ * This function updates time fields to current time. Fields to update are
+ * selected using @mask (see enum @ntfs_time_update_flags for posssible values).
+ */
+void ntfs_inode_update_times(ntfs_inode *ni, ntfs_time_update_flags mask)
+{
+	ntfs_time now;
+
+	if (!ni) {
+		ntfs_log_error("%s(): Invalid arguments.\n", __FUNCTION__);
+		return;
+	}
+
+	if ((ni->mft_no < FILE_first_user && ni->mft_no != FILE_root) ||
+			NVolReadOnly(ni->vol) || !mask)
+		return;
+
+	now = ntfs_current_time();
+	if (mask & NTFS_UPDATE_ATIME)
+		ni->last_access_time = now;
+	if (mask & NTFS_UPDATE_MTIME)
+		ni->last_data_change_time = now;
+	if (mask & NTFS_UPDATE_CTIME)
+		ni->last_mft_change_time = now;
+	
+	NInoFileNameSetDirty(ni);
+	NInoSetDirty(ni);
+}
+
+/**
+ * ntfs_inode_badclus_bad - check for $Badclus:$Bad data attribute
+ * @mft_no:		mft record number where @attr is present
+ * @attr:		attribute record used to check for the $Bad attribute
+ *
+ * Check if the mft record given by @mft_no and @attr contains the bad sector
+ * list. Please note that mft record numbers describing $Badclus extent inodes
+ * will not match the current $Badclus:$Bad check.
+ * 
+ * On success return 1 if the file is $Badclus:$Bad, otherwise return 0.
+ * On error return -1 with errno set to the error code.
+ */
+int ntfs_inode_badclus_bad(u64 mft_no, ATTR_RECORD *attr)
+{
+	int len, ret = 0;
+	ntfschar *ustr;
+
+	if (!attr) {
+		ntfs_log_error("Invalid argument.\n");
+		errno = EINVAL;
+		return -1;
+	}
+	
+	if (mft_no != FILE_BadClus)
+	       	return 0;
+
+	if (attr->type != AT_DATA)
+	       	return 0;
+
+	if ((ustr = ntfs_str2ucs("$Bad", &len)) == NULL) {
+		ntfs_log_perror("Couldn't convert '$Bad' to Unicode");
+		return -1;
+	}
+
+	if (ustr && ntfs_names_are_equal(ustr, len,
+			(ntfschar *)((u8 *)attr + le16_to_cpu(attr->name_offset)),
+			attr->name_length, 0, NULL, 0))
+		ret = 1;
+
+	ntfs_ucsfree(ustr);
+
+	return ret;
+}
+
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+
+/*
+ *		Get high precision NTFS times
+ *
+ *	They are returned in following order : create, update, access, change
+ *	provided they fit in requested size.
+ *
+ *	Returns the modified size if successfull (or 32 if buffer size is null)
+ *		-errno if failed
+ */
+
+int ntfs_inode_get_times(ntfs_inode *ni, char *value, size_t size)
+{
+	ntfs_attr_search_ctx *ctx;
+	STANDARD_INFORMATION *std_info;
+	u64 *times;
+	int ret;
+
+	ret = 0;
+	ctx = ntfs_attr_get_search_ctx(ni, NULL);
+	if (ctx) {
+		if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED,
+				     0, CASE_SENSITIVE, 0, NULL, 0, ctx)) {
+			ntfs_log_perror("Failed to get standard info (inode %lld)",
+					(long long)ni->mft_no);
+		} else {
+			std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr +
+					le16_to_cpu(ctx->attr->value_offset));
+			if (value && (size >= 8)) {
+				times = (u64*)value;
+				times[0] = le64_to_cpu(std_info->creation_time);
+				ret = 8;
+				if (size >= 16) {
+					times[1] = le64_to_cpu(std_info->last_data_change_time);
+					ret = 16;
+				}
+				if (size >= 24) {
+					times[2] = le64_to_cpu(std_info->last_access_time);
+					ret = 24;
+				}
+				if (size >= 32) {
+					times[3] = le64_to_cpu(std_info->last_mft_change_time);
+					ret = 32;
+				}
+			} else
+				if (!size)
+					ret = 32;
+				else
+					ret = -ERANGE;
+			}
+		ntfs_attr_put_search_ctx(ctx);
+	}		
+	return (ret ? ret : -errno);
+}
+
+/*
+ *		Set high precision NTFS times
+ *
+ *	They are expected in this order : create, update, access
+ *	provided they are present in input. The change time is set to
+ *	current time.
+ *
+ *	The times are inserted directly in the standard_information and
+ *	file names attributes to avoid manipulating low precision times
+ *
+ *	Returns 0 if success
+ *		-1 if there were an error (described by errno)
+ */
+
+int ntfs_inode_set_times(ntfs_inode *ni, const char *value, size_t size,
+			int flags)
+{
+	ntfs_attr_search_ctx *ctx;
+	STANDARD_INFORMATION *std_info;
+	FILE_NAME_ATTR *fn;
+	const u64 *times;
+	ntfs_time now;
+	int cnt;
+	int ret;
+
+	ret = -1;
+	if ((size >= 8) && !(flags & XATTR_CREATE)) {
+		times = (const u64*)value;
+		now = ntfs_current_time();
+			/* update the standard information attribute */
+		ctx = ntfs_attr_get_search_ctx(ni, NULL);
+		if (ctx) {
+			if (ntfs_attr_lookup(AT_STANDARD_INFORMATION,
+					AT_UNNAMED, 0, CASE_SENSITIVE,
+					0, NULL, 0, ctx)) {
+				ntfs_log_perror("Failed to get standard info (inode %lld)",
+						(long long)ni->mft_no);
+			} else {
+				std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr +
+					le16_to_cpu(ctx->attr->value_offset));
+				/*
+				 * Mark times set to avoid overwriting
+				 * them when the inode is closed.
+				 * The inode structure must also be updated
+				 * (with loss of precision) because of cacheing.
+				 * TODO : use NTFS precision in inode, and
+				 * return sub-second times in getattr()
+				 */
+				set_nino_flag(ni, TimesSet);
+				std_info->creation_time = cpu_to_le64(times[0]);
+				ni->creation_time
+					= std_info->creation_time;
+				if (size >= 16) {
+					std_info->last_data_change_time = cpu_to_le64(times[1]);
+					ni->last_data_change_time
+						= std_info->last_data_change_time;
+				}
+				if (size >= 24) {
+					std_info->last_access_time = cpu_to_le64(times[2]);
+					ni->last_access_time
+						= std_info->last_access_time;
+				}
+				std_info->last_mft_change_time = now;
+				ni->last_mft_change_time = now;
+				ntfs_inode_mark_dirty(ctx->ntfs_ino);
+				NInoFileNameSetDirty(ni);
+
+				/* update the file names attributes */
+				ntfs_attr_reinit_search_ctx(ctx);
+				cnt = 0;
+				while (!ntfs_attr_lookup(AT_FILE_NAME,
+						AT_UNNAMED, 0, CASE_SENSITIVE,
+						0, NULL, 0, ctx)) {
+					fn = (FILE_NAME_ATTR*)((u8 *)ctx->attr +
+						le16_to_cpu(ctx->attr->value_offset));
+					fn->creation_time
+						= cpu_to_le64(times[0]);
+					if (size >= 16)
+						fn->last_data_change_time
+							= cpu_to_le64(times[1]);
+					if (size >= 24)
+						fn->last_access_time
+							= cpu_to_le64(times[2]);
+					fn->last_mft_change_time = now;
+					cnt++;
+				}
+				if (cnt)
+					ret = 0;
+				else {
+					ntfs_log_perror("Failed to get file names (inode %lld)",
+						(long long)ni->mft_no);
+				}
+			}
+			ntfs_attr_put_search_ctx(ctx);
+		}
+	} else
+		if (size < 8)
+			errno = ERANGE;
+		else
+			errno = EEXIST;
+	return (ret);
+}
+
+#endif /* HAVE_SETXATTR */
diff --git a/libntfs-3g/ioctl.c b/libntfs-3g/ioctl.c
new file mode 100755
index 0000000000000000000000000000000000000000..eb7c8e7b6dea4809bddac2642d3489c85d148db7
--- /dev/null
+++ b/libntfs-3g/ioctl.c
@@ -0,0 +1,378 @@
+/**
+ * ioctl.c - Processing of ioctls
+ *
+ *      This module is part of ntfs-3g library
+ *
+ * Copyright (c) 2014 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_SETXATTR
+#include <sys/xattr.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.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[80], path2[80];
+	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;
+}
+
+#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)
+{
+	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);
+
+	/* 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_debug("fstrim: setting start or length is not supported\n");
+		return -EINVAL;
+	}
+	if (minlen > vol->cluster_size) {
+		ntfs_log_debug("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_debug("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_debug("fstrim: backing device is not aligned for discards\n");
+		return -EOPNOTSUPP;
+	}
+	if (discard_granularity > vol->cluster_size) {
+		ntfs_log_debug("fstrim: discard granularity of backing device is larger than cluster size\n");
+		return -EOPNOTSUPP;
+	}
+	if (discard_max_bytes == 0) {
+		ntfs_log_debug("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.
+		 */
+		for (start_lcn = start_buf; start_lcn < end_buf; ++start_lcn) {
+			if (!ntfs_bit_get(buf, start_lcn-start_buf)) {
+				LCN end_lcn;
+
+				/* 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++;
+
+				ret = fstrim_clusters(vol,
+						start_lcn, end_lcn-start_lcn);
+				if (ret)
+					goto free_out;
+
+				start_lcn = end_lcn-1;
+			}
+		}
+	}
+
+	ret = 0;
+free_out:
+	free(buf);
+	return ret;
+}
+
+#endif /* FITRIM && BLKDISCARD */
+
+int ntfs_ioctl(ntfs_inode *ni, int 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
+			ret = fstrim(ni->vol, data);
+		break;
+#else
+#warning FITRIM or BLKDISCARD not defined
+#endif
+	default :
+		ret = -EINVAL;
+		break;
+	}
+	return (ret);
+}
diff --git a/libntfs-3g/lcnalloc.c b/libntfs-3g/lcnalloc.c
new file mode 100755
index 0000000000000000000000000000000000000000..e84d2431b5d730ed3958d6620e35212514dc5d60
--- /dev/null
+++ b/libntfs-3g/lcnalloc.c
@@ -0,0 +1,771 @@
+/**
+ * lcnalloc.c - Cluster (de)allocation code. Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2002-2004 Anton Altaparmakov
+ * Copyright (c) 2004 Yura Pakhuchiy
+ * Copyright (c) 2004-2008 Szabolcs Szakacsits
+ * Copyright (c) 2008-2009 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_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "types.h"
+#include "attrib.h"
+#include "bitmap.h"
+#include "debug.h"
+#include "runlist.h"
+#include "volume.h"
+#include "lcnalloc.h"
+#include "logging.h"
+#include "misc.h"
+
+/*
+ * Plenty possibilities for big optimizations all over in the cluster
+ * allocation, however at the moment the dominant bottleneck (~ 90%) is 
+ * the update of the mapping pairs which converges to the cubic Faulhaber's
+ * formula as the function of the number of extents (fragments, runs).
+ */
+#define NTFS_LCNALLOC_BSIZE 4096
+#define NTFS_LCNALLOC_SKIP  NTFS_LCNALLOC_BSIZE
+
+enum {
+	ZONE_MFT = 1,
+	ZONE_DATA1 = 2,
+	ZONE_DATA2 = 4
+} ;
+
+static void ntfs_cluster_set_zone_pos(LCN start, LCN end, LCN *pos, LCN tc)
+{
+	ntfs_log_trace("pos: %lld  tc: %lld\n", (long long)*pos, (long long)tc);
+
+	if (tc >= end)
+		*pos = start;
+	else if (tc >= start)
+		*pos = tc;
+}
+
+static void ntfs_cluster_update_zone_pos(ntfs_volume *vol, u8 zone, LCN tc)
+{
+	ntfs_log_trace("tc = %lld, zone = %d\n", (long long)tc, zone);
+	
+	if (zone == ZONE_MFT)
+		ntfs_cluster_set_zone_pos(vol->mft_lcn, vol->mft_zone_end,
+					  &vol->mft_zone_pos, tc);
+	else if (zone == ZONE_DATA1)
+		ntfs_cluster_set_zone_pos(vol->mft_zone_end, vol->nr_clusters,
+					  &vol->data1_zone_pos, tc);
+	else /* zone == ZONE_DATA2 */
+		ntfs_cluster_set_zone_pos(0, vol->mft_zone_start, 
+					  &vol->data2_zone_pos, tc);
+}
+
+/*
+ *		Unmark full zones when a cluster has been freed in a full zone
+ *
+ *	Next allocation will reuse the freed cluster
+ */
+
+static void update_full_status(ntfs_volume *vol, LCN lcn)
+{
+	if (lcn >= vol->mft_zone_end) {
+		if (vol->full_zones & ZONE_DATA1) {
+			ntfs_cluster_update_zone_pos(vol, ZONE_DATA1, lcn);
+			vol->full_zones &= ~ZONE_DATA1;
+		}
+	} else
+		if (lcn < vol->mft_zone_start) {
+			if (vol->full_zones & ZONE_DATA2) {
+				ntfs_cluster_update_zone_pos(vol, ZONE_DATA2, lcn);
+				vol->full_zones &= ~ZONE_DATA2;
+			}
+		} else {
+			if (vol->full_zones & ZONE_MFT) {
+				ntfs_cluster_update_zone_pos(vol, ZONE_MFT, lcn);
+				vol->full_zones &= ~ZONE_MFT;
+			}
+		}
+}
+ 
+static s64 max_empty_bit_range(unsigned char *buf, int size)
+{
+	int i, j, run = 0;
+	int max_range = 0;
+	s64 start_pos = -1;
+	
+	ntfs_log_trace("Entering\n");
+	
+	i = 0;
+	while (i < size) {
+		switch (*buf) {
+		case 0 :
+			do {
+				buf++;
+				run += 8;
+				i++;
+			} while ((i < size) && !*buf);
+			break;
+		case 255 :
+			if (run > max_range) {
+				max_range = run;
+				start_pos = (s64)i * 8 - run;
+			}
+			run = 0;
+			do {
+				buf++;
+				i++;
+			} while ((i < size) && (*buf == 255));
+			break;
+		default :
+			for (j = 0; j < 8; j++) {
+			
+				int bit = *buf & (1 << j);
+		
+				if (bit) {
+					if (run > max_range) {
+						max_range = run;
+						start_pos = (s64)i * 8 + (j - run);
+					}
+					run = 0;
+				} else 
+					run++;
+			}
+			i++;
+			buf++;
+		
+		}
+	}
+	
+	if (run > max_range)
+		start_pos = (s64)i * 8 - run;
+	
+	return start_pos;
+}
+
+static int bitmap_writeback(ntfs_volume *vol, s64 pos, s64 size, void *b, 
+			    u8 *writeback)
+{
+	s64 written;
+	
+	ntfs_log_trace("Entering\n");
+	
+	if (!*writeback)
+		return 0;
+	
+	*writeback = 0;
+	
+	written = ntfs_attr_pwrite(vol->lcnbmp_na, pos, size, b);
+	if (written != size) {
+		if (!written)
+			errno = EIO;
+		ntfs_log_perror("Bitmap write error (%lld, %lld)",
+				(long long)pos, (long long)size);
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
+ * ntfs_cluster_alloc - allocate clusters on an ntfs volume
+ * @vol:	mounted ntfs volume on which to allocate the clusters
+ * @start_vcn:	vcn to use for the first allocated cluster
+ * @count:	number of clusters to allocate
+ * @start_lcn:	starting lcn at which to allocate the clusters (or -1 if none)
+ * @zone:	zone from which to allocate the clusters
+ *
+ * Allocate @count clusters preferably starting at cluster @start_lcn or at the
+ * current allocator position if @start_lcn is -1, on the mounted ntfs volume
+ * @vol. @zone is either DATA_ZONE for allocation of normal clusters and
+ * MFT_ZONE for allocation of clusters for the master file table, i.e. the
+ * $MFT/$DATA attribute.
+ *
+ * On success return a runlist describing the allocated cluster(s).
+ *
+ * On error return NULL with errno set to the error code.
+ *
+ * Notes on the allocation algorithm
+ * =================================
+ *
+ * There are two data zones. First is the area between the end of the mft zone
+ * and the end of the volume, and second is the area between the start of the
+ * volume and the start of the mft zone. On unmodified/standard NTFS 1.x
+ * volumes, the second data zone doesn't exist due to the mft zone being
+ * expanded to cover the start of the volume in order to reserve space for the
+ * mft bitmap attribute.
+ *
+ * The complexity stems from the need of implementing the mft vs data zoned 
+ * approach and from the fact that we have access to the lcn bitmap via up to 
+ * NTFS_LCNALLOC_BSIZE bytes at a time, so we need to cope with crossing over 
+ * boundaries of two buffers. Further, the fact that the allocator allows for 
+ * caller supplied hints as to the location of where allocation should begin 
+ * and the fact that the allocator keeps track of where in the data zones the 
+ * next natural allocation should occur, contribute to the complexity of the 
+ * function. But it should all be worthwhile, because this allocator: 
+ *   1) implements MFT zone reservation
+ *   2) causes reduction in fragmentation. 
+ * The code is not optimized for speed.
+ */
+runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count,
+		LCN start_lcn, const NTFS_CLUSTER_ALLOCATION_ZONES zone)
+{
+	LCN zone_start, zone_end;  /* current search range */
+	LCN last_read_pos, lcn;
+	LCN bmp_pos;		/* current bit position inside the bitmap */
+	LCN prev_lcn = 0, prev_run_len = 0;
+	s64 clusters, br;
+	runlist *rl = NULL, *trl;
+	u8 *buf, *byte, bit, writeback;
+	u8 pass = 1; 	/* 1: inside zone;  2: start of zone */
+	u8 search_zone; /* 4: data2 (start) 1: mft (middle) 2: data1 (end) */
+	u8 done_zones = 0;
+	u8 has_guess, used_zone_pos;
+	int err = 0, rlpos, rlsize, buf_size;
+
+	ntfs_log_enter("Entering with count = 0x%llx, start_lcn = 0x%llx, "
+		       "zone = %s_ZONE.\n", (long long)count, (long long)
+		       start_lcn, zone == MFT_ZONE ? "MFT" : "DATA");
+	
+	if (!vol || count < 0 || start_lcn < -1 || !vol->lcnbmp_na ||
+			(s8)zone < FIRST_ZONE || zone > LAST_ZONE) {
+		errno = EINVAL;
+		ntfs_log_perror("%s: vcn: %lld, count: %lld, lcn: %lld", 
+				__FUNCTION__, (long long)start_vcn, 
+				(long long)count, (long long)start_lcn);
+		goto out;
+	}
+
+	/* Return empty runlist if @count == 0 */
+	if (!count) {
+		rl = ntfs_malloc(0x1000);
+		if (rl) {
+			rl[0].vcn = start_vcn;
+			rl[0].lcn = LCN_RL_NOT_MAPPED;
+			rl[0].length = 0;
+		}
+		goto out;
+	}
+
+	buf = ntfs_malloc(NTFS_LCNALLOC_BSIZE);
+	if (!buf)
+		goto out;
+	/*
+	 * If no @start_lcn was requested, use the current zone
+	 * position otherwise use the requested @start_lcn.
+	 */
+	has_guess = 1;
+	zone_start = start_lcn;
+	
+	if (zone_start < 0) {
+		if (zone == DATA_ZONE)
+			zone_start = vol->data1_zone_pos;
+		else
+			zone_start = vol->mft_zone_pos;
+		has_guess = 0;
+	}
+	
+	used_zone_pos = has_guess ? 0 : 1;
+	
+	if (!zone_start || zone_start == vol->mft_zone_start ||
+			zone_start == vol->mft_zone_end)
+		pass = 2;
+		
+	if (zone_start < vol->mft_zone_start) {
+		zone_end = vol->mft_zone_start;
+		search_zone = ZONE_DATA2;
+	} else if (zone_start < vol->mft_zone_end) {
+		zone_end = vol->mft_zone_end;
+		search_zone = ZONE_MFT;
+	} else {
+		zone_end = vol->nr_clusters;
+		search_zone = ZONE_DATA1;
+	}
+	
+	bmp_pos = zone_start;
+
+	/* Loop until all clusters are allocated. */
+	clusters = count;
+	rlpos = rlsize = 0;
+	while (1) {
+			/* check whether we have exhausted the current zone */
+		if (search_zone & vol->full_zones)
+			goto zone_pass_done;
+		last_read_pos = bmp_pos >> 3;
+		br = ntfs_attr_pread(vol->lcnbmp_na, last_read_pos, 
+				     NTFS_LCNALLOC_BSIZE, buf);
+		if (br <= 0) {
+			if (!br)
+				goto zone_pass_done;
+			err = errno;
+			ntfs_log_perror("Reading $BITMAP failed");
+			goto err_ret;
+		}
+		/*
+		 * We might have read less than NTFS_LCNALLOC_BSIZE bytes
+		 * if we are close to the end of the attribute.
+		 */
+		buf_size = (int)br << 3;
+		lcn = bmp_pos & 7;
+		bmp_pos &= ~7;
+		writeback = 0;
+		
+		while (lcn < buf_size) {
+			byte = buf + (lcn >> 3);
+			bit = 1 << (lcn & 7);
+			if (has_guess) {
+				if (*byte & bit) {
+					has_guess = 0;
+					break;
+				}
+			} else {
+				lcn = max_empty_bit_range(buf, br);
+				if (lcn < 0)
+					break;
+				has_guess = 1;
+				continue;
+			}
+
+			/* First free bit is at lcn + bmp_pos. */
+			 
+			/* Reallocate memory if necessary. */
+			if ((rlpos + 2) * (int)sizeof(runlist) >= rlsize) {
+				rlsize += 4096;
+				trl = realloc(rl, rlsize);
+				if (!trl) {
+					err = ENOMEM;
+					ntfs_log_perror("realloc() failed");
+					goto wb_err_ret;
+				}
+				rl = trl;
+			}
+			
+			/* Allocate the bitmap bit. */
+			*byte |= bit;
+			writeback = 1;
+			if (vol->free_clusters <= 0) 
+				ntfs_log_error("Non-positive free clusters "
+					       "(%lld)!\n",
+						(long long)vol->free_clusters);
+			else	
+				vol->free_clusters--; 
+			
+			/*
+			 * Coalesce with previous run if adjacent LCNs.
+			 * Otherwise, append a new run.
+			 */
+			if (prev_lcn == lcn + bmp_pos - prev_run_len && rlpos) {
+				ntfs_log_debug("Cluster coalesce: prev_lcn: "
+					       "%lld  lcn: %lld  bmp_pos: %lld  "
+					       "prev_run_len: %lld\n", 
+					       (long long)prev_lcn, 
+					       (long long)lcn, (long long)bmp_pos, 
+					       (long long)prev_run_len);
+				rl[rlpos - 1].length = ++prev_run_len;
+			} else {
+				if (rlpos)
+					rl[rlpos].vcn = rl[rlpos - 1].vcn +
+							prev_run_len;
+				else {
+					rl[rlpos].vcn = start_vcn;
+					ntfs_log_debug("Start_vcn: %lld\n", 
+						       (long long)start_vcn);
+				}
+				
+				rl[rlpos].lcn = prev_lcn = lcn + bmp_pos;
+				rl[rlpos].length = prev_run_len = 1;
+				rlpos++;
+			}
+			
+			ntfs_log_debug("RUN:   %-16lld %-16lld %-16lld\n", 
+				       (long long)rl[rlpos - 1].vcn, 
+				       (long long)rl[rlpos - 1].lcn, 
+				       (long long)rl[rlpos - 1].length);
+			/* Done? */
+			if (!--clusters) {
+				if (used_zone_pos)
+					ntfs_cluster_update_zone_pos(vol, 
+						search_zone, lcn + bmp_pos + 1 +
+							NTFS_LCNALLOC_SKIP);
+				goto done_ret;
+			}
+			
+			lcn++;
+		}
+		
+		if (bitmap_writeback(vol, last_read_pos, br, buf, &writeback)) {
+			err = errno;
+			goto err_ret;
+		}
+		
+		if (!used_zone_pos) {
+			
+			used_zone_pos = 1;
+			
+			if (search_zone == ZONE_MFT)
+				zone_start = vol->mft_zone_pos;
+			else if (search_zone == ZONE_DATA1)
+				zone_start = vol->data1_zone_pos;
+			else
+				zone_start = vol->data2_zone_pos;
+			
+			if (!zone_start || zone_start == vol->mft_zone_start ||
+					zone_start == vol->mft_zone_end)
+				pass = 2;
+			bmp_pos = zone_start;
+		} else
+			bmp_pos += buf_size;
+		
+		if (bmp_pos < zone_end)
+			continue;
+
+zone_pass_done:
+		ntfs_log_trace("Finished current zone pass(%i).\n", pass);
+		if (pass == 1) {
+			pass = 2;
+			zone_end = zone_start;
+			
+			if (search_zone == ZONE_MFT)
+				zone_start = vol->mft_zone_start;
+			else if (search_zone == ZONE_DATA1)
+				zone_start = vol->mft_zone_end;
+			else
+				zone_start = 0;
+			
+			/* Sanity check. */
+			if (zone_end < zone_start)
+				zone_end = zone_start;
+			
+			bmp_pos = zone_start;
+			
+			continue;
+		} 
+		/* pass == 2 */
+done_zones_check:
+		done_zones |= search_zone;
+		vol->full_zones |= search_zone;
+		if (done_zones < (ZONE_MFT + ZONE_DATA1 + ZONE_DATA2)) {
+			ntfs_log_trace("Switching zone.\n");
+			pass = 1;
+			if (rlpos) {
+				LCN tc = rl[rlpos - 1].lcn + 
+				      rl[rlpos - 1].length + NTFS_LCNALLOC_SKIP;
+				
+				if (used_zone_pos)
+					ntfs_cluster_update_zone_pos(vol, 
+						search_zone, tc);
+			}
+			
+			switch (search_zone) {
+			case ZONE_MFT:
+				ntfs_log_trace("Zone switch: mft -> data1\n");
+switch_to_data1_zone:		search_zone = ZONE_DATA1;
+				zone_start = vol->data1_zone_pos;
+				zone_end = vol->nr_clusters;
+				if (zone_start == vol->mft_zone_end)
+					pass = 2;
+				break;
+			case ZONE_DATA1:
+				ntfs_log_trace("Zone switch: data1 -> data2\n");
+				search_zone = ZONE_DATA2;
+				zone_start = vol->data2_zone_pos;
+				zone_end = vol->mft_zone_start;
+				if (!zone_start)
+					pass = 2;
+				break;
+			case ZONE_DATA2:
+				if (!(done_zones & ZONE_DATA1)) {
+					ntfs_log_trace("data2 -> data1\n");
+					goto switch_to_data1_zone;
+				}
+				ntfs_log_trace("Zone switch: data2 -> mft\n");
+				search_zone = ZONE_MFT;
+				zone_start = vol->mft_zone_pos;
+				zone_end = vol->mft_zone_end;
+				if (zone_start == vol->mft_zone_start)
+					pass = 2;
+				break;
+			}
+			
+			bmp_pos = zone_start;
+			
+			if (zone_start == zone_end) {
+				ntfs_log_trace("Empty zone, skipped.\n");
+				goto done_zones_check;
+			}
+			
+			continue;
+		}
+		
+		ntfs_log_trace("All zones are finished, no space on device.\n");
+		err = ENOSPC;
+		goto err_ret;
+	}
+done_ret:
+	ntfs_log_debug("At done_ret.\n");
+	/* Add runlist terminator element. */
+	rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length;
+	rl[rlpos].lcn = LCN_RL_NOT_MAPPED;
+	rl[rlpos].length = 0;
+	if (bitmap_writeback(vol, last_read_pos, br, buf, &writeback)) {
+		err = errno;
+		goto err_ret;
+	}
+done_err_ret:
+	free(buf);
+	if (err) {
+		errno = err;
+		ntfs_log_perror("Failed to allocate clusters");
+		rl = NULL;
+	}
+out:	
+	ntfs_log_leave("\n");
+	return rl;
+
+wb_err_ret:
+	ntfs_log_trace("At wb_err_ret.\n");
+	if (bitmap_writeback(vol, last_read_pos, br, buf, &writeback))
+		err = errno;
+err_ret:
+	ntfs_log_trace("At err_ret.\n");
+	if (rl) {
+		/* Add runlist terminator element. */
+		rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length;
+		rl[rlpos].lcn = LCN_RL_NOT_MAPPED;
+		rl[rlpos].length = 0;
+		ntfs_debug_runlist_dump(rl);
+		ntfs_cluster_free_from_rl(vol, rl);
+		free(rl);
+		rl = NULL;
+	}
+	goto done_err_ret;
+}
+
+/**
+ * ntfs_cluster_free_from_rl - free clusters from runlist
+ * @vol:	mounted ntfs volume on which to free the clusters
+ * @rl:		runlist from which deallocate clusters
+ *
+ * On success return 0 and on error return -1 with errno set to the error code.
+ */
+int ntfs_cluster_free_from_rl(ntfs_volume *vol, runlist *rl)
+{
+	s64 nr_freed = 0;
+	int ret = -1;
+
+	ntfs_log_trace("Entering.\n");
+
+	for (; rl->length; rl++) {
+
+		ntfs_log_trace("Dealloc lcn 0x%llx, len 0x%llx.\n",
+			       (long long)rl->lcn, (long long)rl->length);
+
+		if (rl->lcn >= 0) { 
+			update_full_status(vol,rl->lcn);
+			if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn, 
+						  rl->length)) {
+				ntfs_log_perror("Cluster deallocation failed "
+					       "(%lld, %lld)",
+						(long long)rl->lcn, 
+						(long long)rl->length);
+				goto out;
+			}
+			nr_freed += rl->length ; 
+		}
+	}
+
+	ret = 0;
+out:
+	vol->free_clusters += nr_freed; 
+	if (vol->free_clusters > vol->nr_clusters)
+		ntfs_log_error("Too many free clusters (%lld > %lld)!",
+			       (long long)vol->free_clusters, 
+			       (long long)vol->nr_clusters);
+	return ret;
+}
+
+/*
+ *		Basic cluster run free
+ *	Returns 0 if successful
+ */
+
+int ntfs_cluster_free_basic(ntfs_volume *vol, s64 lcn, s64 count)
+{
+	s64 nr_freed = 0;
+	int ret = -1;
+
+	ntfs_log_trace("Entering.\n");
+	ntfs_log_trace("Dealloc lcn 0x%llx, len 0x%llx.\n",
+			       (long long)lcn, (long long)count);
+
+	if (lcn >= 0) { 
+		update_full_status(vol,lcn);
+		if (ntfs_bitmap_clear_run(vol->lcnbmp_na, lcn, 
+						  count)) {
+			ntfs_log_perror("Cluster deallocation failed "
+				       "(%lld, %lld)",
+					(long long)lcn, 
+					(long long)count);
+				goto out;
+		}
+		nr_freed += count; 
+	}
+	ret = 0;
+out:
+	vol->free_clusters += nr_freed;
+	if (vol->free_clusters > vol->nr_clusters)
+		ntfs_log_error("Too many free clusters (%lld > %lld)!",
+			       (long long)vol->free_clusters, 
+			       (long long)vol->nr_clusters);
+	return ret;
+}
+
+/**
+ * ntfs_cluster_free - free clusters on an ntfs volume
+ * @vol:	mounted ntfs volume on which to free the clusters
+ * @na:		attribute whose runlist describes the clusters to free
+ * @start_vcn:	vcn in @rl at which to start freeing clusters
+ * @count:	number of clusters to free or -1 for all clusters
+ *
+ * Free @count clusters starting at the cluster @start_vcn in the runlist
+ * described by the attribute @na from the mounted ntfs volume @vol.
+ *
+ * If @count is -1, all clusters from @start_vcn to the end of the runlist
+ * are deallocated.
+ *
+ * On success return the number of deallocated clusters (not counting sparse
+ * clusters) and on error return -1 with errno set to the error code.
+ */
+int ntfs_cluster_free(ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, s64 count)
+{
+	runlist *rl;
+	s64 delta, to_free, nr_freed = 0;
+	int ret = -1;
+
+	if (!vol || !vol->lcnbmp_na || !na || start_vcn < 0 ||
+			(count < 0 && count != -1)) {
+		ntfs_log_trace("Invalid arguments!\n");
+		errno = EINVAL;
+		return -1;
+	}
+	
+	ntfs_log_enter("Entering for inode 0x%llx, attr 0x%x, count 0x%llx, "
+		       "vcn 0x%llx.\n", (unsigned long long)na->ni->mft_no,
+		       na->type, (long long)count, (long long)start_vcn);
+
+	rl = ntfs_attr_find_vcn(na, start_vcn);
+	if (!rl) {
+		if (errno == ENOENT)
+			ret = 0;
+		goto leave;
+	}
+
+	if (rl->lcn < 0 && rl->lcn != LCN_HOLE) {
+		errno = EIO;
+		ntfs_log_perror("%s: Unexpected lcn (%lld)", __FUNCTION__, 
+				(long long)rl->lcn);
+		goto leave;
+	}
+
+	/* Find the starting cluster inside the run that needs freeing. */
+	delta = start_vcn - rl->vcn;
+
+	/* The number of clusters in this run that need freeing. */
+	to_free = rl->length - delta;
+	if (count >= 0 && to_free > count)
+		to_free = count;
+
+	if (rl->lcn != LCN_HOLE) {
+		/* Do the actual freeing of the clusters in this run. */
+		update_full_status(vol,rl->lcn + delta);
+		if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn + delta,
+					  to_free))
+			goto leave;
+		nr_freed = to_free;
+	} 
+
+	/* Go to the next run and adjust the number of clusters left to free. */
+	++rl;
+	if (count >= 0)
+		count -= to_free;
+
+	/*
+	 * Loop over the remaining runs, using @count as a capping value, and
+	 * free them.
+	 */
+	for (; rl->length && count != 0; ++rl) {
+		// FIXME: Need to try ntfs_attr_map_runlist() for attribute
+		//	  list support! (AIA)
+		if (rl->lcn < 0 && rl->lcn != LCN_HOLE) {
+			// FIXME: Eeek! We need rollback! (AIA)
+			errno = EIO;
+			ntfs_log_perror("%s: Invalid lcn (%lli)", 
+					__FUNCTION__, (long long)rl->lcn);
+			goto out;
+		}
+
+		/* The number of clusters in this run that need freeing. */
+		to_free = rl->length;
+		if (count >= 0 && to_free > count)
+			to_free = count;
+
+		if (rl->lcn != LCN_HOLE) {
+			update_full_status(vol,rl->lcn);
+			if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn,
+					to_free)) {
+				// FIXME: Eeek! We need rollback! (AIA)
+				ntfs_log_perror("%s: Clearing bitmap run failed",
+						__FUNCTION__);
+				goto out;
+			}
+			nr_freed += to_free;
+		}
+
+		if (count >= 0)
+			count -= to_free;
+	}
+
+	if (count != -1 && count != 0) {
+		// FIXME: Eeek! BUG()
+		errno = EIO;
+		ntfs_log_perror("%s: count still not zero (%lld)", __FUNCTION__,
+			       (long long)count);
+		goto out;
+	}
+
+	ret = nr_freed;
+out:
+	vol->free_clusters += nr_freed ; 
+	if (vol->free_clusters > vol->nr_clusters)
+		ntfs_log_error("Too many free clusters (%lld > %lld)!",
+			       (long long)vol->free_clusters, 
+			       (long long)vol->nr_clusters);
+leave:	
+	ntfs_log_leave("\n");
+	return ret;
+}
diff --git a/libntfs-3g/libntfs-3g.pc b/libntfs-3g/libntfs-3g.pc
new file mode 100755
index 0000000000000000000000000000000000000000..637b3032e2926ad5d16d0ff670b54422f6c7127f
--- /dev/null
+++ b/libntfs-3g/libntfs-3g.pc
@@ -0,0 +1,10 @@
+prefix=/usr/local
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: libntfs-3g
+Description: NTFS-3G Read/Write Driver Library
+Version: 2015.3.14
+Cflags: -I${includedir}
+Libs:  -lpthread -L${libdir} -lntfs-3g
diff --git a/libntfs-3g/libntfs-3g.pc.in b/libntfs-3g/libntfs-3g.pc.in
new file mode 100755
index 0000000000000000000000000000000000000000..5f2fea73177c10e00ebee41d068a39dfdc0866b9
--- /dev/null
+++ b/libntfs-3g/libntfs-3g.pc.in
@@ -0,0 +1,10 @@
+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
diff --git a/libntfs-3g/libntfs-3g.script.so b/libntfs-3g/libntfs-3g.script.so
new file mode 100755
index 0000000000000000000000000000000000000000..736d8eb05d23f2586f3e9ee1b1088c0495033669
--- /dev/null
+++ b/libntfs-3g/libntfs-3g.script.so
@@ -0,0 +1,2 @@
+
+GROUP ( /lib/libntfs-3g.so  )
diff --git a/libntfs-3g/libntfs-3g.script.so.in b/libntfs-3g/libntfs-3g.script.so.in
new file mode 100755
index 0000000000000000000000000000000000000000..d050cfa3dd645a1fb6dd9c6f039fb4bf0a6e47d7
--- /dev/null
+++ b/libntfs-3g/libntfs-3g.script.so.in
@@ -0,0 +1,2 @@
+@OUTPUT_FORMAT@
+GROUP ( @rootlibdir@/libntfs-3g.so  )
diff --git a/libntfs-3g/logfile.c b/libntfs-3g/logfile.c
new file mode 100755
index 0000000000000000000000000000000000000000..336bdd282aa7e0b7a1ec806d69a85f07cf602659
--- /dev/null
+++ b/libntfs-3g/logfile.c
@@ -0,0 +1,744 @@
+/**
+ * logfile.c - NTFS journal handling. Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2002-2005 Anton Altaparmakov
+ * Copyright (c) 2005 Yura Pakhuchiy
+ * Copyright (c) 2005-2009 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
+ * 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
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "attrib.h"
+#include "debug.h"
+#include "logfile.h"
+#include "volume.h"
+#include "mst.h"
+#include "logging.h"
+#include "misc.h"
+
+/**
+ * ntfs_check_restart_page_header - check the page header for consistency
+ * @rp:		restart page header to check
+ * @pos:	position in logfile at which the restart page header resides
+ *
+ * Check the restart page header @rp for consistency and return TRUE if it is
+ * consistent and FALSE otherwise.
+ *
+ * This function only needs NTFS_BLOCK_SIZE bytes in @rp, i.e. it does not
+ * require the full restart page.
+ */
+static BOOL ntfs_check_restart_page_header(RESTART_PAGE_HEADER *rp, s64 pos)
+{
+	u32 logfile_system_page_size, logfile_log_page_size;
+	u16 ra_ofs, usa_count, usa_ofs, usa_end = 0;
+	BOOL have_usa = TRUE;
+
+	ntfs_log_trace("Entering.\n");
+	/*
+	 * If the system or log page sizes are smaller than the ntfs block size
+	 * or either is not a power of 2 we cannot handle this log file.
+	 */
+	logfile_system_page_size = le32_to_cpu(rp->system_page_size);
+	logfile_log_page_size = le32_to_cpu(rp->log_page_size);
+	if (logfile_system_page_size < NTFS_BLOCK_SIZE ||
+			logfile_log_page_size < NTFS_BLOCK_SIZE ||
+			logfile_system_page_size &
+			(logfile_system_page_size - 1) ||
+			logfile_log_page_size & (logfile_log_page_size - 1)) {
+		ntfs_log_error("$LogFile uses unsupported page size.\n");
+		return FALSE;
+	}
+	/*
+	 * We must be either at !pos (1st restart page) or at pos = system page
+	 * size (2nd restart page).
+	 */
+	if (pos && pos != logfile_system_page_size) {
+		ntfs_log_error("Found restart area in incorrect "
+				"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_le16(1))
+			 || (rp->minor_ver != const_cpu_to_le16(1)))
+	   && ((rp->major_ver != const_cpu_to_le16(2))
+			 || (rp->minor_ver != const_cpu_to_le16(0)))) {
+		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));
+		return FALSE;
+	}
+	/*
+	 * If chkdsk has been run the restart page may not be protected by an
+	 * update sequence array.
+	 */
+	if (ntfs_is_chkd_record(rp->magic) && !le16_to_cpu(rp->usa_count)) {
+		have_usa = FALSE;
+		goto skip_usa_checks;
+	}
+	/* Verify the size of the update sequence array. */
+	usa_count = 1 + (logfile_system_page_size >> NTFS_BLOCK_SIZE_BITS);
+	if (usa_count != le16_to_cpu(rp->usa_count)) {
+		ntfs_log_error("$LogFile restart page specifies "
+				"inconsistent update sequence array count.\n");
+		return FALSE;
+	}
+	/* 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 < sizeof(RESTART_PAGE_HEADER) ||
+			usa_end > NTFS_BLOCK_SIZE - sizeof(u16)) {
+		ntfs_log_error("$LogFile restart page specifies "
+				"inconsistent update sequence array offset.\n");
+		return FALSE;
+	}
+skip_usa_checks:
+	/*
+	 * Verify the position of the restart area.  It must be:
+	 *	- aligned to 8-byte boundary,
+	 *	- after the update sequence array, and
+	 *	- within the system page size.
+	 */
+	ra_ofs = le16_to_cpu(rp->restart_area_offset);
+	if (ra_ofs & 7 || (have_usa ? ra_ofs < usa_end :
+			ra_ofs < sizeof(RESTART_PAGE_HEADER)) ||
+			ra_ofs > logfile_system_page_size) {
+		ntfs_log_error("$LogFile restart page specifies "
+				"inconsistent restart area offset.\n");
+		return FALSE;
+	}
+	/*
+	 * Only restart pages modified by chkdsk are allowed to have chkdsk_lsn
+	 * set.
+	 */
+	if (!ntfs_is_chkd_record(rp->magic) && sle64_to_cpu(rp->chkdsk_lsn)) {
+		ntfs_log_error("$LogFile restart page is not modified "
+				"by chkdsk but a chkdsk LSN is specified.\n");
+		return FALSE;
+	}
+	ntfs_log_trace("Done.\n");
+	return TRUE;
+}
+
+/**
+ * ntfs_check_restart_area - check the restart area for consistency
+ * @rp:		restart page whose restart area to check
+ *
+ * Check the restart area of the restart page @rp for consistency and return
+ * TRUE if it is consistent and FALSE otherwise.
+ *
+ * This function assumes that the restart page header has already been
+ * consistency checked.
+ *
+ * This function only needs NTFS_BLOCK_SIZE bytes in @rp, i.e. it does not
+ * require the full restart page.
+ */
+static BOOL ntfs_check_restart_area(RESTART_PAGE_HEADER *rp)
+{
+	u64 file_size;
+	RESTART_AREA *ra;
+	u16 ra_ofs, ra_len, ca_ofs;
+	u8 fs_bits;
+
+	ntfs_log_trace("Entering.\n");
+	ra_ofs = le16_to_cpu(rp->restart_area_offset);
+	ra = (RESTART_AREA*)((u8*)rp + ra_ofs);
+	/*
+	 * Everything before ra->file_size must be before the first word
+	 * protected by an update sequence number.  This ensures that it is
+	 * safe to access ra->client_array_offset.
+	 */
+	if (ra_ofs + offsetof(RESTART_AREA, file_size) >
+			NTFS_BLOCK_SIZE - sizeof(u16)) {
+		ntfs_log_error("$LogFile restart area specifies "
+				"inconsistent file offset.\n");
+		return FALSE;
+	}
+	/*
+	 * Now that we can access ra->client_array_offset, make sure everything
+	 * up to the log client array is before the first word protected by an
+	 * update sequence number.  This ensures we can access all of the
+	 * restart area elements safely.  Also, the client array offset must be
+	 * aligned to an 8-byte boundary.
+	 */
+	ca_ofs = le16_to_cpu(ra->client_array_offset);
+	if (((ca_ofs + 7) & ~7) != ca_ofs ||
+			ra_ofs + ca_ofs > (u16)(NTFS_BLOCK_SIZE -
+			sizeof(u16))) {
+		ntfs_log_error("$LogFile restart area specifies "
+				"inconsistent client array offset.\n");
+		return FALSE;
+	}
+	/*
+	 * The restart area must end within the system page size both when
+	 * calculated manually and as specified by ra->restart_area_length.
+	 * Also, the calculated length must not exceed the specified length.
+	 */
+	ra_len = ca_ofs + le16_to_cpu(ra->log_clients) *
+			sizeof(LOG_CLIENT_RECORD);
+	if ((u32)(ra_ofs + ra_len) > le32_to_cpu(rp->system_page_size) ||
+			(u32)(ra_ofs + le16_to_cpu(ra->restart_area_length)) >
+			le32_to_cpu(rp->system_page_size) ||
+			ra_len > le16_to_cpu(ra->restart_area_length)) {
+		ntfs_log_error("$LogFile restart area is out of bounds "
+				"of the system page size specified by the "
+				"restart page header and/or the specified "
+				"restart area length is inconsistent.\n");
+		return FALSE;
+	}
+	/*
+	 * The ra->client_free_list and ra->client_in_use_list must be either
+	 * LOGFILE_NO_CLIENT or less than ra->log_clients or they are
+	 * overflowing the client array.
+	 */
+	if ((ra->client_free_list != LOGFILE_NO_CLIENT &&
+			le16_to_cpu(ra->client_free_list) >=
+			le16_to_cpu(ra->log_clients)) ||
+			(ra->client_in_use_list != LOGFILE_NO_CLIENT &&
+			le16_to_cpu(ra->client_in_use_list) >=
+			le16_to_cpu(ra->log_clients))) {
+		ntfs_log_error("$LogFile restart area specifies "
+				"overflowing client free and/or in use lists.\n");
+		return FALSE;
+	}
+	/*
+	 * Check ra->seq_number_bits against ra->file_size for consistency.
+	 * We cannot just use ffs() because the file size is not a power of 2.
+	 */
+	file_size = (u64)sle64_to_cpu(ra->file_size);
+	fs_bits = 0;
+	while (file_size) {
+		file_size >>= 1;
+		fs_bits++;
+	}
+	if (le32_to_cpu(ra->seq_number_bits) != (u32)(67 - fs_bits)) {
+		ntfs_log_error("$LogFile restart area specifies "
+				"inconsistent sequence number bits.\n");
+		return FALSE;
+	}
+	/* The log record header length must be a multiple of 8. */
+	if (((le16_to_cpu(ra->log_record_header_length) + 7) & ~7) !=
+			le16_to_cpu(ra->log_record_header_length)) {
+		ntfs_log_error("$LogFile restart area specifies "
+				"inconsistent log record header length.\n");
+		return FALSE;
+	}
+	/* Ditto for the log page data offset. */
+	if (((le16_to_cpu(ra->log_page_data_offset) + 7) & ~7) !=
+			le16_to_cpu(ra->log_page_data_offset)) {
+		ntfs_log_error("$LogFile restart area specifies "
+				"inconsistent log page data offset.\n");
+		return FALSE;
+	}
+	ntfs_log_trace("Done.\n");
+	return TRUE;
+}
+
+/**
+ * ntfs_check_log_client_array - check the log client array for consistency
+ * @rp:		restart page whose log client array to check
+ *
+ * Check the log client array of the restart page @rp for consistency and
+ * return TRUE if it is consistent and FALSE otherwise.
+ *
+ * This function assumes that the restart page header and the restart area have
+ * already been consistency checked.
+ *
+ * Unlike ntfs_check_restart_page_header() and ntfs_check_restart_area(), this
+ * function needs @rp->system_page_size bytes in @rp, i.e. it requires the full
+ * restart page and the page must be multi sector transfer deprotected.
+ */
+static BOOL ntfs_check_log_client_array(RESTART_PAGE_HEADER *rp)
+{
+	RESTART_AREA *ra;
+	LOG_CLIENT_RECORD *ca, *cr;
+	u16 nr_clients, idx;
+	BOOL in_free_list, idx_is_first;
+
+	ntfs_log_trace("Entering.\n");
+	ra = (RESTART_AREA*)((u8*)rp + le16_to_cpu(rp->restart_area_offset));
+	ca = (LOG_CLIENT_RECORD*)((u8*)ra +
+			le16_to_cpu(ra->client_array_offset));
+	/*
+	 * Check the ra->client_free_list first and then check the
+	 * ra->client_in_use_list.  Check each of the log client records in
+	 * each of the lists and check that the array does not overflow the
+	 * ra->log_clients value.  Also keep track of the number of records
+	 * visited as there cannot be more than ra->log_clients records and
+	 * that way we detect eventual loops in within a list.
+	 */
+	nr_clients = le16_to_cpu(ra->log_clients);
+	idx = le16_to_cpu(ra->client_free_list);
+	in_free_list = TRUE;
+check_list:
+	for (idx_is_first = TRUE; idx != LOGFILE_NO_CLIENT_CPU; nr_clients--,
+			idx = le16_to_cpu(cr->next_client)) {
+		if (!nr_clients || idx >= le16_to_cpu(ra->log_clients))
+			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. */
+		if (idx_is_first) {
+			if (cr->prev_client != LOGFILE_NO_CLIENT)
+				goto err_out;
+			idx_is_first = FALSE;
+		}
+	}
+	/* Switch to and check the in use list if we just did the free list. */
+	if (in_free_list) {
+		in_free_list = FALSE;
+		idx = le16_to_cpu(ra->client_in_use_list);
+		goto check_list;
+	}
+	ntfs_log_trace("Done.\n");
+	return TRUE;
+err_out:
+	ntfs_log_error("$LogFile log client array is corrupt.\n");
+	return FALSE;
+}
+
+/**
+ * ntfs_check_and_load_restart_page - check the restart page for consistency
+ * @log_na:	opened ntfs attribute for journal $LogFile
+ * @rp:		restart page to check
+ * @pos:	position in @log_na at which the restart page resides
+ * @wrp:       [OUT] copy of the multi sector transfer deprotected restart page
+ * @lsn:       [OUT] set to the current logfile lsn on success
+ *
+ * Check the restart page @rp for consistency and return 0 if it is consistent
+ * and errno otherwise.  The restart page may have been modified by chkdsk in
+ * which case its magic is CHKD instead of RSTR.
+ *
+ * This function only needs NTFS_BLOCK_SIZE bytes in @rp, i.e. it does not
+ * require the full restart page.
+ *
+ * If @wrp is not NULL, on success, *@wrp will point to a buffer containing a
+ * copy of the complete multi sector transfer deprotected page.  On failure,
+ * *@wrp is undefined.
+ *
+ * Similarly, if @lsn is not NULL, on success *@lsn will be set to the current
+ * logfile lsn according to this restart page.  On failure, *@lsn is undefined.
+ *
+ * The following error codes are defined:
+ *     EINVAL - The restart page is inconsistent.
+ *     ENOMEM - Not enough memory to load the restart page.
+ *     EIO    - Failed to reading from $LogFile.
+ */
+static int ntfs_check_and_load_restart_page(ntfs_attr *log_na,
+		RESTART_PAGE_HEADER *rp, s64 pos, RESTART_PAGE_HEADER **wrp,
+		LSN *lsn)
+{
+	RESTART_AREA *ra;
+	RESTART_PAGE_HEADER *trp;
+	int err;
+
+	ntfs_log_trace("Entering.\n");
+	/* Check the restart page header for consistency. */
+	if (!ntfs_check_restart_page_header(rp, pos)) {
+		/* Error output already done inside the function. */
+		return EINVAL;
+	}
+	/* Check the restart area for consistency. */
+	if (!ntfs_check_restart_area(rp)) {
+		/* Error output already done inside the function. */
+		return EINVAL;
+	}
+	ra = (RESTART_AREA*)((u8*)rp + le16_to_cpu(rp->restart_area_offset));
+	/*
+	 * Allocate a buffer to store the whole restart page so we can multi
+	 * sector transfer deprotect it.
+	 */
+	trp = ntfs_malloc(le32_to_cpu(rp->system_page_size));
+	if (!trp)
+		return errno;
+	/*
+	 * Read the whole of the restart page into the buffer.  If it fits
+	 * completely inside @rp, just copy it from there.  Otherwise read it
+	 * from disk.
+	 */
+	if (le32_to_cpu(rp->system_page_size) <= NTFS_BLOCK_SIZE)
+		memcpy(trp, rp, le32_to_cpu(rp->system_page_size));
+	else if (ntfs_attr_pread(log_na, pos,
+			le32_to_cpu(rp->system_page_size), trp) !=
+			le32_to_cpu(rp->system_page_size)) {
+		err = errno;
+		ntfs_log_error("Failed to read whole restart page into the "
+				"buffer.\n");
+		if (err != ENOMEM)
+			err = EIO;
+		goto err_out;
+	}
+	/*
+	 * Perform the multi sector transfer deprotection on the buffer if the
+	 * restart page is protected.
+	 */
+	if ((!ntfs_is_chkd_record(trp->magic) || le16_to_cpu(trp->usa_count))
+			&& ntfs_mst_post_read_fixup((NTFS_RECORD*)trp,
+			le32_to_cpu(rp->system_page_size))) {
+		/*
+		 * A multi sector tranfer error was detected.  We only need to
+		 * abort if the restart page contents exceed the multi sector
+		 * transfer fixup of the first sector.
+		 */
+		if (le16_to_cpu(rp->restart_area_offset) +
+				le16_to_cpu(ra->restart_area_length) >
+				NTFS_BLOCK_SIZE - (int)sizeof(u16)) {
+			ntfs_log_error("Multi sector transfer error "
+				   "detected in $LogFile restart page.\n");
+			err = EINVAL;
+			goto err_out;
+		}
+	}
+	/*
+	 * If the restart page is modified by chkdsk or there are no active
+	 * logfile clients, the logfile is consistent.  Otherwise, need to
+	 * check the log client records for consistency, too.
+	 */
+	err = 0;
+	if (ntfs_is_rstr_record(rp->magic) &&
+			ra->client_in_use_list != LOGFILE_NO_CLIENT) {
+		if (!ntfs_check_log_client_array(trp)) {
+			err = EINVAL;
+			goto err_out;
+		}
+	}
+	if (lsn) {
+		if (ntfs_is_rstr_record(rp->magic))
+			*lsn = sle64_to_cpu(ra->current_lsn);
+		else /* if (ntfs_is_chkd_record(rp->magic)) */
+			*lsn = sle64_to_cpu(rp->chkdsk_lsn);
+	}
+	ntfs_log_trace("Done.\n");
+	if (wrp)
+		*wrp = trp;
+	else {
+err_out:
+		free(trp);
+	}
+	return err;
+}
+
+/**
+ * ntfs_check_logfile - check in the journal if the volume is consistent
+ * @log_na:	ntfs attribute of loaded journal $LogFile to check
+ * @rp:         [OUT] on success this is a copy of the current restart page
+ *
+ * Check the $LogFile journal for consistency and return TRUE if it is
+ * consistent and FALSE if not.  On success, the current restart page is
+ * returned in *@rp.  Caller must call ntfs_free(*@rp) when finished with it.
+ *
+ * At present we only check the two restart pages and ignore the log record
+ * pages.
+ *
+ * Note that the MstProtected flag is not set on the $LogFile inode and hence
+ * when reading pages they are not deprotected.  This is because we do not know
+ * if the $LogFile was created on a system with a different page size to ours
+ * yet and mst deprotection would fail if our page size is smaller.
+ */
+BOOL ntfs_check_logfile(ntfs_attr *log_na, RESTART_PAGE_HEADER **rp)
+{
+	s64 size, pos;
+	LSN rstr1_lsn, rstr2_lsn;
+	ntfs_volume *vol = log_na->ni->vol;
+	u8 *kaddr = NULL;
+	RESTART_PAGE_HEADER *rstr1_ph = NULL;
+	RESTART_PAGE_HEADER *rstr2_ph = NULL;
+	int log_page_size, err;
+	BOOL logfile_is_empty = TRUE;
+	u8 log_page_bits;
+
+	ntfs_log_trace("Entering.\n");
+	/* An empty $LogFile must have been clean before it got emptied. */
+	if (NVolLogFileEmpty(vol))
+		goto is_empty;
+	size = log_na->data_size;
+	/* Make sure the file doesn't exceed the maximum allowed size. */
+	if (size > (s64)MaxLogFileSize)
+		size = MaxLogFileSize;
+	log_page_size = DefaultLogPageSize;
+	/*
+	 * Use generic_ffs() instead of ffs() to enable the compiler to
+	 * optimize log_page_size and log_page_bits into constants.
+	 */
+	log_page_bits = ffs(log_page_size) - 1;
+	size &= ~(log_page_size - 1);
+
+	/*
+	 * Ensure the log file is big enough to store at least the two restart
+	 * pages and the minimum number of log record pages.
+	 */
+	if (size < log_page_size * 2 || (size - log_page_size * 2) >>
+			log_page_bits < MinLogRecordPages) {
+		ntfs_log_error("$LogFile is too small.\n");
+		return FALSE;
+	}
+	/* Allocate memory for restart page. */
+	kaddr = ntfs_malloc(NTFS_BLOCK_SIZE);
+	if (!kaddr)
+		return FALSE;
+	/*
+	 * Read through the file looking for a restart page.  Since the restart
+	 * page header is at the beginning of a page we only need to search at
+	 * what could be the beginning of a page (for each page size) rather
+	 * than scanning the whole file byte by byte.  If all potential places
+	 * contain empty and uninitialized records, the log file can be assumed
+	 * to be empty.
+	 */
+	for (pos = 0; pos < size; pos <<= 1) {
+		/*
+		 * Read first NTFS_BLOCK_SIZE bytes of potential restart page.
+		 */
+		if (ntfs_attr_pread(log_na, pos, NTFS_BLOCK_SIZE, kaddr) !=
+				NTFS_BLOCK_SIZE) {
+			ntfs_log_error("Failed to read first NTFS_BLOCK_SIZE "
+					"bytes of potential restart page.\n");
+			goto err_out;
+		}
+
+		/*
+		 * A non-empty block means the logfile is not empty while an
+		 * empty block after a non-empty block has been encountered
+		 * means we are done.
+		 */
+		if (!ntfs_is_empty_recordp((le32*)kaddr))
+			logfile_is_empty = FALSE;
+		else if (!logfile_is_empty)
+			break;
+		/*
+		 * A log record page means there cannot be a restart page after
+		 * this so no need to continue searching.
+		 */
+		if (ntfs_is_rcrd_recordp((le32*)kaddr))
+			break;
+		/* If not a (modified by chkdsk) restart page, continue. */
+		if (!ntfs_is_rstr_recordp((le32*)kaddr) &&
+				!ntfs_is_chkd_recordp((le32*)kaddr)) {
+			if (!pos)
+				pos = NTFS_BLOCK_SIZE >> 1;
+			continue;
+		}
+		/*
+		 * Check the (modified by chkdsk) restart page for consistency
+		 * and get a copy of the complete multi sector transfer
+		 * deprotected restart page.
+		 */
+		err = ntfs_check_and_load_restart_page(log_na,
+				(RESTART_PAGE_HEADER*)kaddr, pos,
+				!rstr1_ph ? &rstr1_ph : &rstr2_ph,
+				!rstr1_ph ? &rstr1_lsn : &rstr2_lsn);
+		if (!err) {
+			/*
+			 * If we have now found the first (modified by chkdsk)
+			 * restart page, continue looking for the second one.
+			 */
+			if (!pos) {
+				pos = NTFS_BLOCK_SIZE >> 1;
+				continue;
+			}
+			/*
+			 * We have now found the second (modified by chkdsk)
+			 * restart page, so we can stop looking.
+			 */
+			break;
+		}
+		/*
+		 * Error output already done inside the function.  Note, we do
+		 * not abort if the restart page was invalid as we might still
+		 * find a valid one further in the file.
+		 */
+		if (err != EINVAL)
+		      goto err_out;
+		/* Continue looking. */
+		if (!pos)
+			pos = NTFS_BLOCK_SIZE >> 1;
+	}
+	if (kaddr) {
+		free(kaddr);
+		kaddr = NULL;
+	}
+	if (logfile_is_empty) {
+		NVolSetLogFileEmpty(vol);
+is_empty:
+		ntfs_log_trace("Done.  ($LogFile is empty.)\n");
+		return TRUE;
+	}
+	if (!rstr1_ph) {
+		if (rstr2_ph)
+			ntfs_log_error("BUG: rstr2_ph isn't NULL!\n");
+		ntfs_log_error("Did not find any restart pages in "
+			   "$LogFile and it was not empty.\n");
+		return FALSE;
+	}
+	/* If both restart pages were found, use the more recent one. */
+	if (rstr2_ph) {
+		/*
+		 * If the second restart area is more recent, switch to it.
+		 * Otherwise just throw it away.
+		 */
+		if (rstr2_lsn > rstr1_lsn) {
+			ntfs_log_debug("Using second restart page as it is more "
+					"recent.\n");
+			free(rstr1_ph);
+			rstr1_ph = rstr2_ph;
+			/* rstr1_lsn = rstr2_lsn; */
+		} else {
+			ntfs_log_debug("Using first restart page as it is more "
+					"recent.\n");
+			free(rstr2_ph);
+		}
+		rstr2_ph = NULL;
+	}
+	/* All consistency checks passed. */
+	if (rp)
+		*rp = rstr1_ph;
+	else
+		free(rstr1_ph);
+	ntfs_log_trace("Done.\n");
+	return TRUE;
+err_out:
+	free(kaddr);
+	free(rstr1_ph);
+	free(rstr2_ph);
+	return FALSE;
+}
+
+/**
+ * ntfs_is_logfile_clean - check in the journal if the volume is clean
+ * @log_na:	ntfs attribute of loaded journal $LogFile to check
+ * @rp:         copy of the current restart page
+ *
+ * Analyze the $LogFile journal and return TRUE if it indicates the volume was
+ * shutdown cleanly and FALSE if not.
+ *
+ * At present we only look at the two restart pages and ignore the log record
+ * pages.  This is a little bit crude in that there will be a very small number
+ * of cases where we think that a volume is dirty when in fact it is clean.
+ * This should only affect volumes that have not been shutdown cleanly but did
+ * not have any pending, non-check-pointed i/o, i.e. they were completely idle
+ * at least for the five seconds preceding the unclean shutdown.
+ *
+ * This function assumes that the $LogFile journal has already been consistency
+ * checked by a call to ntfs_check_logfile() and in particular if the $LogFile
+ * is empty this function requires that NVolLogFileEmpty() is true otherwise an
+ * empty volume will be reported as dirty.
+ */
+BOOL ntfs_is_logfile_clean(ntfs_attr *log_na, RESTART_PAGE_HEADER *rp)
+{
+	RESTART_AREA *ra;
+
+	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");
+		return TRUE;
+	}
+	if (!rp) {
+		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");
+		return FALSE;
+	}
+
+	ra = (RESTART_AREA*)((u8*)rp + le16_to_cpu(rp->restart_area_offset));
+	/*
+	 * If the $LogFile has active clients, i.e. it is open, and we do not
+	 * have the RESTART_VOLUME_IS_CLEAN bit set in the restart area flags,
+	 * we assume there was an unclean shutdown.
+	 */
+	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));
+		return FALSE;
+	}
+	/* $LogFile indicates a clean shutdown. */
+	ntfs_log_trace("$LogFile indicates a clean shutdown\n");
+	return TRUE;
+}
+
+/**
+ * ntfs_empty_logfile - empty the contents of the $LogFile journal
+ * @na:		ntfs attribute of journal $LogFile to empty
+ *
+ * Empty the contents of the $LogFile journal @na and return 0 on success and
+ * -1 on error.
+ *
+ * This function assumes that the $LogFile journal has already been consistency
+ * checked by a call to ntfs_check_logfile() and that ntfs_is_logfile_clean()
+ * has been used to ensure that the $LogFile is clean.
+ */
+int ntfs_empty_logfile(ntfs_attr *na)
+{
+	s64 pos, count;
+	char buf[NTFS_BUF_SIZE];
+
+	ntfs_log_trace("Entering.\n");
+	
+	if (NVolLogFileEmpty(na->ni->vol))
+		return 0;
+
+	if (!NAttrNonResident(na)) {
+		errno = EIO;
+		ntfs_log_perror("Resident $LogFile $DATA attribute");
+		return -1;
+	}
+
+	memset(buf, -1, NTFS_BUF_SIZE);
+
+	pos = 0;
+	while ((count = na->data_size - 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 != -1)
+				errno = EIO;
+			return -1;
+		}
+		pos += count;
+	}
+
+	NVolSetLogFileEmpty(na->ni->vol);
+	
+	return 0;
+}
diff --git a/libntfs-3g/logging.c b/libntfs-3g/logging.c
new file mode 100755
index 0000000000000000000000000000000000000000..8f3d7bc5434fdcac013016707c9d7c022da6177f
--- /dev/null
+++ b/libntfs-3g/logging.c
@@ -0,0 +1,661 @@
+/**
+ * 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
+ *
+ * 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
+ */
+#define LOG_TAG "NTFS-3G"
+
+#include <utils/Log.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_SYSLOG_H
+#include <syslog.h>
+#endif
+
+#include "logging.h"
+#include "misc.h"
+
+#ifndef PATH_SEP
+#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
+
+#if PLATFORM_SDK_VERSION >= 16
+#define LOGV(fmt,args...) ALOGV(fmt,##args)
+#define LOGD(fmt,args...) ALOGD(fmt,##args)
+#define LOGI(fmt,args...) ALOGI(fmt,##args)
+#define LOGW(fmt,args...) ALOGW(fmt,##args)
+#define LOGE(fmt,args...) ALOGE(fmt,##args)
+#endif
+
+/**
+ * struct ntfs_logging - Control info for the logging system
+ * @levels:	Bitfield of logging levels
+ * @flags:	Flags which affect the output style
+ * @handler:	Function to perform the actual logging
+ */
+struct ntfs_logging {
+	u32 levels;
+	u32 flags;
+	ntfs_log_handler *handler BROKEN_GCC_FORMAT_ATTRIBUTE;
+};
+
+/**
+ * ntfs_log
+ * This struct controls all the logging within the library and tools.
+ */
+static struct ntfs_logging ntfs_log = {
+#ifdef DEBUG
+	NTFS_LOG_LEVEL_DEBUG | NTFS_LOG_LEVEL_TRACE | NTFS_LOG_LEVEL_ENTER |
+	NTFS_LOG_LEVEL_LEAVE |
+#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 |
+	NTFS_LOG_LEVEL_PROGRESS,
+	NTFS_LOG_FLAG_ONLYNAME,
+#ifdef DEBUG
+	ntfs_log_handler_outerr
+#else
+	ntfs_log_handler_null
+#endif
+};
+
+
+/**
+ * ntfs_log_get_levels - Get a list of the current logging levels
+ *
+ * Find out which logging levels are enabled.
+ *
+ * Returns:  Log levels in a 32-bit field
+ */
+u32 ntfs_log_get_levels(void)
+{
+	return ntfs_log.levels;
+}
+
+/**
+ * ntfs_log_set_levels - Enable extra logging levels
+ * @levels:	32-bit field of log levels to set
+ *
+ * Enable one or more logging levels.
+ * The logging levels are named: NTFS_LOG_LEVEL_*.
+ *
+ * Returns:  Log levels that were enabled before the call
+ */
+u32 ntfs_log_set_levels(u32 levels)
+{
+	u32 old;
+	old = ntfs_log.levels;
+	ntfs_log.levels |= levels;
+	return old;
+}
+
+/**
+ * ntfs_log_clear_levels - Disable some logging levels
+ * @levels:	32-bit field of log levels to clear
+ *
+ * Disable one or more logging levels.
+ * The logging levels are named: NTFS_LOG_LEVEL_*.
+ *
+ * Returns:  Log levels that were enabled before the call
+ */
+u32 ntfs_log_clear_levels(u32 levels)
+{
+	u32 old;
+	old = ntfs_log.levels;
+	ntfs_log.levels &= (~levels);
+	return old;
+}
+
+
+/**
+ * ntfs_log_get_flags - Get a list of logging style flags
+ *
+ * Find out which logging flags are enabled.
+ *
+ * Returns:  Logging flags in a 32-bit field
+ */
+u32 ntfs_log_get_flags(void)
+{
+	return ntfs_log.flags;
+}
+
+/**
+ * ntfs_log_set_flags - Enable extra logging style flags
+ * @flags:	32-bit field of logging flags to set
+ *
+ * Enable one or more logging flags.
+ * The log flags are named: NTFS_LOG_LEVEL_*.
+ *
+ * Returns:  Logging flags that were enabled before the call
+ */
+u32 ntfs_log_set_flags(u32 flags)
+{
+	u32 old;
+	old = ntfs_log.flags;
+	ntfs_log.flags |= flags;
+	return old;
+}
+
+/**
+ * ntfs_log_clear_flags - Disable some logging styles
+ * @flags:	32-bit field of logging flags to clear
+ *
+ * Disable one or more logging flags.
+ * The log flags are named: NTFS_LOG_LEVEL_*.
+ *
+ * Returns:  Logging flags that were enabled before the call
+ */
+u32 ntfs_log_clear_flags(u32 flags)
+{
+	u32 old;
+	old = ntfs_log.flags;
+	ntfs_log.flags &= (~flags);
+	return old;
+}
+
+
+/**
+ * ntfs_log_get_stream - Default output streams for logging levels
+ * @level:	Log level
+ *
+ * By default, urgent messages are sent to "stderr".
+ * Other messages are sent to "stdout".
+ *
+ * Returns:  "string"  Prefix to be used
+ */
+static FILE * ntfs_log_get_stream(u32 level)
+{
+	FILE *stream;
+
+	switch (level) {
+		case NTFS_LOG_LEVEL_INFO:
+		case NTFS_LOG_LEVEL_QUIET:
+		case NTFS_LOG_LEVEL_PROGRESS:
+		case NTFS_LOG_LEVEL_VERBOSE:
+			stream = stdout;
+			break;
+
+		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:
+		case NTFS_LOG_LEVEL_PERROR:
+		default:
+			stream = stderr;
+			break;
+	}
+
+	return stream;
+}
+
+/**
+ * ntfs_log_get_prefix - Default prefixes for logging levels
+ * @level:	Log level to be prefixed
+ *
+ * Prefixing the logging output can make it easier to parse.
+ *
+ * Returns:  "string"  Prefix to be used
+ */
+static const char * ntfs_log_get_prefix(u32 level)
+{
+	const char *prefix;
+
+	switch (level) {
+		case NTFS_LOG_LEVEL_DEBUG:
+			prefix = "DEBUG: ";
+			break;
+		case NTFS_LOG_LEVEL_TRACE:
+			prefix = "TRACE: ";
+			break;
+		case NTFS_LOG_LEVEL_QUIET:
+			prefix = "QUIET: ";
+			break;
+		case NTFS_LOG_LEVEL_INFO:
+			prefix = "INFO: ";
+			break;
+		case NTFS_LOG_LEVEL_VERBOSE:
+			prefix = "VERBOSE: ";
+			break;
+		case NTFS_LOG_LEVEL_PROGRESS:
+			prefix = "PROGRESS: ";
+			break;
+		case NTFS_LOG_LEVEL_WARNING:
+			prefix = "WARNING: ";
+			break;
+		case NTFS_LOG_LEVEL_ERROR:
+			prefix = "ERROR: ";
+			break;
+		case NTFS_LOG_LEVEL_PERROR:
+			prefix = "ERROR: ";
+			break;
+		case NTFS_LOG_LEVEL_CRITICAL:
+			prefix = "CRITICAL: ";
+			break;
+		default:
+			prefix = "";
+			break;
+	}
+
+	return prefix;
+}
+
+
+/**
+ * ntfs_log_set_handler - Provide an alternate logging handler
+ * @handler:	function to perform the logging
+ *
+ * This alternate handler will be called for all future logging requests.
+ * If no @handler is specified, logging will revert to the default handler.
+ */
+void ntfs_log_set_handler(ntfs_log_handler *handler)
+{
+	if (handler) {
+		ntfs_log.handler = handler;
+#ifdef HAVE_SYSLOG_H
+		if (handler == ntfs_log_handler_syslog)
+			openlog("ntfs-3g", LOG_PID, LOG_USER);
+#endif
+	} else
+		ntfs_log.handler = ntfs_log_handler_null;
+}
+
+/**
+ * ntfs_log_redirect - Pass on the request to the real handler
+ * @function:	Function in which the log line occurred
+ * @file:	File in which the log line occurred
+ * @line:	Line number on which the log line occurred
+ * @level:	Level at which the line is logged
+ * @data:	User specified data, possibly specific to a handler
+ * @format:	printf-style formatting string
+ * @...:	Arguments to be formatted
+ *
+ * This is just a redirector function.  The arguments are simply passed to the
+ * main logging handler (as defined in the global logging struct @ntfs_log).
+ *
+ * Returns:  -1  Error occurred
+ *            0  Message wasn't logged
+ *          num  Number of output characters
+ */
+int ntfs_log_redirect(const char *function, const char *file,
+	int line, u32 level, void *data, const char *format, ...)
+{
+    #if 1
+	va_list args;
+    char szBuf[512];
+
+	va_start(args, format);
+    vsnprintf(szBuf, sizeof(szBuf)/2, format, args);
+	va_end(args);
+	snprintf(&(szBuf[sizeof(szBuf)/2]), sizeof(szBuf)/2, 
+		", file: %s, function: %s, line: %d", file, function, line);
+	__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, szBuf);
+	return 0;
+    #else
+	int olderr = errno;
+	int ret;
+	va_list args;
+
+	if (!(ntfs_log.levels & level))		/* Don't log this message */
+		return 0;
+
+	va_start(args, format);
+	errno = olderr;
+	ret = ntfs_log.handler(function, file, line, level, data, format, args);
+	va_end(args);
+
+	errno = olderr;
+	return ret;
+	#endif
+}
+
+
+/**
+ * ntfs_log_handler_syslog - syslog logging handler
+ * @function:	Function in which the log line occurred
+ * @file:	File in which the log line occurred
+ * @line:	Line number on which the log line occurred
+ * @level:	Level at which the line is logged
+ * @data:	User specified data, possibly specific to a handler
+ * @format:	printf-style formatting string
+ * @args:	Arguments to be formatted
+ *
+ * A simple syslog logging handler.  Ignores colors.
+ *
+ * Returns:  -1  Error occurred
+ *            0  Message wasn't logged
+ *          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)
+{
+	char logbuf[LOG_LINE_LEN];
+	int ret, 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 ((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:
+	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
+ * @file:	File in which the log line occurred
+ * @line:	Line number on which the log line occurred
+ * @level:	Level at which the line is logged
+ * @data:	User specified data, possibly specific to a handler
+ * @format:	printf-style formatting string
+ * @args:	Arguments to be formatted
+ *
+ * A simple logging handler.  This is where the log line is finally displayed.
+ * It is more likely that you will want to set the handler to either
+ * ntfs_log_handler_outerr or ntfs_log_handler_stderr.
+ *
+ * Note: For this handler, @data is a pointer to a FILE output stream.
+ *       If @data is NULL, nothing will be displayed.
+ *
+ * Returns:  -1  Error occurred
+ *            0  Message wasn't logged
+ *          num  Number of output characters
+ */
+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;
+
+	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;
+	}
+	
+	for (i = 0; i < tab; i++)
+		ret += fprintf(stream, " ");
+#endif	
+	if ((ntfs_log.flags & NTFS_LOG_FLAG_ONLYNAME) &&
+	    (strchr(file, PATH_SEP)))		/* Abbreviate the filename */
+		file = strrchr(file, PATH_SEP) + 1;
+
+	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) || (level & NTFS_LOG_LEVEL_ENTER))
+		ret += fprintf(stream, "%s(): ", function);
+
+	ret += vfprintf(stream, format, args);
+
+	if (level & NTFS_LOG_LEVEL_PERROR)
+		ret += fprintf(stream, ": %s\n", strerror(olderr));
+
+#ifdef DEBUG
+	if (level == NTFS_LOG_LEVEL_ENTER)
+		tab++;
+#endif	
+	fflush(stream);
+	errno = olderr;
+	return ret;
+}
+
+/**
+ * ntfs_log_handler_null - Null logging handler (no output)
+ * @function:	Function in which the log line occurred
+ * @file:	File in which the log line occurred
+ * @line:	Line number on which the log line occurred
+ * @level:	Level at which the line is logged
+ * @data:	User specified data, possibly specific to a handler
+ * @format:	printf-style formatting string
+ * @args:	Arguments to be formatted
+ *
+ * This handler produces no output.  It provides a way to temporarily disable
+ * logging, without having to change the levels and flags.
+ *
+ * Returns:  0  Message wasn't logged
+ */
+int ntfs_log_handler_null(const char *function __attribute__((unused)), const char *file __attribute__((unused)),
+	int line __attribute__((unused)), u32 level __attribute__((unused)), void *data __attribute__((unused)),
+	const char *format __attribute__((unused)), va_list args __attribute__((unused)))
+{
+	return 0;
+}
+
+/**
+ * ntfs_log_handler_stdout - All logs go to stdout
+ * @function:	Function in which the log line occurred
+ * @file:	File in which the log line occurred
+ * @line:	Line number on which the log line occurred
+ * @level:	Level at which the line is logged
+ * @data:	User specified data, possibly specific to a handler
+ * @format:	printf-style formatting string
+ * @args:	Arguments to be formatted
+ *
+ * Display a log message to stdout.
+ *
+ * Note: For this handler, @data is a pointer to a FILE output stream.
+ *       If @data is NULL, then stdout will be used.
+ *
+ * Note: This function calls ntfs_log_handler_fprintf to do the main work.
+ *
+ * Returns:  -1  Error occurred
+ *            0  Message wasn't logged
+ *          num  Number of output characters
+ */
+int ntfs_log_handler_stdout(const char *function, const char *file,
+	int line, u32 level, void *data, const char *format, va_list args)
+{
+	if (!data)
+		data = stdout;
+
+	return ntfs_log_handler_fprintf(function, file, line, level, data, format, args);
+}
+
+/**
+ * ntfs_log_handler_outerr - Logs go to stdout/stderr depending on level
+ * @function:	Function in which the log line occurred
+ * @file:	File in which the log line occurred
+ * @line:	Line number on which the log line occurred
+ * @level:	Level at which the line is logged
+ * @data:	User specified data, possibly specific to a handler
+ * @format:	printf-style formatting string
+ * @args:	Arguments to be formatted
+ *
+ * Display a log message.  The output stream will be determined by the log
+ * level.
+ *
+ * Note: For this handler, @data is a pointer to a FILE output stream.
+ *       If @data is NULL, the function ntfs_log_get_stream will be called
+ *
+ * Note: This function calls ntfs_log_handler_fprintf to do the main work.
+ *
+ * Returns:  -1  Error occurred
+ *            0  Message wasn't logged
+ *          num  Number of output characters
+ */
+int ntfs_log_handler_outerr(const char *function, const char *file,
+	int line, u32 level, void *data, const char *format, va_list args)
+{
+	if (!data)
+		data = ntfs_log_get_stream(level);
+
+	return ntfs_log_handler_fprintf(function, file, line, level, data, format, args);
+}
+
+/**
+ * ntfs_log_handler_stderr - All logs go to stderr
+ * @function:	Function in which the log line occurred
+ * @file:	File in which the log line occurred
+ * @line:	Line number on which the log line occurred
+ * @level:	Level at which the line is logged
+ * @data:	User specified data, possibly specific to a handler
+ * @format:	printf-style formatting string
+ * @args:	Arguments to be formatted
+ *
+ * Display a log message to stderr.
+ *
+ * Note: For this handler, @data is a pointer to a FILE output stream.
+ *       If @data is NULL, then stdout will be used.
+ *
+ * Note: This function calls ntfs_log_handler_fprintf to do the main work.
+ *
+ * Returns:  -1  Error occurred
+ *            0  Message wasn't logged
+ *          num  Number of output characters
+ */
+int ntfs_log_handler_stderr(const char *function, const char *file,
+	int line, u32 level, void *data, const char *format, va_list args)
+{
+	if (!data)
+		data = stderr;
+
+	return ntfs_log_handler_fprintf(function, file, line, level, data, format, args);
+}
+
+
+/**
+ * ntfs_log_parse_option - Act upon command line options
+ * @option:	Option flag
+ *
+ * Delegate some of the work of parsing the command line.  All the options begin
+ * with "--log-".  Options cause log levels to be enabled in @ntfs_log (the
+ * global logging structure).
+ *
+ * Note: The "colour" option changes the logging handler.
+ *
+ * Returns:  TRUE  Option understood
+ *          FALSE  Invalid log option
+ */
+BOOL ntfs_log_parse_option(const char *option)
+{
+	if (strcmp(option, "--log-debug") == 0) {
+		ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG);
+		return TRUE;
+	} else if (strcmp(option, "--log-verbose") == 0) {
+		ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
+		return TRUE;
+	} else if (strcmp(option, "--log-quiet") == 0) {
+		ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
+		return TRUE;
+	} else if (strcmp(option, "--log-trace") == 0) {
+		ntfs_log_set_levels(NTFS_LOG_LEVEL_TRACE);
+		return TRUE;
+	}
+
+	ntfs_log_debug("Unknown logging option '%s'\n", option);
+	return FALSE;
+}
+
diff --git a/libntfs-3g/mft.c b/libntfs-3g/mft.c
new file mode 100755
index 0000000000000000000000000000000000000000..ac4c610b5e5b0ff1a0bb4fd6fe15b2d89a119f67
--- /dev/null
+++ b/libntfs-3g/mft.c
@@ -0,0 +1,1946 @@
+/**
+ * mft.c - Mft record handling code. Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2000-2004 Anton Altaparmakov
+ * Copyright (c) 2004-2005 Richard Russon
+ * Copyright (c) 2004-2008 Szabolcs Szakacsits
+ * Copyright (c)      2005 Yura Pakhuchiy
+ * Copyright (c)      2014 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_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#include <time.h>
+
+#include "compat.h"
+#include "types.h"
+#include "device.h"
+#include "debug.h"
+#include "bitmap.h"
+#include "attrib.h"
+#include "inode.h"
+#include "volume.h"
+#include "layout.h"
+#include "lcnalloc.h"
+#include "mft.h"
+#include "logging.h"
+#include "misc.h"
+
+/**
+ * ntfs_mft_records_read - read records from the mft from disk
+ * @vol:	volume to read from
+ * @mref:	starting mft record number to read
+ * @count:	number of mft records to read
+ * @b:		output data buffer
+ *
+ * Read @count mft records starting at @mref from volume @vol into buffer
+ * @b. Return 0 on success or -1 on error, with errno set to the error
+ * code.
+ *
+ * If any of the records exceed the initialized size of the $MFT/$DATA
+ * attribute, i.e. they cannot possibly be allocated mft records, assume this
+ * is a bug and return error code ESPIPE.
+ *
+ * The read mft records are mst deprotected and are hence ready to use. The
+ * caller should check each record with is_baad_record() in case mst
+ * deprotection failed.
+ *
+ * NOTE: @b has to be at least of size @count * vol->mft_record_size.
+ */
+int ntfs_mft_records_read(const ntfs_volume *vol, const MFT_REF mref,
+		const s64 count, MFT_RECORD *b)
+{
+	s64 br;
+	VCN m;
+
+	ntfs_log_trace("inode %llu\n", (unsigned long long)MREF(mref));
+	
+	if (!vol || !vol->mft_na || !b || count < 0) {
+		errno = EINVAL;
+		ntfs_log_perror("%s: b=%p  count=%lld  mft=%llu", __FUNCTION__,
+			b, (long long)count, (unsigned long long)MREF(mref));
+		return -1;
+	}
+	m = MREF(mref);
+	/* Refuse to read non-allocated mft records. */
+	if (m + count > vol->mft_na->initialized_size >>
+			vol->mft_record_size_bits) {
+		errno = ESPIPE;
+		ntfs_log_perror("Trying to read non-allocated mft records "
+				"(%lld > %lld)", (long long)m + count,
+				(long long)vol->mft_na->initialized_size >>
+				vol->mft_record_size_bits);
+		return -1;
+	}
+	br = ntfs_attr_mst_pread(vol->mft_na, m << vol->mft_record_size_bits,
+			count, vol->mft_record_size, b);
+	if (br != count) {
+		if (br != -1)
+			errno = EIO;
+		ntfs_log_perror("Failed to read of MFT, mft=%llu count=%lld "
+				"br=%lld", (long long)m, (long long)count,
+				(long long)br);
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * ntfs_mft_records_write - write mft records to disk
+ * @vol:	volume to write to
+ * @mref:	starting mft record number to write
+ * @count:	number of mft records to write
+ * @b:		data buffer containing the mft records to write
+ *
+ * Write @count mft records starting at @mref from data buffer @b to volume
+ * @vol. Return 0 on success or -1 on error, with errno set to the error code.
+ *
+ * If any of the records exceed the initialized size of the $MFT/$DATA
+ * attribute, i.e. they cannot possibly be allocated mft records, assume this
+ * is a bug and return error code ESPIPE.
+ *
+ * Before the mft records are written, they are mst protected. After the write,
+ * they are deprotected again, thus resulting in an increase in the update
+ * sequence number inside the data buffer @b.
+ *
+ * If any mft records are written which are also represented in the mft mirror
+ * $MFTMirr, we make a copy of the relevant parts of the data buffer @b into a
+ * temporary buffer before we do the actual write. Then if at least one mft
+ * record was successfully written, we write the appropriate mft records from
+ * the copied buffer to the mft mirror, too.
+ */
+int ntfs_mft_records_write(const ntfs_volume *vol, const MFT_REF mref,
+		const s64 count, MFT_RECORD *b)
+{
+	s64 bw;
+	VCN m;
+	void *bmirr = NULL;
+	int cnt = 0, res = 0;
+
+	if (!vol || !vol->mft_na || vol->mftmirr_size <= 0 || !b || count < 0) {
+		errno = EINVAL;
+		return -1;
+	}
+	m = MREF(mref);
+	/* Refuse to write non-allocated mft records. */
+	if (m + count > vol->mft_na->initialized_size >>
+			vol->mft_record_size_bits) {
+		errno = ESPIPE;
+		ntfs_log_perror("Trying to write non-allocated mft records "
+				"(%lld > %lld)", (long long)m + count,
+				(long long)vol->mft_na->initialized_size >>
+				vol->mft_record_size_bits);
+		return -1;
+	}
+	if (m < vol->mftmirr_size) {
+		if (!vol->mftmirr_na) {
+			errno = EINVAL;
+			return -1;
+		}
+		cnt = vol->mftmirr_size - m;
+		if (cnt > count)
+			cnt = count;
+		bmirr = ntfs_malloc(cnt * vol->mft_record_size);
+		if (!bmirr)
+			return -1;
+		memcpy(bmirr, b, cnt * vol->mft_record_size);
+	}
+	bw = ntfs_attr_mst_pwrite(vol->mft_na, m << vol->mft_record_size_bits,
+			count, vol->mft_record_size, b);
+	if (bw != count) {
+		if (bw != -1)
+			errno = EIO;
+		if (bw >= 0)
+			ntfs_log_debug("Error: partial write while writing $Mft "
+					"record(s)!\n");
+		else
+			ntfs_log_perror("Error writing $Mft record(s)");
+		res = errno;
+	}
+	if (bmirr && bw > 0) {
+		if (bw < cnt)
+			cnt = bw;
+		bw = ntfs_attr_mst_pwrite(vol->mftmirr_na,
+				m << vol->mft_record_size_bits, cnt,
+				vol->mft_record_size, bmirr);
+		if (bw != cnt) {
+			if (bw != -1)
+				errno = EIO;
+			ntfs_log_debug("Error: failed to sync $MFTMirr! Run "
+					"chkdsk.\n");
+			res = errno;
+		}
+	}
+	free(bmirr);
+	if (!res)
+		return res;
+	errno = res;
+	return -1;
+}
+
+int ntfs_mft_record_check(const ntfs_volume *vol, const MFT_REF mref, 
+			  MFT_RECORD *m)
+{			  
+	ATTR_RECORD *a;
+	int ret = -1;
+	
+	if (!ntfs_is_file_record(m->magic)) {
+		if (!NVolNoFixupWarn(vol))
+			ntfs_log_error("Record %llu has no FILE magic (0x%x)\n",
+				(unsigned long long)MREF(mref),
+				(int)le32_to_cpu(*(le32*)m));
+		goto err_out;
+	}
+	
+	if (le32_to_cpu(m->bytes_allocated) != vol->mft_record_size) {
+		ntfs_log_error("Record %llu has corrupt allocation size "
+			       "(%u <> %u)\n", (unsigned long long)MREF(mref),
+			       vol->mft_record_size,
+			       le32_to_cpu(m->bytes_allocated));
+		goto err_out;
+	}
+	
+	a = (ATTR_RECORD *)((char *)m + le16_to_cpu(m->attrs_offset));
+	if (p2n(a) < p2n(m) || (char *)a > (char *)m + vol->mft_record_size) {
+		ntfs_log_error("Record %llu is corrupt\n",
+			       (unsigned long long)MREF(mref));
+		goto err_out;
+	}
+	
+	ret = 0;
+err_out:
+	if (ret)
+		errno = EIO;
+	return ret;
+}
+
+/**
+ * ntfs_file_record_read - read a FILE record from the mft from disk
+ * @vol:	volume to read from
+ * @mref:	mft reference specifying mft record to read
+ * @mrec:	address of pointer in which to return the mft record
+ * @attr:	address of pointer in which to return the first attribute
+ *
+ * Read a FILE record from the mft of @vol from the storage medium. @mref
+ * specifies the mft record to read, including the sequence number, which can
+ * be 0 if no sequence number checking is to be performed.
+ *
+ * The function allocates a buffer large enough to hold the mft record and
+ * reads the record into the buffer (mst deprotecting it in the process).
+ * *@mrec is then set to point to the buffer.
+ *
+ * If @attr is not NULL, *@attr is set to point to the first attribute in the
+ * mft record, i.e. *@attr is a pointer into *@mrec.
+ *
+ * Return 0 on success, or -1 on error, with errno set to the error code.
+ *
+ * The read mft record is checked for having the magic FILE,
+ * and for having a matching sequence number (if MSEQNO(*@mref) != 0).
+ * If either of these fails, -1 is returned and errno is set to EIO. If you get
+ * this, but you still want to read the mft record (e.g. in order to correct
+ * it), use ntfs_mft_record_read() directly.
+ *
+ * Note: Caller has to free *@mrec when finished.
+ *
+ * Note: We do not check if the mft record is flagged in use. The caller can
+ *	 check if desired.
+ */
+int ntfs_file_record_read(const ntfs_volume *vol, const MFT_REF mref,
+		MFT_RECORD **mrec, ATTR_RECORD **attr)
+{
+	MFT_RECORD *m;
+
+	if (!vol || !mrec) {
+		errno = EINVAL;
+		ntfs_log_perror("%s: mrec=%p", __FUNCTION__, mrec);
+		return -1;
+	}
+	
+	m = *mrec;
+	if (!m) {
+		m = ntfs_malloc(vol->mft_record_size);
+		if (!m)
+			return -1;
+	}
+	if (ntfs_mft_record_read(vol, mref, m))
+		goto err_out;
+
+	if (ntfs_mft_record_check(vol, mref, m))
+		goto err_out;
+	
+	if (MSEQNO(mref) && MSEQNO(mref) != le16_to_cpu(m->sequence_number)) {
+		ntfs_log_error("Record %llu has wrong SeqNo (%d <> %d)\n",
+			       (unsigned long long)MREF(mref), MSEQNO(mref),
+			       le16_to_cpu(m->sequence_number));
+		errno = EIO;
+		goto err_out;
+	}
+	*mrec = m;
+	if (attr)
+		*attr = (ATTR_RECORD*)((char*)m + le16_to_cpu(m->attrs_offset));
+	return 0;
+err_out:
+	if (m != *mrec)
+		free(m);
+	return -1;
+}
+
+/**
+ * ntfs_mft_record_layout - layout an mft record into a memory buffer
+ * @vol:	volume to which the mft record will belong
+ * @mref:	mft reference specifying the mft record number
+ * @mrec:	destination buffer of size >= @vol->mft_record_size bytes
+ *
+ * Layout an empty, unused mft record with the mft reference @mref into the
+ * buffer @m.  The volume @vol is needed because the mft record structure was
+ * modified in NTFS 3.1 so we need to know which volume version this mft record
+ * will be used on.
+ *
+ * On success return 0 and on error return -1 with errno set to the error code.
+ */
+int ntfs_mft_record_layout(const ntfs_volume *vol, const MFT_REF mref,
+		MFT_RECORD *mrec)
+{
+	ATTR_RECORD *a;
+
+	if (!vol || !mrec) {
+		errno = EINVAL;
+		ntfs_log_perror("%s: mrec=%p", __FUNCTION__, mrec);
+		return -1;
+	}
+	/* Aligned to 2-byte boundary. */
+	if (vol->major_ver < 3 || (vol->major_ver == 3 && !vol->minor_ver))
+		mrec->usa_ofs = cpu_to_le16((sizeof(MFT_RECORD_OLD) + 1) & ~1);
+	else {
+		/* Abort if mref is > 32 bits. */
+		if (MREF(mref) & 0x0000ffff00000000ull) {
+			errno = ERANGE;
+			ntfs_log_perror("Mft reference exceeds 32 bits");
+			return -1;
+		}
+		mrec->usa_ofs = cpu_to_le16((sizeof(MFT_RECORD) + 1) & ~1);
+		/*
+		 * Set the NTFS 3.1+ specific fields while we know that the
+		 * volume version is 3.1+.
+		 */
+		mrec->reserved = cpu_to_le16(0);
+		mrec->mft_record_number = cpu_to_le32(MREF(mref));
+	}
+	mrec->magic = magic_FILE;
+	if (vol->mft_record_size >= NTFS_BLOCK_SIZE)
+		mrec->usa_count = cpu_to_le16(vol->mft_record_size /
+				NTFS_BLOCK_SIZE + 1);
+	else {
+		mrec->usa_count = cpu_to_le16(1);
+		ntfs_log_error("Sector size is bigger than MFT record size.  "
+				"Setting usa_count to 1.  If Windows chkdsk "
+				"reports this as corruption, please email %s "
+				"stating that you saw this message and that "
+				"the file system created was corrupt.  "
+				"Thank you.\n", NTFS_DEV_LIST);
+	}
+	/* Set the update sequence number to 1. */
+	*(u16*)((u8*)mrec + le16_to_cpu(mrec->usa_ofs)) = cpu_to_le16(1);
+	mrec->lsn = cpu_to_le64(0ull);
+	mrec->sequence_number = cpu_to_le16(1);
+	mrec->link_count = cpu_to_le16(0);
+	/* Aligned to 8-byte boundary. */
+	mrec->attrs_offset = cpu_to_le16((le16_to_cpu(mrec->usa_ofs) +
+			(le16_to_cpu(mrec->usa_count) << 1) + 7) & ~7);
+	mrec->flags = cpu_to_le16(0);
+	/*
+	 * Using attrs_offset plus eight bytes (for the termination attribute),
+	 * aligned to 8-byte boundary.
+	 */
+	mrec->bytes_in_use = cpu_to_le32((le16_to_cpu(mrec->attrs_offset) + 8 +
+			7) & ~7);
+	mrec->bytes_allocated = cpu_to_le32(vol->mft_record_size);
+	mrec->base_mft_record = cpu_to_le64((MFT_REF)0);
+	mrec->next_attr_instance = cpu_to_le16(0);
+	a = (ATTR_RECORD*)((u8*)mrec + le16_to_cpu(mrec->attrs_offset));
+	a->type = AT_END;
+	a->length = cpu_to_le32(0);
+	/* Finally, clear the unused part of the mft record. */
+	memset((u8*)a + 8, 0, vol->mft_record_size - ((u8*)a + 8 - (u8*)mrec));
+	return 0;
+}
+
+/**
+ * ntfs_mft_record_format - format an mft record on an ntfs volume
+ * @vol:	volume on which to format the mft record
+ * @mref:	mft reference specifying mft record to format
+ *
+ * Format the mft record with the mft reference @mref in $MFT/$DATA, i.e. lay
+ * out an empty, unused mft record in memory and write it to the volume @vol.
+ *
+ * On success return 0 and on error return -1 with errno set to the error code.
+ */
+int ntfs_mft_record_format(const ntfs_volume *vol, const MFT_REF mref)
+{
+	MFT_RECORD *m;
+	int ret = -1;
+
+	ntfs_log_enter("Entering\n");
+	
+	m = ntfs_calloc(vol->mft_record_size);
+	if (!m)
+		goto out;
+	
+	if (ntfs_mft_record_layout(vol, mref, m))
+		goto free_m;
+	
+	if (ntfs_mft_record_write(vol, mref, m))
+		goto free_m;
+	
+	ret = 0;
+free_m:
+	free(m);
+out:	
+	ntfs_log_leave("\n");
+	return ret;
+}
+
+static const char *es = "  Leaving inconsistent metadata.  Run chkdsk.";
+
+/**
+ * ntfs_ffz - Find the first unset (zero) bit in a word
+ * @word:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static inline unsigned int ntfs_ffz(unsigned int word)
+{
+	return ffs(~word) - 1;
+}
+
+static int ntfs_is_mft(ntfs_inode *ni)
+{
+	if (ni && ni->mft_no == FILE_MFT)
+		return 1;
+	return 0;
+}
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE 4096
+#endif
+
+#define RESERVED_MFT_RECORDS   64
+
+/**
+ * ntfs_mft_bitmap_find_free_rec - find a free mft record in the mft bitmap
+ * @vol:	volume on which to search for a free mft record
+ * @base_ni:	open base inode if allocating an extent mft record or NULL
+ *
+ * Search for a free mft record in the mft bitmap attribute on the ntfs volume
+ * @vol.
+ *
+ * If @base_ni is NULL start the search at the default allocator position.
+ *
+ * If @base_ni is not NULL start the search at the mft record after the base
+ * mft record @base_ni.
+ *
+ * Return the free mft record on success and -1 on error with errno set to the
+ * error code.  An error code of ENOSPC means that there are no free mft
+ * records in the currently initialized mft bitmap.
+ */
+static int ntfs_mft_bitmap_find_free_rec(ntfs_volume *vol, ntfs_inode *base_ni)
+{
+	s64 pass_end, ll, data_pos, pass_start, ofs, bit;
+	ntfs_attr *mftbmp_na;
+	u8 *buf, *byte;
+	unsigned int size;
+	u8 pass, b;
+	int ret = -1;
+
+	ntfs_log_enter("Entering\n");
+	
+	mftbmp_na = vol->mftbmp_na;
+	/*
+	 * Set the end of the pass making sure we do not overflow the mft
+	 * bitmap.
+	 */
+	size = PAGE_SIZE;
+	pass_end = vol->mft_na->allocated_size >> vol->mft_record_size_bits;
+	ll = mftbmp_na->initialized_size << 3;
+	if (pass_end > ll)
+		pass_end = ll;
+	pass = 1;
+	if (!base_ni)
+		data_pos = vol->mft_data_pos;
+	else
+		data_pos = base_ni->mft_no + 1;
+	if (data_pos < RESERVED_MFT_RECORDS)
+		data_pos = RESERVED_MFT_RECORDS;
+	if (data_pos >= pass_end) {
+		data_pos = RESERVED_MFT_RECORDS;
+		pass = 2;
+		/* This happens on a freshly formatted volume. */
+		if (data_pos >= pass_end) {
+			errno = ENOSPC;
+			goto leave;
+		}
+	}
+	if (ntfs_is_mft(base_ni)) {
+		data_pos = 0;
+		pass = 2;
+	}
+	pass_start = data_pos;
+	buf = ntfs_malloc(PAGE_SIZE);
+	if (!buf)
+		goto leave;
+	
+	ntfs_log_debug("Starting bitmap search: pass %u, pass_start 0x%llx, "
+			"pass_end 0x%llx, data_pos 0x%llx.\n", pass,
+			(long long)pass_start, (long long)pass_end,
+			(long long)data_pos);
+#ifdef DEBUG
+	byte = NULL;
+	b = 0;
+#endif
+	/* Loop until a free mft record is found. */
+	for (; pass <= 2; size = PAGE_SIZE) {
+		/* Cap size to pass_end. */
+		ofs = data_pos >> 3;
+		ll = ((pass_end + 7) >> 3) - ofs;
+		if (size > ll)
+			size = ll;
+		ll = ntfs_attr_pread(mftbmp_na, ofs, size, buf);
+		if (ll < 0) {
+			ntfs_log_perror("Failed to read $MFT bitmap");
+			free(buf);
+			goto leave;
+		}
+		ntfs_log_debug("Read 0x%llx bytes.\n", (long long)ll);
+		/* If we read at least one byte, search @buf for a zero bit. */
+		if (ll) {
+			size = ll << 3;
+			bit = data_pos & 7;
+			data_pos &= ~7ull;
+			ntfs_log_debug("Before inner for loop: size 0x%x, "
+					"data_pos 0x%llx, bit 0x%llx, "
+					"*byte 0x%hhx, b %u.\n", size,
+					(long long)data_pos, (long long)bit,
+					byte ? *byte : -1, b);
+			for (; bit < size && data_pos + bit < pass_end;
+					bit &= ~7ull, bit += 8) {
+				/* 
+				 * If we're extending $MFT and running out of the first
+				 * mft record (base record) then give up searching since
+				 * no guarantee that the found record will be accessible.
+				 */
+				if (ntfs_is_mft(base_ni) && bit > 400)
+					goto out;
+				
+				byte = buf + (bit >> 3);
+				if (*byte == 0xff)
+					continue;
+				
+				/* Note: ffz() result must be zero based. */
+				b = ntfs_ffz((unsigned long)*byte);
+				if (b < 8 && b >= (bit & 7)) {
+					free(buf);
+					ret = data_pos + (bit & ~7ull) + b;
+					goto leave;
+				}
+			}
+			ntfs_log_debug("After inner for loop: size 0x%x, "
+					"data_pos 0x%llx, bit 0x%llx, "
+					"*byte 0x%hhx, b %u.\n", size,
+					(long long)data_pos, (long long)bit,
+					byte ? *byte : -1, b);
+			data_pos += size;
+			/*
+			 * If the end of the pass has not been reached yet,
+			 * continue searching the mft bitmap for a zero bit.
+			 */
+			if (data_pos < pass_end)
+				continue;
+		}
+		/* Do the next pass. */
+		pass++;
+		if (pass == 2) {
+			/*
+			 * Starting the second pass, in which we scan the first
+			 * part of the zone which we omitted earlier.
+			 */
+			pass_end = pass_start;
+			data_pos = pass_start = RESERVED_MFT_RECORDS;
+			ntfs_log_debug("pass %i, pass_start 0x%llx, pass_end "
+					"0x%llx.\n", pass, (long long)pass_start,
+					(long long)pass_end);
+			if (data_pos >= pass_end)
+				break;
+		}
+	}
+	/* No free mft records in currently initialized mft bitmap. */
+out:	
+	free(buf);
+	errno = ENOSPC;
+leave:
+	ntfs_log_leave("\n");
+	return ret;
+}
+
+static int ntfs_mft_attr_extend(ntfs_attr *na)
+{
+	int ret = STATUS_ERROR;
+	ntfs_log_enter("Entering\n");
+
+	if (!NInoAttrList(na->ni)) {
+		if (ntfs_inode_add_attrlist(na->ni)) {
+			ntfs_log_perror("%s: Can not add attrlist #3", __FUNCTION__);
+			goto out;
+		}
+		/* We can't sync the $MFT inode since its runlist is bogus. */
+		ret = STATUS_KEEP_SEARCHING;
+		goto out;
+	}
+
+	if (ntfs_attr_update_mapping_pairs(na, 0)) {
+		ntfs_log_perror("%s: MP update failed", __FUNCTION__);
+		goto out;
+	}
+	
+	ret = STATUS_OK;
+out:	
+	ntfs_log_leave("\n");
+	return ret;
+}
+
+/**
+ * ntfs_mft_bitmap_extend_allocation_i - see ntfs_mft_bitmap_extend_allocation
+ */
+static int ntfs_mft_bitmap_extend_allocation_i(ntfs_volume *vol)
+{
+	LCN lcn;
+	s64 ll = 0; /* silence compiler warning */
+	ntfs_attr *mftbmp_na;
+	runlist_element *rl, *rl2 = NULL; /* silence compiler warning */
+	ntfs_attr_search_ctx *ctx;
+	MFT_RECORD *m = NULL; /* silence compiler warning */
+	ATTR_RECORD *a = NULL; /* silence compiler warning */
+	int err, mp_size;
+	int ret = STATUS_ERROR;
+	u32 old_alen = 0; /* silence compiler warning */
+	BOOL mp_rebuilt = FALSE;
+	BOOL update_mp = FALSE;
+
+	mftbmp_na = vol->mftbmp_na;
+	/*
+	 * Determine the last lcn of the mft bitmap.  The allocated size of the
+	 * mft bitmap cannot be zero so we are ok to do this.
+	 */
+	rl = ntfs_attr_find_vcn(mftbmp_na, (mftbmp_na->allocated_size - 1) >>
+			vol->cluster_size_bits);
+	if (!rl || !rl->length || rl->lcn < 0) {
+		ntfs_log_error("Failed to determine last allocated "
+				"cluster of mft bitmap attribute.\n");
+		if (rl)
+			errno = EIO;
+		return STATUS_ERROR;
+	}
+	lcn = rl->lcn + rl->length;
+	
+	rl2 = ntfs_cluster_alloc(vol, rl[1].vcn, 1, lcn, DATA_ZONE);
+	if (!rl2) {
+		ntfs_log_error("Failed to allocate a cluster for "
+				"the mft bitmap.\n");
+		return STATUS_ERROR;
+	}
+	rl = ntfs_runlists_merge(mftbmp_na->rl, rl2);
+	if (!rl) {
+		err = errno;
+		ntfs_log_error("Failed to merge runlists for mft "
+				"bitmap.\n");
+		if (ntfs_cluster_free_from_rl(vol, rl2))
+			ntfs_log_error("Failed to deallocate "
+					"cluster.%s\n", es);
+		free(rl2);
+		errno = err;
+		return STATUS_ERROR;
+	}
+	mftbmp_na->rl = rl;
+	ntfs_log_debug("Adding one run to mft bitmap.\n");
+	/* Find the last run in the new runlist. */
+	for (; rl[1].length; rl++)
+		;
+	/*
+	 * Update the attribute record as well.  Note: @rl is the last
+	 * (non-terminator) runlist element of mft bitmap.
+	 */
+	ctx = ntfs_attr_get_search_ctx(mftbmp_na->ni, NULL);
+	if (!ctx)
+		goto undo_alloc;
+
+	if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name,
+			mftbmp_na->name_len, 0, rl[1].vcn, NULL, 0, ctx)) {
+		ntfs_log_error("Failed to find last attribute extent of "
+				"mft bitmap attribute.\n");
+		goto undo_alloc;
+	}
+	m = ctx->mrec;
+	a = ctx->attr;
+	ll = sle64_to_cpu(a->lowest_vcn);
+	rl2 = ntfs_attr_find_vcn(mftbmp_na, ll);
+	if (!rl2 || !rl2->length) {
+		ntfs_log_error("Failed to determine previous last "
+				"allocated cluster of mft bitmap attribute.\n");
+		if (rl2)
+			errno = EIO;
+		goto undo_alloc;
+	}
+	/* Get the size for the new mapping pairs array for this extent. */
+	mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll, INT_MAX);
+	if (mp_size <= 0) {
+		ntfs_log_error("Get size for mapping pairs failed for "
+				"mft bitmap attribute extent.\n");
+		goto undo_alloc;
+	}
+	/* Expand the attribute record if necessary. */
+	old_alen = le32_to_cpu(a->length);
+	if (ntfs_attr_record_resize(m, a, mp_size +
+			le16_to_cpu(a->mapping_pairs_offset))) {
+		ntfs_log_info("extending $MFT bitmap\n");
+		ret = ntfs_mft_attr_extend(vol->mftbmp_na);
+		if (ret == STATUS_OK)
+			goto ok;
+		if (ret == STATUS_ERROR) {
+			ntfs_log_perror("%s: ntfs_mft_attr_extend failed", __FUNCTION__);
+			update_mp = TRUE;
+		}
+		goto undo_alloc;
+	}
+	mp_rebuilt = TRUE;
+	/* Generate the mapping pairs array directly into the attr record. */
+	if (ntfs_mapping_pairs_build(vol, (u8*)a +
+			le16_to_cpu(a->mapping_pairs_offset), mp_size, rl2, ll,
+			NULL)) {
+		ntfs_log_error("Failed to build mapping pairs array for "
+				"mft bitmap attribute.\n");
+		errno = EIO;
+		goto undo_alloc;
+	}
+	/* Update the highest_vcn. */
+	a->highest_vcn = cpu_to_sle64(rl[1].vcn - 1);
+	/*
+	 * We now have extended the mft bitmap allocated_size by one cluster.
+	 * Reflect this in the ntfs_attr structure and the attribute record.
+	 */
+	if (a->lowest_vcn) {
+		/*
+		 * We are not in the first attribute extent, switch to it, but
+		 * first ensure the changes will make it to disk later.
+		 */
+		ntfs_inode_mark_dirty(ctx->ntfs_ino);
+		ntfs_attr_reinit_search_ctx(ctx);
+		if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name,
+				mftbmp_na->name_len, 0, 0, NULL, 0, ctx)) {
+			ntfs_log_error("Failed to find first attribute "
+					"extent of mft bitmap attribute.\n");
+			goto restore_undo_alloc;
+		}
+		a = ctx->attr;
+	}
+ok:
+	mftbmp_na->allocated_size += vol->cluster_size;
+	a->allocated_size = cpu_to_sle64(mftbmp_na->allocated_size);
+	/* Ensure the changes make it to disk. */
+	ntfs_inode_mark_dirty(ctx->ntfs_ino);
+	ntfs_attr_put_search_ctx(ctx);
+	return STATUS_OK;
+
+restore_undo_alloc:
+	err = errno;
+	ntfs_attr_reinit_search_ctx(ctx);
+	if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name,
+			mftbmp_na->name_len, 0, rl[1].vcn, NULL, 0, ctx)) {
+		ntfs_log_error("Failed to find last attribute extent of "
+				"mft bitmap attribute.%s\n", es);
+		ntfs_attr_put_search_ctx(ctx);
+		mftbmp_na->allocated_size += vol->cluster_size;
+		/*
+		 * The only thing that is now wrong is ->allocated_size of the
+		 * base attribute extent which chkdsk should be able to fix.
+		 */
+		errno = err;
+		return STATUS_ERROR;
+	}
+	m = ctx->mrec;
+	a = ctx->attr;
+	a->highest_vcn = cpu_to_sle64(rl[1].vcn - 2);
+	errno = err;
+undo_alloc:
+	err = errno;
+
+	/* Remove the last run from the runlist. */
+	lcn = rl->lcn;
+	rl->lcn = rl[1].lcn;
+	rl->length = 0;
+	
+	/* FIXME: use an ntfs_cluster_free_* function */
+	if (ntfs_bitmap_clear_bit(vol->lcnbmp_na, lcn))
+		ntfs_log_error("Failed to free cluster.%s\n", es);
+	else
+		vol->free_clusters++;
+	if (mp_rebuilt) {
+		if (ntfs_mapping_pairs_build(vol, (u8*)a +
+				le16_to_cpu(a->mapping_pairs_offset),
+				old_alen - le16_to_cpu(a->mapping_pairs_offset),
+				rl2, ll, NULL))
+			ntfs_log_error("Failed to restore mapping "
+					"pairs array.%s\n", es);
+		if (ntfs_attr_record_resize(m, a, old_alen))
+			ntfs_log_error("Failed to restore attribute "
+					"record.%s\n", es);
+		ntfs_inode_mark_dirty(ctx->ntfs_ino);
+	}
+	if (update_mp) {
+		if (ntfs_attr_update_mapping_pairs(vol->mftbmp_na, 0))
+			ntfs_log_perror("%s: MP update failed", __FUNCTION__);
+	}
+	if (ctx)
+		ntfs_attr_put_search_ctx(ctx);
+	errno = err;
+	return ret;
+}
+
+/**
+ * ntfs_mft_bitmap_extend_allocation - extend mft bitmap attribute by a cluster
+ * @vol:	volume on which to extend the mft bitmap attribute
+ *
+ * Extend the mft bitmap attribute on the ntfs volume @vol by one cluster.
+ *
+ * Note:  Only changes allocated_size, i.e. does not touch initialized_size or
+ * data_size.
+ *
+ * Return 0 on success and -1 on error with errno set to the error code.
+ */
+static int ntfs_mft_bitmap_extend_allocation(ntfs_volume *vol)
+{
+	int ret;
+	
+	ntfs_log_enter("Entering\n");
+	ret = ntfs_mft_bitmap_extend_allocation_i(vol);
+	ntfs_log_leave("\n");
+	return ret;
+}
+/**
+ * ntfs_mft_bitmap_extend_initialized - extend mft bitmap initialized data
+ * @vol:	volume on which to extend the mft bitmap attribute
+ *
+ * Extend the initialized portion of the mft bitmap attribute on the ntfs
+ * volume @vol by 8 bytes.
+ *
+ * Note:  Only changes initialized_size and data_size, i.e. requires that
+ * allocated_size is big enough to fit the new initialized_size.
+ *
+ * Return 0 on success and -1 on error with errno set to the error code.
+ */
+static int ntfs_mft_bitmap_extend_initialized(ntfs_volume *vol)
+{
+	s64 old_data_size, old_initialized_size, ll;
+	ntfs_attr *mftbmp_na;
+	ntfs_attr_search_ctx *ctx;
+	ATTR_RECORD *a;
+	int err;
+	int ret = -1;
+
+	ntfs_log_enter("Entering\n");
+	
+	mftbmp_na = vol->mftbmp_na;
+	ctx = ntfs_attr_get_search_ctx(mftbmp_na->ni, NULL);
+	if (!ctx)
+		goto out;
+
+	if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name,
+			mftbmp_na->name_len, 0, 0, NULL, 0, ctx)) {
+		ntfs_log_error("Failed to find first attribute extent of "
+				"mft bitmap attribute.\n");
+		err = errno;
+		goto put_err_out;
+	}
+	a = ctx->attr;
+	old_data_size = mftbmp_na->data_size;
+	old_initialized_size = mftbmp_na->initialized_size;
+	mftbmp_na->initialized_size += 8;
+	a->initialized_size = cpu_to_sle64(mftbmp_na->initialized_size);
+	if (mftbmp_na->initialized_size > mftbmp_na->data_size) {
+		mftbmp_na->data_size = mftbmp_na->initialized_size;
+		a->data_size = cpu_to_sle64(mftbmp_na->data_size);
+	}
+	/* Ensure the changes make it to disk. */
+	ntfs_inode_mark_dirty(ctx->ntfs_ino);
+	ntfs_attr_put_search_ctx(ctx);
+	/* Initialize the mft bitmap attribute value with zeroes. */
+	ll = 0;
+	ll = ntfs_attr_pwrite(mftbmp_na, old_initialized_size, 8, &ll);
+	if (ll == 8) {
+		ntfs_log_debug("Wrote eight initialized bytes to mft bitmap.\n");
+		vol->free_mft_records += (8 * 8); 
+		ret = 0;
+		goto out;
+	}
+	ntfs_log_error("Failed to write to mft bitmap.\n");
+	err = errno;
+	if (ll >= 0)
+		err = EIO;
+	/* Try to recover from the error. */
+	ctx = ntfs_attr_get_search_ctx(mftbmp_na->ni, NULL);
+	if (!ctx)
+		goto err_out;
+
+	if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name,
+			mftbmp_na->name_len, 0, 0, NULL, 0, ctx)) {
+		ntfs_log_error("Failed to find first attribute extent of "
+				"mft bitmap attribute.%s\n", es);
+put_err_out:
+		ntfs_attr_put_search_ctx(ctx);
+		goto err_out;
+	}
+	a = ctx->attr;
+	mftbmp_na->initialized_size = old_initialized_size;
+	a->initialized_size = cpu_to_sle64(old_initialized_size);
+	if (mftbmp_na->data_size != old_data_size) {
+		mftbmp_na->data_size = old_data_size;
+		a->data_size = cpu_to_sle64(old_data_size);
+	}
+	ntfs_inode_mark_dirty(ctx->ntfs_ino);
+	ntfs_attr_put_search_ctx(ctx);
+	ntfs_log_debug("Restored status of mftbmp: allocated_size 0x%llx, "
+			"data_size 0x%llx, initialized_size 0x%llx.\n",
+			(long long)mftbmp_na->allocated_size,
+			(long long)mftbmp_na->data_size,
+			(long long)mftbmp_na->initialized_size);
+err_out:
+	errno = err;
+out:
+	ntfs_log_leave("\n");
+	return ret;
+}
+
+/**
+ * ntfs_mft_data_extend_allocation - extend mft data attribute
+ * @vol:	volume on which to extend the mft data attribute
+ *
+ * Extend the mft data attribute on the ntfs volume @vol by 16 mft records
+ * worth of clusters or if not enough space for this by one mft record worth
+ * of clusters.
+ *
+ * Note:  Only changes allocated_size, i.e. does not touch initialized_size or
+ * data_size.
+ *
+ * Return 0 on success and -1 on error with errno set to the error code.
+ */
+static int ntfs_mft_data_extend_allocation(ntfs_volume *vol)
+{
+	LCN lcn;
+	VCN old_last_vcn;
+	s64 min_nr, nr, ll = 0; /* silence compiler warning */
+	ntfs_attr *mft_na;
+	runlist_element *rl, *rl2;
+	ntfs_attr_search_ctx *ctx;
+	MFT_RECORD *m = NULL; /* silence compiler warning */
+	ATTR_RECORD *a = NULL; /* silence compiler warning */
+	int err, mp_size;
+	int ret = STATUS_ERROR;
+	u32 old_alen = 0; /* silence compiler warning */
+	BOOL mp_rebuilt = FALSE;
+	BOOL update_mp = FALSE;
+
+	ntfs_log_enter("Extending mft data allocation.\n");
+	
+	mft_na = vol->mft_na;
+	/*
+	 * Determine the preferred allocation location, i.e. the last lcn of
+	 * the mft data attribute.  The allocated size of the mft data
+	 * attribute cannot be zero so we are ok to do this.
+	 */
+	rl = ntfs_attr_find_vcn(mft_na,
+			(mft_na->allocated_size - 1) >> vol->cluster_size_bits);
+	
+	if (!rl || !rl->length || rl->lcn < 0) {
+		ntfs_log_error("Failed to determine last allocated "
+				"cluster of mft data attribute.\n");
+		if (rl)
+			errno = EIO;
+		goto out;
+	}
+	
+	lcn = rl->lcn + rl->length;
+	ntfs_log_debug("Last lcn of mft data attribute is 0x%llx.\n", (long long)lcn);
+	/* Minimum allocation is one mft record worth of clusters. */
+	min_nr = vol->mft_record_size >> vol->cluster_size_bits;
+	if (!min_nr)
+		min_nr = 1;
+	/* Want to allocate 16 mft records worth of clusters. */
+	nr = vol->mft_record_size << 4 >> vol->cluster_size_bits;
+	if (!nr)
+		nr = min_nr;
+	
+	old_last_vcn = rl[1].vcn;
+	do {
+		rl2 = ntfs_cluster_alloc(vol, old_last_vcn, nr, lcn, MFT_ZONE);
+		if (rl2)
+			break;
+		if (errno != ENOSPC || nr == min_nr) {
+			ntfs_log_perror("Failed to allocate (%lld) clusters "
+					"for $MFT", (long long)nr);
+			goto out;
+		}
+		/*
+		 * There is not enough space to do the allocation, but there
+		 * might be enough space to do a minimal allocation so try that
+		 * before failing.
+		 */
+		nr = min_nr;
+		ntfs_log_debug("Retrying mft data allocation with minimal cluster "
+				"count %lli.\n", (long long)nr);
+	} while (1);
+	
+	ntfs_log_debug("Allocated %lld clusters.\n", (long long)nr);
+	
+	rl = ntfs_runlists_merge(mft_na->rl, rl2);
+	if (!rl) {
+		err = errno;
+		ntfs_log_error("Failed to merge runlists for mft data "
+				"attribute.\n");
+		if (ntfs_cluster_free_from_rl(vol, rl2))
+			ntfs_log_error("Failed to deallocate clusters "
+					"from the mft data attribute.%s\n", es);
+		free(rl2);
+		errno = err;
+		goto out;
+	}
+	mft_na->rl = rl;
+	
+	/* Find the last run in the new runlist. */
+	for (; rl[1].length; rl++)
+		;
+	/* Update the attribute record as well. */
+	ctx = ntfs_attr_get_search_ctx(mft_na->ni, NULL);
+	if (!ctx)
+		goto undo_alloc;
+
+	if (ntfs_attr_lookup(mft_na->type, mft_na->name, mft_na->name_len, 0,
+			rl[1].vcn, NULL, 0, ctx)) {
+		ntfs_log_error("Failed to find last attribute extent of "
+				"mft data attribute.\n");
+		goto undo_alloc;
+	}
+	m = ctx->mrec;
+	a = ctx->attr;
+	ll = sle64_to_cpu(a->lowest_vcn);
+	rl2 = ntfs_attr_find_vcn(mft_na, ll);
+	if (!rl2 || !rl2->length) {
+		ntfs_log_error("Failed to determine previous last "
+				"allocated cluster of mft data attribute.\n");
+		if (rl2)
+			errno = EIO;
+		goto undo_alloc;
+	}
+	/* Get the size for the new mapping pairs array for this extent. */
+	mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll, INT_MAX);
+	if (mp_size <= 0) {
+		ntfs_log_error("Get size for mapping pairs failed for "
+				"mft data attribute extent.\n");
+		goto undo_alloc;
+	}
+	/* Expand the attribute record if necessary. */
+	old_alen = le32_to_cpu(a->length);
+	if (ntfs_attr_record_resize(m, a,
+			mp_size + le16_to_cpu(a->mapping_pairs_offset))) {
+		ret = ntfs_mft_attr_extend(vol->mft_na);
+		if (ret == STATUS_OK)
+			goto ok;
+		if (ret == STATUS_ERROR) {
+			ntfs_log_perror("%s: ntfs_mft_attr_extend failed", __FUNCTION__);
+			update_mp = TRUE;
+		}
+		goto undo_alloc;
+	}
+	mp_rebuilt = TRUE;
+	/*
+	 * Generate the mapping pairs array directly into the attribute record.
+	 */
+	if (ntfs_mapping_pairs_build(vol,
+			(u8*)a + le16_to_cpu(a->mapping_pairs_offset), mp_size,
+			rl2, ll, NULL)) {
+		ntfs_log_error("Failed to build mapping pairs array of "
+				"mft data attribute.\n");
+		errno = EIO;
+		goto undo_alloc;
+	}
+	/* Update the highest_vcn. */
+	a->highest_vcn = cpu_to_sle64(rl[1].vcn - 1);
+	/*
+	 * We now have extended the mft data allocated_size by nr clusters.
+	 * Reflect this in the ntfs_attr structure and the attribute record.
+	 * @rl is the last (non-terminator) runlist element of mft data
+	 * attribute.
+	 */
+	if (a->lowest_vcn) {
+		/*
+		 * We are not in the first attribute extent, switch to it, but
+		 * first ensure the changes will make it to disk later.
+		 */
+		ntfs_inode_mark_dirty(ctx->ntfs_ino);
+		ntfs_attr_reinit_search_ctx(ctx);
+		if (ntfs_attr_lookup(mft_na->type, mft_na->name,
+				mft_na->name_len, 0, 0, NULL, 0, ctx)) {
+			ntfs_log_error("Failed to find first attribute "
+					"extent of mft data attribute.\n");
+			goto restore_undo_alloc;
+		}
+		a = ctx->attr;
+	}
+ok:
+	mft_na->allocated_size += nr << vol->cluster_size_bits;
+	a->allocated_size = cpu_to_sle64(mft_na->allocated_size);
+	/* Ensure the changes make it to disk. */
+	ntfs_inode_mark_dirty(ctx->ntfs_ino);
+	ntfs_attr_put_search_ctx(ctx);
+	ret = STATUS_OK;
+out:
+	ntfs_log_leave("\n");
+	return ret;
+
+restore_undo_alloc:
+	err = errno;
+	ntfs_attr_reinit_search_ctx(ctx);
+	if (ntfs_attr_lookup(mft_na->type, mft_na->name, mft_na->name_len, 0,
+			rl[1].vcn, NULL, 0, ctx)) {
+		ntfs_log_error("Failed to find last attribute extent of "
+				"mft data attribute.%s\n", es);
+		ntfs_attr_put_search_ctx(ctx);
+		mft_na->allocated_size += nr << vol->cluster_size_bits;
+		/*
+		 * The only thing that is now wrong is ->allocated_size of the
+		 * base attribute extent which chkdsk should be able to fix.
+		 */
+		errno = err;
+		ret = STATUS_ERROR;
+		goto out;
+	}
+	m = ctx->mrec;
+	a = ctx->attr;
+	a->highest_vcn = cpu_to_sle64(old_last_vcn - 1);
+	errno = err;
+undo_alloc:
+	err = errno;
+	if (ntfs_cluster_free(vol, mft_na, old_last_vcn, -1) < 0)
+		ntfs_log_error("Failed to free clusters from mft data "
+				"attribute.%s\n", es);
+	if (ntfs_rl_truncate(&mft_na->rl, old_last_vcn))
+		ntfs_log_error("Failed to truncate mft data attribute "
+				"runlist.%s\n", es);
+	if (mp_rebuilt) {
+		if (ntfs_mapping_pairs_build(vol, (u8*)a +
+				le16_to_cpu(a->mapping_pairs_offset),
+				old_alen - le16_to_cpu(a->mapping_pairs_offset),
+				rl2, ll, NULL))
+			ntfs_log_error("Failed to restore mapping pairs "
+					"array.%s\n", es);
+		if (ntfs_attr_record_resize(m, a, old_alen))
+			ntfs_log_error("Failed to restore attribute "
+					"record.%s\n", es);
+		ntfs_inode_mark_dirty(ctx->ntfs_ino);
+	}
+	if (update_mp) {
+		if (ntfs_attr_update_mapping_pairs(vol->mft_na, 0))
+			ntfs_log_perror("%s: MP update failed", __FUNCTION__);
+	}
+	if (ctx)
+		ntfs_attr_put_search_ctx(ctx);
+	errno = err;
+	goto out;
+}
+
+
+static int ntfs_mft_record_init(ntfs_volume *vol, s64 size)
+{
+	int ret = -1;
+	ntfs_attr *mft_na;
+	s64 old_data_initialized, old_data_size;
+	ntfs_attr_search_ctx *ctx;
+	
+	ntfs_log_enter("Entering\n");
+	
+	/* NOTE: Caller must sanity check vol, vol->mft_na and vol->mftbmp_na */
+	
+	mft_na = vol->mft_na;
+	
+	/*
+	 * The mft record is outside the initialized data. Extend the mft data
+	 * attribute until it covers the allocated record. The loop is only
+	 * actually traversed more than once when a freshly formatted volume
+	 * is first written to so it optimizes away nicely in the common case.
+	 */
+	ntfs_log_debug("Status of mft data before extension: "
+			"allocated_size 0x%llx, data_size 0x%llx, "
+			"initialized_size 0x%llx.\n",
+			(long long)mft_na->allocated_size,
+			(long long)mft_na->data_size,
+			(long long)mft_na->initialized_size);
+	while (size > mft_na->allocated_size) {
+		if (ntfs_mft_data_extend_allocation(vol) == STATUS_ERROR)
+			goto out;
+		ntfs_log_debug("Status of mft data after allocation extension: "
+				"allocated_size 0x%llx, data_size 0x%llx, "
+				"initialized_size 0x%llx.\n",
+				(long long)mft_na->allocated_size,
+				(long long)mft_na->data_size,
+				(long long)mft_na->initialized_size);
+	}
+	
+	old_data_initialized = mft_na->initialized_size;
+	old_data_size = mft_na->data_size;
+	
+	/*
+	 * Extend mft data initialized size (and data size of course) to reach
+	 * the allocated mft record, formatting the mft records along the way.
+	 * Note: We only modify the ntfs_attr structure as that is all that is
+	 * needed by ntfs_mft_record_format().  We will update the attribute
+	 * record itself in one fell swoop later on.
+	 */
+	while (size > mft_na->initialized_size) {
+		s64 ll2 = mft_na->initialized_size >> vol->mft_record_size_bits;
+		mft_na->initialized_size += vol->mft_record_size;
+		if (mft_na->initialized_size > mft_na->data_size)
+			mft_na->data_size = mft_na->initialized_size;
+		ntfs_log_debug("Initializing mft record 0x%llx.\n", (long long)ll2);
+		if (ntfs_mft_record_format(vol, ll2) < 0) {
+			ntfs_log_perror("Failed to format mft record");
+			goto undo_data_init;
+		}
+	}
+	
+	/* Update the mft data attribute record to reflect the new sizes. */
+	ctx = ntfs_attr_get_search_ctx(mft_na->ni, NULL);
+	if (!ctx)
+		goto undo_data_init;
+
+	if (ntfs_attr_lookup(mft_na->type, mft_na->name, mft_na->name_len, 0,
+			0, NULL, 0, ctx)) {
+		ntfs_log_error("Failed to find first attribute extent of "
+				"mft data attribute.\n");
+		ntfs_attr_put_search_ctx(ctx);
+		goto undo_data_init;
+	}
+	ctx->attr->initialized_size = cpu_to_sle64(mft_na->initialized_size);
+	ctx->attr->data_size = cpu_to_sle64(mft_na->data_size);
+	ctx->attr->allocated_size = cpu_to_sle64(mft_na->allocated_size);
+	
+	/* Ensure the changes make it to disk. */
+	ntfs_inode_mark_dirty(ctx->ntfs_ino);
+	ntfs_attr_put_search_ctx(ctx);
+	ntfs_log_debug("Status of mft data after mft record initialization: "
+			"allocated_size 0x%llx, data_size 0x%llx, "
+			"initialized_size 0x%llx.\n",
+			(long long)mft_na->allocated_size,
+			(long long)mft_na->data_size,
+			(long long)mft_na->initialized_size);
+	
+	/* Sanity checks. */
+	if (mft_na->data_size > mft_na->allocated_size ||
+	    mft_na->initialized_size > mft_na->data_size)
+		NTFS_BUG("mft_na sanity checks failed");
+	
+	/* Sync MFT to minimize data loss if there won't be clean unmount. */
+	if (ntfs_inode_sync(mft_na->ni))
+		goto undo_data_init;
+	
+	ret = 0;
+out:	
+	ntfs_log_leave("\n");
+	return ret;
+	
+undo_data_init:
+	mft_na->initialized_size = old_data_initialized;
+	mft_na->data_size = old_data_size;
+	goto out;
+}
+
+static int ntfs_mft_rec_init(ntfs_volume *vol, s64 size)
+{
+	int ret = -1;
+	ntfs_attr *mft_na;
+	s64 old_data_initialized, old_data_size;
+	ntfs_attr_search_ctx *ctx;
+	
+	ntfs_log_enter("Entering\n");
+	
+	mft_na = vol->mft_na;
+	
+	if (size > mft_na->allocated_size || size > mft_na->initialized_size) {
+		errno = EIO;
+		ntfs_log_perror("%s: unexpected $MFT sizes, see below", __FUNCTION__);
+		ntfs_log_error("$MFT: size=%lld  allocated_size=%lld  "
+			       "data_size=%lld  initialized_size=%lld\n",
+			       (long long)size,
+			       (long long)mft_na->allocated_size,
+			       (long long)mft_na->data_size,
+			       (long long)mft_na->initialized_size);
+		goto out;
+	}
+	
+	old_data_initialized = mft_na->initialized_size;
+	old_data_size = mft_na->data_size;
+	
+	/* Update the mft data attribute record to reflect the new sizes. */
+	ctx = ntfs_attr_get_search_ctx(mft_na->ni, NULL);
+	if (!ctx)
+		goto undo_data_init;
+
+	if (ntfs_attr_lookup(mft_na->type, mft_na->name, mft_na->name_len, 0,
+			0, NULL, 0, ctx)) {
+		ntfs_log_error("Failed to find first attribute extent of "
+				"mft data attribute.\n");
+		ntfs_attr_put_search_ctx(ctx);
+		goto undo_data_init;
+	}
+	ctx->attr->initialized_size = cpu_to_sle64(mft_na->initialized_size);
+	ctx->attr->data_size = cpu_to_sle64(mft_na->data_size);
+
+	/* CHECKME: ctx->attr->allocation_size is already ok? */
+	
+	/* Ensure the changes make it to disk. */
+	ntfs_inode_mark_dirty(ctx->ntfs_ino);
+	ntfs_attr_put_search_ctx(ctx);
+	
+	/* Sanity checks. */
+	if (mft_na->data_size > mft_na->allocated_size ||
+	    mft_na->initialized_size > mft_na->data_size)
+		NTFS_BUG("mft_na sanity checks failed");
+out:	
+	ntfs_log_leave("\n");
+	return ret;
+	
+undo_data_init:
+	mft_na->initialized_size = old_data_initialized;
+	mft_na->data_size = old_data_size;
+	goto out;
+}
+
+ntfs_inode *ntfs_mft_rec_alloc(ntfs_volume *vol, BOOL mft_data)
+{
+	s64 ll, bit;
+	ntfs_attr *mft_na, *mftbmp_na;
+	MFT_RECORD *m;
+	ntfs_inode *ni = NULL;
+	ntfs_inode *base_ni;
+	int err;
+	le16 seq_no, usn;
+	BOOL forced_mft_data;
+
+	ntfs_log_enter("Entering\n");
+
+	mft_na = vol->mft_na;
+	mftbmp_na = vol->mftbmp_na;
+
+	base_ni = mft_na->ni;
+
+	/*
+	 * The first extent containing $MFT:$AT_DATA is better located
+	 * in record 15 to make sure it can be read at mount time.
+	 * The record 15 is prereserved as a base inode with no
+	 * extents and no name, and it is marked in use.
+	 */
+	forced_mft_data = FALSE;
+	if (mft_data) {
+		ntfs_inode *ext_ni = ntfs_inode_open(vol, FILE_mft_data);
+			/*
+			 * If record 15 cannot be opened, it is probably in
+			 * use as an extent. Apply standard procedure for
+			 * further extents.
+			 */
+		if (ext_ni) {
+			/*
+			 * Make sure record 15 is a base extent and has
+			 * no extents.
+			 * Also make sure it has no name : a base inode with
+			 * no extents and no name cannot be in use.
+			 * Otherwise apply standard procedure.
+			 */
+   			if (!ext_ni->mrec->base_mft_record
+			    && !ext_ni->nr_extents)
+				forced_mft_data = TRUE;
+			ntfs_inode_close(ext_ni);
+		}
+	}
+	if (forced_mft_data)
+		bit = FILE_mft_data;
+	else
+		bit = ntfs_mft_bitmap_find_free_rec(vol, base_ni);
+	if (bit >= 0)
+		goto found_free_rec;
+
+	if (errno != ENOSPC)
+		goto out;
+	
+	errno = ENOSPC;
+	/* strerror() is intentionally used below, we want to log this error. */
+	ntfs_log_error("No free mft record for $MFT: %s\n", strerror(errno));
+	goto err_out;
+
+found_free_rec:
+	if (ntfs_bitmap_set_bit(mftbmp_na, bit)) {
+		ntfs_log_error("Failed to allocate bit in mft bitmap #2\n");
+		goto err_out;
+	}
+	
+	ll = (bit + 1) << vol->mft_record_size_bits;
+	if (ll > mft_na->initialized_size)
+		if (ntfs_mft_rec_init(vol, ll) < 0)
+			goto undo_mftbmp_alloc;
+	/*
+	 * We now have allocated and initialized the mft record.  Need to read
+	 * it from disk and re-format it, preserving the sequence number if it
+	 * is not zero as well as the update sequence number if it is not zero
+	 * or -1 (0xffff).
+	 */
+	m = ntfs_malloc(vol->mft_record_size);
+	if (!m)
+		goto undo_mftbmp_alloc;
+	
+	if (ntfs_mft_record_read(vol, bit, m)) {
+		free(m);
+		goto undo_mftbmp_alloc;
+	}
+	/* Sanity check that the mft record is really not in use. */
+	if (!forced_mft_data
+	    && (ntfs_is_file_record(m->magic)
+	    && (m->flags & MFT_RECORD_IN_USE))) {
+		ntfs_log_error("Inode %lld is used but it wasn't marked in "
+			       "$MFT bitmap. Fixed.\n", (long long)bit);
+		free(m);
+		goto undo_mftbmp_alloc;
+	}
+
+	seq_no = m->sequence_number;
+	usn = *(le16*)((u8*)m + le16_to_cpu(m->usa_ofs));
+	if (ntfs_mft_record_layout(vol, bit, m)) {
+		ntfs_log_error("Failed to re-format mft record.\n");
+		free(m);
+		goto undo_mftbmp_alloc;
+	}
+	if (seq_no)
+		m->sequence_number = seq_no;
+	seq_no = usn;
+	if (seq_no && seq_no != const_cpu_to_le16(0xffff))
+		*(le16*)((u8*)m + le16_to_cpu(m->usa_ofs)) = usn;
+	/* Set the mft record itself in use. */
+	m->flags |= MFT_RECORD_IN_USE;
+	/* Now need to open an ntfs inode for the mft record. */
+	ni = ntfs_inode_allocate(vol);
+	if (!ni) {
+		ntfs_log_error("Failed to allocate buffer for inode.\n");
+		free(m);
+		goto undo_mftbmp_alloc;
+	}
+	ni->mft_no = bit;
+	ni->mrec = m;
+	/*
+	 * If we are allocating an extent mft record, make the opened inode an
+	 * extent inode and attach it to the base inode.  Also, set the base
+	 * mft record reference in the extent inode.
+	 */
+	ni->nr_extents = -1;
+	ni->base_ni = base_ni;
+	m->base_mft_record = MK_LE_MREF(base_ni->mft_no,
+					le16_to_cpu(base_ni->mrec->sequence_number));
+	/*
+	 * Attach the extent inode to the base inode, reallocating
+	 * memory if needed.
+	 */
+	if (!(base_ni->nr_extents & 3)) {
+		ntfs_inode **extent_nis;
+		int i;
+
+		i = (base_ni->nr_extents + 4) * sizeof(ntfs_inode *);
+		extent_nis = ntfs_malloc(i);
+		if (!extent_nis) {
+			free(m);
+			free(ni);
+			goto undo_mftbmp_alloc;
+		}
+		if (base_ni->nr_extents) {
+			memcpy(extent_nis, base_ni->extent_nis,
+					i - 4 * sizeof(ntfs_inode *));
+			free(base_ni->extent_nis);
+		}
+		base_ni->extent_nis = extent_nis;
+	}
+	base_ni->extent_nis[base_ni->nr_extents++] = ni;
+	
+	/* Make sure the allocated inode is written out to disk later. */
+	ntfs_inode_mark_dirty(ni);
+	/* Initialize time, allocated and data size in ntfs_inode struct. */
+	ni->data_size = ni->allocated_size = 0;
+	ni->flags = 0;
+	ni->creation_time = ni->last_data_change_time =
+			ni->last_mft_change_time =
+			ni->last_access_time = ntfs_current_time();
+	/* Update the default mft allocation position if it was used. */
+	if (!base_ni)
+		vol->mft_data_pos = bit + 1;
+	/* Return the opened, allocated inode of the allocated mft record. */
+	ntfs_log_error("allocated %sinode %lld\n",
+			base_ni ? "extent " : "", (long long)bit);
+out:
+	ntfs_log_leave("\n");	
+	return ni;
+
+undo_mftbmp_alloc:
+	err = errno;
+	if (ntfs_bitmap_clear_bit(mftbmp_na, bit))
+		ntfs_log_error("Failed to clear bit in mft bitmap.%s\n", es);
+	errno = err;
+err_out:
+	if (!errno)
+		errno = EIO;
+	ni = NULL;
+	goto out;	
+}
+
+/**
+ * ntfs_mft_record_alloc - allocate an mft record on an ntfs volume
+ * @vol:	volume on which to allocate the mft record
+ * @base_ni:	open base inode if allocating an extent mft record or NULL
+ *
+ * Allocate an mft record in $MFT/$DATA of an open ntfs volume @vol.
+ *
+ * If @base_ni is NULL make the mft record a base mft record and allocate it at
+ * the default allocator position.
+ *
+ * If @base_ni is not NULL make the allocated mft record an extent record,
+ * allocate it starting at the mft record after the base mft record and attach
+ * the allocated and opened ntfs inode to the base inode @base_ni.
+ *
+ * On success return the now opened ntfs (extent) inode of the mft record.
+ *
+ * On error return NULL with errno set to the error code.
+ *
+ * To find a free mft record, we scan the mft bitmap for a zero bit.  To
+ * optimize this we start scanning at the place specified by @base_ni or if
+ * @base_ni is NULL we start where we last stopped and we perform wrap around
+ * when we reach the end.  Note, we do not try to allocate mft records below
+ * number 24 because numbers 0 to 15 are the defined system files anyway and 16
+ * to 24 are used for storing extension mft records or used by chkdsk to store
+ * its log. However the record number 15 is dedicated to the first extent to
+ * the $DATA attribute of $MFT.  This is required to avoid the possibility
+ * of creating a run list with a circular dependence which once written to disk
+ * can never be read in again.  Windows will only use records 16 to 24 for
+ * normal files if the volume is completely out of space.  We never use them
+ * which means that when the volume is really out of space we cannot create any
+ * more files while Windows can still create up to 8 small files.  We can start
+ * doing this at some later time, it does not matter much for now.
+ *
+ * When scanning the mft bitmap, we only search up to the last allocated mft
+ * record.  If there are no free records left in the range 24 to number of
+ * allocated mft records, then we extend the $MFT/$DATA attribute in order to
+ * create free mft records.  We extend the allocated size of $MFT/$DATA by 16
+ * records at a time or one cluster, if cluster size is above 16kiB.  If there
+ * is not sufficient space to do this, we try to extend by a single mft record
+ * or one cluster, if cluster size is above the mft record size, but we only do
+ * this if there is enough free space, which we know from the values returned
+ * by the failed cluster allocation function when we tried to do the first
+ * allocation.
+ *
+ * No matter how many mft records we allocate, we initialize only the first
+ * allocated mft record, incrementing mft data size and initialized size
+ * accordingly, open an ntfs_inode for it and return it to the caller, unless
+ * there are less than 24 mft records, in which case we allocate and initialize
+ * mft records until we reach record 24 which we consider as the first free mft
+ * record for use by normal files.
+ *
+ * If during any stage we overflow the initialized data in the mft bitmap, we
+ * extend the initialized size (and data size) by 8 bytes, allocating another
+ * cluster if required.  The bitmap data size has to be at least equal to the
+ * number of mft records in the mft, but it can be bigger, in which case the
+ * superfluous bits are padded with zeroes.
+ *
+ * Thus, when we return successfully (return value non-zero), we will have:
+ *	- initialized / extended the mft bitmap if necessary,
+ *	- initialized / extended the mft data if necessary,
+ *	- set the bit corresponding to the mft record being allocated in the
+ *	  mft bitmap,
+ *	- open an ntfs_inode for the allocated mft record, and we will
+ *	- return the ntfs_inode.
+ *
+ * On error (return value zero), nothing will have changed.  If we had changed
+ * anything before the error occurred, we will have reverted back to the
+ * starting state before returning to the caller.  Thus, except for bugs, we
+ * should always leave the volume in a consistent state when returning from
+ * this function.
+ *
+ * Note, this function cannot make use of most of the normal functions, like
+ * for example for attribute resizing, etc, because when the run list overflows
+ * the base mft record and an attribute list is used, it is very important that
+ * the extension mft records used to store the $DATA attribute of $MFT can be
+ * reached without having to read the information contained inside them, as
+ * this would make it impossible to find them in the first place after the
+ * volume is dismounted.  $MFT/$BITMAP probably does not need to follow this
+ * rule because the bitmap is not essential for finding the mft records, but on
+ * the other hand, handling the bitmap in this special way would make life
+ * easier because otherwise there might be circular invocations of functions
+ * when reading the bitmap but if we are careful, we should be able to avoid
+ * all problems.
+ */
+//ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, ntfs_inode *base_ni)
+ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, ntfs_inode *base_ni)
+{
+	s64 ll, bit;
+	ntfs_attr *mft_na, *mftbmp_na;
+	MFT_RECORD *m;
+	ntfs_inode *ni = NULL;
+	int err;
+	le16 seq_no, usn;
+
+	if (base_ni)
+		ntfs_log_enter("Entering (allocating an extent mft record for "
+			       "base mft record %lld).\n", 
+			       (long long)base_ni->mft_no);
+	else
+		ntfs_log_enter("Entering (allocating a base mft record)\n");
+	if (!vol || !vol->mft_na || !vol->mftbmp_na) {
+		errno = EINVAL;
+		goto out;
+	}
+	
+	if (ntfs_is_mft(base_ni)) {
+		ni = ntfs_mft_rec_alloc(vol, FALSE);
+		goto out;
+	}
+
+	mft_na = vol->mft_na;
+	mftbmp_na = vol->mftbmp_na;
+retry:	
+	bit = ntfs_mft_bitmap_find_free_rec(vol, base_ni);
+	if (bit >= 0) {
+		ntfs_log_debug("found free record (#1) at %lld\n",
+				(long long)bit);
+		goto found_free_rec;
+	}
+	if (errno != ENOSPC)
+		goto out;
+	/*
+	 * No free mft records left.  If the mft bitmap already covers more
+	 * than the currently used mft records, the next records are all free,
+	 * so we can simply allocate the first unused mft record.
+	 * Note: We also have to make sure that the mft bitmap at least covers
+	 * the first 24 mft records as they are special and whilst they may not
+	 * be in use, we do not allocate from them.
+	 */
+	ll = mft_na->initialized_size >> vol->mft_record_size_bits;
+	if (mftbmp_na->initialized_size << 3 > ll &&
+			mftbmp_na->initialized_size > RESERVED_MFT_RECORDS / 8) {
+		bit = ll;
+		if (bit < RESERVED_MFT_RECORDS)
+			bit = RESERVED_MFT_RECORDS;
+		ntfs_log_debug("found free record (#2) at %lld\n",
+				(long long)bit);
+		goto found_free_rec;
+	}
+	/*
+	 * The mft bitmap needs to be expanded until it covers the first unused
+	 * mft record that we can allocate.
+	 * Note: The smallest mft record we allocate is mft record 24.
+	 */
+	ntfs_log_debug("Status of mftbmp before extension: allocated_size 0x%llx, "
+			"data_size 0x%llx, initialized_size 0x%llx.\n",
+			(long long)mftbmp_na->allocated_size,
+			(long long)mftbmp_na->data_size,
+			(long long)mftbmp_na->initialized_size);
+	if (mftbmp_na->initialized_size + 8 > mftbmp_na->allocated_size) {
+
+		int ret = ntfs_mft_bitmap_extend_allocation(vol);
+
+		if (ret == STATUS_ERROR)
+			goto err_out;
+		if (ret == STATUS_KEEP_SEARCHING) {
+			ret = ntfs_mft_bitmap_extend_allocation(vol);
+			if (ret != STATUS_OK)
+				goto err_out;
+		}
+
+		ntfs_log_debug("Status of mftbmp after allocation extension: "
+				"allocated_size 0x%llx, data_size 0x%llx, "
+				"initialized_size 0x%llx.\n",
+				(long long)mftbmp_na->allocated_size,
+				(long long)mftbmp_na->data_size,
+				(long long)mftbmp_na->initialized_size);
+	}
+	/*
+	 * We now have sufficient allocated space, extend the initialized_size
+	 * as well as the data_size if necessary and fill the new space with
+	 * zeroes.
+	 */
+	bit = mftbmp_na->initialized_size << 3;
+	if (ntfs_mft_bitmap_extend_initialized(vol))
+		goto err_out;
+	ntfs_log_debug("Status of mftbmp after initialized extension: "
+			"allocated_size 0x%llx, data_size 0x%llx, "
+			"initialized_size 0x%llx.\n",
+			(long long)mftbmp_na->allocated_size,
+			(long long)mftbmp_na->data_size,
+			(long long)mftbmp_na->initialized_size);
+	ntfs_log_debug("found free record (#3) at %lld\n", (long long)bit);
+found_free_rec:
+	/* @bit is the found free mft record, allocate it in the mft bitmap. */
+	if (ntfs_bitmap_set_bit(mftbmp_na, bit)) {
+		ntfs_log_error("Failed to allocate bit in mft bitmap.\n");
+		goto err_out;
+	}
+	
+	/* The mft bitmap is now uptodate.  Deal with mft data attribute now. */
+	ll = (bit + 1) << vol->mft_record_size_bits;
+	if (ll > mft_na->initialized_size)
+		if (ntfs_mft_record_init(vol, ll) < 0)
+			goto undo_mftbmp_alloc;
+
+	/*
+	 * We now have allocated and initialized the mft record.  Need to read
+	 * it from disk and re-format it, preserving the sequence number if it
+	 * is not zero as well as the update sequence number if it is not zero
+	 * or -1 (0xffff).
+	 */
+	m = ntfs_malloc(vol->mft_record_size);
+	if (!m)
+		goto undo_mftbmp_alloc;
+	
+	if (ntfs_mft_record_read(vol, bit, m)) {
+		free(m);
+		goto undo_mftbmp_alloc;
+	}
+	/* Sanity check that the mft record is really not in use. */
+	if (ntfs_is_file_record(m->magic) && (m->flags & MFT_RECORD_IN_USE)) {
+		ntfs_log_error("Inode %lld is used but it wasn't marked in "
+			       "$MFT bitmap. Fixed.\n", (long long)bit);
+		free(m);
+		goto retry;
+	}
+	seq_no = m->sequence_number;
+	usn = *(le16*)((u8*)m + le16_to_cpu(m->usa_ofs));
+	if (ntfs_mft_record_layout(vol, bit, m)) {
+		ntfs_log_error("Failed to re-format mft record.\n");
+		free(m);
+		goto undo_mftbmp_alloc;
+	}
+	if (seq_no)
+		m->sequence_number = seq_no;
+	seq_no = usn;
+	if (seq_no && seq_no != const_cpu_to_le16(0xffff))
+		*(le16*)((u8*)m + le16_to_cpu(m->usa_ofs)) = usn;
+	/* Set the mft record itself in use. */
+	m->flags |= MFT_RECORD_IN_USE;
+	/* Now need to open an ntfs inode for the mft record. */
+	ni = ntfs_inode_allocate(vol);
+	if (!ni) {
+		ntfs_log_error("Failed to allocate buffer for inode.\n");
+		free(m);
+		goto undo_mftbmp_alloc;
+	}
+	ni->mft_no = bit;
+	ni->mrec = m;
+	/*
+	 * If we are allocating an extent mft record, make the opened inode an
+	 * extent inode and attach it to the base inode.  Also, set the base
+	 * mft record reference in the extent inode.
+	 */
+	if (base_ni) {
+		ni->nr_extents = -1;
+		ni->base_ni = base_ni;
+		m->base_mft_record = MK_LE_MREF(base_ni->mft_no,
+				le16_to_cpu(base_ni->mrec->sequence_number));
+		/*
+		 * Attach the extent inode to the base inode, reallocating
+		 * memory if needed.
+		 */
+		if (!(base_ni->nr_extents & 3)) {
+			ntfs_inode **extent_nis;
+			int i;
+
+			i = (base_ni->nr_extents + 4) * sizeof(ntfs_inode *);
+			extent_nis = ntfs_malloc(i);
+			if (!extent_nis) {
+				free(m);
+				free(ni);
+				goto undo_mftbmp_alloc;
+			}
+			if (base_ni->nr_extents) {
+				memcpy(extent_nis, base_ni->extent_nis,
+						i - 4 * sizeof(ntfs_inode *));
+				free(base_ni->extent_nis);
+			}
+			base_ni->extent_nis = extent_nis;
+		}
+		base_ni->extent_nis[base_ni->nr_extents++] = ni;
+	}
+	/* Make sure the allocated inode is written out to disk later. */
+	ntfs_inode_mark_dirty(ni);
+	/* Initialize time, allocated and data size in ntfs_inode struct. */
+	ni->data_size = ni->allocated_size = 0;
+	ni->flags = 0;
+	ni->creation_time = ni->last_data_change_time =
+			ni->last_mft_change_time =
+			ni->last_access_time = ntfs_current_time();
+	/* Update the default mft allocation position if it was used. */
+	if (!base_ni)
+		vol->mft_data_pos = bit + 1;
+	/* Return the opened, allocated inode of the allocated mft record. */
+	ntfs_log_debug("allocated %sinode 0x%llx.\n",
+			base_ni ? "extent " : "", (long long)bit);
+	vol->free_mft_records--; 
+out:
+	ntfs_log_leave("\n");	
+	return ni;
+
+undo_mftbmp_alloc:
+	err = errno;
+	if (ntfs_bitmap_clear_bit(mftbmp_na, bit))
+		ntfs_log_error("Failed to clear bit in mft bitmap.%s\n", es);
+	errno = err;
+err_out:
+	if (!errno)
+		errno = EIO;
+	ni = NULL;
+	goto out;	
+}
+
+/**
+ * ntfs_mft_record_free - free an mft record on an ntfs volume
+ * @vol:	volume on which to free the mft record
+ * @ni:		open ntfs inode of the mft record to free
+ *
+ * Free the mft record of the open inode @ni on the mounted ntfs volume @vol.
+ * Note that this function calls ntfs_inode_close() internally and hence you
+ * cannot use the pointer @ni any more after this function returns success.
+ *
+ * On success return 0 and on error return -1 with errno set to the error code.
+ */
+int ntfs_mft_record_free(ntfs_volume *vol, ntfs_inode *ni)
+{
+	u64 mft_no;
+	int err;
+	u16 seq_no;
+	le16 old_seq_no;
+
+	ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no);
+
+	if (!vol || !vol->mftbmp_na || !ni) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	/* Cache the mft reference for later. */
+	mft_no = ni->mft_no;
+
+	/* Mark the mft record as not in use. */
+	ni->mrec->flags &= ~MFT_RECORD_IN_USE;
+
+	/* Increment the sequence number, skipping zero, if it is not zero. */
+	old_seq_no = ni->mrec->sequence_number;
+	seq_no = le16_to_cpu(old_seq_no);
+	if (seq_no == 0xffff)
+		seq_no = 1;
+	else if (seq_no)
+		seq_no++;
+	ni->mrec->sequence_number = cpu_to_le16(seq_no);
+
+	/* Set the inode dirty and write it out. */
+	ntfs_inode_mark_dirty(ni);
+	if (ntfs_inode_sync(ni)) {
+		err = errno;
+		goto sync_rollback;
+	}
+
+	/* Clear the bit in the $MFT/$BITMAP corresponding to this record. */
+	if (ntfs_bitmap_clear_bit(vol->mftbmp_na, mft_no)) {
+		err = errno;
+		// FIXME: If ntfs_bitmap_clear_run() guarantees rollback on
+		//	  error, this could be changed to goto sync_rollback;
+		goto bitmap_rollback;
+	}
+
+	/* Throw away the now freed inode. */
+#if CACHE_NIDATA_SIZE
+	if (!ntfs_inode_real_close(ni)) {
+#else
+	if (!ntfs_inode_close(ni)) {
+#endif
+		vol->free_mft_records++; 
+		return 0;
+	}
+	err = errno;
+
+	/* Rollback what we did... */
+bitmap_rollback:
+	if (ntfs_bitmap_set_bit(vol->mftbmp_na, mft_no))
+		ntfs_log_debug("Eeek! Rollback failed in ntfs_mft_record_free().  "
+				"Leaving inconsistent metadata!\n");
+sync_rollback:
+	ni->mrec->flags |= MFT_RECORD_IN_USE;
+	ni->mrec->sequence_number = old_seq_no;
+	ntfs_inode_mark_dirty(ni);
+	errno = err;
+	return -1;
+}
+
+/**
+ * ntfs_mft_usn_dec - Decrement USN by one
+ * @mrec:	pointer to an mft record
+ *
+ * On success return 0 and on error return -1 with errno set.
+ */
+int ntfs_mft_usn_dec(MFT_RECORD *mrec)
+{
+	u16 usn;
+	le16 *usnp;
+
+	if (!mrec) {
+		errno = EINVAL;
+		return -1;
+	}
+	usnp = (le16*)((char*)mrec + le16_to_cpu(mrec->usa_ofs));
+	usn = le16_to_cpup(usnp);
+	if (usn-- <= 1)
+		usn = 0xfffe;
+	*usnp = cpu_to_le16(usn);
+
+	return 0;
+}
+
diff --git a/libntfs-3g/misc.c b/libntfs-3g/misc.c
new file mode 100755
index 0000000000000000000000000000000000000000..b2e17cbf972fdb9758bfd5dbbc4b4c948095c32b
--- /dev/null
+++ b/libntfs-3g/misc.c
@@ -0,0 +1,61 @@
+/**
+ * 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
+
+#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"
+
+/**
+ * ntfs_calloc
+ * 
+ * Return a pointer to the allocated memory or NULL if the request fails.
+ */
+void *ntfs_calloc(size_t size)
+{
+	void *p;
+	
+	p = calloc(1, size);
+	if (!p)
+		ntfs_log_perror("Failed to calloc %lld bytes", (long long)size);
+	return p;
+}
+
+void *ntfs_malloc(size_t size)
+{
+	void *p;
+	
+	p = malloc(size);
+	if (!p)
+		ntfs_log_perror("Failed to malloc %lld bytes", (long long)size);
+	return p;
+}
diff --git a/libntfs-3g/mst.c b/libntfs-3g/mst.c
new file mode 100755
index 0000000000000000000000000000000000000000..b7937b7a411c04366906210b81e582f57f3056fd
--- /dev/null
+++ b/libntfs-3g/mst.c
@@ -0,0 +1,247 @@
+/**
+ * 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
+ *
+ * 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_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "mst.h"
+#include "logging.h"
+
+/**
+ * ntfs_mst_post_read_fixup - deprotect multi sector transfer protected data
+ * @b:		pointer to the data to deprotect
+ * @size:	size in bytes of @b
+ *
+ * Perform the necessary post read multi sector transfer fixups and detect the
+ * presence of incomplete multi sector transfers. - In that case, overwrite the
+ * magic of the ntfs record header being processed with "BAAD" (in memory only!)
+ * and abort processing.
+ *
+ * Return 0 on success and -1 on error, with errno set to the error code. The
+ * following error codes are defined:
+ *	EINVAL	Invalid arguments or invalid NTFS record in buffer @b.
+ *	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)
+{
+	u16 usa_ofs, usa_count, usn;
+	u16 *usa_pos, *data_pos;
+
+	ntfs_log_trace("Entering\n");
+
+	/* Setup the variables. */
+	usa_ofs = le16_to_cpu(b->usa_ofs);
+	/* 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. */
+	usa_pos = (u16*)b + usa_ofs/sizeof(u16);
+	/*
+	 * The update sequence number which has to be equal to each of the
+	 * u16 values before they are fixed up. Note no need to care for
+	 * endianness since we are comparing and moving data for on disk
+	 * structures which means the data is consistent. - If it is
+	 * consistency the wrong endianness it doesn't make any difference.
+	 */
+	usn = *usa_pos;
+	/*
+	 * Position in protected data of first u16 that needs fixing up.
+	 */
+	data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1;
+	/*
+	 * Check for incomplete multi sector transfer(s).
+	 */
+	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 *)b, size,
+				usa_ofs, usa_count, *data_pos, usn);
+			b->magic = magic_BAAD;
+			return -1;
+		}
+		data_pos += NTFS_BLOCK_SIZE/sizeof(u16);
+	}
+	/* Re-setup the variables. */
+	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--) {
+		/*
+		 * Increment position in usa and restore original data from
+		 * the usa into the data buffer.
+		 */
+		*data_pos = *(++usa_pos);
+		/* Increment position in data as well. */
+		data_pos += NTFS_BLOCK_SIZE/sizeof(u16);
+	}
+	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
+ * @size:	size in bytes of @b
+ *
+ * Perform the necessary pre write multi sector transfer fixup on the data
+ * pointer to by @b of @size.
+ *
+ * Return 0 if fixups applied successfully or -1 if no fixups were performed
+ * due to errors. In that case errno i set to the error code (EINVAL).
+ *
+ * NOTE: We consider the absence / invalidity of an update sequence array to
+ * mean error. This means that you have to create a valid update sequence
+ * array header in the ntfs record before calling this function, otherwise it
+ * will fail (the header needs to contain the position of the update sequence
+ * array together with the number of elements in the array). You also need to
+ * initialise the update sequence number before calling this function
+ * otherwise a random word will be used (whatever was in the record at that
+ * position at that time).
+ */
+int ntfs_mst_pre_write_fixup(NTFS_RECORD *b, const u32 size)
+{
+	u16 usa_ofs, usa_count, usn;
+	u16 *usa_pos, *data_pos;
+
+	ntfs_log_trace("Entering\n");
+
+	/* Sanity check + only fixup if it makes sense. */
+	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);
+	/* 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 = (u16*)((u8*)b + usa_ofs);
+	/*
+	 * Cyclically increment the update sequence number
+	 * (skipping 0 and -1, i.e. 0xffff).
+	 */
+	usn = le16_to_cpup(usa_pos) + 1;
+	if (usn == 0xffff || !usn)
+		usn = 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--) {
+		/*
+		 * 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 = usn;
+		/* Increment position in data as well. */
+		data_pos += NTFS_BLOCK_SIZE/sizeof(u16);
+	}
+	return 0;
+}
+
+/**
+ * ntfs_mst_post_write_fixup - deprotect multi sector transfer protected data
+ * @b:		pointer to the data to deprotect
+ *
+ * Perform the necessary post write multi sector transfer fixup, not checking
+ * for any errors, because we assume we have just used
+ * ntfs_mst_pre_write_fixup(), thus the data will be fine or we would never
+ * have gotten here.
+ */
+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) - 1;
+
+	ntfs_log_trace("Entering\n");
+
+	/* Position of usn in update sequence array. */
+	usa_pos = (u16*)b + usa_ofs/sizeof(u16);
+
+	/* Position in protected data of first u16 that needs fixing up. */
+	data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1;
+
+	/* Fixup all sectors. */
+	while (usa_count--) {
+		/*
+		 * Increment position in usa and restore original data from
+		 * the usa into the data buffer.
+		 */
+		*data_pos = *(++usa_pos);
+
+		/* Increment position in data as well. */
+		data_pos += NTFS_BLOCK_SIZE/sizeof(u16);
+	}
+}
+
diff --git a/libntfs-3g/object_id.c b/libntfs-3g/object_id.c
new file mode 100755
index 0000000000000000000000000000000000000000..299357e56241408b6882b599c6b334382d4a487e
--- /dev/null
+++ b/libntfs-3g/object_id.c
@@ -0,0 +1,640 @@
+/**
+ * object_id.c - Processing of object ids
+ *
+ *	This module is part of ntfs-3g library
+ *
+ * Copyright (c) 2009 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_SETXATTR
+#include <sys/xattr.h>
+#endif
+
+#ifdef HAVE_SYS_SYSMACROS_H
+#include <sys/sysmacros.h>
+#endif
+
+#include "compat.h"
+#include "types.h"
+#include "debug.h"
+#include "attrib.h"
+#include "inode.h"
+#include "dir.h"
+#include "volume.h"
+#include "mft.h"
+#include "index.h"
+#include "lcnalloc.h"
+#include "object_id.h"
+#include "logging.h"
+#include "misc.h"
+
+/*
+ *			Endianness considerations
+ *
+ *	According to RFC 4122, GUIDs should be printed with the most
+ *	significant byte first, and the six fields be compared individually
+ *	for ordering. RFC 4122 does not define the internal representation.
+ *
+ *	Here we always copy disk images with no endianness change,
+ *	and, for indexing, GUIDs are compared as if they were a sequence
+ *	of four unsigned 32 bit integers.
+ *
+ * --------------------- begin from RFC 4122 ----------------------
+ * Consider each field of the UUID to be an unsigned integer as shown
+ * in the table in section Section 4.1.2.  Then, to compare a pair of
+ * UUIDs, arithmetically compare the corresponding fields from each
+ * UUID in order of significance and according to their data type.
+ * Two UUIDs are equal if and only if all the corresponding fields
+ * are equal.
+ *
+ * UUIDs, as defined in this document, can also be ordered
+ * lexicographically.  For a pair of UUIDs, the first one follows the
+ * second if the most significant field in which the UUIDs differ is
+ * greater for the first UUID.  The second precedes the first if the
+ * most significant field in which the UUIDs differ is greater for
+ * the second UUID.
+ *
+ * The fields are encoded as 16 octets, with the sizes and order of the
+ * fields defined above, and with each field encoded with the Most
+ * Significant Byte first (known as network byte order).  Note that the
+ * field names, particularly for multiplexed fields, follow historical
+ * practice.
+ *
+ * 0                   1                   2                   3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                          time_low                             |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |       time_mid                |         time_hi_and_version   |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |clk_seq_hi_res |  clk_seq_low  |         node (0-1)            |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                         node (2-5)                            |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * ---------------------- end from RFC 4122 -----------------------
+ */
+
+typedef struct {
+	union {
+		/* alignment may be needed to evaluate collations */
+		u32 alignment;
+		GUID guid;
+	} object_id;
+} OBJECT_ID_INDEX_KEY;
+
+typedef struct {
+	le64 file_id;
+	GUID birth_volume_id;
+	GUID birth_object_id;
+	GUID domain_id;
+} OBJECT_ID_INDEX_DATA; // known as OBJ_ID_INDEX_DATA
+
+struct OBJECT_ID_INDEX {		/* index entry in $Extend/$ObjId */
+	INDEX_ENTRY_HEADER header;
+	OBJECT_ID_INDEX_KEY key;
+	OBJECT_ID_INDEX_DATA data;
+} ;
+
+static ntfschar objid_index_name[] = { const_cpu_to_le16('$'),
+					 const_cpu_to_le16('O') };
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+
+/*
+ *			Set the index for a new object id
+ *
+ *	Returns 0 if success
+ *		-1 if failure, explained by errno
+ */
+
+static int set_object_id_index(ntfs_inode *ni, ntfs_index_context *xo,
+			const OBJECT_ID_ATTR *object_id)
+{
+	struct OBJECT_ID_INDEX indx;
+	u64 file_id_cpu;
+	le64 file_id;
+	le16 seqn;
+
+	seqn = ni->mrec->sequence_number;
+	file_id_cpu = MK_MREF(ni->mft_no,le16_to_cpu(seqn));
+	file_id = cpu_to_le64(file_id_cpu);
+	indx.header.data_offset = const_cpu_to_le16(
+					sizeof(INDEX_ENTRY_HEADER)
+					+ sizeof(OBJECT_ID_INDEX_KEY));
+	indx.header.data_length = const_cpu_to_le16(
+					sizeof(OBJECT_ID_INDEX_DATA));
+	indx.header.reservedV = const_cpu_to_le32(0);
+	indx.header.length = const_cpu_to_le16(
+					sizeof(struct OBJECT_ID_INDEX));
+	indx.header.key_length = const_cpu_to_le16(
+					sizeof(OBJECT_ID_INDEX_KEY));
+	indx.header.flags = const_cpu_to_le16(0);
+	indx.header.reserved = const_cpu_to_le16(0);
+
+	memcpy(&indx.key.object_id,object_id,sizeof(GUID));
+
+	indx.data.file_id = file_id;
+	memcpy(&indx.data.birth_volume_id,
+			&object_id->birth_volume_id,sizeof(GUID));
+	memcpy(&indx.data.birth_object_id,
+			&object_id->birth_object_id,sizeof(GUID));
+	memcpy(&indx.data.domain_id,
+			&object_id->domain_id,sizeof(GUID));
+	ntfs_index_ctx_reinit(xo);
+	return (ntfs_ie_add(xo,(INDEX_ENTRY*)&indx));
+}
+
+#endif /* HAVE_SETXATTR */
+
+/*
+ *		Open the $Extend/$ObjId file and its index
+ *
+ *	Return the index context if opened
+ *		or NULL if an error occurred (errno tells why)
+ *
+ *	The index has to be freed and inode closed when not needed any more.
+ */
+
+static ntfs_index_context *open_object_id_index(ntfs_volume *vol)
+{
+	u64 inum;
+	ntfs_inode *ni;
+	ntfs_inode *dir_ni;
+	ntfs_index_context *xo;
+
+		/* do not use path_name_to inode - could reopen root */
+	dir_ni = ntfs_inode_open(vol, FILE_Extend);
+	ni = (ntfs_inode*)NULL;
+	if (dir_ni) {
+		inum = ntfs_inode_lookup_by_mbsname(dir_ni,"$ObjId");
+		if (inum != (u64)-1)
+			ni = ntfs_inode_open(vol, inum);
+		ntfs_inode_close(dir_ni);
+	}
+	if (ni) {
+		xo = ntfs_index_ctx_get(ni, objid_index_name, 2);
+		if (!xo) {
+			ntfs_inode_close(ni);
+		}
+	} else
+		xo = (ntfs_index_context*)NULL;
+	return (xo);
+}
+
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+
+/*
+ *		Merge object_id data stored in the index into
+ *	a full object_id struct.
+ *
+ *	returns 0 if merging successful
+ *		-1 if no data could be merged. This is generally not an error
+ */
+
+static int merge_index_data(ntfs_inode *ni,
+			const OBJECT_ID_ATTR *objectid_attr,
+			OBJECT_ID_ATTR *full_objectid)
+{
+	OBJECT_ID_INDEX_KEY key;
+	struct OBJECT_ID_INDEX *entry;
+	ntfs_index_context *xo;
+	ntfs_inode *xoni;
+	int res;
+
+	res = -1;
+	xo = open_object_id_index(ni->vol);
+	if (xo) {
+		memcpy(&key.object_id,objectid_attr,sizeof(GUID));
+		if (!ntfs_index_lookup(&key,
+				sizeof(OBJECT_ID_INDEX_KEY), xo)) {
+			entry = (struct OBJECT_ID_INDEX*)xo->entry;
+			/* make sure inode numbers match */
+			if (entry
+			    && (MREF(le64_to_cpu(entry->data.file_id))
+					== ni->mft_no)) {
+				memcpy(&full_objectid->birth_volume_id,
+						&entry->data.birth_volume_id,
+						sizeof(GUID));
+				memcpy(&full_objectid->birth_object_id,
+						&entry->data.birth_object_id,
+						sizeof(GUID));
+				memcpy(&full_objectid->domain_id,
+						&entry->data.domain_id,
+						sizeof(GUID));
+				res = 0;
+			}
+		}
+		xoni = xo->ni;
+		ntfs_index_ctx_put(xo);
+		ntfs_inode_close(xoni);
+	}
+	return (res);
+}
+
+#endif /* HAVE_SETXATTR */
+
+/*
+ *		Remove an object id index entry if attribute present
+ *
+ *	Returns the size of existing object id
+ *			(the existing object_d is returned)
+ *		-1 if failure, explained by errno
+ */
+
+static int remove_object_id_index(ntfs_attr *na, ntfs_index_context *xo,
+				OBJECT_ID_ATTR *old_attr)
+{
+	OBJECT_ID_INDEX_KEY key;
+	struct OBJECT_ID_INDEX *entry;
+	s64 size;
+	int ret;
+
+	ret = na->data_size;
+	if (ret) {
+			/* read the existing object id attribute */
+		size = ntfs_attr_pread(na, 0, sizeof(GUID), old_attr);
+		if (size >= (s64)sizeof(GUID)) {
+			memcpy(&key.object_id,
+				&old_attr->object_id,sizeof(GUID));
+			if (!ntfs_index_lookup(&key,
+					sizeof(OBJECT_ID_INDEX_KEY), xo)) {
+				entry = (struct OBJECT_ID_INDEX*)xo->entry;
+				memcpy(&old_attr->birth_volume_id,
+					&entry->data.birth_volume_id,
+					sizeof(GUID));
+				memcpy(&old_attr->birth_object_id,
+					&entry->data.birth_object_id,
+					sizeof(GUID));
+				memcpy(&old_attr->domain_id,
+					&entry->data.domain_id,
+					sizeof(GUID));
+				if (ntfs_index_rm(xo))
+					ret = -1;
+			}
+		} else {
+			ret = -1;
+			errno = ENODATA;
+		}
+	}
+	return (ret);
+}
+
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+
+/*
+ *		Update the object id and index
+ *
+ *	The object_id attribute should have been created and the
+ *	non-duplication of the GUID should have been checked before.
+ *
+ *	Returns 0 if success
+ *		-1 if failure, explained by errno
+ *	If could not remove the existing index, nothing is done,
+ *	If could not write the new data, no index entry is inserted
+ *	If failed to insert the index, data is removed
+ */
+
+static int update_object_id(ntfs_inode *ni, ntfs_index_context *xo,
+			const OBJECT_ID_ATTR *value, size_t size)
+{
+	OBJECT_ID_ATTR old_attr;
+	ntfs_attr *na;
+	int oldsize;
+	int written;
+	int res;
+
+	res = 0;
+
+	na = ntfs_attr_open(ni, AT_OBJECT_ID, AT_UNNAMED, 0);
+	if (na) {
+
+			/* remove the existing index entry */
+		oldsize = remove_object_id_index(na,xo,&old_attr);
+		if (oldsize < 0)
+			res = -1;
+		else {
+			/* resize attribute */
+			res = ntfs_attr_truncate(na, (s64)sizeof(GUID));
+				/* write the object_id in attribute */
+			if (!res && value) {
+				written = (int)ntfs_attr_pwrite(na,
+					(s64)0, (s64)sizeof(GUID),
+					&value->object_id);
+				if (written != (s64)sizeof(GUID)) {
+					ntfs_log_error("Failed to update "
+							"object id\n");
+					errno = EIO;
+					res = -1;
+				}
+			}
+				/* write index part if provided */
+			if (!res
+			    && ((size < sizeof(OBJECT_ID_ATTR))
+				 || set_object_id_index(ni,xo,value))) {
+				/*
+				 * If cannot index, try to remove the object
+				 * id and log the error. There will be an
+				 * inconsistency if removal fails.
+				 */
+				ntfs_attr_rm(na);
+				ntfs_log_error("Failed to index object id."
+						" Possible corruption.\n");
+			}
+		}
+		ntfs_attr_close(na);
+		NInoSetDirty(ni);
+	} else
+		res = -1;
+	return (res);
+}
+
+/*
+ *		Add a (dummy) object id to an inode if it does not exist
+ *
+ *	returns 0 if attribute was inserted (or already present)
+ *		-1 if adding failed (explained by errno)
+ */
+
+static int add_object_id(ntfs_inode *ni, int flags)
+{
+	int res;
+	u8 dummy;
+
+	res = -1; /* default return */
+	if (!ntfs_attr_exist(ni,AT_OBJECT_ID, AT_UNNAMED,0)) {
+		if (!(flags & XATTR_REPLACE)) {
+			/*
+			 * no object id 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, AT_OBJECT_ID,
+						AT_UNNAMED, 0, &dummy, (s64)0);
+				NInoSetDirty(ni);
+			} else
+				errno = EOPNOTSUPP;
+		} else
+			errno = ENODATA;
+	} else {
+		if (flags & XATTR_CREATE)
+			errno = EEXIST;
+		else
+			res = 0;
+	}
+	return (res);
+}
+
+#endif /* HAVE_SETXATTR */
+
+/*
+ *		Delete an object_id index entry
+ *
+ *	Returns 0 if success
+ *		-1 if failure, explained by errno
+ */
+
+int ntfs_delete_object_id_index(ntfs_inode *ni)
+{
+	ntfs_index_context *xo;
+	ntfs_inode *xoni;
+	ntfs_attr *na;
+	OBJECT_ID_ATTR old_attr;
+	int res;
+
+	res = 0;
+	na = ntfs_attr_open(ni, AT_OBJECT_ID, AT_UNNAMED, 0);
+	if (na) {
+			/*
+			 * read the existing object id
+			 * and un-index it
+			 */
+		xo = open_object_id_index(ni->vol);
+		if (xo) {
+			if (remove_object_id_index(na,xo,&old_attr) < 0)
+				res = -1;
+			xoni = xo->ni;
+			ntfs_index_entry_mark_dirty(xo);
+			NInoSetDirty(xoni);
+			ntfs_index_ctx_put(xo);
+			ntfs_inode_close(xoni);
+		}
+		ntfs_attr_close(na);
+	}
+	return (res);
+}
+
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+
+/*
+ *		Get the ntfs object id into an extended attribute
+ *
+ *	If present, the object_id from the attribute and the GUIDs
+ *	from the index are returned (formatted as OBJECT_ID_ATTR)
+ *
+ *	Returns the global size (can be 0, 16 or 64)
+ *		and the buffer is updated if it is long enough
+ */
+
+int ntfs_get_ntfs_object_id(ntfs_inode *ni, char *value, size_t size)
+{
+	OBJECT_ID_ATTR full_objectid;
+	OBJECT_ID_ATTR *objectid_attr;
+	s64 attr_size;
+	int full_size;
+
+	full_size = 0;	/* default to no data and some error to be defined */
+	if (ni) {
+		objectid_attr = (OBJECT_ID_ATTR*)ntfs_attr_readall(ni,
+			AT_OBJECT_ID,(ntfschar*)NULL, 0, &attr_size);
+		if (objectid_attr) {
+				/* restrict to only GUID present in attr */
+			if (attr_size == sizeof(GUID)) {
+				memcpy(&full_objectid.object_id,
+						objectid_attr,sizeof(GUID));
+				full_size = sizeof(GUID);
+					/* get data from index, if any */
+				if (!merge_index_data(ni, objectid_attr,
+						&full_objectid)) {
+					full_size = sizeof(OBJECT_ID_ATTR);
+				}
+				if (full_size <= (s64)size) {
+					if (value)
+						memcpy(value,&full_objectid,
+							full_size);
+					else
+						errno = EINVAL;
+				}
+			} else {
+			/* unexpected size, better return unsupported */
+				errno = EOPNOTSUPP;
+				full_size = 0;
+			}
+			free(objectid_attr);
+		} else
+			errno = ENODATA;
+	}
+	return (full_size ? (int)full_size : -errno);
+}
+
+/*
+ *		Set the object id from an extended attribute
+ *
+ *	If the size is 64, the attribute and index are set.
+ *	else if the size is not less than 16 only the attribute is set.
+ *	The object id index is set accordingly.
+ *
+ *	Returns 0, or -1 if there is a problem
+ */
+
+int ntfs_set_ntfs_object_id(ntfs_inode *ni,
+			const char *value, size_t size, int flags)
+{
+	OBJECT_ID_INDEX_KEY key;
+	ntfs_inode *xoni;
+	ntfs_index_context *xo;
+	int res;
+
+	res = 0;
+	if (ni && value && (size >= sizeof(GUID))) {
+		xo = open_object_id_index(ni->vol);
+		if (xo) {
+			/* make sure the GUID was not used somewhere */
+			memcpy(&key.object_id, value, sizeof(GUID));
+			if (ntfs_index_lookup(&key,
+					sizeof(OBJECT_ID_INDEX_KEY), xo)) {
+				ntfs_index_ctx_reinit(xo);
+				res = add_object_id(ni, flags);
+				if (!res) {
+						/* update value and index */
+					res = update_object_id(ni,xo,
+						(const OBJECT_ID_ATTR*)value,
+						size);
+				}
+			} else {
+					/* GUID is present elsewhere */
+				res = -1;
+				errno = EEXIST;
+			}
+			xoni = xo->ni;
+			ntfs_index_entry_mark_dirty(xo);
+			NInoSetDirty(xoni);
+			ntfs_index_ctx_put(xo);
+			ntfs_inode_close(xoni);
+		} else {
+			res = -1;
+		}
+	} else {
+		errno = EINVAL;
+		res = -1;
+	}
+	return (res ? -1 : 0);
+}
+
+/*
+ *		Remove the object id
+ *
+ *	Returns 0, or -1 if there is a problem
+ */
+
+int ntfs_remove_ntfs_object_id(ntfs_inode *ni)
+{
+	int res;
+	int olderrno;
+	ntfs_attr *na;
+	ntfs_inode *xoni;
+	ntfs_index_context *xo;
+	int oldsize;
+	OBJECT_ID_ATTR old_attr;
+
+	res = 0;
+	if (ni) {
+		/*
+		 * open and delete the object id
+		 */
+		na = ntfs_attr_open(ni, AT_OBJECT_ID,
+			AT_UNNAMED,0);
+		if (na) {
+			/* first remove index (old object id needed) */
+			xo = open_object_id_index(ni->vol);
+			if (xo) {
+				oldsize = remove_object_id_index(na,xo,
+						&old_attr);
+				if (oldsize < 0) {
+					res = -1;
+				} else {
+					/* now remove attribute */
+					res = ntfs_attr_rm(na);
+					if (res
+					    && (oldsize > (int)sizeof(GUID))) {
+					/*
+					 * If we could not remove the
+					 * attribute, try to restore the
+					 * index and log the error. There
+					 * will be an inconsistency if
+					 * the reindexing fails.
+					 */
+						set_object_id_index(ni, xo,
+							&old_attr);
+						ntfs_log_error(
+						"Failed to remove object id."
+						" Possible corruption.\n");
+					}
+				}
+
+				xoni = xo->ni;
+				ntfs_index_entry_mark_dirty(xo);
+				NInoSetDirty(xoni);
+				ntfs_index_ctx_put(xo);
+				ntfs_inode_close(xoni);
+			}
+			olderrno = errno;
+			ntfs_attr_close(na);
+					/* avoid errno pollution */
+			if (errno == ENOENT)
+				errno = olderrno;
+		} else {
+			errno = ENODATA;
+			res = -1;
+		}
+		NInoSetDirty(ni);
+	} else {
+		errno = EINVAL;
+		res = -1;
+	}
+	return (res ? -1 : 0);
+}
+
+#endif /* HAVE_SETXATTR */
diff --git a/libntfs-3g/realpath.c b/libntfs-3g/realpath.c
new file mode 100755
index 0000000000000000000000000000000000000000..a93bc698eea6d259caa661693d53a7c1fe5f21a0
--- /dev/null
+++ b/libntfs-3g/realpath.c
@@ -0,0 +1,103 @@
+/*
+ * realpath.c - realpath() aware of device mapper
+ * Originated from the util-linux project.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+
+#include "param.h"
+#include "realpath.h"
+
+/* If there is no realpath() on the system, provide a dummy one. */
+#ifndef HAVE_REALPATH
+char *ntfs_realpath(const char *path, char *resolved_path)
+{
+       strncpy(resolved_path, path, PATH_MAX);
+       resolved_path[PATH_MAX] = '\0';
+       return resolved_path;
+}
+#endif
+
+
+#ifdef linux
+
+/*
+ * Converts private "dm-N" names to "/dev/mapper/<name>"
+ *
+ * Since 2.6.29 (patch 784aae735d9b0bba3f8b9faef4c8b30df3bf0128) kernel sysfs
+ * provides the real DM device names in /sys/block/<ptname>/dm/name
+ */
+static char *
+canonicalize_dm_name(const char *ptname, char *canonical)
+{
+	FILE	*f;
+	size_t	sz;
+	char	path[MAPPERNAMELTH + 24];
+	char	name[MAPPERNAMELTH + 16];
+	char	*res = NULL;
+
+	snprintf(path, sizeof(path), "/sys/block/%s/dm/name", ptname);
+	if (!(f = fopen(path, "r")))
+		return NULL;
+
+	/* read "<name>\n" from sysfs */
+	if (fgets(name, sizeof(name), f) && (sz = strlen(name)) > 1) {
+		name[sz - 1] = '\0';
+		snprintf(path, sizeof(path), "/dev/mapper/%s", name);
+		res = strcpy(canonical, path);
+	}
+	fclose(f);
+	return res;
+}
+
+/*
+ *		Canonicalize a device path
+ *
+ *	Workaround from "basinilya" for fixing device mapper paths.
+ *
+ *  Background (Phillip Susi, 2011-04-09)
+ *	- ntfs-3g canonicalizes the device name so that if you mount with
+ *	  /dev/mapper/foo, the device name listed in mtab is /dev/dm-n,
+ *	  so you can not umount /dev/mapper/foo
+ *	- umount won't even recognize and translate /dev/dm-n to the mount
+ *	  point, apparently because of the '-' involved. Editing mtab and
+ *	  removing the '-' allows you to umount /dev/dmn successfully.
+ *
+ *	This code restores the devmapper name after canonicalization,
+ *	until a proper fix is implemented.
+ */
+
+char *ntfs_realpath_canonicalize(const char *path, char *canonical)
+{
+	char *p;
+
+	if (path == NULL)
+		return NULL;
+
+	if (!ntfs_realpath(path, canonical))
+		return NULL;
+
+	p = strrchr(canonical, '/');
+	if (p && strncmp(p, "/dm-", 4) == 0 && isdigit(*(p + 4))) {
+		p = canonicalize_dm_name(p+1, canonical);
+		if (p)
+			return p;
+	}
+
+	return canonical;
+}
+
+#endif
diff --git a/libntfs-3g/reparse.c b/libntfs-3g/reparse.c
new file mode 100755
index 0000000000000000000000000000000000000000..7b96902c50fc26e70c86edcb2b7f9f5f7d2e41cb
--- /dev/null
+++ b/libntfs-3g/reparse.c
@@ -0,0 +1,1253 @@
+/**
+ * reparse.c - Processing of reparse points
+ *
+ *	This module is part of ntfs-3g library
+ *
+ * Copyright (c) 2008-2014 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_SETXATTR
+#include <sys/xattr.h>
+#endif
+
+#ifdef HAVE_SYS_SYSMACROS_H
+#include <sys/sysmacros.h>
+#endif
+
+#include "compat.h"
+#include "types.h"
+#include "debug.h"
+#include "layout.h"
+#include "attrib.h"
+#include "inode.h"
+#include "dir.h"
+#include "volume.h"
+#include "mft.h"
+#include "index.h"
+#include "lcnalloc.h"
+#include "logging.h"
+#include "misc.h"
+#include "reparse.h"
+
+struct MOUNT_POINT_REPARSE_DATA {      /* reparse data for junctions */
+	le16	subst_name_offset;
+	le16	subst_name_length;
+	le16	print_name_offset;
+	le16	print_name_length;
+	char	path_buffer[0];      /* above data assume this is char array */
+} ;
+
+struct SYMLINK_REPARSE_DATA {          /* reparse data for symlinks */
+	le16	subst_name_offset;
+	le16	subst_name_length;
+	le16	print_name_offset;
+	le16	print_name_length;
+	le32	flags;		     /* 1 for full target, otherwise 0 */
+	char	path_buffer[0];      /* above data assume this is char array */
+} ;
+
+struct REPARSE_INDEX {			/* index entry in $Extend/$Reparse */
+	INDEX_ENTRY_HEADER header;
+	REPARSE_INDEX_KEY key;
+	le32 filling;
+} ;
+
+static const ntfschar dir_junction_head[] = {
+	const_cpu_to_le16('\\'),
+	const_cpu_to_le16('?'),
+	const_cpu_to_le16('?'),
+	const_cpu_to_le16('\\')
+} ;
+
+static const ntfschar vol_junction_head[] = {
+	const_cpu_to_le16('\\'),
+	const_cpu_to_le16('?'),
+	const_cpu_to_le16('?'),
+	const_cpu_to_le16('\\'),
+	const_cpu_to_le16('V'),
+	const_cpu_to_le16('o'),
+	const_cpu_to_le16('l'),
+	const_cpu_to_le16('u'),
+	const_cpu_to_le16('m'),
+	const_cpu_to_le16('e'),
+	const_cpu_to_le16('{'),
+} ;
+
+static ntfschar reparse_index_name[] = { const_cpu_to_le16('$'),
+					 const_cpu_to_le16('R') };
+
+static const char mappingdir[] = ".NTFS-3G/";
+
+/*
+ *		Fix a file name with doubtful case in some directory index
+ *	and return the name with the casing used in directory.
+ *
+ *	Should only be used to translate paths stored with case insensitivity
+ *	(such as directory junctions) when no case conflict is expected.
+ *	If there some ambiguity, the name which collates first is returned.
+ *
+ *	The name is converted to upper case and searched the usual way.
+ *	The collation rules for file names are such that we should get the
+ *	first candidate if any.
+ */
+
+static u64 ntfs_fix_file_name(ntfs_inode *dir_ni, ntfschar *uname,
+		int uname_len)
+{
+	ntfs_volume *vol = dir_ni->vol;
+	ntfs_index_context *icx;
+	u64 mref;
+	le64 lemref;
+	int lkup;
+	int olderrno;
+	int i;
+	u32 cpuchar;
+	INDEX_ENTRY *entry;
+	FILE_NAME_ATTR *found;
+	struct {
+		FILE_NAME_ATTR attr;
+		ntfschar file_name[NTFS_MAX_NAME_LEN + 1];
+	} find;
+
+	mref = (u64)-1; /* default return (not found) */
+	icx = ntfs_index_ctx_get(dir_ni, NTFS_INDEX_I30, 4);
+	if (icx) {
+		if (uname_len > NTFS_MAX_NAME_LEN)
+			uname_len = NTFS_MAX_NAME_LEN;
+		find.attr.file_name_length = uname_len;
+		for (i=0; i<uname_len; i++) {
+			cpuchar = le16_to_cpu(uname[i]);
+			/*
+			 * We need upper or lower value, whichever is smaller,
+			 * but we can only convert to upper case, so we
+			 * will fail when searching for an upper case char
+			 * whose lower case is smaller (such as umlauted Y)
+			 */
+			if ((cpuchar < vol->upcase_len)
+			    && (le16_to_cpu(vol->upcase[cpuchar]) < cpuchar))
+				find.attr.file_name[i] = vol->upcase[cpuchar];
+			else
+				find.attr.file_name[i] = uname[i];
+		}
+		olderrno = errno;
+		lkup = ntfs_index_lookup((char*)&find, uname_len, icx);
+		if (errno == ENOENT)
+			errno = olderrno;
+		/*
+		 * We generally only get the first matching candidate,
+		 * so we still have to check whether this is a real match
+		 */
+		if (icx->entry && (icx->entry->ie_flags & INDEX_ENTRY_END))
+				/* get next entry if reaching end of block */
+			entry = ntfs_index_next(icx->entry, icx);
+		else
+			entry = icx->entry;
+		if (entry) {
+			found = &entry->key.file_name;
+			if (lkup
+			   && ntfs_names_are_equal(find.attr.file_name,
+				find.attr.file_name_length,
+				found->file_name, found->file_name_length,
+				IGNORE_CASE,
+				vol->upcase, vol->upcase_len))
+					lkup = 0;
+			if (!lkup) {
+				/*
+				 * name found :
+				 *    fix original name and return inode
+				 */
+				lemref = entry->indexed_file;
+				mref = le64_to_cpu(lemref);
+				if (NVolCaseSensitive(vol) || !vol->locase) {
+					for (i=0; i<found->file_name_length; i++)
+						uname[i] = found->file_name[i];
+				} else {
+					for (i=0; i<found->file_name_length; i++)
+						uname[i] = vol->locase[found->file_name[i]];
+				}
+			}
+		}
+		ntfs_index_ctx_put(icx);
+	}
+	return (mref);
+}
+
+/*
+ *		Search for a directory junction or a symbolic link
+ *	along the target path, with target defined as a full absolute path
+ *
+ *	Returns the path translated to a Linux path
+ *		or NULL if the path is not valid
+ */
+
+static char *search_absolute(ntfs_volume *vol, ntfschar *path,
+				int count, BOOL isdir)
+{
+	ntfs_inode *ni;
+	u64 inum;
+	char *target;
+	int start;
+	int len;
+
+	target = (char*)NULL; /* default return */
+	ni = ntfs_inode_open(vol, (MFT_REF)FILE_root);
+	if (ni) {
+		start = 0;
+		/*
+		 * Examine and translate the path, until we reach either
+		 *  - the end,
+		 *  - an unknown item
+		 *  - a non-directory
+		 *  - another reparse point,
+		 * A reparse point is not dereferenced, it will be
+		 * examined later when the translated path is dereferenced,
+		 * however the final part of the path will not be adjusted
+		 * to correct case.
+		 */
+		do {
+			len = 0;
+			while (((start + len) < count)
+			    && (path[start + len] != const_cpu_to_le16('\\')))
+				len++;
+			inum = ntfs_fix_file_name(ni, &path[start], len);
+			ntfs_inode_close(ni);
+			ni = (ntfs_inode*)NULL;
+			if (inum != (u64)-1) {
+				inum = MREF(inum);
+				ni = ntfs_inode_open(vol, inum);
+				start += len;
+				if (start < count)
+					path[start++] = const_cpu_to_le16('/');
+			}
+		} while (ni
+		    && (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
+		    && !(ni->flags & FILE_ATTR_REPARSE_POINT)
+		    && (start < count));
+	if (ni
+	    && ((ni->mrec->flags & MFT_RECORD_IS_DIRECTORY ? isdir : !isdir)
+		|| (ni->flags & FILE_ATTR_REPARSE_POINT)))
+		if (ntfs_ucstombs(path, count, &target, 0) < 0) {
+			if (target) {
+				free(target);
+				target = (char*)NULL;
+			}
+		}
+	if (ni)
+		ntfs_inode_close(ni);
+	}
+	return (target);
+}
+
+/*
+ *		Search for a symbolic link along the target path,
+ *	with the target defined as a relative path
+ *
+ *	Note : the path used to access the current inode, may be
+ *	different from the one implied in the target definition,
+ *	when an inode has names in several directories.
+ *
+ *	Returns the path translated to a Linux path
+ *		or NULL if the path is not valid
+ */
+
+static char *search_relative(ntfs_inode *ni, ntfschar *path, int count)
+{
+	char *target = (char*)NULL;
+	ntfs_inode *curni;
+	ntfs_inode *newni;
+	u64 inum;
+	int pos;
+	int lth;
+	BOOL ok;
+	BOOL morelinks;
+	int max = 32; /* safety */
+
+	pos = 0;
+	ok = TRUE;
+	morelinks = FALSE;
+	curni = ntfs_dir_parent_inode(ni);
+		/*
+		 * Examine and translate the path, until we reach either
+		 *  - the end,
+		 *  - an unknown item
+		 *  - a non-directory
+		 *  - another reparse point,
+		 * A reparse point is not dereferenced, it will be
+		 * examined later when the translated path is dereferenced,
+		 * however the final part of the path will not be adjusted
+		 * to correct case.
+		 */
+	while (curni && ok && !morelinks && (pos < (count - 1)) && --max) {
+		if ((count >= (pos + 2))
+		    && (path[pos] == const_cpu_to_le16('.'))
+		    && (path[pos+1] == const_cpu_to_le16('\\'))) {
+			path[pos+1] = const_cpu_to_le16('/');
+			pos += 2;
+		} else {
+			if ((count >= (pos + 3))
+			    && (path[pos] == const_cpu_to_le16('.'))
+			    &&(path[pos+1] == const_cpu_to_le16('.'))
+			    && (path[pos+2] == const_cpu_to_le16('\\'))) {
+				path[pos+2] = const_cpu_to_le16('/');
+				pos += 3;
+				newni = ntfs_dir_parent_inode(curni);
+				if (curni != ni)
+					ntfs_inode_close(curni);
+				curni = newni;
+				if (!curni)
+					ok = FALSE;
+			} else {
+				lth = 0;
+				while (((pos + lth) < count)
+				    && (path[pos + lth] != const_cpu_to_le16('\\')))
+					lth++;
+				if (lth > 0)
+					inum = ntfs_fix_file_name(curni,&path[pos],lth);
+				else
+					inum = (u64)-1;
+				if (!lth
+				    || ((curni != ni)
+					&& ntfs_inode_close(curni))
+				    || (inum == (u64)-1))
+					ok = FALSE;
+				else {
+					curni = ntfs_inode_open(ni->vol, MREF(inum));
+					if (!curni)
+						ok = FALSE;
+					else {
+						if (curni->flags & FILE_ATTR_REPARSE_POINT)
+							morelinks = TRUE;
+						if (ok && ((pos + lth) < count)) {
+							path[pos + lth] = const_cpu_to_le16('/');
+							pos += lth + 1;
+							if (morelinks
+							   && ntfs_inode_close(curni))
+								ok = FALSE;
+						} else {
+							pos += lth;
+							if (!morelinks
+							  && (ni->mrec->flags ^ curni->mrec->flags)
+							    & MFT_RECORD_IS_DIRECTORY)
+								ok = FALSE;
+							if (ntfs_inode_close(curni))
+								ok = FALSE;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	if (ok && (ntfs_ucstombs(path, count, &target, 0) < 0)) {
+		free(target); // needed ?
+		target = (char*)NULL;
+	}
+	return (target);
+}
+
+/*
+ *		Check whether a drive letter has been defined in .NTFS-3G
+ *
+ *	Returns 1 if found,
+ *		0 if not found,
+ *		-1 if there was an error (described by errno)
+ */
+
+static int ntfs_drive_letter(ntfs_volume *vol, ntfschar letter)
+{
+	char defines[NTFS_MAX_NAME_LEN + 5];
+	char *drive;
+	int ret;
+	int sz;
+	int olderrno;
+	ntfs_inode *ni;
+
+	ret = -1;
+	drive = (char*)NULL;
+	sz = ntfs_ucstombs(&letter, 1, &drive, 0);
+	if (sz > 0) {
+		strcpy(defines,mappingdir);
+		if ((*drive >= 'a') && (*drive <= 'z'))
+			*drive += 'A' - 'a';
+		strcat(defines,drive);
+		strcat(defines,":");
+		olderrno = errno;
+		ni = ntfs_pathname_to_inode(vol, NULL, defines);
+		if (ni && !ntfs_inode_close(ni))
+			ret = 1;
+		else
+			if (errno == ENOENT) {
+				ret = 0;
+					/* avoid errno pollution */
+				errno = olderrno;
+			}
+	}
+	if (drive)
+		free(drive);
+	return (ret);
+}
+
+/*
+ *		Do some sanity checks on reparse data
+ *
+ *	The only general check is about the size (at least the tag must
+ *	be present)
+ *	If the reparse data looks like a junction point or symbolic
+ *	link, more checks can be done.
+ *
+ */
+
+static BOOL valid_reparse_data(ntfs_inode *ni,
+			const REPARSE_POINT *reparse_attr, size_t size)
+{
+	BOOL ok;
+	unsigned int offs;
+	unsigned int lth;
+	const struct MOUNT_POINT_REPARSE_DATA *mount_point_data;
+	const struct SYMLINK_REPARSE_DATA *symlink_data;
+
+	ok = ni && reparse_attr
+		&& (size >= sizeof(REPARSE_POINT))
+		&& (((size_t)le16_to_cpu(reparse_attr->reparse_data_length)
+				 + sizeof(REPARSE_POINT)) == size);
+	if (ok) {
+		switch (reparse_attr->reparse_tag) {
+		case IO_REPARSE_TAG_MOUNT_POINT :
+			mount_point_data = (const struct MOUNT_POINT_REPARSE_DATA*)
+						reparse_attr->reparse_data;
+			offs = le16_to_cpu(mount_point_data->subst_name_offset);
+			lth = le16_to_cpu(mount_point_data->subst_name_length);
+				/* consistency checks */
+			if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
+			    || ((size_t)((sizeof(REPARSE_POINT)
+				 + sizeof(struct MOUNT_POINT_REPARSE_DATA)
+				 + offs + lth)) > size))
+				ok = FALSE;
+			break;
+		case IO_REPARSE_TAG_SYMLINK :
+			symlink_data = (const struct SYMLINK_REPARSE_DATA*)
+						reparse_attr->reparse_data;
+			offs = le16_to_cpu(symlink_data->subst_name_offset);
+			lth = le16_to_cpu(symlink_data->subst_name_length);
+			if ((size_t)((sizeof(REPARSE_POINT)
+				 + sizeof(struct SYMLINK_REPARSE_DATA)
+				 + offs + lth)) > size)
+				ok = FALSE;
+			break;
+		default :
+			break;
+		}
+	}
+	if (!ok)
+		errno = EINVAL;
+	return (ok);
+}
+
+/*
+ *		Check and translate the target of a junction point or
+ *	a full absolute symbolic link.
+ *
+ *	A full target definition begins with "\??\" or "\\?\"
+ *
+ *	The fully defined target is redefined as a relative link,
+ *		- either to the target if found on the same device.
+ *		- or into the /.NTFS-3G directory for the user to define
+ *	In the first situation, the target is translated to case-sensitive path.
+ *
+ *	returns the target converted to a relative symlink
+ *		or NULL if there were some problem, as described by errno
+ */
+
+static char *ntfs_get_fulllink(ntfs_volume *vol, ntfschar *junction,
+			int count, const char *mnt_point, BOOL isdir)
+{
+	char *target;
+	char *fulltarget;
+	int sz;
+	char *q;
+	enum { DIR_JUNCTION, VOL_JUNCTION, NO_JUNCTION } kind;
+
+	target = (char*)NULL;
+	fulltarget = (char*)NULL;
+			/*
+			 * For a valid directory junction we want \??\x:\
+			 * where \ is an individual char and x a non-null char
+			 */
+	if ((count >= 7)
+	    && !memcmp(junction,dir_junction_head,8)
+	    && junction[4]
+	    && (junction[5] == const_cpu_to_le16(':'))
+	    && (junction[6] == const_cpu_to_le16('\\')))
+		kind = DIR_JUNCTION;
+	else
+			/*
+			 * For a valid volume junction we want \\?\Volume{
+			 * and a final \ (where \ is an individual char)
+			 */
+		if ((count >= 12)
+		    && !memcmp(junction,vol_junction_head,22)
+		    && (junction[count-1] == const_cpu_to_le16('\\')))
+			kind = VOL_JUNCTION;
+		else
+			kind = NO_JUNCTION;
+			/*
+			 * Directory junction with an explicit path and
+			 * no specific definition for the drive letter :
+			 * try to interpret as a target on the same volume
+			 */
+	if ((kind == DIR_JUNCTION)
+	    && (count >= 7)
+	    && junction[7]
+	    && !ntfs_drive_letter(vol, junction[4])) {
+		target = search_absolute(vol,&junction[7],count - 7, isdir);
+		if (target) {
+			fulltarget = (char*)ntfs_malloc(strlen(mnt_point)
+					+ strlen(target) + 2);
+			if (fulltarget) {
+				strcpy(fulltarget,mnt_point);
+				strcat(fulltarget,"/");
+				strcat(fulltarget,target);
+			}
+			free(target);
+		}
+	}
+			/*
+			 * Volume junctions or directory junctions with
+			 * target not found on current volume :
+			 * link to /.NTFS-3G/target which the user can
+			 * define as a symbolic link to the real target
+			 */
+	if (((kind == DIR_JUNCTION) && !fulltarget)
+	    || (kind == VOL_JUNCTION)) {
+		sz = ntfs_ucstombs(&junction[4],
+			(kind == VOL_JUNCTION ? count - 5 : count - 4),
+			&target, 0);
+		if ((sz > 0) && target) {
+				/* reverse slashes */
+			for (q=target; *q; q++)
+				if (*q == '\\')
+					*q = '/';
+				/* force uppercase drive letter */
+			if ((target[1] == ':')
+			    && (target[0] >= 'a')
+			    && (target[0] <= 'z'))
+				target[0] += 'A' - 'a';
+			fulltarget = (char*)ntfs_malloc(strlen(mnt_point)
+				    + sizeof(mappingdir) + strlen(target) + 1);
+			if (fulltarget) {
+				strcpy(fulltarget,mnt_point);
+				strcat(fulltarget,"/");
+				strcat(fulltarget,mappingdir);
+				strcat(fulltarget,target);
+			}
+		}
+		if (target)
+			free(target);
+	}
+	return (fulltarget);
+}
+
+/*
+ *		Check and translate the target of an absolute symbolic link.
+ *
+ *	An absolute target definition begins with "\" or "x:\"
+ *
+ *	The absolute target is redefined as a relative link,
+ *		- either to the target if found on the same device.
+ *		- or into the /.NTFS-3G directory for the user to define
+ *	In the first situation, the target is translated to case-sensitive path.
+ *
+ *	returns the target converted to a relative symlink
+ *		or NULL if there were some problem, as described by errno
+ */
+
+static char *ntfs_get_abslink(ntfs_volume *vol, ntfschar *junction,
+			int count, const char *mnt_point, BOOL isdir)
+{
+	char *target;
+	char *fulltarget;
+	int sz;
+	char *q;
+	enum { FULL_PATH, ABS_PATH, REJECTED_PATH } kind;
+
+	target = (char*)NULL;
+	fulltarget = (char*)NULL;
+			/*
+			 * For a full valid path we want x:\
+			 * where \ is an individual char and x a non-null char
+			 */
+	if ((count >= 3)
+	    && junction[0]
+	    && (junction[1] == const_cpu_to_le16(':'))
+	    && (junction[2] == const_cpu_to_le16('\\')))
+		kind = FULL_PATH;
+	else
+			/*
+			 * For an absolute path we want an initial \
+			 */
+		if ((count >= 0)
+		    && (junction[0] == const_cpu_to_le16('\\')))
+			kind = ABS_PATH;
+		else
+			kind = REJECTED_PATH;
+			/*
+			 * Full path, with a drive letter and
+			 * no specific definition for the drive letter :
+			 * try to interpret as a target on the same volume.
+			 * Do the same for an abs path with no drive letter.
+			 */
+	if (((kind == FULL_PATH)
+	    && (count >= 3)
+	    && junction[3]
+	    && !ntfs_drive_letter(vol, junction[0]))
+	    || (kind == ABS_PATH)) {
+		if (kind == ABS_PATH)
+			target = search_absolute(vol, &junction[1],
+				count - 1, isdir);
+		else
+			target = search_absolute(vol, &junction[3],
+				count - 3, isdir);
+		if (target) {
+			fulltarget = (char*)ntfs_malloc(strlen(mnt_point)
+					+ strlen(target) + 2);
+			if (fulltarget) {
+				strcpy(fulltarget,mnt_point);
+				strcat(fulltarget,"/");
+				strcat(fulltarget,target);
+			}
+			free(target);
+		}
+	}
+			/*
+			 * full path with target not found on current volume :
+			 * link to /.NTFS-3G/target which the user can
+			 * define as a symbolic link to the real target
+			 */
+	if ((kind == FULL_PATH) && !fulltarget) {
+		sz = ntfs_ucstombs(&junction[0],
+			count,&target, 0);
+		if ((sz > 0) && target) {
+				/* reverse slashes */
+			for (q=target; *q; q++)
+				if (*q == '\\')
+					*q = '/';
+				/* force uppercase drive letter */
+			if ((target[1] == ':')
+			    && (target[0] >= 'a')
+			    && (target[0] <= 'z'))
+				target[0] += 'A' - 'a';
+			fulltarget = (char*)ntfs_malloc(strlen(mnt_point)
+				    + sizeof(mappingdir) + strlen(target) + 1);
+			if (fulltarget) {
+				strcpy(fulltarget,mnt_point);
+				strcat(fulltarget,"/");
+				strcat(fulltarget,mappingdir);
+				strcat(fulltarget,target);
+			}
+		}
+		if (target)
+			free(target);
+	}
+	return (fulltarget);
+}
+
+/*
+ *		Check and translate the target of a relative symbolic link.
+ *
+ *	A relative target definition does not begin with "\"
+ *
+ *	The original definition of relative target is kept, it is just
+ *	translated to a case-sensitive path.
+ *
+ *	returns the target converted to a relative symlink
+ *		or NULL if there were some problem, as described by errno
+ */
+
+static char *ntfs_get_rellink(ntfs_inode *ni, ntfschar *junction, int count)
+{
+	char *target;
+
+	target = search_relative(ni,junction,count);
+	return (target);
+}
+
+/*
+ *		Get the target for a junction point or symbolic link
+ *	Should only be called for files or directories with reparse data
+ *
+ *	returns the target converted to a relative path, or NULL
+ *		if some error occurred, as described by errno
+ *		errno is EOPNOTSUPP if the reparse point is not a valid
+ *			symbolic link or directory junction
+ */
+
+char *ntfs_make_symlink(ntfs_inode *ni, const char *mnt_point,
+			int *pattr_size)
+{
+	s64 attr_size = 0;
+	char *target;
+	unsigned int offs;
+	unsigned int lth;
+	ntfs_volume *vol;
+	REPARSE_POINT *reparse_attr;
+	struct MOUNT_POINT_REPARSE_DATA *mount_point_data;
+	struct SYMLINK_REPARSE_DATA *symlink_data;
+	enum { FULL_TARGET, ABS_TARGET, REL_TARGET } kind;
+	ntfschar *p;
+	BOOL bad;
+	BOOL isdir;
+
+	target = (char*)NULL;
+	bad = TRUE;
+	isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
+			 != const_cpu_to_le16(0);
+	vol = ni->vol;
+	reparse_attr = (REPARSE_POINT*)ntfs_attr_readall(ni,
+			AT_REPARSE_POINT,(ntfschar*)NULL, 0, &attr_size);
+	if (reparse_attr && attr_size
+			&& valid_reparse_data(ni, reparse_attr, attr_size)) {
+		switch (reparse_attr->reparse_tag) {
+		case IO_REPARSE_TAG_MOUNT_POINT :
+			mount_point_data = (struct MOUNT_POINT_REPARSE_DATA*)
+						reparse_attr->reparse_data;
+			offs = le16_to_cpu(mount_point_data->subst_name_offset);
+			lth = le16_to_cpu(mount_point_data->subst_name_length);
+				/* reparse data consistency has been checked */
+			target = ntfs_get_fulllink(vol,
+				(ntfschar*)&mount_point_data->path_buffer[offs],
+				lth/2, mnt_point, isdir);
+			if (target)
+				bad = FALSE;
+			break;
+		case IO_REPARSE_TAG_SYMLINK :
+			symlink_data = (struct SYMLINK_REPARSE_DATA*)
+						reparse_attr->reparse_data;
+			offs = le16_to_cpu(symlink_data->subst_name_offset);
+			lth = le16_to_cpu(symlink_data->subst_name_length);
+			p = (ntfschar*)&symlink_data->path_buffer[offs];
+				/*
+				 * Predetermine the kind of target,
+				 * the called function has to make a full check
+				 */
+			if (*p++ == const_cpu_to_le16('\\')) {
+				if ((*p == const_cpu_to_le16('?'))
+				    || (*p == const_cpu_to_le16('\\')))
+					kind = FULL_TARGET;
+				else
+					kind = ABS_TARGET;
+			} else
+				if (*p == const_cpu_to_le16(':'))
+					kind = ABS_TARGET;
+				else
+					kind = REL_TARGET;
+			p--;
+				/* reparse data consistency has been checked */
+			switch (kind) {
+			case FULL_TARGET :
+				if (!(symlink_data->flags
+				   & const_cpu_to_le32(1))) {
+					target = ntfs_get_fulllink(vol,
+						p, lth/2,
+						mnt_point, isdir);
+					if (target)
+						bad = FALSE;
+				}
+				break;
+			case ABS_TARGET :
+				if (symlink_data->flags
+				   & const_cpu_to_le32(1)) {
+					target = ntfs_get_abslink(vol,
+						p, lth/2,
+						mnt_point, isdir);
+					if (target)
+						bad = FALSE;
+				}
+				break;
+			case REL_TARGET :
+				if (symlink_data->flags
+				   & const_cpu_to_le32(1)) {
+					target = ntfs_get_rellink(ni,
+						p, lth/2);
+					if (target)
+						bad = FALSE;
+				}
+				break;
+			}
+			break;
+		}
+		free(reparse_attr);
+	}
+	*pattr_size = attr_size;
+	if (bad)
+		errno = EOPNOTSUPP;
+	return (target);
+}
+
+/*
+ *		Check whether a reparse point looks like a junction point
+ *	or a symbolic link.
+ *	Should only be called for files or directories with reparse data
+ *
+ *	The validity of the target is not checked.
+ */
+
+BOOL ntfs_possible_symlink(ntfs_inode *ni)
+{
+	s64 attr_size = 0;
+	REPARSE_POINT *reparse_attr;
+	BOOL possible;
+
+	possible = FALSE;
+	reparse_attr = (REPARSE_POINT*)ntfs_attr_readall(ni,
+			AT_REPARSE_POINT,(ntfschar*)NULL, 0, &attr_size);
+	if (reparse_attr && attr_size) {
+		switch (reparse_attr->reparse_tag) {
+		case IO_REPARSE_TAG_MOUNT_POINT :
+		case IO_REPARSE_TAG_SYMLINK :
+			possible = TRUE;
+		default : ;
+		}
+		free(reparse_attr);
+	}
+	return (possible);
+}
+
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+
+/*
+ *			Set the index for new reparse data
+ *
+ *	Returns 0 if success
+ *		-1 if failure, explained by errno
+ */
+
+static int set_reparse_index(ntfs_inode *ni, ntfs_index_context *xr,
+			le32 reparse_tag)
+{
+	struct REPARSE_INDEX indx;
+	u64 file_id_cpu;
+	le64 file_id;
+	le16 seqn;
+
+	seqn = ni->mrec->sequence_number;
+	file_id_cpu = MK_MREF(ni->mft_no,le16_to_cpu(seqn));
+	file_id = cpu_to_le64(file_id_cpu);
+	indx.header.data_offset = const_cpu_to_le16(
+					sizeof(INDEX_ENTRY_HEADER)
+					+ sizeof(REPARSE_INDEX_KEY));
+	indx.header.data_length = const_cpu_to_le16(0);
+	indx.header.reservedV = const_cpu_to_le32(0);
+	indx.header.length = const_cpu_to_le16(
+					sizeof(struct REPARSE_INDEX));
+	indx.header.key_length = const_cpu_to_le16(
+					sizeof(REPARSE_INDEX_KEY));
+	indx.header.flags = const_cpu_to_le16(0);
+	indx.header.reserved = const_cpu_to_le16(0);
+	indx.key.reparse_tag = reparse_tag;
+		/* danger on processors which require proper alignment ! */
+	memcpy(&indx.key.file_id, &file_id, 8);
+	indx.filling = const_cpu_to_le32(0);
+	ntfs_index_ctx_reinit(xr);
+	return (ntfs_ie_add(xr,(INDEX_ENTRY*)&indx));
+}
+
+#endif /* HAVE_SETXATTR */
+
+/*
+ *		Remove a reparse data index entry if attribute present
+ *
+ *	Returns the size of existing reparse data
+ *			(the existing reparse tag is returned)
+ *		-1 if failure, explained by errno
+ */
+
+static int remove_reparse_index(ntfs_attr *na, ntfs_index_context *xr,
+				le32 *preparse_tag)
+{
+	REPARSE_INDEX_KEY key;
+	u64 file_id_cpu;
+	le64 file_id;
+	s64 size;
+	le16 seqn;
+	int ret;
+
+	ret = na->data_size;
+	if (ret) {
+			/* read the existing reparse_tag */
+		size = ntfs_attr_pread(na, 0, 4, preparse_tag);
+		if (size == 4) {
+			seqn = na->ni->mrec->sequence_number;
+			file_id_cpu = MK_MREF(na->ni->mft_no,le16_to_cpu(seqn));
+			file_id = cpu_to_le64(file_id_cpu);
+			key.reparse_tag = *preparse_tag;
+		/* danger on processors which require proper alignment ! */
+			memcpy(&key.file_id, &file_id, 8);
+			if (!ntfs_index_lookup(&key, sizeof(REPARSE_INDEX_KEY), xr)
+			    && ntfs_index_rm(xr))
+				ret = -1;
+		} else {
+			ret = -1;
+			errno = ENODATA;
+		}
+	}
+	return (ret);
+}
+
+/*
+ *		Open the $Extend/$Reparse file and its index
+ *
+ *	Return the index context if opened
+ *		or NULL if an error occurred (errno tells why)
+ *
+ *	The index has to be freed and inode closed when not needed any more.
+ */
+
+static ntfs_index_context *open_reparse_index(ntfs_volume *vol)
+{
+	u64 inum;
+	ntfs_inode *ni;
+	ntfs_inode *dir_ni;
+	ntfs_index_context *xr;
+
+		/* do not use path_name_to inode - could reopen root */
+	dir_ni = ntfs_inode_open(vol, FILE_Extend);
+	ni = (ntfs_inode*)NULL;
+	if (dir_ni) {
+		inum = ntfs_inode_lookup_by_mbsname(dir_ni,"$Reparse");
+		if (inum != (u64)-1)
+			ni = ntfs_inode_open(vol, inum);
+		ntfs_inode_close(dir_ni);
+	}
+	if (ni) {
+		xr = ntfs_index_ctx_get(ni, reparse_index_name, 2);
+		if (!xr) {
+			ntfs_inode_close(ni);
+		}
+	} else
+		xr = (ntfs_index_context*)NULL;
+	return (xr);
+}
+
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+
+/*
+ *		Update the reparse data and index
+ *
+ *	The reparse data attribute should have been created, and
+ *	an existing index is expected if there is an existing value.
+ *
+ *	Returns 0 if success
+ *		-1 if failure, explained by errno
+ *	If could not remove the existing index, nothing is done,
+ *	If could not write the new data, no index entry is inserted
+ *	If failed to insert the index, data is removed
+ */
+
+static int update_reparse_data(ntfs_inode *ni, ntfs_index_context *xr,
+			const char *value, size_t size)
+{
+	int res;
+	int written;
+	int oldsize;
+	ntfs_attr *na;
+	le32 reparse_tag;
+
+	res = 0;
+	na = ntfs_attr_open(ni, AT_REPARSE_POINT, AT_UNNAMED, 0);
+	if (na) {
+			/* remove the existing reparse data */
+		oldsize = remove_reparse_index(na,xr,&reparse_tag);
+		if (oldsize < 0)
+			res = -1;
+		else {
+			/* 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 "
+						"reparse data\n");
+					errno = EIO;
+					res = -1;
+				}
+			}
+			if (!res
+			    && set_reparse_index(ni,xr,
+				((const REPARSE_POINT*)value)->reparse_tag)
+			    && (oldsize > 0)) {
+				/*
+				 * If cannot index, try to remove the reparse
+				 * data and log the error. There will be an
+				 * inconsistency if removal fails.
+				 */
+				ntfs_attr_rm(na);
+				ntfs_log_error("Failed to index reparse data."
+						" Possible corruption.\n");
+			}
+		}
+		ntfs_attr_close(na);
+		NInoSetDirty(ni);
+	} else
+		res = -1;
+	return (res);
+}
+
+#endif /* HAVE_SETXATTR */
+
+/*
+ *		Delete a reparse index entry
+ *
+ *	Returns 0 if success
+ *		-1 if failure, explained by errno
+ */
+
+int ntfs_delete_reparse_index(ntfs_inode *ni)
+{
+	ntfs_index_context *xr;
+	ntfs_inode *xrni;
+	ntfs_attr *na;
+	le32 reparse_tag;
+	int res;
+
+	res = 0;
+	na = ntfs_attr_open(ni, AT_REPARSE_POINT, AT_UNNAMED, 0);
+	if (na) {
+			/*
+			 * read the existing reparse data (the tag is enough)
+			 * and un-index it
+			 */
+		xr = open_reparse_index(ni->vol);
+		if (xr) {
+			if (remove_reparse_index(na,xr,&reparse_tag) < 0)
+				res = -1;
+			xrni = xr->ni;
+			ntfs_index_entry_mark_dirty(xr);
+			NInoSetDirty(xrni);
+			ntfs_index_ctx_put(xr);
+			ntfs_inode_close(xrni);
+		}
+		ntfs_attr_close(na);
+	}
+	return (res);
+}
+
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+
+/*
+ *		Get the ntfs reparse data into an extended attribute
+ *
+ *	Returns the reparse data size
+ *		and the buffer is updated if it is long enough
+ */
+
+int ntfs_get_ntfs_reparse_data(ntfs_inode *ni, char *value, size_t size)
+{
+	REPARSE_POINT *reparse_attr;
+	s64 attr_size;
+
+	attr_size = 0;	/* default to no data and no error */
+	if (ni) {
+		if (ni->flags & FILE_ATTR_REPARSE_POINT) {
+			reparse_attr = (REPARSE_POINT*)ntfs_attr_readall(ni,
+				AT_REPARSE_POINT,(ntfschar*)NULL, 0, &attr_size);
+			if (reparse_attr) {
+				if (attr_size <= (s64)size) {
+					if (value)
+						memcpy(value,reparse_attr,
+							attr_size);
+					else
+						errno = EINVAL;
+				}
+				free(reparse_attr);
+			}
+		} else
+			errno = ENODATA;
+	}
+	return (attr_size ? (int)attr_size : -errno);
+}
+
+/*
+ *		Set the reparse data from an extended attribute
+ *
+ *	Warning : the new data is not checked
+ *
+ *	Returns 0, or -1 if there is a problem
+ */
+
+int ntfs_set_ntfs_reparse_data(ntfs_inode *ni,
+			const char *value, size_t size, int flags)
+{
+	int res;
+	u8 dummy;
+	ntfs_inode *xrni;
+	ntfs_index_context *xr;
+
+	res = 0;
+			/* reparse data is not compatible with EA */
+	if (ni
+	    && !ntfs_attr_exist(ni, AT_EA_INFORMATION, AT_UNNAMED, 0)
+	    && !ntfs_attr_exist(ni, AT_EA, AT_UNNAMED, 0)
+	    && valid_reparse_data(ni, (const REPARSE_POINT*)value, size)) {
+		xr = open_reparse_index(ni->vol);
+		if (xr) {
+			if (!ntfs_attr_exist(ni,AT_REPARSE_POINT,
+						AT_UNNAMED,0)) {
+				if (!(flags & XATTR_REPLACE)) {
+			/*
+			 * no reparse data 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,
+							AT_REPARSE_POINT,
+							AT_UNNAMED,0,&dummy,
+							(s64)0);
+						if (!res) {
+						    ni->flags |=
+							FILE_ATTR_REPARSE_POINT;
+						    NInoFileNameSetDirty(ni);
+						}
+						NInoSetDirty(ni);
+					} else {
+						errno = EOPNOTSUPP;
+						res = -1;
+					}
+				} else {
+					errno = ENODATA;
+					res = -1;
+				}
+			} else {
+				if (flags & XATTR_CREATE) {
+					errno = EEXIST;
+					res = -1;
+				}
+			}
+			if (!res) {
+					/* update value and index */
+				res = update_reparse_data(ni,xr,value,size);
+			}
+			xrni = xr->ni;
+			ntfs_index_entry_mark_dirty(xr);
+			NInoSetDirty(xrni);
+			ntfs_index_ctx_put(xr);
+			ntfs_inode_close(xrni);
+		} else {
+			res = -1;
+		}
+	} else {
+		errno = EINVAL;
+		res = -1;
+	}
+	return (res ? -1 : 0);
+}
+
+/*
+ *		Remove the reparse data
+ *
+ *	Returns 0, or -1 if there is a problem
+ */
+
+int ntfs_remove_ntfs_reparse_data(ntfs_inode *ni)
+{
+	int res;
+	int olderrno;
+	ntfs_attr *na;
+	ntfs_inode *xrni;
+	ntfs_index_context *xr;
+	le32 reparse_tag;
+
+	res = 0;
+	if (ni) {
+		/*
+		 * open and delete the reparse data
+		 */
+		na = ntfs_attr_open(ni, AT_REPARSE_POINT,
+			AT_UNNAMED,0);
+		if (na) {
+			/* first remove index (reparse data needed) */
+			xr = open_reparse_index(ni->vol);
+			if (xr) {
+				if (remove_reparse_index(na,xr,
+						&reparse_tag) < 0) {
+					res = -1;
+				} else {
+					/* now remove attribute */
+					res = ntfs_attr_rm(na);
+					if (!res) {
+						ni->flags &=
+						    ~FILE_ATTR_REPARSE_POINT;
+						NInoFileNameSetDirty(ni);
+					} else {
+					/*
+					 * If we could not remove the
+					 * attribute, try to restore the
+					 * index and log the error. There
+					 * will be an inconsistency if
+					 * the reindexing fails.
+					 */
+						set_reparse_index(ni, xr,
+							reparse_tag);
+						ntfs_log_error(
+						"Failed to remove reparse data."
+						" Possible corruption.\n");
+					}
+				}
+				xrni = xr->ni;
+				ntfs_index_entry_mark_dirty(xr);
+				NInoSetDirty(xrni);
+				ntfs_index_ctx_put(xr);
+				ntfs_inode_close(xrni);
+			}
+			olderrno = errno;
+			ntfs_attr_close(na);
+					/* avoid errno pollution */
+			if (errno == ENOENT)
+				errno = olderrno;
+		} else {
+			errno = ENODATA;
+			res = -1;
+		}
+		NInoSetDirty(ni);
+	} else {
+		errno = EINVAL;
+		res = -1;
+	}
+	return (res ? -1 : 0);
+}
+
+#endif /* HAVE_SETXATTR */
diff --git a/libntfs-3g/runlist.c b/libntfs-3g/runlist.c
new file mode 100755
index 0000000000000000000000000000000000000000..7e158d443a33d93772db3a0cc752074195fd768d
--- /dev/null
+++ b/libntfs-3g/runlist.c
@@ -0,0 +1,2174 @@
+/**
+ * runlist.c - Run list handling code. Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2002-2005 Anton Altaparmakov
+ * Copyright (c) 2002-2005 Richard Russon
+ * Copyright (c) 2002-2008 Szabolcs Szakacsits
+ * Copyright (c) 2004 Yura Pakhuchiy
+ * 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
+ * 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_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "compat.h"
+#include "types.h"
+#include "volume.h"
+#include "layout.h"
+#include "debug.h"
+#include "device.h"
+#include "logging.h"
+#include "misc.h"
+
+/**
+ * ntfs_rl_mm - runlist memmove
+ * @base:
+ * @dst:
+ * @src:
+ * @size:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static void ntfs_rl_mm(runlist_element *base, int dst, int src, int size)
+{
+	if ((dst != src) && (size > 0))
+		memmove(base + dst, base + src, size * sizeof(*base));
+}
+
+/**
+ * ntfs_rl_mc - runlist memory copy
+ * @dstbase:
+ * @dst:
+ * @srcbase:
+ * @src:
+ * @size:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static void ntfs_rl_mc(runlist_element *dstbase, int dst,
+		       runlist_element *srcbase, int src, int size)
+{
+	if (size > 0)
+		memcpy(dstbase + dst, srcbase + src, size * sizeof(*dstbase));
+}
+
+/**
+ * ntfs_rl_realloc - Reallocate memory for runlists
+ * @rl:		original runlist
+ * @old_size:	number of runlist elements in the original runlist @rl
+ * @new_size:	number of runlist elements we need space for
+ *
+ * As the runlists grow, more memory will be required. To prevent large
+ * numbers of small reallocations of memory, this function returns a 4kiB block
+ * of memory.
+ *
+ * N.B.	If the new allocation doesn't require a different number of 4kiB
+ *	blocks in memory, the function will return the original pointer.
+ *
+ * On success, return a pointer to the newly allocated, or recycled, memory.
+ * On error, return NULL with errno set to the error code.
+ */
+static runlist_element *ntfs_rl_realloc(runlist_element *rl, int old_size, 
+					int new_size)
+{
+	old_size = (old_size * sizeof(runlist_element) + 0xfff) & ~0xfff;
+	new_size = (new_size * sizeof(runlist_element) + 0xfff) & ~0xfff;
+	if (old_size == new_size)
+		return rl;
+	return realloc(rl, new_size);
+}
+
+/*
+ *		Extend a runlist by some entry count
+ *	The runlist may have to be reallocated
+ *
+ *	Returns the reallocated runlist
+ *		or NULL if reallocation was not possible (with errno set)
+ *		the runlist is left unchanged if the reallocation fails
+ */
+
+runlist_element *ntfs_rl_extend(ntfs_attr *na, runlist_element *rl,
+			int more_entries)
+{
+	runlist_element *newrl;
+	int last;
+	int irl;
+
+	if (na->rl && rl) {
+		irl = (int)(rl - na->rl);
+		last = irl;
+		while (na->rl[last].length)
+			last++;
+		newrl = ntfs_rl_realloc(na->rl,last+1,last+more_entries+1);
+		if (!newrl) {
+			errno = ENOMEM;
+			rl = (runlist_element*)NULL;
+		} else {
+			na->rl = newrl;
+			rl = &newrl[irl];
+		}
+	} else {
+		ntfs_log_error("Cannot extend unmapped runlist");
+		errno = EIO;
+		rl = (runlist_element*)NULL;
+	}
+	return (rl);
+}
+
+/**
+ * ntfs_rl_are_mergeable - test if two runlists can be joined together
+ * @dst:	original runlist
+ * @src:	new runlist to test for mergeability with @dst
+ *
+ * Test if two runlists can be joined together. For this, their VCNs and LCNs
+ * must be adjacent.
+ *
+ * Return: TRUE   Success, the runlists can be merged.
+ *	   FALSE  Failure, the runlists cannot be merged.
+ */
+static BOOL ntfs_rl_are_mergeable(runlist_element *dst, runlist_element *src)
+{
+	if (!dst || !src) {
+		ntfs_log_debug("Eeek. ntfs_rl_are_mergeable() invoked with NULL "
+				"pointer!\n");
+		return FALSE;
+	}
+
+	/* We can merge unmapped regions even if they are misaligned. */
+	if ((dst->lcn == LCN_RL_NOT_MAPPED) && (src->lcn == LCN_RL_NOT_MAPPED))
+		return TRUE;
+	/* If the runs are misaligned, we cannot merge them. */
+	if ((dst->vcn + dst->length) != src->vcn)
+		return FALSE;
+	/* If both runs are non-sparse and contiguous, we can merge them. */
+	if ((dst->lcn >= 0) && (src->lcn >= 0) &&
+		((dst->lcn + dst->length) == src->lcn))
+		return TRUE;
+	/* If we are merging two holes, we can merge them. */
+	if ((dst->lcn == LCN_HOLE) && (src->lcn == LCN_HOLE))
+		return TRUE;
+	/* Cannot merge. */
+	return FALSE;
+}
+
+/**
+ * __ntfs_rl_merge - merge two runlists without testing if they can be merged
+ * @dst:	original, destination runlist
+ * @src:	new runlist to merge with @dst
+ *
+ * Merge the two runlists, writing into the destination runlist @dst. The
+ * caller must make sure the runlists can be merged or this will corrupt the
+ * destination runlist.
+ */
+static void __ntfs_rl_merge(runlist_element *dst, runlist_element *src)
+{
+	dst->length += src->length;
+}
+
+/**
+ * ntfs_rl_append - append a runlist after a given element
+ * @dst:	original runlist to be worked on
+ * @dsize:	number of elements in @dst (including end marker)
+ * @src:	runlist to be inserted into @dst
+ * @ssize:	number of elements in @src (excluding end marker)
+ * @loc:	append the new runlist @src after this element in @dst
+ *
+ * Append the runlist @src after element @loc in @dst.  Merge the right end of
+ * the new runlist, if necessary. Adjust the size of the hole before the
+ * appended runlist.
+ *
+ * On success, return a pointer to the new, combined, runlist. Note, both
+ * runlists @dst and @src are deallocated before returning so you cannot use
+ * the pointers for anything any more. (Strictly speaking the returned runlist
+ * may be the same as @dst but this is irrelevant.)
+ *
+ * On error, return NULL, with errno set to the error code. Both runlists are
+ * left unmodified.
+ */
+static runlist_element *ntfs_rl_append(runlist_element *dst, int dsize,
+				       runlist_element *src, int ssize, int loc)
+{
+	BOOL right = FALSE;	/* Right end of @src needs merging */
+	int marker;		/* End of the inserted runs */
+
+	if (!dst || !src) {
+		ntfs_log_debug("Eeek. ntfs_rl_append() invoked with NULL "
+				"pointer!\n");
+		errno = EINVAL;
+		return NULL;
+	}
+
+	/* First, check if the right hand end needs merging. */
+	if ((loc + 1) < dsize)
+		right = ntfs_rl_are_mergeable(src + ssize - 1, dst + loc + 1);
+
+	/* Space required: @dst size + @src size, less one if we merged. */
+	dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - right);
+	if (!dst)
+		return NULL;
+	/*
+	 * We are guaranteed to succeed from here so can start modifying the
+	 * original runlists.
+	 */
+
+	/* First, merge the right hand end, if necessary. */
+	if (right)
+		__ntfs_rl_merge(src + ssize - 1, dst + loc + 1);
+
+	/* marker - First run after the @src runs that have been inserted */
+	marker = loc + ssize + 1;
+
+	/* Move the tail of @dst out of the way, then copy in @src. */
+	ntfs_rl_mm(dst, marker, loc + 1 + right, dsize - loc - 1 - right);
+	ntfs_rl_mc(dst, loc + 1, src, 0, ssize);
+
+	/* Adjust the size of the preceding hole. */
+	dst[loc].length = dst[loc + 1].vcn - dst[loc].vcn;
+
+	/* We may have changed the length of the file, so fix the end marker */
+	if (dst[marker].lcn == LCN_ENOENT)
+		dst[marker].vcn = dst[marker-1].vcn + dst[marker-1].length;
+
+	return dst;
+}
+
+/**
+ * ntfs_rl_insert - insert a runlist into another
+ * @dst:	original runlist to be worked on
+ * @dsize:	number of elements in @dst (including end marker)
+ * @src:	new runlist to be inserted
+ * @ssize:	number of elements in @src (excluding end marker)
+ * @loc:	insert the new runlist @src before this element in @dst
+ *
+ * Insert the runlist @src before element @loc in the runlist @dst. Merge the
+ * left end of the new runlist, if necessary. Adjust the size of the hole
+ * after the inserted runlist.
+ *
+ * On success, return a pointer to the new, combined, runlist. Note, both
+ * runlists @dst and @src are deallocated before returning so you cannot use
+ * the pointers for anything any more. (Strictly speaking the returned runlist
+ * may be the same as @dst but this is irrelevant.)
+ *
+ * On error, return NULL, with errno set to the error code. Both runlists are
+ * left unmodified.
+ */
+static runlist_element *ntfs_rl_insert(runlist_element *dst, int dsize,
+				       runlist_element *src, int ssize, int loc)
+{
+	BOOL left = FALSE;	/* Left end of @src needs merging */
+	BOOL disc = FALSE;	/* Discontinuity between @dst and @src */
+	int marker;		/* End of the inserted runs */
+
+	if (!dst || !src) {
+		ntfs_log_debug("Eeek. ntfs_rl_insert() invoked with NULL "
+				"pointer!\n");
+		errno = EINVAL;
+		return NULL;
+	}
+
+	/* disc => Discontinuity between the end of @dst and the start of @src.
+	 *	   This means we might need to insert a "notmapped" run.
+	 */
+	if (loc == 0)
+		disc = (src[0].vcn > 0);
+	else {
+		s64 merged_length;
+
+		left = ntfs_rl_are_mergeable(dst + loc - 1, src);
+
+		merged_length = dst[loc - 1].length;
+		if (left)
+			merged_length += src->length;
+
+		disc = (src[0].vcn > dst[loc - 1].vcn + merged_length);
+	}
+
+	/* Space required: @dst size + @src size, less one if we merged, plus
+	 * one if there was a discontinuity.
+	 */
+	dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left + disc);
+	if (!dst)
+		return NULL;
+	/*
+	 * We are guaranteed to succeed from here so can start modifying the
+	 * original runlist.
+	 */
+
+	if (left)
+		__ntfs_rl_merge(dst + loc - 1, src);
+
+	/*
+	 * marker - First run after the @src runs that have been inserted
+	 * Nominally: marker = @loc + @ssize (location + number of runs in @src)
+	 * If "left", then the first run in @src has been merged with one in @dst.
+	 * If "disc", then @dst and @src don't meet and we need an extra run to fill the gap.
+	 */
+	marker = loc + ssize - left + disc;
+
+	/* Move the tail of @dst out of the way, then copy in @src. */
+	ntfs_rl_mm(dst, marker, loc, dsize - loc);
+	ntfs_rl_mc(dst, loc + disc, src, left, ssize - left);
+
+	/* Adjust the VCN of the first run after the insertion ... */
+	dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length;
+	/* ... and the length. */
+	if (dst[marker].lcn == LCN_HOLE || dst[marker].lcn == LCN_RL_NOT_MAPPED)
+		dst[marker].length = dst[marker + 1].vcn - dst[marker].vcn;
+
+	/* Writing beyond the end of the file and there's a discontinuity. */
+	if (disc) {
+		if (loc > 0) {
+			dst[loc].vcn = dst[loc - 1].vcn + dst[loc - 1].length;
+			dst[loc].length = dst[loc + 1].vcn - dst[loc].vcn;
+		} else {
+			dst[loc].vcn = 0;
+			dst[loc].length = dst[loc + 1].vcn;
+		}
+		dst[loc].lcn = LCN_RL_NOT_MAPPED;
+	}
+	return dst;
+}
+
+/**
+ * ntfs_rl_replace - overwrite a runlist element with another runlist
+ * @dst:	original runlist to be worked on
+ * @dsize:	number of elements in @dst (including end marker)
+ * @src:	new runlist to be inserted
+ * @ssize:	number of elements in @src (excluding end marker)
+ * @loc:	index in runlist @dst to overwrite with @src
+ *
+ * Replace the runlist element @dst at @loc with @src. Merge the left and
+ * right ends of the inserted runlist, if necessary.
+ *
+ * On success, return a pointer to the new, combined, runlist. Note, both
+ * runlists @dst and @src are deallocated before returning so you cannot use
+ * the pointers for anything any more. (Strictly speaking the returned runlist
+ * may be the same as @dst but this is irrelevant.)
+ *
+ * On error, return NULL, with errno set to the error code. Both runlists are
+ * left unmodified.
+ */
+static runlist_element *ntfs_rl_replace(runlist_element *dst, int dsize,
+					runlist_element *src, int ssize, 
+					int loc)
+{
+	signed delta;
+	BOOL left  = FALSE;	/* Left end of @src needs merging */
+	BOOL right = FALSE;	/* Right end of @src needs merging */
+	int tail;		/* Start of tail of @dst */
+	int marker;		/* End of the inserted runs */
+
+	if (!dst || !src) {
+		ntfs_log_debug("Eeek. ntfs_rl_replace() invoked with NULL "
+				"pointer!\n");
+		errno = EINVAL;
+		return NULL;
+	}
+
+	/* First, see if the left and right ends need merging. */
+	if ((loc + 1) < dsize)
+		right = ntfs_rl_are_mergeable(src + ssize - 1, dst + loc + 1);
+	if (loc > 0)
+		left = ntfs_rl_are_mergeable(dst + loc - 1, src);
+
+	/* Allocate some space. We'll need less if the left, right, or both
+	 * ends get merged.  The -1 accounts for the run being replaced.
+	 */
+	delta = ssize - 1 - left - right;
+	if (delta > 0) {
+		dst = ntfs_rl_realloc(dst, dsize, dsize + delta);
+		if (!dst)
+			return NULL;
+	}
+	/*
+	 * We are guaranteed to succeed from here so can start modifying the
+	 * original runlists.
+	 */
+
+	/* First, merge the left and right ends, if necessary. */
+	if (right)
+		__ntfs_rl_merge(src + ssize - 1, dst + loc + 1);
+	if (left)
+		__ntfs_rl_merge(dst + loc - 1, src);
+
+	/*
+	 * tail - Offset of the tail of @dst
+	 * Nominally: @tail = @loc + 1 (location, skipping the replaced run)
+	 * If "right", then one of @dst's runs is already merged into @src.
+	 */
+	tail = loc + right + 1;
+
+	/*
+	 * marker - First run after the @src runs that have been inserted
+	 * Nominally: @marker = @loc + @ssize (location + number of runs in @src)
+	 * If "left", then the first run in @src has been merged with one in @dst.
+	 */
+	marker = loc + ssize - left;
+
+	/* Move the tail of @dst out of the way, then copy in @src. */
+	ntfs_rl_mm(dst, marker, tail, dsize - tail);
+	ntfs_rl_mc(dst, loc, src, left, ssize - left);
+
+	/* We may have changed the length of the file, so fix the end marker */
+	if (((dsize - tail) > 0) && (dst[marker].lcn == LCN_ENOENT))
+		dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length;
+
+	return dst;
+}
+
+/**
+ * ntfs_rl_split - insert a runlist into the centre of a hole
+ * @dst:	original runlist to be worked on
+ * @dsize:	number of elements in @dst (including end marker)
+ * @src:	new runlist to be inserted
+ * @ssize:	number of elements in @src (excluding end marker)
+ * @loc:	index in runlist @dst at which to split and insert @src
+ *
+ * Split the runlist @dst at @loc into two and insert @new in between the two
+ * fragments. No merging of runlists is necessary. Adjust the size of the
+ * holes either side.
+ *
+ * On success, return a pointer to the new, combined, runlist. Note, both
+ * runlists @dst and @src are deallocated before returning so you cannot use
+ * the pointers for anything any more. (Strictly speaking the returned runlist
+ * may be the same as @dst but this is irrelevant.)
+ *
+ * On error, return NULL, with errno set to the error code. Both runlists are
+ * left unmodified.
+ */
+static runlist_element *ntfs_rl_split(runlist_element *dst, int dsize,
+				      runlist_element *src, int ssize, int loc)
+{
+	if (!dst || !src) {
+		ntfs_log_debug("Eeek. ntfs_rl_split() invoked with NULL pointer!\n");
+		errno = EINVAL;
+		return NULL;
+	}
+
+	/* Space required: @dst size + @src size + one new hole. */
+	dst = ntfs_rl_realloc(dst, dsize, dsize + ssize + 1);
+	if (!dst)
+		return dst;
+	/*
+	 * We are guaranteed to succeed from here so can start modifying the
+	 * original runlists.
+	 */
+
+	/* Move the tail of @dst out of the way, then copy in @src. */
+	ntfs_rl_mm(dst, loc + 1 + ssize, loc, dsize - loc);
+	ntfs_rl_mc(dst, loc + 1, src, 0, ssize);
+
+	/* Adjust the size of the holes either size of @src. */
+	dst[loc].length		= dst[loc+1].vcn       - dst[loc].vcn;
+	dst[loc+ssize+1].vcn	= dst[loc+ssize].vcn   + dst[loc+ssize].length;
+	dst[loc+ssize+1].length	= dst[loc+ssize+2].vcn - dst[loc+ssize+1].vcn;
+
+	return dst;
+}
+
+
+/**
+ * ntfs_runlists_merge_i - see ntfs_runlists_merge
+ */
+static runlist_element *ntfs_runlists_merge_i(runlist_element *drl, 
+					      runlist_element *srl)
+{
+	int di, si;		/* Current index into @[ds]rl. */
+	int sstart;		/* First index with lcn > LCN_RL_NOT_MAPPED. */
+	int dins;		/* Index into @drl at which to insert @srl. */
+	int dend, send;		/* Last index into @[ds]rl. */
+	int dfinal, sfinal;	/* The last index into @[ds]rl with
+				   lcn >= LCN_HOLE. */
+	int marker = 0;
+	VCN marker_vcn = 0;
+
+	ntfs_log_debug("dst:\n");
+	ntfs_debug_runlist_dump(drl);
+	ntfs_log_debug("src:\n");
+	ntfs_debug_runlist_dump(srl);
+
+	/* Check for silly calling... */
+	if (!srl)
+		return drl;
+
+	/* Check for the case where the first mapping is being done now. */
+	if (!drl) {
+		drl = srl;
+		/* Complete the source runlist if necessary. */
+		if (drl[0].vcn) {
+			/* Scan to the end of the source runlist. */
+			for (dend = 0; drl[dend].length; dend++)
+				;
+			dend++;
+			drl = ntfs_rl_realloc(drl, dend, dend + 1);
+			if (!drl)
+				return drl;
+			/* Insert start element at the front of the runlist. */
+			ntfs_rl_mm(drl, 1, 0, dend);
+			drl[0].vcn = 0;
+			drl[0].lcn = LCN_RL_NOT_MAPPED;
+			drl[0].length = drl[1].vcn;
+		}
+		goto finished;
+	}
+
+	si = di = 0;
+
+	/* Skip any unmapped start element(s) in the source runlist. */
+	while (srl[si].length && srl[si].lcn < (LCN)LCN_HOLE)
+		si++;
+
+	/* Can't have an entirely unmapped source runlist. */
+	if (!srl[si].length) {
+		errno = EINVAL;
+		ntfs_log_perror("%s: unmapped source runlist", __FUNCTION__);
+		return NULL;
+	}
+
+	/* Record the starting points. */
+	sstart = si;
+
+	/*
+	 * Skip forward in @drl until we reach the position where @srl needs to
+	 * be inserted. If we reach the end of @drl, @srl just needs to be
+	 * appended to @drl.
+	 */
+	for (; drl[di].length; di++) {
+		if (drl[di].vcn + drl[di].length > srl[sstart].vcn)
+			break;
+	}
+	dins = di;
+
+	/* Sanity check for illegal overlaps. */
+	if ((drl[di].vcn == srl[si].vcn) && (drl[di].lcn >= 0) &&
+			(srl[si].lcn >= 0)) {
+		errno = ERANGE;
+		ntfs_log_perror("Run lists overlap. Cannot merge");
+		return NULL;
+	}
+
+	/* Scan to the end of both runlists in order to know their sizes. */
+	for (send = si; srl[send].length; send++)
+		;
+	for (dend = di; drl[dend].length; dend++)
+		;
+
+	if (srl[send].lcn == (LCN)LCN_ENOENT)
+		marker_vcn = srl[marker = send].vcn;
+
+	/* Scan to the last element with lcn >= LCN_HOLE. */
+	for (sfinal = send; sfinal >= 0 && srl[sfinal].lcn < LCN_HOLE; sfinal--)
+		;
+	for (dfinal = dend; dfinal >= 0 && drl[dfinal].lcn < LCN_HOLE; dfinal--)
+		;
+
+	{
+	BOOL start;
+	BOOL finish;
+	int ds = dend + 1;		/* Number of elements in drl & srl */
+	int ss = sfinal - sstart + 1;
+
+	start  = ((drl[dins].lcn <  LCN_RL_NOT_MAPPED) ||    /* End of file   */
+		  (drl[dins].vcn == srl[sstart].vcn));	     /* Start of hole */
+	finish = ((drl[dins].lcn >= LCN_RL_NOT_MAPPED) &&    /* End of file   */
+		 ((drl[dins].vcn + drl[dins].length) <=      /* End of hole   */
+		  (srl[send - 1].vcn + srl[send - 1].length)));
+
+	/* Or we'll lose an end marker */
+	if (finish && !drl[dins].length)
+		ss++;
+	if (marker && (drl[dins].vcn + drl[dins].length > srl[send - 1].vcn))
+		finish = FALSE;
+
+	ntfs_log_debug("dfinal = %i, dend = %i\n", dfinal, dend);
+	ntfs_log_debug("sstart = %i, sfinal = %i, send = %i\n", sstart, sfinal, send);
+	ntfs_log_debug("start = %i, finish = %i\n", start, finish);
+	ntfs_log_debug("ds = %i, ss = %i, dins = %i\n", ds, ss, dins);
+
+	if (start) {
+		if (finish)
+			drl = ntfs_rl_replace(drl, ds, srl + sstart, ss, dins);
+		else
+			drl = ntfs_rl_insert(drl, ds, srl + sstart, ss, dins);
+	} else {
+		if (finish)
+			drl = ntfs_rl_append(drl, ds, srl + sstart, ss, dins);
+		else
+			drl = ntfs_rl_split(drl, ds, srl + sstart, ss, dins);
+	}
+	if (!drl) {
+		ntfs_log_perror("Merge failed");
+		return drl;
+	}
+	free(srl);
+	if (marker) {
+		ntfs_log_debug("Triggering marker code.\n");
+		for (ds = dend; drl[ds].length; ds++)
+			;
+		/* We only need to care if @srl ended after @drl. */
+		if (drl[ds].vcn <= marker_vcn) {
+			int slots = 0;
+
+			if (drl[ds].vcn == marker_vcn) {
+				ntfs_log_debug("Old marker = %lli, replacing with "
+						"LCN_ENOENT.\n",
+						(long long)drl[ds].lcn);
+				drl[ds].lcn = (LCN)LCN_ENOENT;
+				goto finished;
+			}
+			/*
+			 * We need to create an unmapped runlist element in
+			 * @drl or extend an existing one before adding the
+			 * ENOENT terminator.
+			 */
+			if (drl[ds].lcn == (LCN)LCN_ENOENT) {
+				ds--;
+				slots = 1;
+			}
+			if (drl[ds].lcn != (LCN)LCN_RL_NOT_MAPPED) {
+				/* Add an unmapped runlist element. */
+				if (!slots) {
+					/* FIXME/TODO: We need to have the
+					 * extra memory already! (AIA)
+					 */
+					drl = ntfs_rl_realloc(drl, ds, ds + 2);
+					if (!drl)
+						goto critical_error;
+					slots = 2;
+				}
+				ds++;
+				/* Need to set vcn if it isn't set already. */
+				if (slots != 1)
+					drl[ds].vcn = drl[ds - 1].vcn +
+							drl[ds - 1].length;
+				drl[ds].lcn = (LCN)LCN_RL_NOT_MAPPED;
+				/* We now used up a slot. */
+				slots--;
+			}
+			drl[ds].length = marker_vcn - drl[ds].vcn;
+			/* Finally add the ENOENT terminator. */
+			ds++;
+			if (!slots) {
+				/* FIXME/TODO: We need to have the extra
+				 * memory already! (AIA)
+				 */
+				drl = ntfs_rl_realloc(drl, ds, ds + 1);
+				if (!drl)
+					goto critical_error;
+			}
+			drl[ds].vcn = marker_vcn;
+			drl[ds].lcn = (LCN)LCN_ENOENT;
+			drl[ds].length = (s64)0;
+		}
+	}
+	}
+
+finished:
+	/* The merge was completed successfully. */
+	ntfs_log_debug("Merged runlist:\n");
+	ntfs_debug_runlist_dump(drl);
+	return drl;
+
+critical_error:
+	/* Critical error! We cannot afford to fail here. */
+	ntfs_log_perror("libntfs: Critical error");
+	ntfs_log_debug("Forcing segmentation fault!\n");
+	marker_vcn = ((runlist*)NULL)->lcn;
+	return drl;
+}
+
+/**
+ * ntfs_runlists_merge - merge two runlists into one
+ * @drl:	original runlist to be worked on
+ * @srl:	new runlist to be merged into @drl
+ *
+ * First we sanity check the two runlists @srl and @drl to make sure that they
+ * are sensible and can be merged. The runlist @srl must be either after the
+ * runlist @drl or completely within a hole (or unmapped region) in @drl.
+ *
+ * Merging of runlists is necessary in two cases:
+ *   1. When attribute lists are used and a further extent is being mapped.
+ *   2. When new clusters are allocated to fill a hole or extend a file.
+ *
+ * There are four possible ways @srl can be merged. It can:
+ *	- be inserted at the beginning of a hole,
+ *	- split the hole in two and be inserted between the two fragments,
+ *	- be appended at the end of a hole, or it can
+ *	- replace the whole hole.
+ * It can also be appended to the end of the runlist, which is just a variant
+ * of the insert case.
+ *
+ * On success, return a pointer to the new, combined, runlist. Note, both
+ * runlists @drl and @srl are deallocated before returning so you cannot use
+ * the pointers for anything any more. (Strictly speaking the returned runlist
+ * may be the same as @dst but this is irrelevant.)
+ *
+ * On error, return NULL, with errno set to the error code. Both runlists are
+ * left unmodified. The following error codes are defined:
+ *	ENOMEM		Not enough memory to allocate runlist array.
+ *	EINVAL		Invalid parameters were passed in.
+ *	ERANGE		The runlists overlap and cannot be merged.
+ */
+runlist_element *ntfs_runlists_merge(runlist_element *drl,
+		runlist_element *srl)
+{
+	runlist_element *rl; 
+	
+	ntfs_log_enter("Entering\n");
+	rl = ntfs_runlists_merge_i(drl, srl);
+	ntfs_log_leave("\n");
+	return rl;
+}
+
+/**
+ * ntfs_mapping_pairs_decompress - convert mapping pairs array to runlist
+ * @vol:	ntfs volume on which the attribute resides
+ * @attr:	attribute record whose mapping pairs array to decompress
+ * @old_rl:	optional runlist in which to insert @attr's runlist
+ *
+ * Decompress the attribute @attr's mapping pairs array into a runlist. On
+ * success, return the decompressed runlist.
+ *
+ * If @old_rl is not NULL, decompressed runlist is inserted into the
+ * appropriate place in @old_rl and the resultant, combined runlist is
+ * returned. The original @old_rl is deallocated.
+ *
+ * On error, return NULL with errno set to the error code. @old_rl is left
+ * unmodified in that case.
+ *
+ * The following error codes are defined:
+ *	ENOMEM		Not enough memory to allocate runlist array.
+ *	EIO		Corrupt runlist.
+ *	EINVAL		Invalid parameters were passed in.
+ *	ERANGE		The two runlists overlap.
+ *
+ * FIXME: For now we take the conceptionally simplest approach of creating the
+ * new runlist disregarding the already existing one and then splicing the
+ * two into one, if that is possible (we check for overlap and discard the new
+ * runlist if overlap present before returning NULL, with errno = ERANGE).
+ */
+static runlist_element *ntfs_mapping_pairs_decompress_i(const ntfs_volume *vol,
+		const ATTR_RECORD *attr, runlist_element *old_rl)
+{
+	VCN vcn;		/* Current vcn. */
+	LCN lcn;		/* Current lcn. */
+	s64 deltaxcn;		/* Change in [vl]cn. */
+	runlist_element *rl;	/* The output runlist. */
+	const u8 *buf;		/* Current position in mapping pairs array. */
+	const u8 *attr_end;	/* End of attribute. */
+	int err, rlsize;	/* Size of runlist buffer. */
+	u16 rlpos;		/* Current runlist position in units of
+				   runlist_elements. */
+	u8 b;			/* Current byte offset in buf. */
+
+	ntfs_log_trace("Entering for attr 0x%x.\n",
+			(unsigned)le32_to_cpu(attr->type));
+	/* Make sure attr exists and is non-resident. */
+	if (!attr || !attr->non_resident ||
+			sle64_to_cpu(attr->lowest_vcn) < (VCN)0) {
+		errno = EINVAL;
+		return NULL;
+	}
+	/* Start at vcn = lowest_vcn and lcn 0. */
+	vcn = sle64_to_cpu(attr->lowest_vcn);
+	lcn = 0;
+	/* Get start of the mapping pairs array. */
+	buf = (const u8*)attr + le16_to_cpu(attr->mapping_pairs_offset);
+	attr_end = (const u8*)attr + le32_to_cpu(attr->length);
+	if (buf < (const u8*)attr || buf > attr_end) {
+		ntfs_log_debug("Corrupt attribute.\n");
+		errno = EIO;
+		return NULL;
+	}
+	/* Current position in runlist array. */
+	rlpos = 0;
+	/* Allocate first 4kiB block and set current runlist size to 4kiB. */
+	rlsize = 0x1000;
+	rl = ntfs_malloc(rlsize);
+	if (!rl)
+		return NULL;
+	/* Insert unmapped starting element if necessary. */
+	if (vcn) {
+		rl->vcn = (VCN)0;
+		rl->lcn = (LCN)LCN_RL_NOT_MAPPED;
+		rl->length = vcn;
+		rlpos++;
+	}
+	while (buf < attr_end && *buf) {
+		/*
+		 * Allocate more memory if needed, including space for the
+		 * not-mapped and terminator elements.
+		 */
+		if ((int)((rlpos + 3) * sizeof(*old_rl)) > rlsize) {
+			runlist_element *rl2;
+
+			rlsize += 0x1000;
+			rl2 = realloc(rl, rlsize);
+			if (!rl2) {
+				int eo = errno;
+				free(rl);
+				errno = eo;
+				return NULL;
+			}
+			rl = rl2;
+		}
+		/* Enter the current vcn into the current runlist element. */
+		rl[rlpos].vcn = vcn;
+		/*
+		 * Get the change in vcn, i.e. the run length in clusters.
+		 * Doing it this way ensures that we signextend negative values.
+		 * A negative run length doesn't make any sense, but hey, I
+		 * didn't make up the NTFS specs and Windows NT4 treats the run
+		 * length as a signed value so that's how it is...
+		 */
+		b = *buf & 0xf;
+		if (b) {
+			if (buf + b > attr_end)
+				goto io_error;
+			for (deltaxcn = (s8)buf[b--]; b; b--)
+				deltaxcn = (deltaxcn << 8) + buf[b];
+		} else { /* The length entry is compulsory. */
+			ntfs_log_debug("Missing length entry in mapping pairs "
+					"array.\n");
+			deltaxcn = (s64)-1;
+		}
+		/*
+		 * Assume a negative length to indicate data corruption and
+		 * hence clean-up and return NULL.
+		 */
+		if (deltaxcn < 0) {
+			ntfs_log_debug("Invalid length in mapping pairs array.\n");
+			goto err_out;
+		}
+		/*
+		 * Enter the current run length into the current runlist
+		 * element.
+		 */
+		rl[rlpos].length = deltaxcn;
+		/* Increment the current vcn by the current run length. */
+		vcn += deltaxcn;
+		/*
+		 * There might be no lcn change at all, as is the case for
+		 * sparse clusters on NTFS 3.0+, in which case we set the lcn
+		 * to LCN_HOLE.
+		 */
+		if (!(*buf & 0xf0))
+			rl[rlpos].lcn = (LCN)LCN_HOLE;
+		else {
+			/* Get the lcn change which really can be negative. */
+			u8 b2 = *buf & 0xf;
+			b = b2 + ((*buf >> 4) & 0xf);
+			if (buf + b > attr_end)
+				goto io_error;
+			for (deltaxcn = (s8)buf[b--]; b > b2; b--)
+				deltaxcn = (deltaxcn << 8) + buf[b];
+			/* Change the current lcn to it's new value. */
+			lcn += deltaxcn;
+#ifdef DEBUG
+			/*
+			 * On NTFS 1.2-, apparently can have lcn == -1 to
+			 * indicate a hole. But we haven't verified ourselves
+			 * whether it is really the lcn or the deltaxcn that is
+			 * -1. So if either is found give us a message so we
+			 * can investigate it further!
+			 */
+			if (vol->major_ver < 3) {
+				if (deltaxcn == (LCN)-1)
+					ntfs_log_debug("lcn delta == -1\n");
+				if (lcn == (LCN)-1)
+					ntfs_log_debug("lcn == -1\n");
+			}
+#endif
+			/* Check lcn is not below -1. */
+			if (lcn < (LCN)-1) {
+				ntfs_log_debug("Invalid LCN < -1 in mapping pairs "
+						"array.\n");
+				goto err_out;
+			}
+			/* Enter the current lcn into the runlist element. */
+			rl[rlpos].lcn = lcn;
+		}
+		/* Get to the next runlist element. */
+		rlpos++;
+		/* Increment the buffer position to the next mapping pair. */
+		buf += (*buf & 0xf) + ((*buf >> 4) & 0xf) + 1;
+	}
+	if (buf >= attr_end)
+		goto io_error;
+	/*
+	 * If there is a highest_vcn specified, it must be equal to the final
+	 * vcn in the runlist - 1, or something has gone badly wrong.
+	 */
+	deltaxcn = sle64_to_cpu(attr->highest_vcn);
+	if (deltaxcn && vcn - 1 != deltaxcn) {
+mpa_err:
+		ntfs_log_debug("Corrupt mapping pairs array in non-resident "
+				"attribute.\n");
+		goto err_out;
+	}
+	/* Setup not mapped runlist element if this is the base extent. */
+	if (!attr->lowest_vcn) {
+		VCN max_cluster;
+
+		max_cluster = ((sle64_to_cpu(attr->allocated_size) +
+				vol->cluster_size - 1) >>
+				vol->cluster_size_bits) - 1;
+		/*
+		 * A highest_vcn of zero means this is a single extent
+		 * attribute so simply terminate the runlist with LCN_ENOENT).
+		 */
+		if (deltaxcn) {
+			/*
+			 * If there is a difference between the highest_vcn and
+			 * the highest cluster, the runlist is either corrupt
+			 * or, more likely, there are more extents following
+			 * this one.
+			 */
+			if (deltaxcn < max_cluster) {
+				ntfs_log_debug("More extents to follow; deltaxcn = "
+						"0x%llx, max_cluster = 0x%llx\n",
+						(long long)deltaxcn,
+						(long long)max_cluster);
+				rl[rlpos].vcn = vcn;
+				vcn += rl[rlpos].length = max_cluster - deltaxcn;
+				rl[rlpos].lcn = (LCN)LCN_RL_NOT_MAPPED;
+				rlpos++;
+			} else if (deltaxcn > max_cluster) {
+				ntfs_log_debug("Corrupt attribute. deltaxcn = "
+						"0x%llx, max_cluster = 0x%llx\n",
+						(long long)deltaxcn,
+						(long long)max_cluster);
+				goto mpa_err;
+			}
+		}
+		rl[rlpos].lcn = (LCN)LCN_ENOENT;
+	} else /* Not the base extent. There may be more extents to follow. */
+		rl[rlpos].lcn = (LCN)LCN_RL_NOT_MAPPED;
+
+	/* Setup terminating runlist element. */
+	rl[rlpos].vcn = vcn;
+	rl[rlpos].length = (s64)0;
+	/* If no existing runlist was specified, we are done. */
+	if (!old_rl) {
+		ntfs_log_debug("Mapping pairs array successfully decompressed:\n");
+		ntfs_debug_runlist_dump(rl);
+		return rl;
+	}
+	/* Now combine the new and old runlists checking for overlaps. */
+	old_rl = ntfs_runlists_merge(old_rl, rl);
+	if (old_rl)
+		return old_rl;
+	err = errno;
+	free(rl);
+	ntfs_log_debug("Failed to merge runlists.\n");
+	errno = err;
+	return NULL;
+io_error:
+	ntfs_log_debug("Corrupt attribute.\n");
+err_out:
+	free(rl);
+	errno = EIO;
+	return NULL;
+}
+
+runlist_element *ntfs_mapping_pairs_decompress(const ntfs_volume *vol,
+		const ATTR_RECORD *attr, runlist_element *old_rl)
+{
+	runlist_element *rle; 
+	
+	ntfs_log_enter("Entering\n");
+	rle = ntfs_mapping_pairs_decompress_i(vol, attr, old_rl);
+	ntfs_log_leave("\n");
+	return rle;
+}
+
+/**
+ * ntfs_rl_vcn_to_lcn - convert a vcn into a lcn given a runlist
+ * @rl:		runlist to use for conversion
+ * @vcn:	vcn to convert
+ *
+ * Convert the virtual cluster number @vcn of an attribute into a logical
+ * cluster number (lcn) of a device using the runlist @rl to map vcns to their
+ * corresponding lcns.
+ *
+ * Since lcns must be >= 0, we use negative return values with special meaning:
+ *
+ * Return value			Meaning / Description
+ * ==================================================
+ *  -1 = LCN_HOLE		Hole / not allocated on disk.
+ *  -2 = LCN_RL_NOT_MAPPED	This is part of the runlist which has not been
+ *				inserted into the runlist yet.
+ *  -3 = LCN_ENOENT		There is no such vcn in the attribute.
+ *  -4 = LCN_EINVAL		Input parameter error.
+ */
+LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn)
+{
+	int i;
+
+	if (vcn < (VCN)0)
+		return (LCN)LCN_EINVAL;
+	/*
+	 * If rl is NULL, assume that we have found an unmapped runlist. The
+	 * caller can then attempt to map it and fail appropriately if
+	 * necessary.
+	 */
+	if (!rl)
+		return (LCN)LCN_RL_NOT_MAPPED;
+
+	/* Catch out of lower bounds vcn. */
+	if (vcn < rl[0].vcn)
+		return (LCN)LCN_ENOENT;
+
+	for (i = 0; rl[i].length; i++) {
+		if (vcn < rl[i+1].vcn) {
+			if (rl[i].lcn >= (LCN)0)
+				return rl[i].lcn + (vcn - rl[i].vcn);
+			return rl[i].lcn;
+		}
+	}
+	/*
+	 * The terminator element is setup to the correct value, i.e. one of
+	 * LCN_HOLE, LCN_RL_NOT_MAPPED, or LCN_ENOENT.
+	 */
+	if (rl[i].lcn < (LCN)0)
+		return rl[i].lcn;
+	/* Just in case... We could replace this with BUG() some day. */
+	return (LCN)LCN_ENOENT;
+}
+
+/**
+ * ntfs_rl_pread - gather read from disk
+ * @vol:	ntfs volume to read from
+ * @rl:		runlist specifying where to read the data from
+ * @pos:	byte position within runlist @rl at which to begin the read
+ * @count:	number of bytes to read
+ * @b:		data buffer into which to read from disk
+ *
+ * This function will read @count bytes from the volume @vol to the data buffer
+ * @b gathering the data as specified by the runlist @rl. The read begins at
+ * offset @pos into the runlist @rl.
+ *
+ * On success, return the number of successfully read bytes. If this number is
+ * lower than @count this means that the read reached end of file or that an
+ * error was encountered during the read so that the read is partial. 0 means
+ * nothing was read (also return 0 when @count is 0).
+ *
+ * On error and nothing has been read, return -1 with errno set appropriately
+ * to the return code of ntfs_pread(), or to EINVAL in case of invalid
+ * arguments.
+ *
+ * NOTE: If we encounter EOF while reading we return EIO because we assume that
+ * the run list must point to valid locations within the ntfs volume.
+ */
+s64 ntfs_rl_pread(const ntfs_volume *vol, const runlist_element *rl,
+		const s64 pos, s64 count, void *b)
+{
+	s64 bytes_read, to_read, ofs, total;
+	int err = EIO;
+
+	if (!vol || !rl || pos < 0 || count < 0) {
+		errno = EINVAL;
+		ntfs_log_perror("Failed to read runlist [vol: %p rl: %p "
+				"pos: %lld count: %lld]", vol, rl,
+				(long long)pos, (long long)count);
+		return -1;
+	}
+	if (!count)
+		return count;
+	/* Seek in @rl to the run containing @pos. */
+	for (ofs = 0; rl->length && (ofs + (rl->length <<
+			vol->cluster_size_bits) <= pos); rl++)
+		ofs += (rl->length << vol->cluster_size_bits);
+	/* Offset in the run at which to begin reading. */
+	ofs = pos - ofs;
+	for (total = 0LL; count; rl++, ofs = 0) {
+		if (!rl->length)
+			goto rl_err_out;
+		if (rl->lcn < (LCN)0) {
+			if (rl->lcn != (LCN)LCN_HOLE)
+				goto rl_err_out;
+			/* It is a hole. Just fill buffer @b with zeroes. */
+			to_read = min(count, (rl->length <<
+					vol->cluster_size_bits) - ofs);
+			memset(b, 0, to_read);
+			/* Update counters and proceed with next run. */
+			total += to_read;
+			count -= to_read;
+			b = (u8*)b + to_read;
+			continue;
+		}
+		/* It is a real lcn, read it from the volume. */
+		to_read = min(count, (rl->length << vol->cluster_size_bits) -
+				ofs);
+retry:
+		bytes_read = ntfs_pread(vol->dev, (rl->lcn <<
+				vol->cluster_size_bits) + ofs, to_read, b);
+		/* If everything ok, update progress counters and continue. */
+		if (bytes_read > 0) {
+			total += bytes_read;
+			count -= bytes_read;
+			b = (u8*)b + bytes_read;
+			continue;
+		}
+		/* If the syscall was interrupted, try again. */
+		if (bytes_read == (s64)-1 && errno == EINTR)
+			goto retry;
+		if (bytes_read == (s64)-1)
+			err = errno;
+		goto rl_err_out;
+	}
+	/* Finally, return the number of bytes read. */
+	return total;
+rl_err_out:
+	if (total)
+		return total;
+	errno = err;
+	return -1;
+}
+
+/**
+ * ntfs_rl_pwrite - scatter write to disk
+ * @vol:	ntfs volume to write to
+ * @rl:		runlist entry specifying where to write the data to
+ * @ofs:	offset in file for runlist element indicated in @rl
+ * @pos:	byte position from runlist beginning at which to begin the write
+ * @count:	number of bytes to write
+ * @b:		data buffer to write to disk
+ *
+ * This function will write @count bytes from data buffer @b to the volume @vol
+ * scattering the data as specified by the runlist @rl. The write begins at
+ * offset @pos into the runlist @rl. If a run is sparse then the related buffer
+ * data is ignored which means that the caller must ensure they are consistent.
+ *
+ * On success, return the number of successfully written bytes. If this number
+ * is lower than @count this means that the write has been interrupted in
+ * flight or that an error was encountered during the write so that the write
+ * is partial. 0 means nothing was written (also return 0 when @count is 0).
+ *
+ * On error and nothing has been written, return -1 with errno set
+ * appropriately to the return code of ntfs_pwrite(), or to to EINVAL in case
+ * of invalid arguments.
+ */
+s64 ntfs_rl_pwrite(const ntfs_volume *vol, const runlist_element *rl,
+		s64 ofs, const s64 pos, s64 count, void *b)
+{
+	s64 written, to_write, total = 0;
+	int err = EIO;
+
+	if (!vol || !rl || pos < 0 || count < 0) {
+		errno = EINVAL;
+		ntfs_log_perror("Failed to write runlist [vol: %p rl: %p "
+				"pos: %lld count: %lld]", vol, rl,
+				(long long)pos, (long long)count);
+		goto errno_set;
+	}
+	if (!count)
+		goto out;
+	/* Seek in @rl to the run containing @pos. */
+	while (rl->length && (ofs + (rl->length <<
+			vol->cluster_size_bits) <= pos)) {
+		ofs += (rl->length << vol->cluster_size_bits);
+		rl++;
+	}
+	/* Offset in the run at which to begin writing. */
+	ofs = pos - ofs;
+	for (total = 0LL; count; rl++, ofs = 0) {
+		if (!rl->length)
+			goto rl_err_out;
+		if (rl->lcn < (LCN)0) {
+
+			if (rl->lcn != (LCN)LCN_HOLE)
+				goto rl_err_out;
+			
+			to_write = min(count, (rl->length <<
+					       vol->cluster_size_bits) - ofs);
+			
+			total += to_write;
+			count -= to_write;
+			b = (u8*)b + to_write;
+			continue;
+		}
+		/* It is a real lcn, write it to the volume. */
+		to_write = min(count, (rl->length << vol->cluster_size_bits) -
+				ofs);
+retry:
+		if (!NVolReadOnly(vol))
+			written = ntfs_pwrite(vol->dev, (rl->lcn <<
+					vol->cluster_size_bits) + ofs,
+					to_write, b);
+		else
+			written = to_write;
+		/* If everything ok, update progress counters and continue. */
+		if (written > 0) {
+			total += written;
+			count -= written;
+			b = (u8*)b + written;
+			continue;
+		}
+		/* If the syscall was interrupted, try again. */
+		if (written == (s64)-1 && errno == EINTR)
+			goto retry;
+		if (written == (s64)-1)
+			err = errno;
+		goto rl_err_out;
+	}
+out:
+	return total;
+rl_err_out:
+	if (total)
+		goto out;
+	errno = err;
+errno_set:
+	total = -1;
+	goto out;
+}
+
+/**
+ * ntfs_get_nr_significant_bytes - get number of bytes needed to store a number
+ * @n:		number for which to get the number of bytes for
+ *
+ * Return the number of bytes required to store @n unambiguously as
+ * a signed number.
+ *
+ * This is used in the context of the mapping pairs array to determine how
+ * many bytes will be needed in the array to store a given logical cluster
+ * number (lcn) or a specific run length.
+ *
+ * Return the number of bytes written. This function cannot fail.
+ */
+int ntfs_get_nr_significant_bytes(const s64 n)
+{
+	u64 l;
+	int i;
+
+	l = (n < 0 ? ~n : n);
+	i = 1;
+	if (l >= 128) {
+		l >>= 7;
+		do {
+			i++;
+			l >>= 8;
+		} while (l);
+	}
+	return i;
+}
+
+/**
+ * ntfs_get_size_for_mapping_pairs - get bytes needed for mapping pairs array
+ * @vol:	ntfs volume (needed for the ntfs version)
+ * @rl:		runlist for which to determine the size of the mapping pairs
+ * @start_vcn:	vcn at which to start the mapping pairs array
+ *
+ * Walk the runlist @rl and calculate the size in bytes of the mapping pairs
+ * array corresponding to the runlist @rl, starting at vcn @start_vcn.  This
+ * for example allows us to allocate a buffer of the right size when building
+ * the mapping pairs array.
+ *
+ * If @rl is NULL, just return 1 (for the single terminator byte).
+ *
+ * Return the calculated size in bytes on success.  On error, return -1 with
+ * errno set to the error code.  The following error codes are defined:
+ *	EINVAL	- Run list contains unmapped elements. Make sure to only pass
+ *		  fully mapped runlists to this function.
+ *		- @start_vcn is invalid.
+ *	EIO	- The runlist is corrupt.
+ */
+int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol,
+		const runlist_element *rl, const VCN start_vcn, int max_size)
+{
+	LCN prev_lcn;
+	int rls;
+
+	if (start_vcn < 0) {
+		ntfs_log_trace("start_vcn %lld (should be >= 0)\n",
+				(long long) start_vcn);
+		errno = EINVAL;
+		goto errno_set;
+	}
+	if (!rl) {
+		if (start_vcn) {
+			ntfs_log_trace("rl NULL, start_vcn %lld (should be > 0)\n",
+					(long long) start_vcn);
+			errno = EINVAL;
+			goto errno_set;
+		}
+		rls = 1;
+		goto out;
+	}
+	/* Skip to runlist element containing @start_vcn. */
+	while (rl->length && start_vcn >= rl[1].vcn)
+		rl++;
+	if ((!rl->length && start_vcn > rl->vcn) || start_vcn < rl->vcn) {
+		errno = EINVAL;
+		goto errno_set;
+	}
+	prev_lcn = 0;
+	/* Always need the terminating zero byte. */
+	rls = 1;
+	/* Do the first partial run if present. */
+	if (start_vcn > rl->vcn) {
+		s64 delta;
+
+		/* We know rl->length != 0 already. */
+		if (rl->length < 0 || rl->lcn < LCN_HOLE)
+			goto err_out;
+		delta = start_vcn - rl->vcn;
+		/* Header byte + length. */
+		rls += 1 + ntfs_get_nr_significant_bytes(rl->length - delta);
+		/*
+		 * If the logical cluster number (lcn) denotes a hole and we
+		 * are on NTFS 3.0+, we don't store it at all, i.e. we need
+		 * zero space. On earlier NTFS versions we just store the lcn.
+		 * Note: this assumes that on NTFS 1.2-, holes are stored with
+		 * an lcn of -1 and not a delta_lcn of -1 (unless both are -1).
+		 */
+		if (rl->lcn >= 0 || vol->major_ver < 3) {
+			prev_lcn = rl->lcn;
+			if (rl->lcn >= 0)
+				prev_lcn += delta;
+			/* Change in lcn. */
+			rls += ntfs_get_nr_significant_bytes(prev_lcn);
+		}
+		/* Go to next runlist element. */
+		rl++;
+	}
+	/* Do the full runs. */
+	for (; rl->length && (rls <= max_size); rl++) {
+		if (rl->length < 0 || rl->lcn < LCN_HOLE)
+			goto err_out;
+		/* Header byte + length. */
+		rls += 1 + ntfs_get_nr_significant_bytes(rl->length);
+		/*
+		 * If the logical cluster number (lcn) denotes a hole and we
+		 * are on NTFS 3.0+, we don't store it at all, i.e. we need
+		 * zero space. On earlier NTFS versions we just store the lcn.
+		 * Note: this assumes that on NTFS 1.2-, holes are stored with
+		 * an lcn of -1 and not a delta_lcn of -1 (unless both are -1).
+		 */
+		if (rl->lcn >= 0 || vol->major_ver < 3) {
+			/* Change in lcn. */
+			rls += ntfs_get_nr_significant_bytes(rl->lcn -
+					prev_lcn);
+			prev_lcn = rl->lcn;
+		}
+	}
+out:	
+	return rls;
+err_out:
+	if (rl->lcn == LCN_RL_NOT_MAPPED)
+		errno = EINVAL;
+	else
+		errno = EIO;
+errno_set:	
+	rls = -1;
+	goto out;
+}
+
+/**
+ * ntfs_write_significant_bytes - write the significant bytes of a number
+ * @dst:	destination buffer to write to
+ * @dst_max:	pointer to last byte of destination buffer for bounds checking
+ * @n:		number whose significant bytes to write
+ *
+ * Store in @dst, the minimum bytes of the number @n which are required to
+ * identify @n unambiguously as a signed number, taking care not to exceed
+ * @dest_max, the maximum position within @dst to which we are allowed to
+ * write.
+ *
+ * This is used when building the mapping pairs array of a runlist to compress
+ * a given logical cluster number (lcn) or a specific run length to the minimum
+ * size possible.
+ *
+ * Return the number of bytes written on success. On error, i.e. the
+ * destination buffer @dst is too small, return -1 with errno set ENOSPC.
+ */
+int ntfs_write_significant_bytes(u8 *dst, const u8 *dst_max, const s64 n)
+{
+	s64 l = n;
+	int i;
+
+	i = 0;
+	if (dst > dst_max)
+		goto err_out;
+	*dst++ = l;
+	i++;
+	while ((l > 0x7f) || (l < -0x80)) {
+		if (dst > dst_max)
+			goto err_out;
+		l >>= 8;
+		*dst++ = l;
+		i++;
+	}
+	return i;
+err_out:
+	errno = ENOSPC;
+	return -1;
+}
+
+/**
+ * ntfs_mapping_pairs_build - build the mapping pairs array from a runlist
+ * @vol:	ntfs volume (needed for the ntfs version)
+ * @dst:	destination buffer to which to write the mapping pairs array
+ * @dst_len:	size of destination buffer @dst in bytes
+ * @rl:		runlist for which to build the mapping pairs array
+ * @start_vcn:	vcn at which to start the mapping pairs array
+ * @stop_vcn:	first vcn outside destination buffer on success or ENOSPC error
+ *
+ * Create the mapping pairs array from the runlist @rl, starting at vcn
+ * @start_vcn and save the array in @dst.  @dst_len is the size of @dst in
+ * bytes and it should be at least equal to the value obtained by calling
+ * ntfs_get_size_for_mapping_pairs().
+ *
+ * If @rl is NULL, just write a single terminator byte to @dst.
+ *
+ * On success or ENOSPC error, if @stop_vcn is not NULL, *@stop_vcn is set to
+ * the first vcn outside the destination buffer. Note that on error @dst has
+ * been filled with all the mapping pairs that will fit, thus it can be treated
+ * as partial success, in that a new attribute extent needs to be created or the
+ * next extent has to be used and the mapping pairs build has to be continued
+ * with @start_vcn set to *@stop_vcn.
+ *
+ * Return 0 on success.  On error, return -1 with errno set to the error code.
+ * The following error codes are defined:
+ *	EINVAL	- Run list contains unmapped elements. Make sure to only pass
+ *		  fully mapped runlists to this function.
+ *		- @start_vcn is invalid.
+ *	EIO	- The runlist is corrupt.
+ *	ENOSPC	- The destination buffer is too small.
+ */
+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)
+{
+	LCN prev_lcn;
+	u8 *dst_max, *dst_next;
+	s8 len_len, lcn_len;
+	int ret = 0;
+
+	if (start_vcn < 0)
+		goto val_err;
+	if (!rl) {
+		if (start_vcn)
+			goto val_err;
+		if (stop_rl)
+			*stop_rl = rl;
+		if (dst_len < 1)
+			goto nospc_err;
+		goto ok;
+	}
+	/* Skip to runlist element containing @start_vcn. */
+	while (rl->length && start_vcn >= rl[1].vcn)
+		rl++;
+	if ((!rl->length && start_vcn > rl->vcn) || start_vcn < rl->vcn)
+		goto val_err;
+	/*
+	 * @dst_max is used for bounds checking in
+	 * ntfs_write_significant_bytes().
+	 */
+	dst_max = dst + dst_len - 1;
+	prev_lcn = 0;
+	/* Do the first partial run if present. */
+	if (start_vcn > rl->vcn) {
+		s64 delta;
+
+		/* We know rl->length != 0 already. */
+		if (rl->length < 0 || rl->lcn < LCN_HOLE)
+			goto err_out;
+		delta = start_vcn - rl->vcn;
+		/* Write length. */
+		len_len = ntfs_write_significant_bytes(dst + 1, dst_max,
+				rl->length - delta);
+		if (len_len < 0)
+			goto size_err;
+		/*
+		 * If the logical cluster number (lcn) denotes a hole and we
+		 * are on NTFS 3.0+, we don't store it at all, i.e. we need
+		 * zero space. On earlier NTFS versions we just write the lcn
+		 * change.  FIXME: Do we need to write the lcn change or just
+		 * the lcn in that case?  Not sure as I have never seen this
+		 * case on NT4. - We assume that we just need to write the lcn
+		 * change until someone tells us otherwise... (AIA)
+		 */
+		if (rl->lcn >= 0 || vol->major_ver < 3) {
+			prev_lcn = rl->lcn;
+			if (rl->lcn >= 0)
+				prev_lcn += delta;
+			/* Write change in lcn. */
+			lcn_len = ntfs_write_significant_bytes(dst + 1 +
+					len_len, dst_max, prev_lcn);
+			if (lcn_len < 0)
+				goto size_err;
+		} else
+			lcn_len = 0;
+		dst_next = dst + len_len + lcn_len + 1;
+		if (dst_next > dst_max)
+			goto size_err;
+		/* Update header byte. */
+		*dst = lcn_len << 4 | len_len;
+		/* Position at next mapping pairs array element. */
+		dst = dst_next;
+		/* Go to next runlist element. */
+		rl++;
+	}
+	/* Do the full runs. */
+	for (; rl->length; rl++) {
+		if (rl->length < 0 || rl->lcn < LCN_HOLE)
+			goto err_out;
+		/* Write length. */
+		len_len = ntfs_write_significant_bytes(dst + 1, dst_max,
+				rl->length);
+		if (len_len < 0)
+			goto size_err;
+		/*
+		 * If the logical cluster number (lcn) denotes a hole and we
+		 * are on NTFS 3.0+, we don't store it at all, i.e. we need
+		 * zero space. On earlier NTFS versions we just write the lcn
+		 * change. FIXME: Do we need to write the lcn change or just
+		 * the lcn in that case? Not sure as I have never seen this
+		 * case on NT4. - We assume that we just need to write the lcn
+		 * change until someone tells us otherwise... (AIA)
+		 */
+		if (rl->lcn >= 0 || vol->major_ver < 3) {
+			/* Write change in lcn. */
+			lcn_len = ntfs_write_significant_bytes(dst + 1 +
+					len_len, dst_max, rl->lcn - prev_lcn);
+			if (lcn_len < 0)
+				goto size_err;
+			prev_lcn = rl->lcn;
+		} else
+			lcn_len = 0;
+		dst_next = dst + len_len + lcn_len + 1;
+		if (dst_next > dst_max)
+			goto size_err;
+		/* Update header byte. */
+		*dst = lcn_len << 4 | len_len;
+		/* Position at next mapping pairs array element. */
+		dst += 1 + len_len + lcn_len;
+	}
+	/* Set stop vcn. */
+	if (stop_rl)
+		*stop_rl = rl;
+ok:	
+	/* Add terminator byte. */
+	*dst = 0;
+out:
+	return ret;
+size_err:
+	/* Set stop vcn. */
+	if (stop_rl)
+		*stop_rl = rl;
+	/* Add terminator byte. */
+	*dst = 0;
+nospc_err:
+	errno = ENOSPC;
+	goto errno_set;
+val_err:
+	errno = EINVAL;
+	goto errno_set;
+err_out:
+	if (rl->lcn == LCN_RL_NOT_MAPPED)
+		errno = EINVAL;
+	else
+		errno = EIO;
+errno_set:
+	ret = -1;
+	goto out;
+}
+
+/**
+ * ntfs_rl_truncate - truncate a runlist starting at a specified vcn
+ * @arl:	address of runlist to truncate
+ * @start_vcn:	first vcn which should be cut off
+ *
+ * Truncate the runlist *@arl starting at vcn @start_vcn as well as the memory
+ * buffer holding the runlist.
+ *
+ * Return 0 on success and -1 on error with errno set to the error code.
+ *
+ * NOTE: @arl is the address of the runlist. We need the address so we can
+ * modify the pointer to the runlist with the new, reallocated memory buffer.
+ */
+int ntfs_rl_truncate(runlist **arl, const VCN start_vcn)
+{
+	runlist *rl;
+	/* BOOL is_end = FALSE; */
+
+	if (!arl || !*arl) {
+		errno = EINVAL;
+		if (!arl)
+			ntfs_log_perror("rl_truncate error: arl: %p", arl);
+		else
+			ntfs_log_perror("rl_truncate error:"
+				" arl: %p *arl: %p", arl, *arl);
+		return -1;
+	}
+	
+	rl = *arl;
+	
+	if (start_vcn < rl->vcn) {
+		errno = EINVAL;
+		ntfs_log_perror("Start_vcn lies outside front of runlist");
+		return -1;
+	}
+	
+	/* Find the starting vcn in the run list. */
+	while (rl->length) {
+		if (start_vcn < rl[1].vcn)
+			break;
+		rl++;
+	}
+	
+	if (!rl->length) {
+		errno = EIO;
+		ntfs_log_trace("Truncating already truncated runlist?\n");
+		return -1;
+	}
+	
+	/* Truncate the run. */
+	rl->length = start_vcn - rl->vcn;
+	
+	/*
+	 * If a run was partially truncated, make the following runlist
+	 * element a terminator instead of the truncated runlist
+	 * element itself.
+	 */
+	if (rl->length) {
+		++rl;
+/*
+		if (!rl->length)
+			is_end = TRUE;
+*/
+		rl->vcn = start_vcn;
+		rl->length = 0;
+	}
+	rl->lcn = (LCN)LCN_ENOENT;
+	/**
+	 * Reallocate memory if necessary.
+	 * FIXME: Below code is broken, because runlist allocations must be 
+	 * a multiple of 4096. The code caused crashes and corruptions.
+	 */
+/*	
+	 if (!is_end) {
+		size_t new_size = (rl - *arl + 1) * sizeof(runlist_element);
+		rl = realloc(*arl, new_size);
+		if (rl)
+			*arl = rl;
+	}
+*/
+	return 0;
+}
+
+/**
+ * ntfs_rl_sparse - check whether runlist have sparse regions or not.
+ * @rl:		runlist to check
+ *
+ * Return 1 if have, 0 if not, -1 on error with errno set to the error code.
+ */
+int ntfs_rl_sparse(runlist *rl)
+{
+	runlist *rlc;
+
+	if (!rl) {
+		errno = EINVAL;
+		ntfs_log_perror("%s: ", __FUNCTION__);
+		return -1;
+	}
+
+	for (rlc = rl; rlc->length; rlc++)
+		if (rlc->lcn < 0) {
+			if (rlc->lcn != LCN_HOLE) {
+				errno = EINVAL;
+				ntfs_log_perror("%s: bad runlist", __FUNCTION__);
+				return -1;
+			}
+			return 1;
+		}
+	return 0;
+}
+
+/**
+ * ntfs_rl_get_compressed_size - calculate length of non sparse regions
+ * @vol:	ntfs volume (need for cluster size)
+ * @rl:		runlist to calculate for
+ *
+ * Return compressed size or -1 on error with errno set to the error code.
+ */
+s64 ntfs_rl_get_compressed_size(ntfs_volume *vol, runlist *rl)
+{
+	runlist *rlc;
+	s64 ret = 0;
+
+	if (!rl) {
+		errno = EINVAL;
+		ntfs_log_perror("%s: ", __FUNCTION__);
+		return -1;
+	}
+
+	for (rlc = rl; rlc->length; rlc++) {
+		if (rlc->lcn < 0) {
+			if (rlc->lcn != LCN_HOLE) {
+				errno = EINVAL;
+				ntfs_log_perror("%s: bad runlist", __FUNCTION__);
+				return -1;
+			}
+		} else
+			ret += rlc->length;
+	}
+	return ret << vol->cluster_size_bits;
+}
+
+
+#ifdef NTFS_TEST
+/**
+ * test_rl_helper
+ */
+#define MKRL(R,V,L,S)				\
+	(R)->vcn = V;				\
+	(R)->lcn = L;				\
+	(R)->length = S;
+/*
+}
+*/
+/**
+ * test_rl_dump_runlist - Runlist test: Display the contents of a runlist
+ * @rl:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static void test_rl_dump_runlist(const runlist_element *rl)
+{
+	int abbr = 0;	/* abbreviate long lists */
+	int len = 0;
+	int i;
+	const char *lcn_str[5] = { "HOLE", "NOTMAP", "ENOENT", "XXXX" };
+
+	if (!rl) {
+		printf("    Run list not present.\n");
+		return;
+	}
+
+	if (abbr)
+		for (len = 0; rl[len].length; len++) ;
+
+	printf("     VCN      LCN      len\n");
+	for (i = 0; ; i++, rl++) {
+		LCN lcn = rl->lcn;
+
+		if ((abbr) && (len > 20)) {
+			if (i == 4)
+				printf("     ...\n");
+			if ((i > 3) && (i < (len - 3)))
+				continue;
+		}
+
+		if (lcn < (LCN)0) {
+			int ind = -lcn - 1;
+
+			if (ind > -LCN_ENOENT - 1)
+				ind = 3;
+			printf("%8lld %8s %8lld\n",
+				rl->vcn, lcn_str[ind], rl->length);
+		} else
+			printf("%8lld %8lld %8lld\n",
+				rl->vcn, rl->lcn, rl->length);
+		if (!rl->length)
+			break;
+	}
+	if ((abbr) && (len > 20))
+		printf("    (%d entries)\n", len+1);
+	printf("\n");
+}
+
+/**
+ * test_rl_runlists_merge - Runlist test: Merge two runlists
+ * @drl:
+ * @srl:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static runlist_element * test_rl_runlists_merge(runlist_element *drl, runlist_element *srl)
+{
+	runlist_element *res = NULL;
+
+	printf("dst:\n");
+	test_rl_dump_runlist(drl);
+	printf("src:\n");
+	test_rl_dump_runlist(srl);
+
+	res = ntfs_runlists_merge(drl, srl);
+
+	printf("res:\n");
+	test_rl_dump_runlist(res);
+
+	return res;
+}
+
+/**
+ * test_rl_read_buffer - Runlist test: Read a file containing a runlist
+ * @file:
+ * @buf:
+ * @bufsize:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static int test_rl_read_buffer(const char *file, u8 *buf, int bufsize)
+{
+	FILE *fptr;
+
+	fptr = fopen(file, "r");
+	if (!fptr) {
+		printf("open %s\n", file);
+		return 0;
+	}
+
+	if (fread(buf, bufsize, 1, fptr) == 99) {
+		printf("read %s\n", file);
+		return 0;
+	}
+
+	fclose(fptr);
+	return 1;
+}
+
+/**
+ * test_rl_pure_src - Runlist test: Complicate the simple tests a little
+ * @contig:
+ * @multi:
+ * @vcn:
+ * @len:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static runlist_element * test_rl_pure_src(BOOL contig, BOOL multi, int vcn, int len)
+{
+	runlist_element *result;
+	int fudge;
+
+	if (contig)
+		fudge = 0;
+	else
+		fudge = 999;
+
+	result = ntfs_malloc(4096);
+	if (!result)
+		return NULL;
+	
+	if (multi) {
+		MKRL(result+0, vcn + (0*len/4), fudge + vcn + 1000 + (0*len/4), len / 4)
+		MKRL(result+1, vcn + (1*len/4), fudge + vcn + 1000 + (1*len/4), len / 4)
+		MKRL(result+2, vcn + (2*len/4), fudge + vcn + 1000 + (2*len/4), len / 4)
+		MKRL(result+3, vcn + (3*len/4), fudge + vcn + 1000 + (3*len/4), len / 4)
+		MKRL(result+4, vcn + (4*len/4), LCN_RL_NOT_MAPPED,              0)
+	} else {
+		MKRL(result+0, vcn,       fudge + vcn + 1000, len)
+		MKRL(result+1, vcn + len, LCN_RL_NOT_MAPPED,  0)
+	}
+	return result;
+}
+
+/**
+ * test_rl_pure_test - Runlist test: Perform tests using simple runlists
+ * @test:
+ * @contig:
+ * @multi:
+ * @vcn:
+ * @len:
+ * @file:
+ * @size:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static void test_rl_pure_test(int test, BOOL contig, BOOL multi, int vcn, int len, runlist_element *file, int size)
+{
+	runlist_element *src;
+	runlist_element *dst;
+	runlist_element *res;
+
+	src = test_rl_pure_src(contig, multi, vcn, len);
+	dst = ntfs_malloc(4096);
+	if (!src || !dst) {
+		printf("Test %2d ---------- FAILED! (no free memory?)\n", test);
+		return;
+	}
+
+	memcpy(dst, file, size);
+
+	printf("Test %2d ----------\n", test);
+	res = test_rl_runlists_merge(dst, src);
+
+	free(res);
+}
+
+/**
+ * test_rl_pure - Runlist test: Create tests using simple runlists
+ * @contig:
+ * @multi:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static void test_rl_pure(char *contig, char *multi)
+{
+		/* VCN,  LCN, len */
+	static runlist_element file1[] = {
+		{    0,   -1, 100 },	/* HOLE */
+		{  100, 1100, 100 },	/* DATA */
+		{  200,   -1, 100 },	/* HOLE */
+		{  300, 1300, 100 },	/* DATA */
+		{  400,   -1, 100 },	/* HOLE */
+		{  500,   -3,   0 }	/* NOENT */
+	};
+	static runlist_element file2[] = {
+		{    0, 1000, 100 },	/* DATA */
+		{  100,   -1, 100 },	/* HOLE */
+		{  200,   -3,   0 }	/* NOENT */
+	};
+	static runlist_element file3[] = {
+		{    0, 1000, 100 },	/* DATA */
+		{  100,   -3,   0 }	/* NOENT */
+	};
+	static runlist_element file4[] = {
+		{    0,   -3,   0 }	/* NOENT */
+	};
+	static runlist_element file5[] = {
+		{    0,   -2, 100 },	/* NOTMAP */
+		{  100, 1100, 100 },	/* DATA */
+		{  200,   -2, 100 },	/* NOTMAP */
+		{  300, 1300, 100 },	/* DATA */
+		{  400,   -2, 100 },	/* NOTMAP */
+		{  500,   -3,   0 }	/* NOENT */
+	};
+	static runlist_element file6[] = {
+		{    0, 1000, 100 },	/* DATA */
+		{  100,   -2, 100 },	/* NOTMAP */
+		{  200,   -3,   0 }	/* NOENT */
+	};
+	BOOL c, m;
+
+	if (strcmp(contig, "contig") == 0)
+		c = TRUE;
+	else if (strcmp(contig, "noncontig") == 0)
+		c = FALSE;
+	else {
+		printf("rl pure [contig|noncontig] [single|multi]\n");
+		return;
+	}
+	if (strcmp(multi, "multi") == 0)
+		m = TRUE;
+	else if (strcmp(multi, "single") == 0)
+		m = FALSE;
+	else {
+		printf("rl pure [contig|noncontig] [single|multi]\n");
+		return;
+	}
+
+	test_rl_pure_test(1,  c, m,   0,  40, file1, sizeof(file1));
+	test_rl_pure_test(2,  c, m,  40,  40, file1, sizeof(file1));
+	test_rl_pure_test(3,  c, m,  60,  40, file1, sizeof(file1));
+	test_rl_pure_test(4,  c, m,   0, 100, file1, sizeof(file1));
+	test_rl_pure_test(5,  c, m, 200,  40, file1, sizeof(file1));
+	test_rl_pure_test(6,  c, m, 240,  40, file1, sizeof(file1));
+	test_rl_pure_test(7,  c, m, 260,  40, file1, sizeof(file1));
+	test_rl_pure_test(8,  c, m, 200, 100, file1, sizeof(file1));
+	test_rl_pure_test(9,  c, m, 400,  40, file1, sizeof(file1));
+	test_rl_pure_test(10, c, m, 440,  40, file1, sizeof(file1));
+	test_rl_pure_test(11, c, m, 460,  40, file1, sizeof(file1));
+	test_rl_pure_test(12, c, m, 400, 100, file1, sizeof(file1));
+	test_rl_pure_test(13, c, m, 160, 100, file2, sizeof(file2));
+	test_rl_pure_test(14, c, m, 100, 140, file2, sizeof(file2));
+	test_rl_pure_test(15, c, m, 200,  40, file2, sizeof(file2));
+	test_rl_pure_test(16, c, m, 240,  40, file2, sizeof(file2));
+	test_rl_pure_test(17, c, m, 100,  40, file3, sizeof(file3));
+	test_rl_pure_test(18, c, m, 140,  40, file3, sizeof(file3));
+	test_rl_pure_test(19, c, m,   0,  40, file4, sizeof(file4));
+	test_rl_pure_test(20, c, m,  40,  40, file4, sizeof(file4));
+	test_rl_pure_test(21, c, m,   0,  40, file5, sizeof(file5));
+	test_rl_pure_test(22, c, m,  40,  40, file5, sizeof(file5));
+	test_rl_pure_test(23, c, m,  60,  40, file5, sizeof(file5));
+	test_rl_pure_test(24, c, m,   0, 100, file5, sizeof(file5));
+	test_rl_pure_test(25, c, m, 200,  40, file5, sizeof(file5));
+	test_rl_pure_test(26, c, m, 240,  40, file5, sizeof(file5));
+	test_rl_pure_test(27, c, m, 260,  40, file5, sizeof(file5));
+	test_rl_pure_test(28, c, m, 200, 100, file5, sizeof(file5));
+	test_rl_pure_test(29, c, m, 400,  40, file5, sizeof(file5));
+	test_rl_pure_test(30, c, m, 440,  40, file5, sizeof(file5));
+	test_rl_pure_test(31, c, m, 460,  40, file5, sizeof(file5));
+	test_rl_pure_test(32, c, m, 400, 100, file5, sizeof(file5));
+	test_rl_pure_test(33, c, m, 160, 100, file6, sizeof(file6));
+	test_rl_pure_test(34, c, m, 100, 140, file6, sizeof(file6));
+}
+
+/**
+ * test_rl_zero - Runlist test: Merge a zero-length runlist
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static void test_rl_zero(void)
+{
+	runlist_element *jim = NULL;
+	runlist_element *bob = NULL;
+
+	bob = calloc(3, sizeof(runlist_element));
+	if (!bob)
+		return;
+
+	MKRL(bob+0, 10, 99, 5)
+	MKRL(bob+1, 15, LCN_RL_NOT_MAPPED, 0)
+
+	jim = test_rl_runlists_merge(jim, bob);
+	if (!jim)
+		return;
+
+	free(jim);
+}
+
+/**
+ * test_rl_frag_combine - Runlist test: Perform tests using fragmented files
+ * @vol:
+ * @attr1:
+ * @attr2:
+ * @attr3:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static void test_rl_frag_combine(ntfs_volume *vol, ATTR_RECORD *attr1, ATTR_RECORD *attr2, ATTR_RECORD *attr3)
+{
+	runlist_element *run1;
+	runlist_element *run2;
+	runlist_element *run3;
+
+	run1 = ntfs_mapping_pairs_decompress(vol, attr1, NULL);
+	if (!run1)
+		return;
+
+	run2 = ntfs_mapping_pairs_decompress(vol, attr2, NULL);
+	if (!run2)
+		return;
+
+	run1 = test_rl_runlists_merge(run1, run2);
+
+	run3 = ntfs_mapping_pairs_decompress(vol, attr3, NULL);
+	if (!run3)
+		return;
+
+	run1 = test_rl_runlists_merge(run1, run3);
+
+	free(run1);
+}
+
+/**
+ * test_rl_frag - Runlist test: Create tests using very fragmented files
+ * @test:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static void test_rl_frag(char *test)
+{
+	ntfs_volume vol;
+	ATTR_RECORD *attr1 = ntfs_malloc(1024);
+	ATTR_RECORD *attr2 = ntfs_malloc(1024);
+	ATTR_RECORD *attr3 = ntfs_malloc(1024);
+
+	if (!attr1 || !attr2 || !attr3)
+		goto out;
+
+	vol.sb = NULL;
+	vol.sector_size_bits = 9;
+	vol.cluster_size = 2048;
+	vol.cluster_size_bits = 11;
+	vol.major_ver = 3;
+
+	if (!test_rl_read_buffer("runlist-data/attr1.bin", (u8*) attr1, 1024))
+		goto out;
+	if (!test_rl_read_buffer("runlist-data/attr2.bin", (u8*) attr2, 1024))
+		goto out;
+	if (!test_rl_read_buffer("runlist-data/attr3.bin", (u8*) attr3, 1024))
+		goto out;
+
+	if      (strcmp(test, "123") == 0)  test_rl_frag_combine(&vol, attr1, attr2, attr3);
+	else if (strcmp(test, "132") == 0)  test_rl_frag_combine(&vol, attr1, attr3, attr2);
+	else if (strcmp(test, "213") == 0)  test_rl_frag_combine(&vol, attr2, attr1, attr3);
+	else if (strcmp(test, "231") == 0)  test_rl_frag_combine(&vol, attr2, attr3, attr1);
+	else if (strcmp(test, "312") == 0)  test_rl_frag_combine(&vol, attr3, attr1, attr2);
+	else if (strcmp(test, "321") == 0)  test_rl_frag_combine(&vol, attr3, attr2, attr1);
+	else
+		printf("Frag: No such test '%s'\n", test);
+
+out:
+	free(attr1);
+	free(attr2);
+	free(attr3);
+}
+
+/**
+ * test_rl_main - Runlist test: Program start (main)
+ * @argc:
+ * @argv:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+int test_rl_main(int argc, char *argv[])
+{
+	if      ((argc == 2) && (strcmp(argv[1], "zero") == 0)) test_rl_zero();
+	else if ((argc == 3) && (strcmp(argv[1], "frag") == 0)) test_rl_frag(argv[2]);
+	else if ((argc == 4) && (strcmp(argv[1], "pure") == 0)) test_rl_pure(argv[2], argv[3]);
+	else
+		printf("rl [zero|frag|pure] {args}\n");
+
+	return 0;
+}
+
+#endif
+
diff --git a/libntfs-3g/security.c b/libntfs-3g/security.c
new file mode 100755
index 0000000000000000000000000000000000000000..e6d0587c79f32c3585fee213e9231aab981bfa97
--- /dev/null
+++ b/libntfs-3g/security.c
@@ -0,0 +1,5373 @@
+/**
+ * security.c - Handling security/ACLs in NTFS.  Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2004 Anton Altaparmakov
+ * Copyright (c) 2005-2006 Szabolcs Szakacsits
+ * Copyright (c) 2006 Yura Pakhuchiy
+ * Copyright (c) 2007-2014 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_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SETXATTR
+#include <sys/xattr.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include "compat.h"
+#include "param.h"
+#include "types.h"
+#include "layout.h"
+#include "attrib.h"
+#include "index.h"
+#include "dir.h"
+#include "bitmap.h"
+#include "security.h"
+#include "acls.h"
+#include "cache.h"
+#include "misc.h"
+
+/*
+ *	JPA NTFS constants or structs
+ *	should be moved to layout.h
+ */
+
+#define ALIGN_SDS_BLOCK 0x40000 /* Alignment for a $SDS block */
+#define ALIGN_SDS_ENTRY 16 /* Alignment for a $SDS entry */
+#define STUFFSZ 0x4000 /* unitary stuffing size for $SDS */
+#define FIRST_SECURITY_ID 0x100 /* Lowest security id */
+
+	/* Mask for attributes which can be forced */
+#define FILE_ATTR_SETTABLE ( FILE_ATTR_READONLY		\
+				| FILE_ATTR_HIDDEN	\
+				| FILE_ATTR_SYSTEM	\
+				| FILE_ATTR_ARCHIVE	\
+				| FILE_ATTR_TEMPORARY	\
+				| FILE_ATTR_OFFLINE	\
+				| FILE_ATTR_NOT_CONTENT_INDEXED )
+
+struct SII {		/* this is an image of an $SII index entry */
+	le16 offs;
+	le16 size;
+	le32 fill1;
+	le16 indexsz;
+	le16 indexksz;
+	le16 flags;
+	le16 fill2;
+	le32 keysecurid;
+
+	/* did not find official description for the following */
+	le32 hash;
+	le32 securid;
+	le32 dataoffsl;	/* documented as badly aligned */
+	le32 dataoffsh;
+	le32 datasize;
+} ;
+
+struct SDH {		/* this is an image of an $SDH index entry */
+	le16 offs;
+	le16 size;
+	le32 fill1;
+	le16 indexsz;
+	le16 indexksz;
+	le16 flags;
+	le16 fill2;
+	le32 keyhash;
+	le32 keysecurid;
+
+	/* did not find official description for the following */
+	le32 hash;
+	le32 securid;
+	le32 dataoffsl;
+	le32 dataoffsh;
+	le32 datasize;
+	le32 fill3;
+	} ;
+
+/*
+ *	A few useful constants
+ */
+
+static ntfschar sii_stream[] = { const_cpu_to_le16('$'),
+				 const_cpu_to_le16('S'),
+				 const_cpu_to_le16('I'),   
+				 const_cpu_to_le16('I'),   
+				 const_cpu_to_le16(0) };
+static ntfschar sdh_stream[] = { const_cpu_to_le16('$'),
+				 const_cpu_to_le16('S'),
+				 const_cpu_to_le16('D'),
+				 const_cpu_to_le16('H'),
+				 const_cpu_to_le16(0) };
+
+/*
+ *		null SID (S-1-0-0)
+ */
+
+extern const SID *nullsid;
+
+/*
+ * The zero GUID.
+ */
+
+static const GUID __zero_guid = { const_cpu_to_le32(0), const_cpu_to_le16(0),
+		const_cpu_to_le16(0), { 0, 0, 0, 0, 0, 0, 0, 0 } };
+static const GUID *const zero_guid = &__zero_guid;
+
+/**
+ * ntfs_guid_is_zero - check if a GUID is zero
+ * @guid:	[IN] guid to check
+ *
+ * Return TRUE if @guid is a valid pointer to a GUID and it is the zero GUID
+ * and FALSE otherwise.
+ */
+BOOL ntfs_guid_is_zero(const GUID *guid)
+{
+	return (memcmp(guid, zero_guid, sizeof(*zero_guid)));
+}
+
+/**
+ * ntfs_guid_to_mbs - convert a GUID to a multi byte string
+ * @guid:	[IN]  guid to convert
+ * @guid_str:	[OUT] string in which to return the GUID (optional)
+ *
+ * Convert the GUID pointed to by @guid to a multi byte string of the form
+ * "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX".  Therefore, @guid_str (if not NULL)
+ * needs to be able to store at least 37 bytes.
+ *
+ * If @guid_str is not NULL it will contain the converted GUID on return.  If
+ * it is NULL a string will be allocated and this will be returned.  The caller
+ * is responsible for free()ing the string in that case.
+ *
+ * On success return the converted string and on failure return NULL with errno
+ * set to the error code.
+ */
+char *ntfs_guid_to_mbs(const GUID *guid, char *guid_str)
+{
+	char *_guid_str;
+	int res;
+
+	if (!guid) {
+		errno = EINVAL;
+		return NULL;
+	}
+	_guid_str = guid_str;
+	if (!_guid_str) {
+		_guid_str = (char*)ntfs_malloc(37);
+		if (!_guid_str)
+			return _guid_str;
+	}
+	res = snprintf(_guid_str, 37,
+			"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+			(unsigned int)le32_to_cpu(guid->data1),
+			le16_to_cpu(guid->data2), le16_to_cpu(guid->data3),
+			guid->data4[0], guid->data4[1],
+			guid->data4[2], guid->data4[3], guid->data4[4],
+			guid->data4[5], guid->data4[6], guid->data4[7]);
+	if (res == 36)
+		return _guid_str;
+	if (!guid_str)
+		free(_guid_str);
+	errno = EINVAL;
+	return NULL;
+}
+
+/**
+ * ntfs_sid_to_mbs_size - determine maximum size for the string of a SID
+ * @sid:	[IN]  SID for which to determine the maximum string size
+ *
+ * Determine the maximum multi byte string size in bytes which is needed to
+ * store the standard textual representation of the SID pointed to by @sid.
+ * See ntfs_sid_to_mbs(), below.
+ *
+ * On success return the maximum number of bytes needed to store the multi byte
+ * string and on failure return -1 with errno set to the error code.
+ */
+int ntfs_sid_to_mbs_size(const SID *sid)
+{
+	int size, i;
+
+	if (!ntfs_sid_is_valid(sid)) {
+		errno = EINVAL;
+		return -1;
+	}
+	/* Start with "S-". */
+	size = 2;
+	/*
+	 * Add the SID_REVISION.  Hopefully the compiler will optimize this
+	 * away as SID_REVISION is a constant.
+	 */
+	for (i = SID_REVISION; i > 0; i /= 10)
+		size++;
+	/* Add the "-". */
+	size++;
+	/*
+	 * Add the identifier authority.  If it needs to be in decimal, the
+	 * maximum is 2^32-1 = 4294967295 = 10 characters.  If it needs to be
+	 * in hexadecimal, then maximum is 0x665544332211 = 14 characters.
+	 */
+	if (!sid->identifier_authority.high_part)
+		size += 10;
+	else
+		size += 14;
+	/*
+	 * Finally, add the sub authorities.  For each we have a "-" followed
+	 * by a decimal which can be up to 2^32-1 = 4294967295 = 10 characters.
+	 */
+	size += (1 + 10) * sid->sub_authority_count;
+	/* We need the zero byte at the end, too. */
+	size++;
+	return size * sizeof(char);
+}
+
+/**
+ * ntfs_sid_to_mbs - convert a SID to a multi byte string
+ * @sid:		[IN]  SID to convert
+ * @sid_str:		[OUT] string in which to return the SID (optional)
+ * @sid_str_size:	[IN]  size in bytes of @sid_str
+ *
+ * Convert the SID pointed to by @sid to its standard textual representation.
+ * @sid_str (if not NULL) needs to be able to store at least
+ * ntfs_sid_to_mbs_size() bytes.  @sid_str_size is the size in bytes of
+ * @sid_str if @sid_str is not NULL.
+ *
+ * The standard textual representation of the SID is of the form:
+ *	S-R-I-S-S...
+ * Where:
+ *    - The first "S" is the literal character 'S' identifying the following
+ *	digits as a SID.
+ *    - R is the revision level of the SID expressed as a sequence of digits
+ *	in decimal.
+ *    - I is the 48-bit identifier_authority, expressed as digits in decimal,
+ *	if I < 2^32, or hexadecimal prefixed by "0x", if I >= 2^32.
+ *    - S... is one or more sub_authority values, expressed as digits in
+ *	decimal.
+ *
+ * If @sid_str is not NULL it will contain the converted SUID on return.  If it
+ * is NULL a string will be allocated and this will be returned.  The caller is
+ * responsible for free()ing the string in that case.
+ *
+ * On success return the converted string and on failure return NULL with errno
+ * set to the error code.
+ */
+char *ntfs_sid_to_mbs(const SID *sid, char *sid_str, size_t sid_str_size)
+{
+	u64 u;
+	le32 leauth;
+	char *s;
+	int i, j, cnt;
+
+	/*
+	 * No need to check @sid if !@sid_str since ntfs_sid_to_mbs_size() will
+	 * check @sid, too.  8 is the minimum SID string size.
+	 */
+	if (sid_str && (sid_str_size < 8 || !ntfs_sid_is_valid(sid))) {
+		errno = EINVAL;
+		return NULL;
+	}
+	/* Allocate string if not provided. */
+	if (!sid_str) {
+		cnt = ntfs_sid_to_mbs_size(sid);
+		if (cnt < 0)
+			return NULL;
+		s = (char*)ntfs_malloc(cnt);
+		if (!s)
+			return s;
+		sid_str = s;
+		/* So we know we allocated it. */
+		sid_str_size = 0;
+	} else {
+		s = sid_str;
+		cnt = sid_str_size;
+	}
+	/* Start with "S-R-". */
+	i = snprintf(s, cnt, "S-%hhu-", (unsigned char)sid->revision);
+	if (i < 0 || i >= cnt)
+		goto err_out;
+	s += i;
+	cnt -= i;
+	/* Add the identifier authority. */
+	for (u = i = 0, j = 40; i < 6; i++, j -= 8)
+		u += (u64)sid->identifier_authority.value[i] << j;
+	if (!sid->identifier_authority.high_part)
+		i = snprintf(s, cnt, "%lu", (unsigned long)u);
+	else
+		i = snprintf(s, cnt, "0x%llx", (unsigned long long)u);
+	if (i < 0 || i >= cnt)
+		goto err_out;
+	s += i;
+	cnt -= i;
+	/* Finally, add the sub authorities. */
+	for (j = 0; j < sid->sub_authority_count; j++) {
+		leauth = sid->sub_authority[j];
+		i = snprintf(s, cnt, "-%u", (unsigned int)
+				le32_to_cpu(leauth));
+		if (i < 0 || i >= cnt)
+			goto err_out;
+		s += i;
+		cnt -= i;
+	}
+	return sid_str;
+err_out:
+	if (i >= cnt)
+		i = EMSGSIZE;
+	else
+		i = errno;
+	if (!sid_str_size)
+		free(sid_str);
+	errno = i;
+	return NULL;
+}
+
+/**
+ * ntfs_generate_guid - generatates a random current guid.
+ * @guid:	[OUT]   pointer to a GUID struct to hold the generated guid.
+ *
+ * perhaps not a very good random number generator though...
+ */
+void ntfs_generate_guid(GUID *guid)
+{
+	unsigned int i;
+	u8 *p = (u8 *)guid;
+
+	/* this is called at most once from mkntfs */
+	srandom(time((time_t*)NULL) ^ (getpid() << 16));
+	for (i = 0; i < sizeof(GUID); i++) {
+		p[i] = (u8)(random() & 0xFF);
+		if (i == 7)
+			p[7] = (p[7] & 0x0F) | 0x40;
+		if (i == 8)
+			p[8] = (p[8] & 0x3F) | 0x80;
+	}
+}
+
+/**
+ * ntfs_security_hash - calculate the hash of a security descriptor
+ * @sd:         self-relative security descriptor whose hash to calculate
+ * @length:     size in bytes of the security descritor @sd
+ *
+ * Calculate the hash of the self-relative security descriptor @sd of length
+ * @length bytes.
+ *
+ * This hash is used in the $Secure system file as the primary key for the $SDH
+ * index and is also stored in the header of each security descriptor in the
+ * $SDS data stream as well as in the index data of both the $SII and $SDH
+ * indexes.  In all three cases it forms part of the SDS_ENTRY_HEADER
+ * structure.
+ *
+ * Return the calculated security hash in little endian.
+ */
+le32 ntfs_security_hash(const SECURITY_DESCRIPTOR_RELATIVE *sd, const u32 len)
+{
+	const le32 *pos = (const le32*)sd;
+	const le32 *end = pos + (len >> 2);
+	u32 hash = 0;
+
+	while (pos < end) {
+		hash = le32_to_cpup(pos) + ntfs_rol32(hash, 3);
+		pos++;
+	}
+	return cpu_to_le32(hash);
+}
+
+/*
+ *	Get the first entry of current index block
+ *	cut and pasted form ntfs_ie_get_first() in index.c
+ */
+
+static INDEX_ENTRY *ntfs_ie_get_first(INDEX_HEADER *ih)
+{
+	return (INDEX_ENTRY*)((u8*)ih + le32_to_cpu(ih->entries_offset));
+}
+
+/*
+ *		Stuff a 256KB block into $SDS before writing descriptors
+ *	into the block.
+ *
+ *	This prevents $SDS from being automatically declared as sparse
+ *	when the second copy of the first security descriptor is written
+ *	256KB further ahead.
+ *
+ *	Having $SDS declared as a sparse file is not wrong by itself
+ *	and chkdsk leaves it as a sparse file. It does however complain
+ *	and add a sparse flag (0x0200) into field file_attributes of
+ *	STANDARD_INFORMATION of $Secure. This probably means that a
+ *	sparse attribute (ATTR_IS_SPARSE) is only allowed in sparse
+ *	files (FILE_ATTR_SPARSE_FILE).
+ *
+ *	Windows normally does not convert to sparse attribute or sparse
+ *	file. Stuffing is just a way to get to the same result.
+ */
+
+static int entersecurity_stuff(ntfs_volume *vol, off_t offs)
+{
+	int res;
+	int written;
+	unsigned long total;
+	char *stuff;
+
+	res = 0;
+	total = 0;
+	stuff = (char*)ntfs_malloc(STUFFSZ);
+	if (stuff) {
+		memset(stuff, 0, STUFFSZ);
+		do {
+			written = ntfs_attr_data_write(vol->secure_ni,
+				STREAM_SDS, 4, stuff, STUFFSZ, offs);
+			if (written == STUFFSZ) {
+				total += STUFFSZ;
+				offs += STUFFSZ;
+			} else {
+				errno = ENOSPC;
+				res = -1;
+			}
+		} while (!res && (total < ALIGN_SDS_BLOCK));
+		free(stuff);
+	} else {
+		errno = ENOMEM;
+		res = -1;
+	}
+	return (res);
+}
+
+/*
+ *		Enter a new security descriptor into $Secure (data only)
+ *      it has to be written twice with an offset of 256KB
+ *
+ *	Should only be called by entersecurityattr() to ensure consistency
+ *
+ *	Returns zero if sucessful
+ */
+
+static int entersecurity_data(ntfs_volume *vol,
+			const SECURITY_DESCRIPTOR_RELATIVE *attr, s64 attrsz,
+			le32 hash, le32 keyid, off_t offs, int gap)
+{
+	int res;
+	int written1;
+	int written2;
+	char *fullattr;
+	int fullsz;
+	SECURITY_DESCRIPTOR_HEADER *phsds;
+
+	res = -1;
+	fullsz = attrsz + gap + sizeof(SECURITY_DESCRIPTOR_HEADER);
+	fullattr = (char*)ntfs_malloc(fullsz);
+	if (fullattr) {
+			/*
+			 * Clear the gap from previous descriptor
+			 * this could be useful for appending the second
+			 * copy to the end of file. When creating a new
+			 * 256K block, the gap is cleared while writing
+			 * the first copy
+			 */
+		if (gap)
+			memset(fullattr,0,gap);
+		memcpy(&fullattr[gap + sizeof(SECURITY_DESCRIPTOR_HEADER)],
+				attr,attrsz);
+		phsds = (SECURITY_DESCRIPTOR_HEADER*)&fullattr[gap];
+		phsds->hash = hash;
+		phsds->security_id = keyid;
+		phsds->offset = cpu_to_le64(offs);
+		phsds->length = cpu_to_le32(fullsz - gap);
+		written1 = ntfs_attr_data_write(vol->secure_ni,
+			STREAM_SDS, 4, fullattr, fullsz,
+			offs - gap);
+		written2 = ntfs_attr_data_write(vol->secure_ni,
+			STREAM_SDS, 4, fullattr, fullsz,
+			offs - gap + ALIGN_SDS_BLOCK);
+		if ((written1 == fullsz)
+		     && (written2 == written1)) {
+			/*
+			 * Make sure the data size for $SDS marks the end
+			 * of the last security attribute. Windows uses
+			 * this to determine where the next attribute will
+			 * be written, which causes issues if chkdsk had
+			 * previously deleted the last entries without
+			 * adjusting the size.
+			 */
+			res = ntfs_attr_shrink_size(vol->secure_ni,STREAM_SDS,
+				4, offs - gap + ALIGN_SDS_BLOCK + fullsz);
+		}
+		else
+			errno = ENOSPC;
+		free(fullattr);
+	} else
+		errno = ENOMEM;
+	return (res);
+}
+
+/*
+ *	Enter a new security descriptor in $Secure (indexes only)
+ *
+ *	Should only be called by entersecurityattr() to ensure consistency
+ *
+ *	Returns zero if sucessful
+ */
+
+static int entersecurity_indexes(ntfs_volume *vol, s64 attrsz,
+			le32 hash, le32 keyid, off_t offs)
+{
+	union {
+		struct {
+			le32 dataoffsl;
+			le32 dataoffsh;
+		} parts;
+		le64 all;
+	} realign;
+	int res;
+	ntfs_index_context *xsii;
+	ntfs_index_context *xsdh;
+	struct SII newsii;
+	struct SDH newsdh;
+
+	res = -1;
+				/* enter a new $SII record */
+
+	xsii = vol->secure_xsii;
+	ntfs_index_ctx_reinit(xsii);
+	newsii.offs = const_cpu_to_le16(20);
+	newsii.size = const_cpu_to_le16(sizeof(struct SII) - 20);
+	newsii.fill1 = const_cpu_to_le32(0);
+	newsii.indexsz = const_cpu_to_le16(sizeof(struct SII));
+	newsii.indexksz = const_cpu_to_le16(sizeof(SII_INDEX_KEY));
+	newsii.flags = const_cpu_to_le16(0);
+	newsii.fill2 = const_cpu_to_le16(0);
+	newsii.keysecurid = keyid;
+	newsii.hash = hash;
+	newsii.securid = keyid;
+	realign.all = cpu_to_le64(offs);
+	newsii.dataoffsh = realign.parts.dataoffsh;
+	newsii.dataoffsl = realign.parts.dataoffsl;
+	newsii.datasize = cpu_to_le32(attrsz
+			 + sizeof(SECURITY_DESCRIPTOR_HEADER));
+	if (!ntfs_ie_add(xsii,(INDEX_ENTRY*)&newsii)) {
+
+		/* enter a new $SDH record */
+
+		xsdh = vol->secure_xsdh;
+		ntfs_index_ctx_reinit(xsdh);
+		newsdh.offs = const_cpu_to_le16(24);
+		newsdh.size = const_cpu_to_le16(
+			sizeof(SECURITY_DESCRIPTOR_HEADER));
+		newsdh.fill1 = const_cpu_to_le32(0);
+		newsdh.indexsz = const_cpu_to_le16(
+				sizeof(struct SDH));
+		newsdh.indexksz = const_cpu_to_le16(
+				sizeof(SDH_INDEX_KEY));
+		newsdh.flags = const_cpu_to_le16(0);
+		newsdh.fill2 = const_cpu_to_le16(0);
+		newsdh.keyhash = hash;
+		newsdh.keysecurid = keyid;
+		newsdh.hash = hash;
+		newsdh.securid = keyid;
+		newsdh.dataoffsh = realign.parts.dataoffsh;
+		newsdh.dataoffsl = realign.parts.dataoffsl;
+		newsdh.datasize = cpu_to_le32(attrsz
+			 + sizeof(SECURITY_DESCRIPTOR_HEADER));
+                           /* special filler value, Windows generally */
+                           /* fills with 0x00490049, sometimes with zero */
+		newsdh.fill3 = const_cpu_to_le32(0x00490049);
+		if (!ntfs_ie_add(xsdh,(INDEX_ENTRY*)&newsdh))
+			res = 0;
+	}
+	return (res);
+}
+
+/*
+ *	Enter a new security descriptor in $Secure (data and indexes)
+ *	Returns id of entry, or zero if there is a problem.
+ *	(should not be called for NTFS version < 3.0)
+ *
+ *	important : calls have to be serialized, however no locking is
+ *	needed while fuse is not multithreaded
+ */
+
+static le32 entersecurityattr(ntfs_volume *vol,
+			const SECURITY_DESCRIPTOR_RELATIVE *attr, s64 attrsz,
+			le32 hash)
+{
+	union {
+		struct {
+			le32 dataoffsl;
+			le32 dataoffsh;
+		} parts;
+		le64 all;
+	} realign;
+	le32 securid;
+	le32 keyid;
+	u32 newkey;
+	off_t offs;
+	int gap;
+	int size;
+	BOOL found;
+	struct SII *psii;
+	INDEX_ENTRY *entry;
+	INDEX_ENTRY *next;
+	ntfs_index_context *xsii;
+	int retries;
+	ntfs_attr *na;
+	int olderrno;
+
+	/* find the first available securid beyond the last key */
+	/* in $Secure:$SII. This also determines the first */
+	/* available location in $Secure:$SDS, as this stream */
+	/* is always appended to and the id's are allocated */
+	/* in sequence */
+
+	securid = const_cpu_to_le32(0);
+	xsii = vol->secure_xsii;
+	ntfs_index_ctx_reinit(xsii);
+	offs = size = 0;
+	keyid = const_cpu_to_le32(-1);
+	olderrno = errno;
+	found = !ntfs_index_lookup((char*)&keyid,
+			       sizeof(SII_INDEX_KEY), xsii);
+	if (!found && (errno != ENOENT)) {
+		ntfs_log_perror("Inconsistency in index $SII");
+		psii = (struct SII*)NULL;
+	} else {
+			/* restore errno to avoid misinterpretation */
+		errno = olderrno;
+		entry = xsii->entry;
+		psii = (struct SII*)xsii->entry;
+	}
+	if (psii) {
+		/*
+		 * Get last entry in block, but must get first one
+		 * one first, as we should already be beyond the
+		 * last one. For some reason the search for the last
+		 * entry sometimes does not return the last block...
+		 * we assume this can only happen in root block
+		 */
+		if (xsii->is_in_root)
+			entry = ntfs_ie_get_first
+				((INDEX_HEADER*)&xsii->ir->index);
+		else
+			entry = ntfs_ie_get_first
+				((INDEX_HEADER*)&xsii->ib->index);
+		/*
+		 * All index blocks should be at least half full
+		 * so there always is a last entry but one,
+		 * except when creating the first entry in index root.
+		 * This was however found not to be true : chkdsk
+		 * sometimes deletes all the (unused) keys in the last
+		 * index block without rebalancing the tree.
+		 * When this happens, a new search is restarted from
+		 * the smallest key.
+		 */
+		keyid = const_cpu_to_le32(0);
+		retries = 0;
+		while (entry) {
+			next = ntfs_index_next(entry,xsii);
+			if (next) { 
+				psii = (struct SII*)next;
+					/* save last key and */
+					/* available position */
+				keyid = psii->keysecurid;
+				realign.parts.dataoffsh
+						 = psii->dataoffsh;
+				realign.parts.dataoffsl
+						 = psii->dataoffsl;
+				offs = le64_to_cpu(realign.all);
+				size = le32_to_cpu(psii->datasize);
+			}
+			entry = next;
+			if (!entry && !keyid && !retries) {
+				/* search failed, retry from smallest key */
+				ntfs_index_ctx_reinit(xsii);
+				found = !ntfs_index_lookup((char*)&keyid,
+					       sizeof(SII_INDEX_KEY), xsii);
+				if (!found && (errno != ENOENT)) {
+					ntfs_log_perror("Index $SII is broken");
+					psii = (struct SII*)NULL;
+				} else {
+						/* restore errno */
+					errno = olderrno;
+					entry = xsii->entry;
+					psii = (struct SII*)entry;
+				}
+				if (psii
+				    && !(psii->flags & INDEX_ENTRY_END)) {
+						/* save first key and */
+						/* available position */
+					keyid = psii->keysecurid;
+					realign.parts.dataoffsh
+							 = psii->dataoffsh;
+					realign.parts.dataoffsl
+							 = psii->dataoffsl;
+					offs = le64_to_cpu(realign.all);
+					size = le32_to_cpu(psii->datasize);
+				}
+				retries++;
+			}
+		}
+	}
+	if (!keyid) {
+		/*
+		 * could not find any entry, before creating the first
+		 * entry, make a double check by making sure size of $SII
+		 * is less than needed for one entry
+		 */
+		securid = const_cpu_to_le32(0);
+		na = ntfs_attr_open(vol->secure_ni,AT_INDEX_ROOT,sii_stream,4);
+		if (na) {
+			if ((size_t)na->data_size < (sizeof(struct SII)
+					+ sizeof(INDEX_ENTRY_HEADER))) {
+				ntfs_log_error("Creating the first security_id\n");
+				securid = const_cpu_to_le32(FIRST_SECURITY_ID);
+			}
+			ntfs_attr_close(na);
+		}
+		if (!securid) {
+			ntfs_log_error("Error creating a security_id\n");
+			errno = EIO;
+		}
+	} else {
+		newkey = le32_to_cpu(keyid) + 1;
+		securid = cpu_to_le32(newkey);
+	}
+	/*
+	 * The security attr has to be written twice 256KB
+	 * apart. This implies that offsets like
+	 * 0x40000*odd_integer must be left available for
+	 * the second copy. So align to next block when
+	 * the last byte overflows on a wrong block.
+	 */
+
+	if (securid) {
+		gap = (-size) & (ALIGN_SDS_ENTRY - 1);
+		offs += gap + size;
+		if ((offs + attrsz + sizeof(SECURITY_DESCRIPTOR_HEADER) - 1)
+	 	   & ALIGN_SDS_BLOCK) {
+			offs = ((offs + attrsz
+				 + sizeof(SECURITY_DESCRIPTOR_HEADER) - 1)
+			 	| (ALIGN_SDS_BLOCK - 1)) + 1;
+		}
+		if (!(offs & (ALIGN_SDS_BLOCK - 1)))
+			entersecurity_stuff(vol, offs);
+		/*
+		 * now write the security attr to storage :
+		 * first data, then SII, then SDH
+		 * If failure occurs while writing SDS, data will never
+		 *    be accessed through indexes, and will be overwritten
+		 *    by the next allocated descriptor
+		 * If failure occurs while writing SII, the id has not
+		 *    recorded and will be reallocated later
+		 * If failure occurs while writing SDH, the space allocated
+		 *    in SDS or SII will not be reused, an inconsistency
+		 *    will persist with no significant consequence
+		 */
+		if (entersecurity_data(vol, attr, attrsz, hash, securid, offs, gap)
+		    || entersecurity_indexes(vol, attrsz, hash, securid, offs))
+			securid = const_cpu_to_le32(0);
+	}
+		/* inode now is dirty, synchronize it all */
+	ntfs_index_entry_mark_dirty(vol->secure_xsii);
+	ntfs_index_ctx_reinit(vol->secure_xsii);
+	ntfs_index_entry_mark_dirty(vol->secure_xsdh);
+	ntfs_index_ctx_reinit(vol->secure_xsdh);
+	NInoSetDirty(vol->secure_ni);
+	if (ntfs_inode_sync(vol->secure_ni))
+		ntfs_log_perror("Could not sync $Secure\n");
+	return (securid);
+}
+
+/*
+ *		Find a matching security descriptor in $Secure,
+ *	if none, allocate a new id and write the descriptor to storage
+ *	Returns id of entry, or zero if there is a problem.
+ *
+ *	important : calls have to be serialized, however no locking is
+ *	needed while fuse is not multithreaded
+ */
+
+static le32 setsecurityattr(ntfs_volume *vol,
+			const SECURITY_DESCRIPTOR_RELATIVE *attr, s64 attrsz)
+{
+	struct SDH *psdh;	/* this is an image of index (le) */
+	union {
+		struct {
+			le32 dataoffsl;
+			le32 dataoffsh;
+		} parts;
+		le64 all;
+	} realign;
+	BOOL found;
+	BOOL collision;
+	size_t size;
+	size_t rdsize;
+	s64 offs;
+	int res;
+	ntfs_index_context *xsdh;
+	char *oldattr;
+	SDH_INDEX_KEY key;
+	INDEX_ENTRY *entry;
+	le32 securid;
+	le32 hash;
+	int olderrno;
+
+	hash = ntfs_security_hash(attr,attrsz);
+	oldattr = (char*)NULL;
+	securid = const_cpu_to_le32(0);
+	res = 0;
+	xsdh = vol->secure_xsdh;
+	if (vol->secure_ni && xsdh && !vol->secure_reentry++) {
+		ntfs_index_ctx_reinit(xsdh);
+		/*
+		 * find the nearest key as (hash,0)
+		 * (do not search for partial key : in case of collision,
+		 * it could return a key which is not the first one which
+		 * collides)
+		 */
+		key.hash = hash;
+		key.security_id = const_cpu_to_le32(0);
+		olderrno = errno;
+		found = !ntfs_index_lookup((char*)&key,
+				 sizeof(SDH_INDEX_KEY), xsdh);
+		if (!found && (errno != ENOENT))
+			ntfs_log_perror("Inconsistency in index $SDH");
+		else {
+				/* restore errno to avoid misinterpretation */
+			errno = olderrno;
+			entry = xsdh->entry;
+			found = FALSE;
+			/*
+			 * lookup() may return a node with no data,
+			 * if so get next
+			 */
+			if (entry->ie_flags & INDEX_ENTRY_END)
+				entry = ntfs_index_next(entry,xsdh);
+			do {
+				collision = FALSE;
+				psdh = (struct SDH*)entry;
+				if (psdh)
+					size = (size_t) le32_to_cpu(psdh->datasize)
+						 - sizeof(SECURITY_DESCRIPTOR_HEADER);
+				else size = 0;
+			   /* if hash is not the same, the key is not present */
+				if (psdh && (size > 0)
+				   && (psdh->keyhash == hash)) {
+					   /* if hash is the same */
+					   /* check the whole record */
+					realign.parts.dataoffsh = psdh->dataoffsh;
+					realign.parts.dataoffsl = psdh->dataoffsl;
+					offs = le64_to_cpu(realign.all)
+						+ sizeof(SECURITY_DESCRIPTOR_HEADER);
+					oldattr = (char*)ntfs_malloc(size);
+					if (oldattr) {
+						rdsize = ntfs_attr_data_read(
+							vol->secure_ni,
+							STREAM_SDS, 4,
+							oldattr, size, offs);
+						found = (rdsize == size)
+							&& !memcmp(oldattr,attr,size);
+						free(oldattr);
+					  /* if the records do not compare */
+					  /* (hash collision), try next one */
+						if (!found) {
+							entry = ntfs_index_next(
+								entry,xsdh);
+							collision = TRUE;
+						}
+					} else
+						res = ENOMEM;
+				}
+			} while (collision && entry);
+			if (found)
+				securid = psdh->keysecurid;
+			else {
+				if (res) {
+					errno = res;
+					securid = const_cpu_to_le32(0);
+				} else {
+					/*
+					 * no matching key :
+					 * have to build a new one
+					 */
+					securid = entersecurityattr(vol,
+						attr, attrsz, hash);
+				}
+			}
+		}
+	}
+	if (--vol->secure_reentry)
+		ntfs_log_perror("Reentry error, check no multithreading\n");
+	return (securid);
+}
+
+
+/*
+ *		Update the security descriptor of a file
+ *	Either as an attribute (complying with pre v3.x NTFS version)
+ *	or, when possible, as an entry in $Secure (for NTFS v3.x)
+ *
+ *	returns 0 if success
+ */
+
+static int update_secur_descr(ntfs_volume *vol,
+				char *newattr, ntfs_inode *ni)
+{
+	int newattrsz;
+	int written;
+	int res;
+	ntfs_attr *na;
+
+	newattrsz = ntfs_attr_size(newattr);
+
+#if !FORCE_FORMAT_v1x
+	if ((vol->major_ver < 3) || !vol->secure_ni) {
+#endif
+
+		/* update for NTFS format v1.x */
+
+		/* update the old security attribute */
+		na = ntfs_attr_open(ni, AT_SECURITY_DESCRIPTOR, AT_UNNAMED, 0);
+		if (na) {
+			/* resize attribute */
+			res = ntfs_attr_truncate(na, (s64) newattrsz);
+			/* overwrite value */
+			if (!res) {
+				written = (int)ntfs_attr_pwrite(na, (s64) 0,
+					 (s64) newattrsz, newattr);
+				if (written != newattrsz) {
+					ntfs_log_error("Failed to update "
+						"a v1.x security descriptor\n");
+					errno = EIO;
+					res = -1;
+				}
+			}
+
+			ntfs_attr_close(na);
+			/* if old security attribute was found, also */
+			/* truncate standard information attribute to v1.x */
+			/* this is needed when security data is wanted */
+			/* as v1.x though volume is formatted for v3.x */
+			na = ntfs_attr_open(ni, AT_STANDARD_INFORMATION,
+				AT_UNNAMED, 0);
+			if (na) {
+				clear_nino_flag(ni, v3_Extensions);
+			/*
+			 * Truncating the record does not sweep extensions
+			 * from copy in memory. Clear security_id to be safe
+			 */
+				ni->security_id = const_cpu_to_le32(0);
+				res = ntfs_attr_truncate(na, (s64)48);
+				ntfs_attr_close(na);
+				clear_nino_flag(ni, v3_Extensions);
+			}
+		} else {
+			/*
+			 * insert the new security attribute if there
+			 * were none
+			 */
+			res = ntfs_attr_add(ni, AT_SECURITY_DESCRIPTOR,
+					    AT_UNNAMED, 0, (u8*)newattr,
+					    (s64) newattrsz);
+		}
+#if !FORCE_FORMAT_v1x
+	} else {
+
+		/* update for NTFS format v3.x */
+
+		le32 securid;
+
+		securid = setsecurityattr(vol,
+			(const SECURITY_DESCRIPTOR_RELATIVE*)newattr,
+			(s64)newattrsz);
+		if (securid) {
+			na = ntfs_attr_open(ni, AT_STANDARD_INFORMATION,
+				AT_UNNAMED, 0);
+			if (na) {
+				res = 0;
+				if (!test_nino_flag(ni, v3_Extensions)) {
+			/* expand standard information attribute to v3.x */
+					res = ntfs_attr_truncate(na,
+					 (s64)sizeof(STANDARD_INFORMATION));
+					ni->owner_id = const_cpu_to_le32(0);
+					ni->quota_charged = const_cpu_to_le64(0);
+					ni->usn = const_cpu_to_le64(0);
+					ntfs_attr_remove(ni,
+						AT_SECURITY_DESCRIPTOR,
+						AT_UNNAMED, 0);
+			}
+				set_nino_flag(ni, v3_Extensions);
+				ni->security_id = securid;
+				ntfs_attr_close(na);
+			} else {
+				ntfs_log_error("Failed to update "
+					"standard informations\n");
+				errno = EIO;
+				res = -1;
+			}
+		} else
+			res = -1;
+	}
+#endif
+
+	/* mark node as dirty */
+	NInoSetDirty(ni);
+	return (res);
+}
+
+/*
+ *		Upgrade the security descriptor of a file
+ *	This is intended to allow graceful upgrades for files which
+ *	were created in previous versions, with a security attributes
+ *	and no security id.
+ *	
+ *      It will allocate a security id and replace the individual
+ *	security attribute by a reference to the global one
+ *
+ *	Special files are not upgraded (currently / and files in
+ *	directories /$*)
+ *
+ *	Though most code is similar to update_secur_desc() it has
+ *	been kept apart to facilitate the further processing of
+ *	special cases or even to remove it if found dangerous.
+ *
+ *	returns 0 if success,
+ *		1 if not upgradable. This is not an error.
+ *		-1 if there is a problem
+ */
+
+static int upgrade_secur_desc(ntfs_volume *vol,
+				const char *attr, ntfs_inode *ni)
+{
+	int attrsz;
+	int res;
+	le32 securid;
+	ntfs_attr *na;
+
+		/*
+		 * upgrade requires NTFS format v3.x
+		 * also refuse upgrading for special files
+		 * whose number is less than FILE_first_user
+		 */
+
+	if ((vol->major_ver >= 3)
+	    && (ni->mft_no >= FILE_first_user)) {
+		attrsz = ntfs_attr_size(attr);
+		securid = setsecurityattr(vol,
+			(const SECURITY_DESCRIPTOR_RELATIVE*)attr,
+			(s64)attrsz);
+		if (securid) {
+			na = ntfs_attr_open(ni, AT_STANDARD_INFORMATION,
+				AT_UNNAMED, 0);
+			if (na) {
+			/* expand standard information attribute to v3.x */
+				res = ntfs_attr_truncate(na,
+					 (s64)sizeof(STANDARD_INFORMATION));
+				ni->owner_id = const_cpu_to_le32(0);
+				ni->quota_charged = const_cpu_to_le64(0);
+				ni->usn = const_cpu_to_le64(0);
+				ntfs_attr_remove(ni, AT_SECURITY_DESCRIPTOR,
+						AT_UNNAMED, 0);
+				set_nino_flag(ni, v3_Extensions);
+				ni->security_id = securid;
+				ntfs_attr_close(na);
+			} else {
+				ntfs_log_error("Failed to upgrade "
+					"standard informations\n");
+				errno = EIO;
+				res = -1;
+			}
+		} else
+			res = -1;
+			/* mark node as dirty */
+		NInoSetDirty(ni);
+	} else
+		res = 1;
+
+	return (res);
+}
+
+/*
+ *		Optional simplified checking of group membership
+ *
+ *	This only takes into account the groups defined in
+ *	/etc/group at initialization time.
+ *	It does not take into account the groups dynamically set by
+ *	setgroups() nor the changes in /etc/group since initialization
+ *
+ *	This optional method could be useful if standard checking
+ *	leads to a performance concern.
+ *
+ *	Should not be called for user root, however the group may be root
+ *
+ */
+
+static BOOL staticgroupmember(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t gid)
+{
+	BOOL ingroup;
+	int grcnt;
+	gid_t *groups;
+	struct MAPPING *user;
+
+	ingroup = FALSE;
+	if (uid) {
+		user = scx->mapping[MAPUSERS];
+		while (user && ((uid_t)user->xid != uid))
+			user = user->next;
+		if (user) {
+			groups = user->groups;
+			grcnt = user->grcnt;
+			while ((--grcnt >= 0) && (groups[grcnt] != gid)) { }
+			ingroup = (grcnt >= 0);
+		}
+	}
+	return (ingroup);
+}
+
+#if defined(__sun) && defined (__SVR4)
+
+/*
+ *		Check whether current thread owner is member of file group
+ *				Solaris/OpenIndiana version
+ *	Should not be called for user root, however the group may be root
+ *
+ * The group list is available in "/proc/$PID/cred"
+ *
+ */
+
+static BOOL groupmember(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t gid)
+{
+	typedef struct prcred {
+		uid_t pr_euid;	    /* effective user id */
+		uid_t pr_ruid;	    /* real user id */
+		uid_t pr_suid;	    /* saved user id (from exec) */
+		gid_t pr_egid;	    /* effective group id */
+		gid_t pr_rgid;	    /* real group id */
+		gid_t pr_sgid;	    /* saved group id (from exec) */
+		int pr_ngroups;     /* number of supplementary groups */
+		gid_t pr_groups[1]; /* array of supplementary groups */
+	} prcred_t;
+	enum { readset = 16 };
+
+	prcred_t basecreds;
+	gid_t groups[readset];
+	char filename[64];
+	int fd;
+	int k;
+	int cnt;
+	gid_t *p;
+	BOOL ismember;
+	int got;
+	pid_t tid;
+
+	if (scx->vol->secure_flags & (1 << SECURITY_STATICGRPS))
+		ismember = staticgroupmember(scx, uid, gid);
+	else {
+		ismember = FALSE; /* default return */
+		tid = scx->tid;
+		sprintf(filename,"/proc/%u/cred",tid);
+		fd = open(filename,O_RDONLY);
+		if (fd >= 0) {
+			got = read(fd, &basecreds, sizeof(prcred_t));
+			if (got == sizeof(prcred_t)) {
+				if (basecreds.pr_egid == gid)
+					ismember = TRUE;
+				p = basecreds.pr_groups;
+				cnt = 1;
+				k = 0;
+				while (!ismember
+				    && (k < basecreds.pr_ngroups)
+				    && (cnt > 0)
+				    && (*p != gid)) {
+					k++;
+					cnt--;
+					p++;
+					if (cnt <= 0) {
+						got = read(fd, groups,
+							readset*sizeof(gid_t));
+						cnt = got/sizeof(gid_t);
+						p = groups;
+					}
+				}
+				if ((cnt > 0)
+				    && (k < basecreds.pr_ngroups))
+					ismember = TRUE;
+			}
+		close(fd);
+		}
+	}
+	return (ismember);
+}
+
+#else /* defined(__sun) && defined (__SVR4) */
+
+/*
+ *		Check whether current thread owner is member of file group
+ *				Linux version
+ *	Should not be called for user root, however the group may be root
+ *
+ * As indicated by Miklos Szeredi :
+ *
+ * The group list is available in
+ *
+ *   /proc/$PID/task/$TID/status
+ *
+ * and fuse supplies TID in get_fuse_context()->pid.  The only problem is
+ * finding out PID, for which I have no good solution, except to iterate
+ * through all processes.  This is rather slow, but may be speeded up
+ * with caching and heuristics (for single threaded programs PID = TID).
+ *
+ * The following implementation gets the group list from
+ *   /proc/$TID/task/$TID/status which apparently exists and
+ * contains the same data.
+ */
+
+static BOOL groupmember(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t gid)
+{
+	static char key[] = "\nGroups:";
+	char buf[BUFSZ+1];
+	char filename[64];
+	enum { INKEY, INSEP, INNUM, INEND } state;
+	int fd;
+	char c;
+	int matched;
+	BOOL ismember;
+	int got;
+	char *p;
+	gid_t grp;
+	pid_t tid;
+
+	if (scx->vol->secure_flags & (1 << SECURITY_STATICGRPS))
+		ismember = staticgroupmember(scx, uid, gid);
+	else {
+		ismember = FALSE; /* default return */
+		tid = scx->tid;
+		sprintf(filename,"/proc/%u/task/%u/status",tid,tid);
+		fd = open(filename,O_RDONLY);
+		if (fd >= 0) {
+			got = read(fd, buf, BUFSZ);
+			buf[got] = 0;
+			state = INKEY;
+			matched = 0;
+			p = buf;
+			grp = 0;
+				/*
+				 *  A simple automaton to process lines like
+				 *  Groups: 14 500 513
+				 */
+			do {
+				c = *p++;
+				if (!c) {
+					/* refill buffer */
+					got = read(fd, buf, BUFSZ);
+					buf[got] = 0;
+					p = buf;
+					c = *p++; /* 0 at end of file */
+				}
+				switch (state) {
+				case INKEY :
+					if (key[matched] == c) {
+						if (!key[++matched])
+							state = INSEP;
+					} else
+						if (key[0] == c)
+							matched = 1;
+						else
+							matched = 0;
+					break;
+				case INSEP :
+					if ((c >= '0') && (c <= '9')) {
+						grp = c - '0';
+						state = INNUM;
+					} else
+						if ((c != ' ') && (c != '\t'))
+							state = INEND;
+					break;
+				case INNUM :
+					if ((c >= '0') && (c <= '9'))
+						grp = grp*10 + c - '0';
+					else {
+						ismember = (grp == gid);
+						if ((c != ' ') && (c != '\t'))
+							state = INEND;
+						else
+							state = INSEP;
+					}
+				default :
+					break;
+				}
+			} while (!ismember && c && (state != INEND));
+		close(fd);
+		if (!c)
+			ntfs_log_error("No group record found in %s\n",filename);
+		} else
+			ntfs_log_error("Could not open %s\n",filename);
+	}
+	return (ismember);
+}
+
+#endif /* defined(__sun) && defined (__SVR4) */
+
+#if POSIXACLS
+
+/*
+ *		Extract the basic permissions from a Posix ACL
+ *
+ *	This is only to be used when Posix ACLs are compiled in,
+ *	but not enabled in the mount options.
+ *
+ *	it replaces the permission mask by the group permissions.
+ *	If special groups are mapped, they are also considered as world.
+ */
+
+static int ntfs_basic_perms(const struct SECURITY_CONTEXT *scx,
+			const struct POSIX_SECURITY *pxdesc)
+{
+	int k;
+	int perms;
+	const struct POSIX_ACE *pace;
+	const struct MAPPING* group;
+
+	k = 0;
+	perms = pxdesc->mode;
+	for (k=0; k < pxdesc->acccnt; k++) {
+		pace = &pxdesc->acl.ace[k];
+		if (pace->tag == POSIX_ACL_GROUP_OBJ)
+			perms = (perms & 07707)
+				| ((pace->perms & 7) << 3);
+		else
+			if (pace->tag == POSIX_ACL_GROUP) {
+				group = scx->mapping[MAPGROUPS];
+				while (group && (group->xid != pace->id))
+					group = group->next;
+				if (group && group->grcnt
+				    && (*(group->groups) == (gid_t)pace->id))
+					perms |= pace->perms & 7;
+			}
+	}
+	return (perms);
+}
+
+#endif /* POSIXACLS */
+
+/*
+ *	Cacheing is done two-way :
+ *	- from uid, gid and perm to securid (CACHED_SECURID)
+ *	- from a securid to uid, gid and perm (CACHED_PERMISSIONS)
+ *
+ *	CACHED_SECURID data is kept in a most-recent-first list
+ *	which should not be too long to be efficient. Its optimal
+ *	size is depends on usage and is hard to determine.
+ *
+ *	CACHED_PERMISSIONS data is kept in a two-level indexed array. It
+ *	is optimal at the expense of storage. Use of a most-recent-first
+ *	list would save memory and provide similar performances for
+ *	standard usage, but not for file servers with too many file
+ *	owners
+ *
+ *	CACHED_PERMISSIONS_LEGACY is a special case for CACHED_PERMISSIONS
+ *	for legacy directories which were not allocated a security_id
+ *	it is organized in a most-recent-first list.
+ *
+ *	In main caches, data is never invalidated, as the meaning of
+ *	a security_id only changes when user mapping is changed, which
+ *	current implies remounting. However returned entries may be
+ *	overwritten at next update, so data has to be copied elsewhere
+ *	before another cache update is made.
+ *	In legacy cache, data has to be invalidated when protection is
+ *	changed.
+ *
+ *	Though the same data may be found in both list, they
+ *	must be kept separately : the interpretation of ACL
+ *	in both direction are approximations which could be non
+ *	reciprocal for some configuration of the user mapping data
+ *
+ *	During the process of recompiling ntfs-3g from a tgz archive,
+ *	security processing added 7.6% to the cpu time used by ntfs-3g
+ *	and 30% if the cache is disabled.
+ */
+
+static struct PERMISSIONS_CACHE *create_caches(struct SECURITY_CONTEXT *scx,
+			u32 securindex)
+{
+	struct PERMISSIONS_CACHE *cache;
+	unsigned int index1;
+	unsigned int i;
+
+	cache = (struct PERMISSIONS_CACHE*)NULL;
+		/* create the first permissions blocks */
+	index1 = securindex >> CACHE_PERMISSIONS_BITS;
+	cache = (struct PERMISSIONS_CACHE*)
+		ntfs_malloc(sizeof(struct PERMISSIONS_CACHE)
+		      + index1*sizeof(struct CACHED_PERMISSIONS*));
+	if (cache) {
+		cache->head.last = index1;
+		cache->head.p_reads = 0;
+		cache->head.p_hits = 0;
+		cache->head.p_writes = 0;
+		*scx->pseccache = cache;
+		for (i=0; i<=index1; i++)
+			cache->cachetable[i]
+			   = (struct CACHED_PERMISSIONS*)NULL;
+	}
+	return (cache);
+}
+
+/*
+ *		Free memory used by caches
+ *	The only purpose is to facilitate the detection of memory leaks
+ */
+
+static void free_caches(struct SECURITY_CONTEXT *scx)
+{
+	unsigned int index1;
+	struct PERMISSIONS_CACHE *pseccache;
+
+	pseccache = *scx->pseccache;
+	if (pseccache) {
+		for (index1=0; index1<=pseccache->head.last; index1++)
+			if (pseccache->cachetable[index1]) {
+#if POSIXACLS
+				struct CACHED_PERMISSIONS *cacheentry;
+				unsigned int index2;
+
+				for (index2=0; index2<(1<< CACHE_PERMISSIONS_BITS); index2++) {
+					cacheentry = &pseccache->cachetable[index1][index2];
+					if (cacheentry->valid
+					    && cacheentry->pxdesc)
+						free(cacheentry->pxdesc);
+					}
+#endif
+				free(pseccache->cachetable[index1]);
+			}
+		free(pseccache);
+	}
+}
+
+static int compare(const struct CACHED_SECURID *cached,
+			const struct CACHED_SECURID *item)
+{
+#if POSIXACLS
+	size_t csize;
+	size_t isize;
+
+		/* only compare data and sizes */
+	csize = (cached->variable ?
+		sizeof(struct POSIX_ACL)
+		+ (((struct POSIX_SECURITY*)cached->variable)->acccnt
+		   + ((struct POSIX_SECURITY*)cached->variable)->defcnt)
+			*sizeof(struct POSIX_ACE) :
+		0);
+	isize = (item->variable ?
+		sizeof(struct POSIX_ACL)
+		+ (((struct POSIX_SECURITY*)item->variable)->acccnt
+		   + ((struct POSIX_SECURITY*)item->variable)->defcnt)
+			*sizeof(struct POSIX_ACE) :
+		0);
+	return ((cached->uid != item->uid)
+		 || (cached->gid != item->gid)
+		 || (cached->dmode != item->dmode)
+		 || (csize != isize)
+		 || (csize
+		    && isize
+		    && memcmp(&((struct POSIX_SECURITY*)cached->variable)->acl,
+		       &((struct POSIX_SECURITY*)item->variable)->acl, csize)));
+#else
+	return ((cached->uid != item->uid)
+		 || (cached->gid != item->gid)
+		 || (cached->dmode != item->dmode));
+#endif
+}
+
+static int leg_compare(const struct CACHED_PERMISSIONS_LEGACY *cached,
+			const struct CACHED_PERMISSIONS_LEGACY *item)
+{
+	return (cached->mft_no != item->mft_no);
+}
+
+/*
+ *	Resize permission cache table
+ *	do not call unless resizing is needed
+ *	
+ *	If allocation fails, the cache size is not updated
+ *	Lack of memory is not considered as an error, the cache is left
+ *	consistent and errno is not set.
+ */
+
+static void resize_cache(struct SECURITY_CONTEXT *scx,
+			u32 securindex)
+{
+	struct PERMISSIONS_CACHE *oldcache;
+	struct PERMISSIONS_CACHE *newcache;
+	int newcnt;
+	int oldcnt;
+	unsigned int index1;
+	unsigned int i;
+
+	oldcache = *scx->pseccache;
+	index1 = securindex >> CACHE_PERMISSIONS_BITS;
+	newcnt = index1 + 1;
+	if (newcnt <= ((CACHE_PERMISSIONS_SIZE
+			+ (1 << CACHE_PERMISSIONS_BITS)
+			- 1) >> CACHE_PERMISSIONS_BITS)) {
+		/* expand cache beyond current end, do not use realloc() */
+		/* to avoid losing data when there is no more memory */
+		oldcnt = oldcache->head.last + 1;
+		newcache = (struct PERMISSIONS_CACHE*)
+			ntfs_malloc(
+			    sizeof(struct PERMISSIONS_CACHE)
+			      + (newcnt - 1)*sizeof(struct CACHED_PERMISSIONS*));
+		if (newcache) {
+			memcpy(newcache,oldcache,
+			    sizeof(struct PERMISSIONS_CACHE)
+			      + (oldcnt - 1)*sizeof(struct CACHED_PERMISSIONS*));
+			free(oldcache);
+			     /* mark new entries as not valid */
+			for (i=newcache->head.last+1; i<=index1; i++)
+				newcache->cachetable[i]
+					 = (struct CACHED_PERMISSIONS*)NULL;
+			newcache->head.last = index1;
+			*scx->pseccache = newcache;
+		}
+	}
+}
+
+/*
+ *	Enter uid, gid and mode into cache, if possible
+ *
+ *	returns the updated or created cache entry,
+ *	or NULL if not possible (typically if there is no
+ *		security id associated)
+ */
+
+#if POSIXACLS
+static struct CACHED_PERMISSIONS *enter_cache(struct SECURITY_CONTEXT *scx,
+		ntfs_inode *ni, uid_t uid, gid_t gid,
+		struct POSIX_SECURITY *pxdesc)
+#else
+static struct CACHED_PERMISSIONS *enter_cache(struct SECURITY_CONTEXT *scx,
+		ntfs_inode *ni, uid_t uid, gid_t gid, mode_t mode)
+#endif
+{
+	struct CACHED_PERMISSIONS *cacheentry;
+	struct CACHED_PERMISSIONS *cacheblock;
+	struct PERMISSIONS_CACHE *pcache;
+	u32 securindex;
+#if POSIXACLS
+	int pxsize;
+	struct POSIX_SECURITY *pxcached;
+#endif
+	unsigned int index1;
+	unsigned int index2;
+	int i;
+
+	/* cacheing is only possible if a security_id has been defined */
+	if (test_nino_flag(ni, v3_Extensions)
+	   && ni->security_id) {
+		/*
+		 *  Immediately test the most frequent situation
+		 *  where the entry exists
+		 */
+		securindex = le32_to_cpu(ni->security_id);
+		index1 = securindex >> CACHE_PERMISSIONS_BITS;
+		index2 = securindex & ((1 << CACHE_PERMISSIONS_BITS) - 1);
+		pcache = *scx->pseccache;
+		if (pcache
+		     && (pcache->head.last >= index1)
+		     && pcache->cachetable[index1]) {
+			cacheentry = &pcache->cachetable[index1][index2];
+			cacheentry->uid = uid;
+			cacheentry->gid = gid;
+#if POSIXACLS
+			if (cacheentry->valid && cacheentry->pxdesc)
+				free(cacheentry->pxdesc);
+			if (pxdesc) {
+				pxsize = sizeof(struct POSIX_SECURITY)
+					+ (pxdesc->acccnt + pxdesc->defcnt)*sizeof(struct POSIX_ACE);
+				pxcached = (struct POSIX_SECURITY*)malloc(pxsize);
+				if (pxcached) {
+					memcpy(pxcached, pxdesc, pxsize);
+					cacheentry->pxdesc = pxcached;
+				} else {
+					cacheentry->valid = 0;
+					cacheentry = (struct CACHED_PERMISSIONS*)NULL;
+				}
+				cacheentry->mode = pxdesc->mode & 07777;
+			} else
+				cacheentry->pxdesc = (struct POSIX_SECURITY*)NULL;
+#else
+			cacheentry->mode = mode & 07777;
+#endif
+			cacheentry->inh_fileid = const_cpu_to_le32(0);
+			cacheentry->inh_dirid = const_cpu_to_le32(0);
+			cacheentry->valid = 1;
+			pcache->head.p_writes++;
+		} else {
+			if (!pcache) {
+				/* create the first cache block */
+				pcache = create_caches(scx, securindex);
+			} else {
+				if (index1 > pcache->head.last) {
+					resize_cache(scx, securindex);
+					pcache = *scx->pseccache;
+				}
+			}
+			/* allocate block, if cache table was allocated */
+			if (pcache && (index1 <= pcache->head.last)) {
+				cacheblock = (struct CACHED_PERMISSIONS*)
+					malloc(sizeof(struct CACHED_PERMISSIONS)
+						<< CACHE_PERMISSIONS_BITS);
+				pcache->cachetable[index1] = cacheblock;
+				for (i=0; i<(1 << CACHE_PERMISSIONS_BITS); i++)
+					cacheblock[i].valid = 0;
+				cacheentry = &cacheblock[index2];
+				if (cacheentry) {
+					cacheentry->uid = uid;
+					cacheentry->gid = gid;
+#if POSIXACLS
+					if (pxdesc) {
+						pxsize = sizeof(struct POSIX_SECURITY)
+							+ (pxdesc->acccnt + pxdesc->defcnt)*sizeof(struct POSIX_ACE);
+						pxcached = (struct POSIX_SECURITY*)malloc(pxsize);
+						if (pxcached) {
+							memcpy(pxcached, pxdesc, pxsize);
+							cacheentry->pxdesc = pxcached;
+						} else {
+							cacheentry->valid = 0;
+							cacheentry = (struct CACHED_PERMISSIONS*)NULL;
+						}
+						cacheentry->mode = pxdesc->mode & 07777;
+					} else
+						cacheentry->pxdesc = (struct POSIX_SECURITY*)NULL;
+#else
+					cacheentry->mode = mode & 07777;
+#endif
+					cacheentry->inh_fileid = const_cpu_to_le32(0);
+					cacheentry->inh_dirid = const_cpu_to_le32(0);
+					cacheentry->valid = 1;
+					pcache->head.p_writes++;
+				}
+			} else
+				cacheentry = (struct CACHED_PERMISSIONS*)NULL;
+		}
+	} else {
+		cacheentry = (struct CACHED_PERMISSIONS*)NULL;
+#if CACHE_LEGACY_SIZE
+		if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
+			struct CACHED_PERMISSIONS_LEGACY wanted;
+			struct CACHED_PERMISSIONS_LEGACY *legacy;
+
+			wanted.perm.uid = uid;
+			wanted.perm.gid = gid;
+#if POSIXACLS
+			wanted.perm.mode = pxdesc->mode & 07777;
+			wanted.perm.inh_fileid = const_cpu_to_le32(0);
+			wanted.perm.inh_dirid = const_cpu_to_le32(0);
+			wanted.mft_no = ni->mft_no;
+			wanted.variable = (void*)pxdesc;
+			wanted.varsize = sizeof(struct POSIX_SECURITY)
+					+ (pxdesc->acccnt + pxdesc->defcnt)*sizeof(struct POSIX_ACE);
+#else
+			wanted.perm.mode = mode & 07777;
+			wanted.perm.inh_fileid = const_cpu_to_le32(0);
+			wanted.perm.inh_dirid = const_cpu_to_le32(0);
+			wanted.mft_no = ni->mft_no;
+			wanted.variable = (void*)NULL;
+			wanted.varsize = 0;
+#endif
+			legacy = (struct CACHED_PERMISSIONS_LEGACY*)ntfs_enter_cache(
+				scx->vol->legacy_cache, GENERIC(&wanted),
+				(cache_compare)leg_compare);
+			if (legacy) {
+				cacheentry = &legacy->perm;
+#if POSIXACLS
+				/*
+				 * give direct access to the cached pxdesc
+				 * in the permissions structure
+				 */
+				cacheentry->pxdesc = legacy->variable;
+#endif
+			}
+		}
+#endif
+	}
+	return (cacheentry);
+}
+
+/*
+ *	Fetch owner, group and permission of a file, if cached
+ *
+ *	Beware : do not use the returned entry after a cache update :
+ *	the cache may be relocated making the returned entry meaningless
+ *
+ *	returns the cache entry, or NULL if not available
+ */
+
+static struct CACHED_PERMISSIONS *fetch_cache(struct SECURITY_CONTEXT *scx,
+		ntfs_inode *ni)
+{
+	struct CACHED_PERMISSIONS *cacheentry;
+	struct PERMISSIONS_CACHE *pcache;
+	u32 securindex;
+	unsigned int index1;
+	unsigned int index2;
+
+	/* cacheing is only possible if a security_id has been defined */
+	cacheentry = (struct CACHED_PERMISSIONS*)NULL;
+	if (test_nino_flag(ni, v3_Extensions)
+	   && (ni->security_id)) {
+		securindex = le32_to_cpu(ni->security_id);
+		index1 = securindex >> CACHE_PERMISSIONS_BITS;
+		index2 = securindex & ((1 << CACHE_PERMISSIONS_BITS) - 1);
+		pcache = *scx->pseccache;
+		if (pcache
+		     && (pcache->head.last >= index1)
+		     && pcache->cachetable[index1]) {
+			cacheentry = &pcache->cachetable[index1][index2];
+			/* reject if entry is not valid */
+			if (!cacheentry->valid)
+				cacheentry = (struct CACHED_PERMISSIONS*)NULL;
+			else
+				pcache->head.p_hits++;
+		if (pcache)
+			pcache->head.p_reads++;
+		}
+	}
+#if CACHE_LEGACY_SIZE
+	else {
+		cacheentry = (struct CACHED_PERMISSIONS*)NULL;
+		if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
+			struct CACHED_PERMISSIONS_LEGACY wanted;
+			struct CACHED_PERMISSIONS_LEGACY *legacy;
+
+			wanted.mft_no = ni->mft_no;
+			wanted.variable = (void*)NULL;
+			wanted.varsize = 0;
+			legacy = (struct CACHED_PERMISSIONS_LEGACY*)ntfs_fetch_cache(
+				scx->vol->legacy_cache, GENERIC(&wanted),
+				(cache_compare)leg_compare);
+			if (legacy) cacheentry = &legacy->perm;
+		}
+	}
+#endif
+#if POSIXACLS
+	if (cacheentry && !cacheentry->pxdesc) {
+		ntfs_log_error("No Posix descriptor in cache\n");
+		cacheentry = (struct CACHED_PERMISSIONS*)NULL;
+	}
+#endif
+	return (cacheentry);
+}
+
+/*
+ *	Retrieve a security attribute from $Secure
+ */
+
+static char *retrievesecurityattr(ntfs_volume *vol, SII_INDEX_KEY id)
+{
+	struct SII *psii;
+	union {
+		struct {
+			le32 dataoffsl;
+			le32 dataoffsh;
+		} parts;
+		le64 all;
+	} realign;
+	int found;
+	size_t size;
+	size_t rdsize;
+	s64 offs;
+	ntfs_inode *ni;
+	ntfs_index_context *xsii;
+	char *securattr;
+
+	securattr = (char*)NULL;
+	ni = vol->secure_ni;
+	xsii = vol->secure_xsii;
+	if (ni && xsii) {
+		ntfs_index_ctx_reinit(xsii);
+		found =
+		    !ntfs_index_lookup((char*)&id,
+				       sizeof(SII_INDEX_KEY), xsii);
+		if (found) {
+			psii = (struct SII*)xsii->entry;
+			size =
+			    (size_t) le32_to_cpu(psii->datasize)
+				 - sizeof(SECURITY_DESCRIPTOR_HEADER);
+			/* work around bad alignment problem */
+			realign.parts.dataoffsh = psii->dataoffsh;
+			realign.parts.dataoffsl = psii->dataoffsl;
+			offs = le64_to_cpu(realign.all)
+				+ sizeof(SECURITY_DESCRIPTOR_HEADER);
+
+			securattr = (char*)ntfs_malloc(size);
+			if (securattr) {
+				rdsize = ntfs_attr_data_read(
+					ni, STREAM_SDS, 4,
+					securattr, size, offs);
+				if ((rdsize != size)
+					|| !ntfs_valid_descr(securattr,
+						rdsize)) {
+					/* error to be logged by caller */
+					free(securattr);
+					securattr = (char*)NULL;
+				}
+			}
+		} else
+			if (errno != ENOENT)
+				ntfs_log_perror("Inconsistency in index $SII");
+	}
+	if (!securattr) {
+		ntfs_log_error("Failed to retrieve a security descriptor\n");
+		errno = EIO;
+	}
+	return (securattr);
+}
+
+/*
+ *		Get the security descriptor associated to a file
+ *
+ *	Either :
+ *	   - read the security descriptor attribute (v1.x format)
+ *	   - or find the descriptor in $Secure:$SDS (v3.x format)
+ *
+ *	in both case, sanity checks are done on the attribute and
+ *	the descriptor can be assumed safe
+ *
+ *	The returned descriptor is dynamically allocated and has to be freed
+ */
+
+static char *getsecurityattr(ntfs_volume *vol, ntfs_inode *ni)
+{
+	SII_INDEX_KEY securid;
+	char *securattr;
+	s64 readallsz;
+
+		/*
+		 * Warning : in some situations, after fixing by chkdsk,
+		 * v3_Extensions are marked present (long standard informations)
+		 * with a default security descriptor inserted in an
+		 * attribute
+		 */
+	if (test_nino_flag(ni, v3_Extensions)
+	    && vol->secure_ni && ni->security_id) {
+			/* get v3.x descriptor in $Secure */
+		securid.security_id = ni->security_id;
+		securattr = retrievesecurityattr(vol,securid);
+		if (!securattr)
+			ntfs_log_error("Bad security descriptor for 0x%lx\n",
+					(long)le32_to_cpu(ni->security_id));
+	} else {
+			/* get v1.x security attribute */
+		readallsz = 0;
+		securattr = ntfs_attr_readall(ni, AT_SECURITY_DESCRIPTOR,
+				AT_UNNAMED, 0, &readallsz);
+		if (securattr && !ntfs_valid_descr(securattr, readallsz)) {
+			ntfs_log_error("Bad security descriptor for inode %lld\n",
+				(long long)ni->mft_no);
+			free(securattr);
+			securattr = (char*)NULL;
+		}
+	}
+	if (!securattr) {
+			/*
+			 * in some situations, there is no security
+			 * descriptor, and chkdsk does not detect or fix
+			 * anything. This could be a normal situation.
+			 * When this happens, simulate a descriptor with
+			 * minimum rights, so that a real descriptor can
+			 * be created by chown or chmod
+			 */
+		ntfs_log_error("No security descriptor found for inode %lld\n",
+				(long long)ni->mft_no);
+		securattr = ntfs_build_descr(0, 0, adminsid, adminsid);
+	}
+	return (securattr);
+}
+
+#if POSIXACLS
+
+/*
+ *		Determine which access types to a file are allowed
+ *	according to the relation of current process to the file
+ *
+ *	When Posix ACLs are compiled in but not enabled in the mount
+ *	options POSIX_ACL_USER, POSIX_ACL_GROUP and POSIX_ACL_MASK
+ *	are ignored.
+ */
+
+static int access_check_posix(struct SECURITY_CONTEXT *scx,
+			struct POSIX_SECURITY *pxdesc, mode_t request,
+			uid_t uid, gid_t gid)
+{
+	struct POSIX_ACE *pxace;
+	int userperms;
+	int groupperms;
+	int mask;
+	BOOL somegroup;
+	BOOL needgroups;
+	BOOL noacl;
+	mode_t perms;
+	int i;
+
+	noacl = !(scx->vol->secure_flags & (1 << SECURITY_ACL));
+	if (noacl)
+		perms = ntfs_basic_perms(scx, pxdesc);
+	else
+		perms = pxdesc->mode;
+					/* owner and root access */
+	if (!scx->uid || (uid == scx->uid)) {
+		if (!scx->uid) {
+					/* root access if owner or other execution */
+			if (perms & 0101)
+				perms |= 01777;
+			else {
+					/* root access if some group execution */
+				groupperms = 0;
+				mask = 7;
+				for (i=pxdesc->acccnt-1; i>=0 ; i--) {
+					pxace = &pxdesc->acl.ace[i];
+					switch (pxace->tag) {
+					case POSIX_ACL_USER_OBJ :
+					case POSIX_ACL_GROUP_OBJ :
+						groupperms |= pxace->perms;
+						break;
+					case POSIX_ACL_GROUP :
+						if (!noacl)
+							groupperms
+							    |= pxace->perms;
+						break;
+					case POSIX_ACL_MASK :
+						if (!noacl)
+							mask = pxace->perms & 7;
+						break;
+					default :
+						break;
+					}
+				}
+				perms = (groupperms & mask & 1) | 6;
+			}
+		} else
+			perms &= 07700;
+	} else {
+				/*
+				 * analyze designated users, get mask
+				 * and identify whether we need to check
+				 * the group memberships. The groups are
+				 * not needed when all groups have the
+				 * same permissions as other for the
+				 * requested modes.
+				 */
+		userperms = -1;
+		groupperms = -1;
+		needgroups = FALSE;
+		mask = 7;
+		for (i=pxdesc->acccnt-1; i>=0 ; i--) {
+			pxace = &pxdesc->acl.ace[i];
+			switch (pxace->tag) {
+			case POSIX_ACL_USER :
+				if (!noacl
+				    && ((uid_t)pxace->id == scx->uid))
+					userperms = pxace->perms;
+				break;
+			case POSIX_ACL_MASK :
+				if (!noacl)
+					mask = pxace->perms & 7;
+				break;
+			case POSIX_ACL_GROUP_OBJ :
+				if (((pxace->perms & mask) ^ perms)
+				    & (request >> 6) & 7)
+					needgroups = TRUE;
+				break;
+			case POSIX_ACL_GROUP :
+				if (!noacl
+				    && (((pxace->perms & mask) ^ perms)
+					    & (request >> 6) & 7))
+					needgroups = TRUE;
+				break;
+			default :
+				break;
+			}
+		}
+					/* designated users */
+		if (userperms >= 0)
+			perms = (perms & 07000) + (userperms & mask);
+		else if (!needgroups)
+				perms &= 07007;
+		else {
+					/* owning group */
+			if (!(~(perms >> 3) & request & mask)
+			    && ((gid == scx->gid)
+				|| groupmember(scx, scx->uid, gid)))
+				perms &= 07070;
+			else if (!noacl) {
+					/* other groups */
+				groupperms = -1;
+				somegroup = FALSE;
+				for (i=pxdesc->acccnt-1; i>=0 ; i--) {
+					pxace = &pxdesc->acl.ace[i];
+					if ((pxace->tag == POSIX_ACL_GROUP)
+					    && groupmember(scx, scx->uid, pxace->id)) {
+						if (!(~pxace->perms & request & mask))
+							groupperms = pxace->perms;
+						somegroup = TRUE;
+					}
+				}
+				if (groupperms >= 0)
+					perms = (perms & 07000) + (groupperms & mask);
+				else
+					if (somegroup)
+						perms = 0;
+					else
+						perms &= 07007;
+			} else
+				perms &= 07007;
+		}
+	}
+	return (perms);
+}
+
+/*
+ *		Get permissions to access a file
+ *	Takes into account the relation of user to file (owner, group, ...)
+ *	Do no use as mode of the file
+ *	Do no call if default_permissions is set
+ *
+ *	returns -1 if there is a problem
+ */
+
+static int ntfs_get_perm(struct SECURITY_CONTEXT *scx,
+		 ntfs_inode * ni, mode_t request)
+{
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	const struct CACHED_PERMISSIONS *cached;
+	char *securattr;
+	const SID *usid;	/* owner of file/directory */
+	const SID *gsid;	/* group of file/directory */
+	uid_t uid;
+	gid_t gid;
+	int perm;
+	BOOL isdir;
+	struct POSIX_SECURITY *pxdesc;
+
+	if (!scx->mapping[MAPUSERS])
+		perm = 07777;
+	else {
+		/* check whether available in cache */
+		cached = fetch_cache(scx,ni);
+		if (cached) {
+			uid = cached->uid;
+			gid = cached->gid;
+			perm = access_check_posix(scx,cached->pxdesc,request,uid,gid);
+		} else {
+			perm = 0;	/* default to no permission */
+			isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
+				!= const_cpu_to_le16(0);
+			securattr = getsecurityattr(scx->vol, ni);
+			if (securattr) {
+				phead = (const SECURITY_DESCRIPTOR_RELATIVE*)
+				    	securattr;
+				gsid = (const SID*)&
+					   securattr[le32_to_cpu(phead->group)];
+				gid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid);
+#if OWNERFROMACL
+				usid = ntfs_acl_owner(securattr);
+				pxdesc = ntfs_build_permissions_posix(scx->mapping,securattr,
+						 usid, gsid, isdir);
+				if (pxdesc)
+					perm = pxdesc->mode & 07777;
+				else
+					perm = -1;
+				uid = ntfs_find_user(scx->mapping[MAPUSERS],usid);
+#else
+				usid = (const SID*)&
+					    securattr[le32_to_cpu(phead->owner)];
+				pxdesc = ntfs_build_permissions_posix(scx,securattr,
+						 usid, gsid, isdir);
+				if (pxdesc)
+					perm = pxdesc->mode & 07777;
+				else
+					perm = -1;
+				if (!perm && ntfs_same_sid(usid, adminsid)) {
+					uid = find_tenant(scx, securattr);
+					if (uid)
+						perm = 0700;
+				} else
+					uid = ntfs_find_user(scx->mapping[MAPUSERS],usid);
+#endif
+				/*
+				 *  Create a security id if there were none
+				 * and upgrade option is selected
+				 */
+				if (!test_nino_flag(ni, v3_Extensions)
+				   && (perm >= 0)
+				   && (scx->vol->secure_flags
+				     & (1 << SECURITY_ADDSECURIDS))) {
+					upgrade_secur_desc(scx->vol,
+						securattr, ni);
+					/*
+					 * fetch owner and group for cacheing
+					 * if there is a securid
+					 */
+				}
+				if (test_nino_flag(ni, v3_Extensions)
+				    && (perm >= 0)) {
+					enter_cache(scx, ni, uid,
+							gid, pxdesc);
+				}
+				if (pxdesc) {
+					perm = access_check_posix(scx,pxdesc,request,uid,gid);
+					free(pxdesc);
+				}
+				free(securattr);
+			} else {
+				perm = -1;
+				uid = gid = 0;
+			}
+		}
+	}
+	return (perm);
+}
+
+/*
+ *		Get a Posix ACL
+ *
+ *	returns size or -errno if there is a problem
+ *	if size was too small, no copy is done and errno is not set,
+ *	the caller is expected to issue a new call
+ */
+
+int ntfs_get_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
+			const char *name, char *value, size_t size) 
+{
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	struct POSIX_SECURITY *pxdesc;
+	const struct CACHED_PERMISSIONS *cached;
+	char *securattr;
+	const SID *usid;	/* owner of file/directory */
+	const SID *gsid;	/* group of file/directory */
+	uid_t uid;
+	gid_t gid;
+	BOOL isdir;
+	size_t outsize;
+
+	outsize = 0;	/* default to error */
+	if (!scx->mapping[MAPUSERS])
+		errno = ENOTSUP;
+	else {
+			/* check whether available in cache */
+		cached = fetch_cache(scx,ni);
+		if (cached)
+			pxdesc = cached->pxdesc;
+		else {
+			securattr = getsecurityattr(scx->vol, ni);
+			isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
+				!= const_cpu_to_le16(0);
+			if (securattr) {
+				phead =
+				    (const SECURITY_DESCRIPTOR_RELATIVE*)
+			    			securattr;
+				gsid = (const SID*)&
+					  securattr[le32_to_cpu(phead->group)];
+#if OWNERFROMACL
+				usid = ntfs_acl_owner(securattr);
+#else
+				usid = (const SID*)&
+					  securattr[le32_to_cpu(phead->owner)];
+#endif
+				pxdesc = ntfs_build_permissions_posix(scx->mapping,securattr,
+					  usid, gsid, isdir);
+
+					/*
+					 * fetch owner and group for cacheing
+					 */
+				if (pxdesc) {
+				/*
+				 *  Create a security id if there were none
+				 * and upgrade option is selected
+				 */
+					if (!test_nino_flag(ni, v3_Extensions)
+					   && (scx->vol->secure_flags
+					     & (1 << SECURITY_ADDSECURIDS))) {
+						upgrade_secur_desc(scx->vol,
+							 securattr, ni);
+					}
+#if OWNERFROMACL
+					uid = ntfs_find_user(scx->mapping[MAPUSERS],usid);
+#else
+					if (!(pxdesc->mode & 07777)
+					    && ntfs_same_sid(usid, adminsid)) {
+						uid = find_tenant(scx,
+								securattr);
+					} else
+						uid = ntfs_find_user(scx->mapping[MAPUSERS],usid);
+#endif
+					gid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid);
+					if (pxdesc->tagsset & POSIX_ACL_EXTENSIONS)
+					enter_cache(scx, ni, uid,
+							gid, pxdesc);
+				}
+				free(securattr);
+			} else
+				pxdesc = (struct POSIX_SECURITY*)NULL;
+		}
+
+		if (pxdesc) {
+			if (ntfs_valid_posix(pxdesc)) {
+				if (!strcmp(name,"system.posix_acl_default")) {
+					if (ni->mrec->flags
+						    & MFT_RECORD_IS_DIRECTORY)
+						outsize = sizeof(struct POSIX_ACL)
+							+ pxdesc->defcnt*sizeof(struct POSIX_ACE);
+					else {
+					/*
+					 * getting default ACL from plain file :
+					 * return EACCES if size > 0 as
+					 * indicated in the man, but return ok
+					 * if size == 0, so that ls does not
+					 * display an error
+					 */
+						if (size > 0) {
+							outsize = 0;
+							errno = EACCES;
+						} else
+							outsize = sizeof(struct POSIX_ACL);
+					}
+					if (outsize && (outsize <= size)) {
+						memcpy(value,&pxdesc->acl,sizeof(struct POSIX_ACL));
+						memcpy(&value[sizeof(struct POSIX_ACL)],
+							&pxdesc->acl.ace[pxdesc->firstdef],
+							outsize-sizeof(struct POSIX_ACL));
+					}
+				} else {
+					outsize = sizeof(struct POSIX_ACL)
+						+ pxdesc->acccnt*sizeof(struct POSIX_ACE);
+					if (outsize <= size)
+						memcpy(value,&pxdesc->acl,outsize);
+				}
+			} else {
+				outsize = 0;
+				errno = EIO;
+				ntfs_log_error("Invalid Posix ACL built\n");
+			}
+			if (!cached)
+				free(pxdesc);
+		} else
+			outsize = 0;
+	}
+	return (outsize ? (int)outsize : -errno);
+}
+
+#else /* POSIXACLS */
+
+
+/*
+ *		Get permissions to access a file
+ *	Takes into account the relation of user to file (owner, group, ...)
+ *	Do no use as mode of the file
+ *
+ *	returns -1 if there is a problem
+ */
+
+static int ntfs_get_perm(struct SECURITY_CONTEXT *scx,
+		ntfs_inode *ni,	mode_t request)
+{
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	const struct CACHED_PERMISSIONS *cached;
+	char *securattr;
+	const SID *usid;	/* owner of file/directory */
+	const SID *gsid;	/* group of file/directory */
+	BOOL isdir;
+	uid_t uid;
+	gid_t gid;
+	int perm;
+
+	if (!scx->mapping[MAPUSERS] || (!scx->uid && !(request & S_IEXEC)))
+		perm = 07777;
+	else {
+		/* check whether available in cache */
+		cached = fetch_cache(scx,ni);
+		if (cached) {
+			perm = cached->mode;
+			uid = cached->uid;
+			gid = cached->gid;
+		} else {
+			perm = 0;	/* default to no permission */
+			isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
+				!= const_cpu_to_le16(0);
+			securattr = getsecurityattr(scx->vol, ni);
+			if (securattr) {
+				phead = (const SECURITY_DESCRIPTOR_RELATIVE*)
+				    	securattr;
+				gsid = (const SID*)&
+					   securattr[le32_to_cpu(phead->group)];
+				gid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid);
+#if OWNERFROMACL
+				usid = ntfs_acl_owner(securattr);
+				perm = ntfs_build_permissions(securattr,
+						 usid, gsid, isdir);
+				uid = ntfs_find_user(scx->mapping[MAPUSERS],usid);
+#else
+				usid = (const SID*)&
+					    securattr[le32_to_cpu(phead->owner)];
+				perm = ntfs_build_permissions(securattr,
+						 usid, gsid, isdir);
+				if (!perm && ntfs_same_sid(usid, adminsid)) {
+					uid = find_tenant(scx, securattr);
+					if (uid)
+						perm = 0700;
+				} else
+					uid = ntfs_find_user(scx->mapping[MAPUSERS],usid);
+#endif
+				/*
+				 *  Create a security id if there were none
+				 * and upgrade option is selected
+				 */
+				if (!test_nino_flag(ni, v3_Extensions)
+				   && (perm >= 0)
+				   && (scx->vol->secure_flags
+				     & (1 << SECURITY_ADDSECURIDS))) {
+					upgrade_secur_desc(scx->vol,
+						securattr, ni);
+					/*
+					 * fetch owner and group for cacheing
+					 * if there is a securid
+					 */
+				}
+				if (test_nino_flag(ni, v3_Extensions)
+				    && (perm >= 0)) {
+					enter_cache(scx, ni, uid,
+							gid, perm);
+				}
+				free(securattr);
+			} else {
+				perm = -1;
+				uid = gid = 0;
+			}
+		}
+		if (perm >= 0) {
+			if (!scx->uid) {
+				/* root access and execution */
+				if (perm & 0111)
+					perm |= 01777;
+				else
+					perm = 0;
+			} else
+				if (uid == scx->uid)
+					perm &= 07700;
+				else
+				/*
+				 * avoid checking group membership
+				 * when the requested perms for group
+				 * are the same as perms for other
+				 */
+					if ((gid == scx->gid)
+					  || ((((perm >> 3) ^ perm)
+						& (request >> 6) & 7)
+					    && groupmember(scx, scx->uid, gid)))
+						perm &= 07070;
+					else
+						perm &= 07007;
+		}
+	}
+	return (perm);
+}
+
+#endif /* POSIXACLS */
+
+/*
+ *		Get an NTFS ACL
+ *
+ *	Returns size or -errno if there is a problem
+ *	if size was too small, no copy is done and errno is not set,
+ *	the caller is expected to issue a new call
+ */
+
+int ntfs_get_ntfs_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
+			char *value, size_t size)
+{
+	char *securattr;
+	size_t outsize;
+
+	outsize = 0;	/* default to no data and no error */
+	securattr = getsecurityattr(scx->vol, ni);
+	if (securattr) {
+		outsize = ntfs_attr_size(securattr);
+		if (outsize <= size) {
+			memcpy(value,securattr,outsize);
+		}
+		free(securattr);
+	}
+	return (outsize ? (int)outsize : -errno);
+}
+
+/*
+ *		Get owner, group and permissions in an stat structure
+ *	returns permissions, or -1 if there is a problem
+ */
+
+int ntfs_get_owner_mode(struct SECURITY_CONTEXT *scx,
+		ntfs_inode * ni, struct stat *stbuf)
+{
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	char *securattr;
+	const SID *usid;	/* owner of file/directory */
+	const SID *gsid;	/* group of file/directory */
+	const struct CACHED_PERMISSIONS *cached;
+	int perm;
+	BOOL isdir;
+#if POSIXACLS
+	struct POSIX_SECURITY *pxdesc;
+#endif
+
+	if (!scx->mapping[MAPUSERS])
+		perm = 07777;
+	else {
+			/* check whether available in cache */
+		cached = fetch_cache(scx,ni);
+		if (cached) {
+#if POSIXACLS
+			if (!(scx->vol->secure_flags & (1 << SECURITY_ACL))
+			    && cached->pxdesc)
+				perm = ntfs_basic_perms(scx,cached->pxdesc);
+			else
+#endif
+				perm = cached->mode;
+			stbuf->st_uid = cached->uid;
+			stbuf->st_gid = cached->gid;
+			stbuf->st_mode = (stbuf->st_mode & ~07777) + perm;
+		} else {
+			perm = -1;	/* default to error */
+			isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
+				!= const_cpu_to_le16(0);
+			securattr = getsecurityattr(scx->vol, ni);
+			if (securattr) {
+				phead =
+				    (const SECURITY_DESCRIPTOR_RELATIVE*)
+					    	securattr;
+				gsid = (const SID*)&
+					  securattr[le32_to_cpu(phead->group)];
+#if OWNERFROMACL
+				usid = ntfs_acl_owner(securattr);
+#else
+				usid = (const SID*)&
+					  securattr[le32_to_cpu(phead->owner)];
+#endif
+#if POSIXACLS
+				pxdesc = ntfs_build_permissions_posix(
+						scx->mapping, securattr,
+					usid, gsid, isdir);
+				if (pxdesc) {
+					if (!(scx->vol->secure_flags
+					    & (1 << SECURITY_ACL)))
+						perm = ntfs_basic_perms(scx,
+								pxdesc);
+					else
+						perm = pxdesc->mode & 07777;
+				} else
+					perm = -1;
+#else
+				perm = ntfs_build_permissions(securattr,
+					  usid, gsid, isdir);
+#endif
+					/*
+					 * fetch owner and group for cacheing
+					 */
+				if (perm >= 0) {
+				/*
+				 *  Create a security id if there were none
+				 * and upgrade option is selected
+				 */
+					if (!test_nino_flag(ni, v3_Extensions)
+					   && (scx->vol->secure_flags
+					     & (1 << SECURITY_ADDSECURIDS))) {
+						upgrade_secur_desc(scx->vol,
+							 securattr, ni);
+					}
+#if OWNERFROMACL
+					stbuf->st_uid = ntfs_find_user(scx->mapping[MAPUSERS],usid);
+#else
+					if (!perm && ntfs_same_sid(usid, adminsid)) {
+						stbuf->st_uid = 
+							find_tenant(scx,
+								securattr);
+						if (stbuf->st_uid)
+							perm = 0700;
+					} else
+						stbuf->st_uid = ntfs_find_user(scx->mapping[MAPUSERS],usid);
+#endif
+					stbuf->st_gid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid);
+					stbuf->st_mode =
+					    (stbuf->st_mode & ~07777) + perm;
+#if POSIXACLS
+					enter_cache(scx, ni, stbuf->st_uid,
+						stbuf->st_gid, pxdesc);
+					free(pxdesc);
+#else
+					enter_cache(scx, ni, stbuf->st_uid,
+						stbuf->st_gid, perm);
+#endif
+				}
+				free(securattr);
+			}
+		}
+	}
+	return (perm);
+}
+
+#if POSIXACLS
+
+/*
+ *		Get the base for a Posix inheritance and
+ *	build an inherited Posix descriptor
+ */
+
+static struct POSIX_SECURITY *inherit_posix(struct SECURITY_CONTEXT *scx,
+			ntfs_inode *dir_ni, mode_t mode, BOOL isdir)
+{
+	const struct CACHED_PERMISSIONS *cached;
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	struct POSIX_SECURITY *pxdesc;
+	struct POSIX_SECURITY *pydesc;
+	char *securattr;
+	const SID *usid;
+	const SID *gsid;
+	uid_t uid;
+	gid_t gid;
+
+	pydesc = (struct POSIX_SECURITY*)NULL;
+		/* check whether parent directory is available in cache */
+	cached = fetch_cache(scx,dir_ni);
+	if (cached) {
+		uid = cached->uid;
+		gid = cached->gid;
+		pxdesc = cached->pxdesc;
+		if (pxdesc) {
+			if (scx->vol->secure_flags & (1 << SECURITY_ACL))
+				pydesc = ntfs_build_inherited_posix(pxdesc,
+					mode, scx->umask, isdir);
+			else
+				pydesc = ntfs_build_basic_posix(pxdesc,
+					mode, scx->umask, isdir);
+		}
+	} else {
+		securattr = getsecurityattr(scx->vol, dir_ni);
+		if (securattr) {
+			phead = (const SECURITY_DESCRIPTOR_RELATIVE*)
+			    	securattr;
+			gsid = (const SID*)&
+				   securattr[le32_to_cpu(phead->group)];
+			gid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid);
+#if OWNERFROMACL
+			usid = ntfs_acl_owner(securattr);
+			pxdesc = ntfs_build_permissions_posix(scx->mapping,securattr,
+						 usid, gsid, TRUE);
+			uid = ntfs_find_user(scx->mapping[MAPUSERS],usid);
+#else
+			usid = (const SID*)&
+				    securattr[le32_to_cpu(phead->owner)];
+			pxdesc = ntfs_build_permissions_posix(scx->mapping,securattr,
+						 usid, gsid, TRUE);
+			if (pxdesc && ntfs_same_sid(usid, adminsid)) {
+				uid = find_tenant(scx, securattr);
+			} else
+				uid = ntfs_find_user(scx->mapping[MAPUSERS],usid);
+#endif
+			if (pxdesc) {
+				/*
+				 *  Create a security id if there were none
+				 * and upgrade option is selected
+				 */
+				if (!test_nino_flag(dir_ni, v3_Extensions)
+				   && (scx->vol->secure_flags
+				     & (1 << SECURITY_ADDSECURIDS))) {
+					upgrade_secur_desc(scx->vol,
+						securattr, dir_ni);
+					/*
+					 * fetch owner and group for cacheing
+					 * if there is a securid
+					 */
+				}
+				if (test_nino_flag(dir_ni, v3_Extensions)) {
+					enter_cache(scx, dir_ni, uid,
+							gid, pxdesc);
+				}
+				if (scx->vol->secure_flags
+							& (1 << SECURITY_ACL))
+					pydesc = ntfs_build_inherited_posix(
+						pxdesc, mode,
+						scx->umask, isdir);
+				else
+					pydesc = ntfs_build_basic_posix(
+						pxdesc, mode,
+						scx->umask, isdir);
+				free(pxdesc);
+			}
+			free(securattr);
+		}
+	}
+	return (pydesc);
+}
+
+/*
+ *		Allocate a security_id for a file being created
+ *	
+ *	Returns zero if not possible (NTFS v3.x required)
+ */
+
+le32 ntfs_alloc_securid(struct SECURITY_CONTEXT *scx,
+		uid_t uid, gid_t gid, ntfs_inode *dir_ni,
+		mode_t mode, BOOL isdir)
+{
+#if !FORCE_FORMAT_v1x
+	const struct CACHED_SECURID *cached;
+	struct CACHED_SECURID wanted;
+	struct POSIX_SECURITY *pxdesc;
+	char *newattr;
+	int newattrsz;
+	const SID *usid;
+	const SID *gsid;
+	BIGSID defusid;
+	BIGSID defgsid;
+	le32 securid;
+#endif
+
+	securid = const_cpu_to_le32(0);
+
+#if !FORCE_FORMAT_v1x
+
+	pxdesc = inherit_posix(scx, dir_ni, mode, isdir);
+	if (pxdesc) {
+		/* check whether target securid is known in cache */
+
+		wanted.uid = uid;
+		wanted.gid = gid;
+		wanted.dmode = pxdesc->mode & mode & 07777;
+		if (isdir) wanted.dmode |= 0x10000;
+		wanted.variable = (void*)pxdesc;
+		wanted.varsize = sizeof(struct POSIX_SECURITY)
+				+ (pxdesc->acccnt + pxdesc->defcnt)*sizeof(struct POSIX_ACE);
+		cached = (const struct CACHED_SECURID*)ntfs_fetch_cache(
+				scx->vol->securid_cache, GENERIC(&wanted),
+				(cache_compare)compare);
+			/* quite simple, if we are lucky */
+		if (cached)
+			securid = cached->securid;
+
+			/* not in cache : make sure we can create ids */
+
+		if (!cached && (scx->vol->major_ver >= 3)) {
+			usid = ntfs_find_usid(scx->mapping[MAPUSERS],uid,(SID*)&defusid);
+			gsid = ntfs_find_gsid(scx->mapping[MAPGROUPS],gid,(SID*)&defgsid);
+			if (!usid || !gsid) {
+				ntfs_log_error("File created by an unmapped user/group %d/%d\n",
+						(int)uid, (int)gid);
+				usid = gsid = adminsid;
+			}
+			newattr = ntfs_build_descr_posix(scx->mapping, pxdesc,
+					isdir, usid, gsid);
+			if (newattr) {
+				newattrsz = ntfs_attr_size(newattr);
+				securid = setsecurityattr(scx->vol,
+					(const SECURITY_DESCRIPTOR_RELATIVE*)newattr,
+					newattrsz);
+				if (securid) {
+					/* update cache, for subsequent use */
+					wanted.securid = securid;
+					ntfs_enter_cache(scx->vol->securid_cache,
+							GENERIC(&wanted),
+							(cache_compare)compare);
+				}
+				free(newattr);
+			} else {
+				/*
+				 * could not build new security attribute
+				 * errno set by ntfs_build_descr()
+				 */
+			}
+		}
+	free(pxdesc);
+	}
+#endif
+	return (securid);
+}
+
+/*
+ *		Apply Posix inheritance to a newly created file
+ *	(for NTFS 1.x only : no securid)
+ */
+
+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)
+{
+	struct POSIX_SECURITY *pxdesc;
+	char *newattr;
+	const SID *usid;
+	const SID *gsid;
+	BIGSID defusid;
+	BIGSID defgsid;
+	BOOL isdir;
+	int res;
+
+	res = -1;
+	isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) != const_cpu_to_le16(0);
+	pxdesc = inherit_posix(scx, dir_ni, mode, isdir);
+	if (pxdesc) {
+		usid = ntfs_find_usid(scx->mapping[MAPUSERS],uid,(SID*)&defusid);
+		gsid = ntfs_find_gsid(scx->mapping[MAPGROUPS],gid,(SID*)&defgsid);
+		if (!usid || !gsid) {
+			ntfs_log_error("File created by an unmapped user/group %d/%d\n",
+					(int)uid, (int)gid);
+			usid = gsid = adminsid;
+		}
+		newattr = ntfs_build_descr_posix(scx->mapping, pxdesc,
+					isdir, usid, gsid);
+		if (newattr) {
+				/* Adjust Windows read-only flag */
+			res = update_secur_descr(scx->vol, newattr, ni);
+			if (!res && !isdir) {
+				if (mode & S_IWUSR)
+					ni->flags &= ~FILE_ATTR_READONLY;
+				else
+					ni->flags |= FILE_ATTR_READONLY;
+			}
+#if CACHE_LEGACY_SIZE
+			/* also invalidate legacy cache */
+			if (isdir && !ni->security_id) {
+				struct CACHED_PERMISSIONS_LEGACY legacy;
+
+				legacy.mft_no = ni->mft_no;
+				legacy.variable = pxdesc;
+				legacy.varsize = sizeof(struct POSIX_SECURITY)
+					+ (pxdesc->acccnt + pxdesc->defcnt)*sizeof(struct POSIX_ACE);
+				ntfs_invalidate_cache(scx->vol->legacy_cache,
+						GENERIC(&legacy),
+						(cache_compare)leg_compare,0);
+			}
+#endif
+			free(newattr);
+
+		} else {
+			/*
+			 * could not build new security attribute
+			 * errno set by ntfs_build_descr()
+			 */
+		}
+	}
+	return (res);
+}
+
+#else
+
+le32 ntfs_alloc_securid(struct SECURITY_CONTEXT *scx,
+		uid_t uid, gid_t gid, mode_t mode, BOOL isdir)
+{
+#if !FORCE_FORMAT_v1x
+	const struct CACHED_SECURID *cached;
+	struct CACHED_SECURID wanted;
+	char *newattr;
+	int newattrsz;
+	const SID *usid;
+	const SID *gsid;
+	BIGSID defusid;
+	BIGSID defgsid;
+	le32 securid;
+#endif
+
+	securid = const_cpu_to_le32(0);
+
+#if !FORCE_FORMAT_v1x
+		/* check whether target securid is known in cache */
+
+	wanted.uid = uid;
+	wanted.gid = gid;
+	wanted.dmode = mode & 07777;
+	if (isdir) wanted.dmode |= 0x10000;
+	wanted.variable = (void*)NULL;
+	wanted.varsize = 0;
+	cached = (const struct CACHED_SECURID*)ntfs_fetch_cache(
+			scx->vol->securid_cache, GENERIC(&wanted),
+			(cache_compare)compare);
+		/* quite simple, if we are lucky */
+	if (cached)
+		securid = cached->securid;
+
+		/* not in cache : make sure we can create ids */
+
+	if (!cached && (scx->vol->major_ver >= 3)) {
+		usid = ntfs_find_usid(scx->mapping[MAPUSERS],uid,(SID*)&defusid);
+		gsid = ntfs_find_gsid(scx->mapping[MAPGROUPS],gid,(SID*)&defgsid);
+		if (!usid || !gsid) {
+			ntfs_log_error("File created by an unmapped user/group %d/%d\n",
+					(int)uid, (int)gid);
+			usid = gsid = adminsid;
+		}
+		newattr = ntfs_build_descr(mode, isdir, usid, gsid);
+		if (newattr) {
+			newattrsz = ntfs_attr_size(newattr);
+			securid = setsecurityattr(scx->vol,
+				(const SECURITY_DESCRIPTOR_RELATIVE*)newattr,
+				newattrsz);
+			if (securid) {
+				/* update cache, for subsequent use */
+				wanted.securid = securid;
+				ntfs_enter_cache(scx->vol->securid_cache,
+						GENERIC(&wanted),
+						(cache_compare)compare);
+			}
+			free(newattr);
+		} else {
+			/*
+			 * could not build new security attribute
+			 * errno set by ntfs_build_descr()
+			 */
+		}
+	}
+#endif
+	return (securid);
+}
+
+#endif
+
+/*
+ *		Update ownership and mode of a file, reusing an existing
+ *	security descriptor when possible
+ *	
+ *	Returns zero if successful
+ */
+
+#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
+{
+	int res;
+	const struct CACHED_SECURID *cached;
+	struct CACHED_SECURID wanted;
+	char *newattr;
+	const SID *usid;
+	const SID *gsid;
+	BIGSID defusid;
+	BIGSID defgsid;
+	BOOL isdir;
+
+	res = 0;
+
+		/* check whether target securid is known in cache */
+
+	isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) != const_cpu_to_le16(0);
+	wanted.uid = uid;
+	wanted.gid = gid;
+	wanted.dmode = mode & 07777;
+	if (isdir) wanted.dmode |= 0x10000;
+#if POSIXACLS
+	wanted.variable = (void*)pxdesc;
+	if (pxdesc)
+		wanted.varsize = sizeof(struct POSIX_SECURITY)
+			+ (pxdesc->acccnt + pxdesc->defcnt)*sizeof(struct POSIX_ACE);
+	else
+		wanted.varsize = 0;
+#else
+	wanted.variable = (void*)NULL;
+	wanted.varsize = 0;
+#endif
+	if (test_nino_flag(ni, v3_Extensions)) {
+		cached = (const struct CACHED_SECURID*)ntfs_fetch_cache(
+				scx->vol->securid_cache, GENERIC(&wanted),
+				(cache_compare)compare);
+			/* quite simple, if we are lucky */
+		if (cached) {
+			ni->security_id = cached->securid;
+			NInoSetDirty(ni);
+		}
+	} else cached = (struct CACHED_SECURID*)NULL;
+
+	if (!cached) {
+			/*
+			 * Do not use usid and gsid from former attributes,
+			 * but recompute them to get repeatable results
+			 * which can be kept in cache.
+			 */
+		usid = ntfs_find_usid(scx->mapping[MAPUSERS],uid,(SID*)&defusid);
+		gsid = ntfs_find_gsid(scx->mapping[MAPGROUPS],gid,(SID*)&defgsid);
+		if (!usid || !gsid) {
+			ntfs_log_error("File made owned by an unmapped user/group %d/%d\n",
+				uid, gid);
+			usid = gsid = adminsid;
+		}
+#if POSIXACLS
+		if (pxdesc)
+			newattr = ntfs_build_descr_posix(scx->mapping, pxdesc,
+					 isdir, usid, gsid);
+		else
+			newattr = ntfs_build_descr(mode,
+					 isdir, usid, gsid);
+#else
+		newattr = ntfs_build_descr(mode,
+					 isdir, usid, gsid);
+#endif
+		if (newattr) {
+			res = update_secur_descr(scx->vol, newattr, ni);
+			if (!res) {
+				/* adjust Windows read-only flag */
+				if (!isdir) {
+					if (mode & S_IWUSR)
+						ni->flags &= ~FILE_ATTR_READONLY;
+					else
+						ni->flags |= FILE_ATTR_READONLY;
+					NInoFileNameSetDirty(ni);
+				}
+				/* update cache, for subsequent use */
+				if (test_nino_flag(ni, v3_Extensions)) {
+					wanted.securid = ni->security_id;
+					ntfs_enter_cache(scx->vol->securid_cache,
+							GENERIC(&wanted),
+							(cache_compare)compare);
+				}
+#if CACHE_LEGACY_SIZE
+				/* also invalidate legacy cache */
+				if (isdir && !ni->security_id) {
+					struct CACHED_PERMISSIONS_LEGACY legacy;
+
+					legacy.mft_no = ni->mft_no;
+#if POSIXACLS
+					legacy.variable = wanted.variable;
+					legacy.varsize = wanted.varsize;
+#else
+					legacy.variable = (void*)NULL;
+					legacy.varsize = 0;
+#endif
+					ntfs_invalidate_cache(scx->vol->legacy_cache,
+						GENERIC(&legacy),
+						(cache_compare)leg_compare,0);
+				}
+#endif
+			}
+			free(newattr);
+		} else {
+			/*
+			 * could not build new security attribute
+			 * errno set by ntfs_build_descr()
+			 */
+			res = -1;
+		}
+	}
+	return (res);
+}
+
+/*
+ *		Check whether user has ownership rights on a file
+ *
+ *	Returns TRUE if allowed
+ *		if not, errno tells why
+ */
+
+BOOL ntfs_allowed_as_owner(struct SECURITY_CONTEXT *scx, ntfs_inode *ni)
+{
+	const struct CACHED_PERMISSIONS *cached;
+	char *oldattr;
+	const SID *usid;
+	uid_t processuid;
+	uid_t uid;
+	BOOL gotowner;
+	int allowed;
+
+	processuid = scx->uid;
+/* TODO : use CAP_FOWNER process capability */
+	/*
+	 * Always allow for root
+	 * Also always allow if no mapping has been defined
+	 */
+	if (!scx->mapping[MAPUSERS] || !processuid)
+		allowed = TRUE;
+	else {
+		gotowner = FALSE; /* default */
+		/* get the owner, either from cache or from old attribute  */
+		cached = fetch_cache(scx, ni);
+		if (cached) {
+			uid = cached->uid;
+			gotowner = TRUE;
+		} else {
+			oldattr = getsecurityattr(scx->vol, ni);
+			if (oldattr) {
+#if OWNERFROMACL
+				usid = ntfs_acl_owner(oldattr);
+#else
+				const SECURITY_DESCRIPTOR_RELATIVE *phead;
+
+				phead = (const SECURITY_DESCRIPTOR_RELATIVE*)
+								oldattr;
+				usid = (const SID*)&oldattr
+						[le32_to_cpu(phead->owner)];
+#endif
+				uid = ntfs_find_user(scx->mapping[MAPUSERS],
+						usid);
+				gotowner = TRUE;
+				free(oldattr);
+			}
+		}
+		allowed = FALSE;
+		if (gotowner) {
+/* TODO : use CAP_FOWNER process capability */
+			if (!processuid || (processuid == uid))
+				allowed = TRUE;
+			else
+				errno = EPERM;
+		}
+	}
+	return (allowed);
+}
+
+#ifdef HAVE_SETXATTR    /* extended attributes interface required */
+
+#if POSIXACLS
+
+/*
+ *		Set a new access or default Posix ACL to a file
+ *		(or remove ACL if no input data)
+ *	Validity of input data is checked after merging
+ *
+ *	Returns 0, or -1 if there is a problem which errno describes
+ */
+
+int ntfs_set_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
+			const char *name, const char *value, size_t size,
+			int flags)
+{
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	const struct CACHED_PERMISSIONS *cached;
+	char *oldattr;
+	uid_t processuid;
+	const SID *usid;
+	const SID *gsid;
+	uid_t uid;
+	uid_t gid;
+	int res;
+	BOOL isdir;
+	BOOL deflt;
+	BOOL exist;
+	int count;
+	struct POSIX_SECURITY *oldpxdesc;
+	struct POSIX_SECURITY *newpxdesc;
+
+	/* get the current pxsec, either from cache or from old attribute  */
+	res = -1;
+	deflt = !strcmp(name,"system.posix_acl_default");
+	if (size)
+		count = (size - sizeof(struct POSIX_ACL)) / sizeof(struct POSIX_ACE);
+	else
+		count = 0;
+	isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) != const_cpu_to_le16(0);
+	newpxdesc = (struct POSIX_SECURITY*)NULL;
+	if ((!value
+		|| (((const struct POSIX_ACL*)value)->version == POSIX_VERSION))
+	    && (!deflt || isdir || (!size && !value))) {
+		cached = fetch_cache(scx, ni);
+		if (cached) {
+			uid = cached->uid;
+			gid = cached->gid;
+			oldpxdesc = cached->pxdesc;
+			if (oldpxdesc) {
+				newpxdesc = ntfs_replace_acl(oldpxdesc,
+						(const struct POSIX_ACL*)value,count,deflt);
+				}
+		} else {
+			oldattr = getsecurityattr(scx->vol, ni);
+			if (oldattr) {
+				phead = (const SECURITY_DESCRIPTOR_RELATIVE*)oldattr;
+#if OWNERFROMACL
+				usid = ntfs_acl_owner(oldattr);
+#else
+				usid = (const SID*)&oldattr[le32_to_cpu(phead->owner)];
+#endif
+				gsid = (const SID*)&oldattr[le32_to_cpu(phead->group)];
+				uid = ntfs_find_user(scx->mapping[MAPUSERS],usid);
+				gid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid);
+				oldpxdesc = ntfs_build_permissions_posix(scx->mapping,
+					oldattr, usid, gsid, isdir);
+				if (oldpxdesc) {
+					if (deflt)
+						exist = oldpxdesc->defcnt > 0;
+					else
+						exist = oldpxdesc->acccnt > 3;
+					if ((exist && (flags & XATTR_CREATE))
+					  || (!exist && (flags & XATTR_REPLACE))) {
+						errno = (exist ? EEXIST : ENODATA);
+					} else {
+						newpxdesc = ntfs_replace_acl(oldpxdesc,
+							(const struct POSIX_ACL*)value,count,deflt);
+					}
+					free(oldpxdesc);
+				}
+				free(oldattr);
+			}
+		}
+	} else
+		errno = EINVAL;
+
+	if (newpxdesc) {
+		processuid = scx->uid;
+/* TODO : use CAP_FOWNER process capability */
+		if (!processuid || (uid == processuid)) {
+				/*
+				 * clear setgid if file group does
+				 * not match process group
+				 */
+			if (processuid && (gid != scx->gid)
+			    && !groupmember(scx, scx->uid, gid)) {
+				newpxdesc->mode &= ~S_ISGID;
+			}
+			res = ntfs_set_owner_mode(scx, ni, uid, gid,
+				newpxdesc->mode, newpxdesc);
+		} else
+			errno = EPERM;
+		free(newpxdesc);
+	}
+	return (res ? -1 : 0);
+}
+
+/*
+ *		Remove a default Posix ACL from a file
+ *
+ *	Returns 0, or -1 if there is a problem which errno describes
+ */
+
+int ntfs_remove_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
+			const char *name)
+{
+	return (ntfs_set_posix_acl(scx, ni, name,
+			(const char*)NULL, 0, 0));
+}
+
+#endif
+
+/*
+ *		Set a new NTFS ACL to a file
+ *
+ *	Returns 0, or -1 if there is a problem
+ */
+
+int ntfs_set_ntfs_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
+			const char *value, size_t size,	int flags)
+{
+	char *attr;
+	int res;
+
+	res = -1;
+	if ((size > 0)
+	   && !(flags & XATTR_CREATE)
+	   && ntfs_valid_descr(value,size)
+	   && (ntfs_attr_size(value) == size)) {
+			/* need copying in order to write */
+		attr = (char*)ntfs_malloc(size);
+		if (attr) {
+			memcpy(attr,value,size);
+			res = update_secur_descr(scx->vol, attr, ni);
+			/*
+			 * No need to invalidate standard caches :
+			 * the relation between a securid and
+			 * the associated protection is unchanged,
+			 * only the relation between a file and
+			 * its securid and protection is changed.
+			 */
+#if CACHE_LEGACY_SIZE
+			/*
+			 * we must however invalidate the legacy
+			 * cache, which is based on inode numbers.
+			 * For safety, invalidate even if updating
+			 * failed.
+			 */
+			if ((ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
+			   && !ni->security_id) {
+				struct CACHED_PERMISSIONS_LEGACY legacy;
+
+				legacy.mft_no = ni->mft_no;
+				legacy.variable = (char*)NULL;
+				legacy.varsize = 0;
+				ntfs_invalidate_cache(scx->vol->legacy_cache,
+					GENERIC(&legacy),
+					(cache_compare)leg_compare,0);
+			}
+#endif
+			free(attr);
+		} else
+			errno = ENOMEM;
+	} else
+		errno = EINVAL;
+	return (res ? -1 : 0);
+}
+
+#endif /* HAVE_SETXATTR */
+
+/*
+ *		Set new permissions to a file
+ *	Checks user mapping has been defined before request for setting
+ *
+ *	rejected if request is not originated by owner or root
+ *
+ *	returns 0 on success
+ *		-1 on failure, with errno = EIO
+ */
+
+int ntfs_set_mode(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, mode_t mode)
+{
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	const struct CACHED_PERMISSIONS *cached;
+	char *oldattr;
+	const SID *usid;
+	const SID *gsid;
+	uid_t processuid;
+	uid_t uid;
+	uid_t gid;
+	int res;
+#if POSIXACLS
+	BOOL isdir;
+	int pxsize;
+	const struct POSIX_SECURITY *oldpxdesc;
+	struct POSIX_SECURITY *newpxdesc = (struct POSIX_SECURITY*)NULL;
+#endif
+
+	/* get the current owner, either from cache or from old attribute  */
+	res = 0;
+	cached = fetch_cache(scx, ni);
+	if (cached) {
+		uid = cached->uid;
+		gid = cached->gid;
+#if POSIXACLS
+		oldpxdesc = cached->pxdesc;
+		if (oldpxdesc) {
+				/* must copy before merging */
+			pxsize = sizeof(struct POSIX_SECURITY)
+				+ (oldpxdesc->acccnt + oldpxdesc->defcnt)*sizeof(struct POSIX_ACE);
+			newpxdesc = (struct POSIX_SECURITY*)malloc(pxsize);
+			if (newpxdesc) {
+				memcpy(newpxdesc, oldpxdesc, pxsize);
+				if (ntfs_merge_mode_posix(newpxdesc, mode))
+					res = -1;
+			} else
+				res = -1;
+		} else
+			newpxdesc = (struct POSIX_SECURITY*)NULL;
+#endif
+	} else {
+		oldattr = getsecurityattr(scx->vol, ni);
+		if (oldattr) {
+			phead = (const SECURITY_DESCRIPTOR_RELATIVE*)oldattr;
+#if OWNERFROMACL
+			usid = ntfs_acl_owner(oldattr);
+#else
+			usid = (const SID*)&oldattr[le32_to_cpu(phead->owner)];
+#endif
+			gsid = (const SID*)&oldattr[le32_to_cpu(phead->group)];
+			uid = ntfs_find_user(scx->mapping[MAPUSERS],usid);
+			gid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid);
+#if POSIXACLS
+			isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) != const_cpu_to_le16(0);
+			newpxdesc = ntfs_build_permissions_posix(scx->mapping,
+				oldattr, usid, gsid, isdir);
+			if (!newpxdesc || ntfs_merge_mode_posix(newpxdesc, mode))
+				res = -1;
+#endif
+			free(oldattr);
+		} else
+			res = -1;
+	}
+
+	if (!res) {
+		processuid = scx->uid;
+/* TODO : use CAP_FOWNER process capability */
+		if (!processuid || (uid == processuid)) {
+				/*
+				 * clear setgid if file group does
+				 * not match process group
+				 */
+			if (processuid && (gid != scx->gid)
+			    && !groupmember(scx, scx->uid, gid))
+				mode &= ~S_ISGID;
+#if POSIXACLS
+			if (newpxdesc) {
+				newpxdesc->mode = mode;
+				res = ntfs_set_owner_mode(scx, ni, uid, gid,
+					mode, newpxdesc);
+			} else
+				res = ntfs_set_owner_mode(scx, ni, uid, gid,
+					mode, newpxdesc);
+#else
+			res = ntfs_set_owner_mode(scx, ni, uid, gid, mode);
+#endif
+		} else {
+			errno = EPERM;
+			res = -1;	/* neither owner nor root */
+		}
+	} else {
+		/*
+		 * Should not happen : a default descriptor is generated
+		 * by getsecurityattr() when there are none
+		 */
+		ntfs_log_error("File has no security descriptor\n");
+		res = -1;
+		errno = EIO;
+	}
+#if POSIXACLS
+	if (newpxdesc) free(newpxdesc);
+#endif
+	return (res ? -1 : 0);
+}
+
+/*
+ *	Create a default security descriptor for files whose descriptor
+ *	cannot be inherited
+ */
+
+int ntfs_sd_add_everyone(ntfs_inode *ni)
+{
+	/* JPA SECURITY_DESCRIPTOR_ATTR *sd; */
+	SECURITY_DESCRIPTOR_RELATIVE *sd;
+	ACL *acl;
+	ACCESS_ALLOWED_ACE *ace;
+	SID *sid;
+	int ret, sd_len;
+	
+	/* Create SECURITY_DESCRIPTOR attribute (everyone has full access). */
+	/*
+	 * Calculate security descriptor length. We have 2 sub-authorities in
+	 * owner and group SIDs, but structure SID contain only one, so add
+	 * 4 bytes to every SID.
+	 */
+	sd_len = sizeof(SECURITY_DESCRIPTOR_ATTR) + 2 * (sizeof(SID) + 4) +
+		sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE); 
+	sd = (SECURITY_DESCRIPTOR_RELATIVE*)ntfs_calloc(sd_len);
+	if (!sd)
+		return -1;
+	
+	sd->revision = SECURITY_DESCRIPTOR_REVISION;
+	sd->control = SE_DACL_PRESENT | SE_SELF_RELATIVE;
+	
+	sid = (SID*)((u8*)sd + sizeof(SECURITY_DESCRIPTOR_ATTR));
+	sid->revision = SID_REVISION;
+	sid->sub_authority_count = 2;
+	sid->sub_authority[0] = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
+	sid->sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
+	sid->identifier_authority.value[5] = 5;
+	sd->owner = cpu_to_le32((u8*)sid - (u8*)sd);
+	
+	sid = (SID*)((u8*)sid + sizeof(SID) + 4); 
+	sid->revision = SID_REVISION;
+	sid->sub_authority_count = 2;
+	sid->sub_authority[0] = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
+	sid->sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
+	sid->identifier_authority.value[5] = 5;
+	sd->group = cpu_to_le32((u8*)sid - (u8*)sd);
+	
+	acl = (ACL*)((u8*)sid + sizeof(SID) + 4);
+	acl->revision = ACL_REVISION;
+	acl->size = const_cpu_to_le16(sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE));
+	acl->ace_count = const_cpu_to_le16(1);
+	sd->dacl = cpu_to_le32((u8*)acl - (u8*)sd);
+	
+	ace = (ACCESS_ALLOWED_ACE*)((u8*)acl + sizeof(ACL));
+	ace->type = ACCESS_ALLOWED_ACE_TYPE;
+	ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
+	ace->size = const_cpu_to_le16(sizeof(ACCESS_ALLOWED_ACE));
+	ace->mask = const_cpu_to_le32(0x1f01ff); /* FIXME */
+	ace->sid.revision = SID_REVISION;
+	ace->sid.sub_authority_count = 1;
+	ace->sid.sub_authority[0] = const_cpu_to_le32(0);
+	ace->sid.identifier_authority.value[5] = 1;
+
+	ret = ntfs_attr_add(ni, AT_SECURITY_DESCRIPTOR, AT_UNNAMED, 0, (u8*)sd,
+			    sd_len);
+	if (ret)
+		ntfs_log_perror("Failed to add initial SECURITY_DESCRIPTOR");
+	
+	free(sd);
+	return ret;
+}
+
+/*
+ *		Check whether user can access a file in a specific way
+ *
+ *	Returns 1 if access is allowed, including user is root or no
+ *		  user mapping defined
+ *		2 if sticky and accesstype is S_IWRITE + S_IEXEC + S_ISVTX
+ *		0 and sets errno if there is a problem or if access
+ *		  is not allowed
+ *
+ *	This is used for Posix ACL and checking creation of DOS file names
+ */
+
+int ntfs_allowed_access(struct SECURITY_CONTEXT *scx,
+		ntfs_inode *ni,
+		int accesstype) /* access type required (S_Ixxx values) */
+{
+	int perm;
+	int res;
+	int allow;
+	struct stat stbuf;
+
+	/*
+	 * Always allow for root unless execution is requested.
+	 * (was checked by fuse until kernel 2.6.29)
+	 * Also always allow if no mapping has been defined
+	 */
+	if (!scx->mapping[MAPUSERS]
+	    || (!scx->uid
+		&& (!(accesstype & S_IEXEC)
+		    || (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY))))
+		allow = 1;
+	else {
+		perm = ntfs_get_perm(scx, ni, accesstype);
+		if (perm >= 0) {
+			res = EACCES;
+			switch (accesstype) {
+			case S_IEXEC:
+				allow = (perm & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0;
+				break;
+			case S_IWRITE:
+				allow = (perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0;
+				break;
+			case S_IWRITE + S_IEXEC:
+				allow = ((perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0)
+				    && ((perm & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0);
+				break;
+			case S_IREAD:
+				allow = (perm & (S_IRUSR | S_IRGRP | S_IROTH)) != 0;
+				break;
+			case S_IREAD + S_IEXEC:
+				allow = ((perm & (S_IRUSR | S_IRGRP | S_IROTH)) != 0)
+				    && ((perm & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0);
+				break;
+			case S_IREAD + S_IWRITE:
+				allow = ((perm & (S_IRUSR | S_IRGRP | S_IROTH)) != 0)
+				    && ((perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0);
+				break;
+			case S_IWRITE + S_IEXEC + S_ISVTX:
+				if (perm & S_ISVTX) {
+					if ((ntfs_get_owner_mode(scx,ni,&stbuf) >= 0)
+					    && (stbuf.st_uid == scx->uid))
+						allow = 1;
+					else
+						allow = 2;
+				} else
+					allow = ((perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0)
+					    && ((perm & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0);
+				break;
+			case S_IREAD + S_IWRITE + S_IEXEC:
+				allow = ((perm & (S_IRUSR | S_IRGRP | S_IROTH)) != 0)
+				    && ((perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0)
+				    && ((perm & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0);
+				break;
+			default :
+				res = EINVAL;
+				allow = 0;
+				break;
+			}
+			if (!allow)
+				errno = res;
+		} else
+			allow = 0;
+	}
+	return (allow);
+}
+
+/*
+ *		Check whether user can create a file (or directory)
+ *
+ *	Returns TRUE if access is allowed,
+ *	Also returns the gid and dsetgid applicable to the created file
+ */
+
+int ntfs_allowed_create(struct SECURITY_CONTEXT *scx,
+		ntfs_inode *dir_ni, gid_t *pgid, mode_t *pdsetgid)
+{
+	int perm;
+	int res;
+	int allow;
+	struct stat stbuf;
+
+	/*
+	 * Always allow for root.
+	 * Also always allow if no mapping has been defined
+	 */
+	if (!scx->mapping[MAPUSERS])
+		perm = 0777;
+	else
+		perm = ntfs_get_perm(scx, dir_ni, S_IWRITE + S_IEXEC);
+	if (!scx->mapping[MAPUSERS]
+	    || !scx->uid) {
+		allow = 1;
+	} else {
+		perm = ntfs_get_perm(scx, dir_ni, S_IWRITE + S_IEXEC);
+		if (perm >= 0) {
+			res = EACCES;
+			allow = ((perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0)
+				    && ((perm & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0);
+			if (!allow)
+				errno = res;
+		} else
+			allow = 0;
+	}
+	*pgid = scx->gid;
+	*pdsetgid = 0;
+		/* return directory group if S_ISGID is set */
+	if (allow && (perm & S_ISGID)) {
+		if (ntfs_get_owner_mode(scx, dir_ni, &stbuf) >= 0) {
+			*pdsetgid = stbuf.st_mode & S_ISGID;
+			if (perm & S_ISGID)
+				*pgid = stbuf.st_gid;
+		}
+	}
+	return (allow);
+}
+
+#if 0 /* not needed any more */
+
+/*
+ *		Check whether user can access the parent directory
+ *	of a file in a specific way
+ *
+ *	Returns true if access is allowed, including user is root and
+ *		no user mapping defined
+ *	
+ *	Sets errno if there is a problem or if not allowed
+ *
+ *	This is used for Posix ACL and checking creation of DOS file names
+ */
+
+BOOL old_ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx,
+		const char *path, int accesstype)
+{
+	int allow;
+	char *dirpath;
+	char *name;
+	ntfs_inode *ni;
+	ntfs_inode *dir_ni;
+	struct stat stbuf;
+
+	allow = 0;
+	dirpath = strdup(path);
+	if (dirpath) {
+		/* the root of file system is seen as a parent of itself */
+		/* is that correct ? */
+		name = strrchr(dirpath, '/');
+		*name = 0;
+		dir_ni = ntfs_pathname_to_inode(scx->vol, NULL, dirpath);
+		if (dir_ni) {
+			allow = ntfs_allowed_access(scx,
+				 dir_ni, accesstype);
+			ntfs_inode_close(dir_ni);
+				/*
+				 * for an not-owned sticky directory, have to
+				 * check whether file itself is owned
+				 */
+			if ((accesstype == (S_IWRITE + S_IEXEC + S_ISVTX))
+			   && (allow == 2)) {
+				ni = ntfs_pathname_to_inode(scx->vol, NULL,
+					 path);
+				allow = FALSE;
+				if (ni) {
+					allow = (ntfs_get_owner_mode(scx,ni,&stbuf) >= 0)
+						&& (stbuf.st_uid == scx->uid);
+				ntfs_inode_close(ni);
+				}
+			}
+		}
+		free(dirpath);
+	}
+	return (allow);		/* errno is set if not allowed */
+}
+
+#endif
+
+/*
+ *		Define a new owner/group to a file
+ *
+ *	returns zero if successful
+ */
+
+int ntfs_set_owner(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
+			uid_t uid, gid_t gid)
+{
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	const struct CACHED_PERMISSIONS *cached;
+	char *oldattr;
+	const SID *usid;
+	const SID *gsid;
+	uid_t fileuid;
+	uid_t filegid;
+	mode_t mode;
+	int perm;
+	BOOL isdir;
+	int res;
+#if POSIXACLS
+	struct POSIX_SECURITY *pxdesc;
+	BOOL pxdescbuilt = FALSE;
+#endif
+
+	res = 0;
+	/* get the current owner and mode from cache or security attributes */
+	oldattr = (char*)NULL;
+	cached = fetch_cache(scx,ni);
+	if (cached) {
+		fileuid = cached->uid;
+		filegid = cached->gid;
+		mode = cached->mode;
+#if POSIXACLS
+		pxdesc = cached->pxdesc;
+		if (!pxdesc)
+			res = -1;
+#endif
+	} else {
+		fileuid = 0;
+		filegid = 0;
+		mode = 0;
+		oldattr = getsecurityattr(scx->vol, ni);
+		if (oldattr) {
+			isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
+				!= const_cpu_to_le16(0);
+			phead = (const SECURITY_DESCRIPTOR_RELATIVE*)
+				oldattr;
+			gsid = (const SID*)
+				&oldattr[le32_to_cpu(phead->group)];
+#if OWNERFROMACL
+			usid = ntfs_acl_owner(oldattr);
+#else
+			usid = (const SID*)
+				&oldattr[le32_to_cpu(phead->owner)];
+#endif
+#if POSIXACLS
+			pxdesc = ntfs_build_permissions_posix(scx->mapping, oldattr,
+					usid, gsid, isdir);
+			if (pxdesc) {
+				pxdescbuilt = TRUE;
+				fileuid = ntfs_find_user(scx->mapping[MAPUSERS],usid);
+				filegid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid);
+				mode = perm = pxdesc->mode;
+			} else
+				res = -1;
+#else
+			mode = perm = ntfs_build_permissions(oldattr,
+					 usid, gsid, isdir);
+			if (perm >= 0) {
+				fileuid = ntfs_find_user(scx->mapping[MAPUSERS],usid);
+				filegid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid);
+			} else
+				res = -1;
+#endif
+			free(oldattr);
+		} else
+			res = -1;
+	}
+	if (!res) {
+		/* check requested by root */
+		/* or chgrp requested by owner to an owned group */
+		if (!scx->uid
+		   || ((((int)uid < 0) || (uid == fileuid))
+		      && ((gid == scx->gid) || groupmember(scx, scx->uid, gid))
+		      && (fileuid == scx->uid))) {
+			/* replace by the new usid and gsid */
+			/* or reuse old gid and sid for cacheing */
+			if ((int)uid < 0)
+				uid = fileuid;
+			if ((int)gid < 0)
+				gid = filegid;
+#if !defined(__sun) || !defined (__SVR4)
+			/* clear setuid and setgid if owner has changed */
+                        /* unless request originated by root */
+			if (uid && (fileuid != uid))
+				mode &= 01777;
+#endif
+#if POSIXACLS
+			res = ntfs_set_owner_mode(scx, ni, uid, gid, 
+				mode, pxdesc);
+#else
+			res = ntfs_set_owner_mode(scx, ni, uid, gid, mode);
+#endif
+		} else {
+			res = -1;	/* neither owner nor root */
+			errno = EPERM;
+		}
+#if POSIXACLS
+		if (pxdescbuilt)
+			free(pxdesc);
+#endif
+	} else {
+		/*
+		 * Should not happen : a default descriptor is generated
+		 * by getsecurityattr() when there are none
+		 */
+		ntfs_log_error("File has no security descriptor\n");
+		res = -1;
+		errno = EIO;
+	}
+	return (res ? -1 : 0);
+}
+
+/*
+ *		Define new owner/group and mode to a file
+ *
+ *	returns zero if successful
+ */
+
+int ntfs_set_ownmod(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
+			uid_t uid, gid_t gid, const mode_t mode)
+{
+	const struct CACHED_PERMISSIONS *cached;
+	char *oldattr;
+	uid_t fileuid;
+	uid_t filegid;
+	int res;
+#if POSIXACLS
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	const SID *usid;
+	const SID *gsid;
+	BOOL isdir;
+	const struct POSIX_SECURITY *oldpxdesc;
+	struct POSIX_SECURITY *newpxdesc = (struct POSIX_SECURITY*)NULL;
+	int pxsize;
+#endif
+
+	res = 0;
+	/* get the current owner and mode from cache or security attributes */
+	oldattr = (char*)NULL;
+	cached = fetch_cache(scx,ni);
+	if (cached) {
+		fileuid = cached->uid;
+		filegid = cached->gid;
+#if POSIXACLS
+		oldpxdesc = cached->pxdesc;
+		if (oldpxdesc) {
+				/* must copy before merging */
+			pxsize = sizeof(struct POSIX_SECURITY)
+				+ (oldpxdesc->acccnt + oldpxdesc->defcnt)*sizeof(struct POSIX_ACE);
+			newpxdesc = (struct POSIX_SECURITY*)malloc(pxsize);
+			if (newpxdesc) {
+				memcpy(newpxdesc, oldpxdesc, pxsize);
+				if (ntfs_merge_mode_posix(newpxdesc, mode))
+					res = -1;
+			} else
+				res = -1;
+		}
+#endif
+	} else {
+		fileuid = 0;
+		filegid = 0;
+		oldattr = getsecurityattr(scx->vol, ni);
+		if (oldattr) {
+#if POSIXACLS
+			isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
+				!= const_cpu_to_le16(0);
+			phead = (const SECURITY_DESCRIPTOR_RELATIVE*)
+				oldattr;
+			gsid = (const SID*)
+				&oldattr[le32_to_cpu(phead->group)];
+#if OWNERFROMACL
+			usid = ntfs_acl_owner(oldattr);
+#else
+			usid = (const SID*)
+				&oldattr[le32_to_cpu(phead->owner)];
+#endif
+			newpxdesc = ntfs_build_permissions_posix(scx->mapping, oldattr,
+					usid, gsid, isdir);
+			if (!newpxdesc || ntfs_merge_mode_posix(newpxdesc, mode))
+				res = -1;
+			else {
+				fileuid = ntfs_find_user(scx->mapping[MAPUSERS],usid);
+				filegid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid);
+			}
+#endif
+			free(oldattr);
+		} else
+			res = -1;
+	}
+	if (!res) {
+		/* check requested by root */
+		/* or chgrp requested by owner to an owned group */
+		if (!scx->uid
+		   || ((((int)uid < 0) || (uid == fileuid))
+		      && ((gid == scx->gid) || groupmember(scx, scx->uid, gid))
+		      && (fileuid == scx->uid))) {
+			/* replace by the new usid and gsid */
+			/* or reuse old gid and sid for cacheing */
+			if ((int)uid < 0)
+				uid = fileuid;
+			if ((int)gid < 0)
+				gid = filegid;
+#if POSIXACLS
+			res = ntfs_set_owner_mode(scx, ni, uid, gid, 
+				mode, newpxdesc);
+#else
+			res = ntfs_set_owner_mode(scx, ni, uid, gid, mode);
+#endif
+		} else {
+			res = -1;	/* neither owner nor root */
+			errno = EPERM;
+		}
+	} else {
+		/*
+		 * Should not happen : a default descriptor is generated
+		 * by getsecurityattr() when there are none
+		 */
+		ntfs_log_error("File has no security descriptor\n");
+		res = -1;
+		errno = EIO;
+	}
+#if POSIXACLS
+	free(newpxdesc);
+#endif
+	return (res ? -1 : 0);
+}
+
+/*
+ *		Build a security id for a descriptor inherited from
+ *	parent directory the Windows way
+ */
+
+static le32 build_inherited_id(struct SECURITY_CONTEXT *scx,
+			const char *parentattr, BOOL fordir)
+{
+	const SECURITY_DESCRIPTOR_RELATIVE *pphead;
+	const ACL *ppacl;
+	const SID *usid;
+	const SID *gsid;
+	BIGSID defusid;
+	BIGSID defgsid;
+	int offpacl;
+	int offgroup;
+	SECURITY_DESCRIPTOR_RELATIVE *pnhead;
+	ACL *pnacl;
+	int parentattrsz;
+	char *newattr;
+	int newattrsz;
+	int aclsz;
+	int usidsz;
+	int gsidsz;
+	int pos;
+	le32 securid;
+
+	parentattrsz = ntfs_attr_size(parentattr);
+	pphead = (const SECURITY_DESCRIPTOR_RELATIVE*)parentattr;
+	if (scx->mapping[MAPUSERS]) {
+		usid = ntfs_find_usid(scx->mapping[MAPUSERS], scx->uid, (SID*)&defusid);
+		gsid = ntfs_find_gsid(scx->mapping[MAPGROUPS], scx->gid, (SID*)&defgsid);
+#if OWNERFROMACL
+			/* Get approximation of parent owner when cannot map */
+		if (!gsid)
+			gsid = adminsid;
+		if (!usid) {
+			usid = ntfs_acl_owner(parentattr);
+			if (!ntfs_is_user_sid(gsid))
+				gsid = usid;
+		}
+#else
+			/* Define owner as root when cannot map */
+		if (!usid)
+			usid = adminsid;
+		if (!gsid)
+			gsid = adminsid;
+#endif
+	} else {
+		/*
+		 * If there is no user mapping and this is not a root
+		 * user, we have to get owner and group from somewhere,
+		 * and the parent directory has to contribute.
+		 * Windows never has to do that, because it can always
+		 * rely on a user mapping
+		 */
+		if (!scx->uid)
+			usid = adminsid;
+		else {
+#if OWNERFROMACL
+			usid = ntfs_acl_owner(parentattr);
+#else
+			int offowner;
+
+			offowner = le32_to_cpu(pphead->owner);
+			usid = (const SID*)&parentattr[offowner];
+#endif
+		}
+		if (!scx->gid)
+			gsid = adminsid;
+		else {
+			offgroup = le32_to_cpu(pphead->group);
+			gsid = (const SID*)&parentattr[offgroup];
+		}
+	}
+		/*
+		 * new attribute is smaller than parent's
+		 * except for differences in SIDs which appear in
+		 * owner, group and possible grants and denials in
+		 * generic creator-owner and creator-group ACEs.
+		 * For directories, an ACE may be duplicated for
+		 * access and inheritance, so we double the count.
+		 */
+	usidsz = ntfs_sid_size(usid);
+	gsidsz = ntfs_sid_size(gsid);
+	newattrsz = parentattrsz + 3*usidsz + 3*gsidsz;
+	if (fordir)
+		newattrsz *= 2;
+	newattr = (char*)ntfs_malloc(newattrsz);
+	if (newattr) {
+		pnhead = (SECURITY_DESCRIPTOR_RELATIVE*)newattr;
+		pnhead->revision = SECURITY_DESCRIPTOR_REVISION;
+		pnhead->alignment = 0;
+		pnhead->control = (pphead->control
+			& (SE_DACL_AUTO_INHERITED | SE_SACL_AUTO_INHERITED))
+				| SE_SELF_RELATIVE;
+		pos = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
+			/*
+			 * locate and inherit DACL
+			 * do not test SE_DACL_PRESENT (wrong for "DR Watson")
+			 */
+		pnhead->dacl = const_cpu_to_le32(0);
+		if (pphead->dacl) {
+			offpacl = le32_to_cpu(pphead->dacl);
+			ppacl = (const ACL*)&parentattr[offpacl];
+			pnacl = (ACL*)&newattr[pos];
+			aclsz = ntfs_inherit_acl(ppacl, pnacl, usid, gsid,
+				fordir, pphead->control
+					& SE_DACL_AUTO_INHERITED);
+			if (aclsz) {
+				pnhead->dacl = cpu_to_le32(pos);
+				pos += aclsz;
+				pnhead->control |= SE_DACL_PRESENT;
+			}
+		}
+			/*
+			 * locate and inherit SACL
+			 */
+		pnhead->sacl = const_cpu_to_le32(0);
+		if (pphead->sacl) {
+			offpacl = le32_to_cpu(pphead->sacl);
+			ppacl = (const ACL*)&parentattr[offpacl];
+			pnacl = (ACL*)&newattr[pos];
+			aclsz = ntfs_inherit_acl(ppacl, pnacl, usid, gsid,
+				fordir, pphead->control
+					& SE_SACL_AUTO_INHERITED);
+			if (aclsz) {
+				pnhead->sacl = cpu_to_le32(pos);
+				pos += aclsz;
+				pnhead->control |= SE_SACL_PRESENT;
+			}
+		}
+			/*
+			 * inherit or redefine owner
+			 */
+		memcpy(&newattr[pos],usid,usidsz);
+		pnhead->owner = cpu_to_le32(pos);
+		pos += usidsz;
+			/*
+			 * inherit or redefine group
+			 */
+		memcpy(&newattr[pos],gsid,gsidsz);
+		pnhead->group = cpu_to_le32(pos);
+		pos += gsidsz;
+		securid = setsecurityattr(scx->vol,
+			(SECURITY_DESCRIPTOR_RELATIVE*)newattr, pos);
+		free(newattr);
+	} else
+		securid = const_cpu_to_le32(0);
+	return (securid);
+}
+
+/*
+ *		Get an inherited security id
+ *
+ *	For Windows compatibility, the normal initial permission setting
+ *	may be inherited from the parent directory instead of being
+ *	defined by the creation arguments.
+ *
+ *	The following creates an inherited id for that purpose.
+ *
+ *	Note : the owner and group of parent directory are also
+ *	inherited (which is not the case on Windows) if no user mapping
+ *	is defined.
+ *
+ *	Returns the inherited id, or zero if not possible (eg on NTFS 1.x)
+ */
+
+le32 ntfs_inherited_id(struct SECURITY_CONTEXT *scx,
+			ntfs_inode *dir_ni, BOOL fordir)
+{
+	struct CACHED_PERMISSIONS *cached;
+	char *parentattr;
+	le32 securid;
+
+	securid = const_cpu_to_le32(0);
+	cached = (struct CACHED_PERMISSIONS*)NULL;
+		/*
+		 * Try to get inherited id from cache, possible when
+		 * the current process owns the parent directory
+		 */
+	if (test_nino_flag(dir_ni, v3_Extensions)
+			&& dir_ni->security_id) {
+		cached = fetch_cache(scx, dir_ni);
+		if (cached
+		    && (cached->uid == scx->uid) && (cached->gid == scx->gid))
+			securid = (fordir ? cached->inh_dirid
+					: cached->inh_fileid);
+	}
+		/*
+		 * Not cached or not available in cache, compute it all
+		 * Note : if parent directory has no id, it is not cacheable
+		 */
+	if (!securid) {
+		parentattr = getsecurityattr(scx->vol, dir_ni);
+		if (parentattr) {
+			securid = build_inherited_id(scx,
+						parentattr, fordir);
+			free(parentattr);
+			/*
+			 * Store the result into cache for further use
+			 * if the current process owns the parent directory
+			 */
+			if (securid) {
+				cached = fetch_cache(scx, dir_ni);
+				if (cached
+				    && (cached->uid == scx->uid)
+				    && (cached->gid == scx->gid)) {
+					if (fordir)
+						cached->inh_dirid = securid;
+					else
+						cached->inh_fileid = securid;
+				}
+			}
+		}
+	}
+	return (securid);
+}
+
+/*
+ *		Link a group to a member of group
+ *
+ *	Returns 0 if OK, -1 (and errno set) if error
+ */
+
+static int link_single_group(struct MAPPING *usermapping, struct passwd *user,
+			gid_t gid)
+{
+	struct group *group;
+	char **grmem;
+	int grcnt;
+	gid_t *groups;
+	int res;
+
+	res = 0;
+	group = getgrgid(gid);
+	if (group && group->gr_mem) {
+		grcnt = usermapping->grcnt;
+		groups = usermapping->groups;
+		grmem = group->gr_mem;
+		while (*grmem && strcmp(user->pw_name, *grmem))
+			grmem++;
+		if (*grmem) {
+			if (!grcnt)
+				groups = (gid_t*)malloc(sizeof(gid_t));
+			else
+				groups = (gid_t*)realloc(groups,
+					(grcnt+1)*sizeof(gid_t));
+			if (groups)
+				groups[grcnt++]	= gid;
+			else {
+				res = -1;
+				errno = ENOMEM;
+			}
+		}
+		usermapping->grcnt = grcnt;
+		usermapping->groups = groups;
+	}
+	return (res);
+}
+
+
+/*
+ *		Statically link group to users
+ *	This is based on groups defined in /etc/group and does not take
+ *	the groups dynamically set by setgroups() nor any changes in
+ *	/etc/group into account
+ *
+ *	Only mapped groups and root group are linked to mapped users
+ *
+ *	Returns 0 if OK, -1 (and errno set) if error
+ *
+ */
+
+static int link_group_members(struct SECURITY_CONTEXT *scx)
+{
+	struct MAPPING *usermapping;
+	struct MAPPING *groupmapping;
+	struct passwd *user;
+	int res;
+
+	res = 0;
+	for (usermapping=scx->mapping[MAPUSERS]; usermapping && !res;
+			usermapping=usermapping->next) {
+		usermapping->grcnt = 0;
+		usermapping->groups = (gid_t*)NULL;
+		user = getpwuid(usermapping->xid);
+		if (user && user->pw_name) {
+			for (groupmapping=scx->mapping[MAPGROUPS];
+					groupmapping && !res;
+					groupmapping=groupmapping->next) {
+				if (link_single_group(usermapping, user,
+				    groupmapping->xid))
+					res = -1;
+				}
+			if (!res && link_single_group(usermapping,
+					 user, (gid_t)0))
+				res = -1;
+		}
+	}
+	return (res);
+}
+
+/*
+ *		Apply default single user mapping
+ *	returns zero if successful
+ */
+
+static int ntfs_do_default_mapping(struct SECURITY_CONTEXT *scx,
+			 uid_t uid, gid_t gid, const SID *usid)
+{
+	struct MAPPING *usermapping;
+	struct MAPPING *groupmapping;
+	SID *sid;
+	int sidsz;
+	int res;
+
+	res = -1;
+	sidsz = ntfs_sid_size(usid);
+	sid = (SID*)ntfs_malloc(sidsz);
+	if (sid) {
+		memcpy(sid,usid,sidsz);
+		usermapping = (struct MAPPING*)ntfs_malloc(sizeof(struct MAPPING));
+		if (usermapping) {
+			groupmapping = (struct MAPPING*)ntfs_malloc(sizeof(struct MAPPING));
+			if (groupmapping) {
+				usermapping->sid = sid;
+				usermapping->xid = uid;
+				usermapping->next = (struct MAPPING*)NULL;
+				groupmapping->sid = sid;
+				groupmapping->xid = gid;
+				groupmapping->next = (struct MAPPING*)NULL;
+				scx->mapping[MAPUSERS] = usermapping;
+				scx->mapping[MAPGROUPS] = groupmapping;
+				res = 0;
+			}
+		}
+	}
+	return (res);
+}
+
+/*
+ *		Make sure there are no ambiguous mapping
+ *	Ambiguous mapping may lead to undesired configurations and
+ *	we had rather be safe until the consequences are understood
+ */
+
+#if 0 /* not activated for now */
+
+static BOOL check_mapping(const struct MAPPING *usermapping,
+		const struct MAPPING *groupmapping)
+{
+	const struct MAPPING *mapping1;
+	const struct MAPPING *mapping2;
+	BOOL ambiguous;
+
+	ambiguous = FALSE;
+	for (mapping1=usermapping; mapping1; mapping1=mapping1->next)
+		for (mapping2=mapping1->next; mapping2; mapping1=mapping2->next)
+			if (ntfs_same_sid(mapping1->sid,mapping2->sid)) {
+				if (mapping1->xid != mapping2->xid)
+					ambiguous = TRUE;
+			} else {
+				if (mapping1->xid == mapping2->xid)
+					ambiguous = TRUE;
+			}
+	for (mapping1=groupmapping; mapping1; mapping1=mapping1->next)
+		for (mapping2=mapping1->next; mapping2; mapping1=mapping2->next)
+			if (ntfs_same_sid(mapping1->sid,mapping2->sid)) {
+				if (mapping1->xid != mapping2->xid)
+					ambiguous = TRUE;
+			} else {
+				if (mapping1->xid == mapping2->xid)
+					ambiguous = TRUE;
+			}
+	return (ambiguous);
+}
+
+#endif
+
+#if 0 /* not used any more */
+
+/*
+ *		Try and apply default single user mapping
+ *	returns zero if successful
+ */
+
+static int ntfs_default_mapping(struct SECURITY_CONTEXT *scx)
+{
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	ntfs_inode *ni;
+	char *securattr;
+	const SID *usid;
+	int res;
+
+	res = -1;
+	ni = ntfs_pathname_to_inode(scx->vol, NULL, "/.");
+	if (ni) {
+		securattr = getsecurityattr(scx->vol, ni);
+		if (securattr) {
+			phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr;
+			usid = (SID*)&securattr[le32_to_cpu(phead->owner)];
+			if (ntfs_is_user_sid(usid))
+				res = ntfs_do_default_mapping(scx,
+						scx->uid, scx->gid, usid);
+			free(securattr);
+		}
+		ntfs_inode_close(ni);
+	}
+	return (res);
+}
+
+#endif
+
+/*
+ *		Basic read from a user mapping file on another volume
+ */
+
+static int basicread(void *fileid, char *buf, size_t size, off_t offs __attribute__((unused)))
+{
+	return (read(*(int*)fileid, buf, size));
+}
+
+
+/*
+ *		Read from a user mapping file on current NTFS partition
+ */
+
+static int localread(void *fileid, char *buf, size_t size, off_t offs)
+{
+	return (ntfs_attr_data_read((ntfs_inode*)fileid,
+			AT_UNNAMED, 0, buf, size, offs));
+}
+
+/*
+ *		Build the user mapping
+ *	- according to a mapping file if defined (or default present),
+ *	- or try default single user mapping if possible
+ *
+ *	The mapping is specific to a mounted device
+ *	No locking done, mounting assumed non multithreaded
+ *
+ *	returns zero if mapping is successful
+ *	(failure should not be interpreted as an error)
+ */
+
+int ntfs_build_mapping(struct SECURITY_CONTEXT *scx, const char *usermap_path,
+			BOOL allowdef)
+{
+	struct MAPLIST *item;
+	struct MAPLIST *firstitem;
+	struct MAPPING *usermapping;
+	struct MAPPING *groupmapping;
+	ntfs_inode *ni;
+	int fd;
+	static struct {
+		u8 revision;
+		u8 levels;
+		be16 highbase;
+		be32 lowbase;
+		le32 level1;
+		le32 level2;
+		le32 level3;
+		le32 level4;
+		le32 level5;
+	} defmap = {
+		1, 5, const_cpu_to_be16(0), const_cpu_to_be32(5),
+		const_cpu_to_le32(21),
+		const_cpu_to_le32(DEFSECAUTH1), const_cpu_to_le32(DEFSECAUTH2),
+		const_cpu_to_le32(DEFSECAUTH3), const_cpu_to_le32(DEFSECBASE)
+	} ;
+
+	/* be sure not to map anything until done */
+	scx->mapping[MAPUSERS] = (struct MAPPING*)NULL;
+	scx->mapping[MAPGROUPS] = (struct MAPPING*)NULL;
+
+	if (!usermap_path) usermap_path = MAPPINGFILE;
+	if (usermap_path[0] == '/') {
+		fd = open(usermap_path,O_RDONLY);
+		if (fd > 0) {
+			firstitem = ntfs_read_mapping(basicread, (void*)&fd);
+			close(fd);
+		} else
+			firstitem = (struct MAPLIST*)NULL;
+	} else {
+		ni = ntfs_pathname_to_inode(scx->vol, NULL, usermap_path);
+		if (ni) {
+			firstitem = ntfs_read_mapping(localread, ni);
+			ntfs_inode_close(ni);
+		} else
+			firstitem = (struct MAPLIST*)NULL;
+	}
+
+
+	if (firstitem) {
+		usermapping = ntfs_do_user_mapping(firstitem);
+		groupmapping = ntfs_do_group_mapping(firstitem);
+		if (usermapping && groupmapping) {
+			scx->mapping[MAPUSERS] = usermapping;
+			scx->mapping[MAPGROUPS] = groupmapping;
+		} else
+			ntfs_log_error("There were no valid user or no valid group\n");
+		/* now we can free the memory copy of input text */
+		/* and rely on internal representation */
+		while (firstitem) {
+			item = firstitem->next;
+			free(firstitem);
+			firstitem = item;
+		}
+	} else {
+			/* no mapping file, try a default mapping */
+		if (allowdef) {
+			if (!ntfs_do_default_mapping(scx,
+					0, 0, (const SID*)&defmap))
+				ntfs_log_info("Using default user mapping\n");
+		}
+	}
+	return (!scx->mapping[MAPUSERS] || link_group_members(scx));
+}
+
+#ifdef HAVE_SETXATTR    /* extended attributes interface required */
+
+/*
+ *		Get the ntfs attribute into an extended attribute
+ *	The attribute is returned according to cpu endianness
+ */
+
+int ntfs_get_ntfs_attrib(ntfs_inode *ni, char *value, size_t size)
+{
+	u32 attrib;
+	size_t outsize;
+
+	outsize = 0;	/* default to no data and no error */
+	if (ni) {
+		attrib = le32_to_cpu(ni->flags);
+		if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
+			attrib |= const_le32_to_cpu(FILE_ATTR_DIRECTORY);
+		else
+			attrib &= ~const_le32_to_cpu(FILE_ATTR_DIRECTORY);
+		if (!attrib)
+			attrib |= const_le32_to_cpu(FILE_ATTR_NORMAL);
+		outsize = sizeof(FILE_ATTR_FLAGS);
+		if (size >= outsize) {
+			if (value)
+				memcpy(value,&attrib,outsize);
+			else
+				errno = EINVAL;
+		}
+	}
+	return (outsize ? (int)outsize : -errno);
+}
+
+/*
+ *		Return the ntfs attribute into an extended attribute
+ *	The attribute is expected according to cpu endianness
+ *
+ *	Returns 0, or -1 if there is a problem
+ */
+
+int ntfs_set_ntfs_attrib(ntfs_inode *ni,
+			const char *value, size_t size,	int flags)
+{
+	u32 attrib;
+	le32 settable;
+	ATTR_FLAGS dirflags;
+	int res;
+
+	res = -1;
+	if (ni && value && (size >= sizeof(FILE_ATTR_FLAGS))) {
+		if (!(flags & XATTR_CREATE)) {
+			/* copy to avoid alignment problems */
+			memcpy(&attrib,value,sizeof(FILE_ATTR_FLAGS));
+			settable = FILE_ATTR_SETTABLE;
+			res = 0;
+			if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
+				/*
+				 * Accept changing compression for a directory
+				 * and set index root accordingly
+				 */
+				settable |= FILE_ATTR_COMPRESSED;
+				if ((ni->flags ^ cpu_to_le32(attrib))
+				             & FILE_ATTR_COMPRESSED) {
+					if (ni->flags & FILE_ATTR_COMPRESSED)
+						dirflags = const_cpu_to_le16(0);
+					else
+						dirflags = ATTR_IS_COMPRESSED;
+					res = ntfs_attr_set_flags(ni,
+						AT_INDEX_ROOT,
+					        NTFS_INDEX_I30, 4,
+						dirflags,
+						ATTR_COMPRESSION_MASK);
+				}
+			}
+			if (!res) {
+				ni->flags = (ni->flags & ~settable)
+					 | (cpu_to_le32(attrib) & settable);
+				NInoFileNameSetDirty(ni);
+				NInoSetDirty(ni);
+			}
+		} else
+			errno = EEXIST;
+	} else
+		errno = EINVAL;
+	return (res ? -1 : 0);
+}
+
+#endif /* HAVE_SETXATTR */
+
+/*
+ *	Open $Secure once for all
+ *	returns zero if it succeeds
+ *		non-zero if it fails. This is not an error (on NTFS v1.x)
+ */
+
+
+int ntfs_open_secure(ntfs_volume *vol)
+{
+	ntfs_inode *ni;
+	int res;
+
+	res = -1;
+	vol->secure_ni = (ntfs_inode*)NULL;
+	vol->secure_xsii = (ntfs_index_context*)NULL;
+	vol->secure_xsdh = (ntfs_index_context*)NULL;
+	if (vol->major_ver >= 3) {
+			/* make sure this is a genuine $Secure inode 9 */
+		ni = ntfs_pathname_to_inode(vol, NULL, "$Secure");
+		if (ni && (ni->mft_no == 9)) {
+			vol->secure_reentry = 0;
+			vol->secure_xsii = ntfs_index_ctx_get(ni,
+						sii_stream, 4);
+			vol->secure_xsdh = ntfs_index_ctx_get(ni,
+						sdh_stream, 4);
+			if (ni && vol->secure_xsii && vol->secure_xsdh) {
+				vol->secure_ni = ni;
+				res = 0;
+			}
+		}
+	}
+	return (res);
+}
+
+/*
+ *		Final cleaning
+ *	Allocated memory is freed to facilitate the detection of memory leaks
+ */
+
+void ntfs_close_secure(struct SECURITY_CONTEXT *scx)
+{
+	ntfs_volume *vol;
+
+	vol = scx->vol;
+	if (vol->secure_ni) {
+		ntfs_index_ctx_put(vol->secure_xsii);
+		ntfs_index_ctx_put(vol->secure_xsdh);
+		ntfs_inode_close(vol->secure_ni);
+		
+	}
+	ntfs_free_mapping(scx->mapping);
+	free_caches(scx);
+}
+
+/*
+ *		API for direct access to security descriptors
+ *	based on Win32 API
+ */
+
+
+/*
+ *		Selective feeding of a security descriptor into user buffer
+ *
+ *	Returns TRUE if successful
+ */
+
+static BOOL feedsecurityattr(const char *attr, u32 selection,
+		char *buf, u32 buflen, u32 *psize)
+{
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	SECURITY_DESCRIPTOR_RELATIVE *pnhead;
+	const ACL *pdacl;
+	const ACL *psacl;
+	const SID *pusid;
+	const SID *pgsid;
+	unsigned int offdacl;
+	unsigned int offsacl;
+	unsigned int offowner;
+	unsigned int offgroup;
+	unsigned int daclsz;
+	unsigned int saclsz;
+	unsigned int usidsz;
+	unsigned int gsidsz;
+	unsigned int size; /* size of requested attributes */
+	BOOL ok;
+	unsigned int pos;
+	unsigned int avail;
+	le16 control;
+
+	avail = 0;
+	control = SE_SELF_RELATIVE;
+	phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr;
+	size = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
+
+		/* locate DACL if requested and available */
+	if (phead->dacl && (selection & DACL_SECURITY_INFORMATION)) {
+		offdacl = le32_to_cpu(phead->dacl);
+		pdacl = (const ACL*)&attr[offdacl];
+		daclsz = le16_to_cpu(pdacl->size);
+		size += daclsz;
+		avail |= DACL_SECURITY_INFORMATION;
+	} else
+		offdacl = daclsz = 0;
+
+		/* locate owner if requested and available */
+	offowner = le32_to_cpu(phead->owner);
+	if (offowner && (selection & OWNER_SECURITY_INFORMATION)) {
+			/* find end of USID */
+		pusid = (const SID*)&attr[offowner];
+		usidsz = ntfs_sid_size(pusid);
+		size += usidsz;
+		avail |= OWNER_SECURITY_INFORMATION;
+	} else
+		offowner = usidsz = 0;
+
+		/* locate group if requested and available */
+	offgroup = le32_to_cpu(phead->group);
+	if (offgroup && (selection & GROUP_SECURITY_INFORMATION)) {
+			/* find end of GSID */
+		pgsid = (const SID*)&attr[offgroup];
+		gsidsz = ntfs_sid_size(pgsid);
+		size += gsidsz;
+		avail |= GROUP_SECURITY_INFORMATION;
+	} else
+		offgroup = gsidsz = 0;
+
+		/* locate SACL if requested and available */
+	if (phead->sacl && (selection & SACL_SECURITY_INFORMATION)) {
+			/* find end of SACL */
+		offsacl = le32_to_cpu(phead->sacl);
+		psacl = (const ACL*)&attr[offsacl];
+		saclsz = le16_to_cpu(psacl->size);
+		size += saclsz;
+		avail |= SACL_SECURITY_INFORMATION;
+	} else
+		offsacl = saclsz = 0;
+
+		/*
+		 * Check having enough size in destination buffer
+		 * (required size is returned nevertheless so that
+		 * the request can be reissued with adequate size)
+		 */
+	if (size > buflen) {
+		*psize = size;
+		errno = EINVAL;
+		ok = FALSE;
+	} else {
+		if (selection & OWNER_SECURITY_INFORMATION)
+			control |= phead->control & SE_OWNER_DEFAULTED;
+		if (selection & GROUP_SECURITY_INFORMATION)
+			control |= phead->control & SE_GROUP_DEFAULTED;
+		if (selection & DACL_SECURITY_INFORMATION)
+			control |= phead->control
+					& (SE_DACL_PRESENT
+					   | SE_DACL_DEFAULTED
+					   | SE_DACL_AUTO_INHERITED
+					   | SE_DACL_PROTECTED);
+		if (selection & SACL_SECURITY_INFORMATION)
+			control |= phead->control
+					& (SE_SACL_PRESENT
+					   | SE_SACL_DEFAULTED
+					   | SE_SACL_AUTO_INHERITED
+					   | SE_SACL_PROTECTED);
+		/*
+		 * copy header and feed new flags, even if no detailed data
+		 */
+		memcpy(buf,attr,sizeof(SECURITY_DESCRIPTOR_RELATIVE));
+		pnhead = (SECURITY_DESCRIPTOR_RELATIVE*)buf;
+		pnhead->control = control;
+		pos = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
+
+		/* copy DACL if requested and available */
+		if (selection & avail & DACL_SECURITY_INFORMATION) {
+			pnhead->dacl = cpu_to_le32(pos);
+			memcpy(&buf[pos],&attr[offdacl],daclsz);
+			pos += daclsz;
+		} else
+			pnhead->dacl = const_cpu_to_le32(0);
+
+		/* copy SACL if requested and available */
+		if (selection & avail & SACL_SECURITY_INFORMATION) {
+			pnhead->sacl = cpu_to_le32(pos);
+			memcpy(&buf[pos],&attr[offsacl],saclsz);
+			pos += saclsz;
+		} else
+			pnhead->sacl = const_cpu_to_le32(0);
+
+		/* copy owner if requested and available */
+		if (selection & avail & OWNER_SECURITY_INFORMATION) {
+			pnhead->owner = cpu_to_le32(pos);
+			memcpy(&buf[pos],&attr[offowner],usidsz);
+			pos += usidsz;
+		} else
+			pnhead->owner = const_cpu_to_le32(0);
+
+		/* copy group if requested and available */
+		if (selection & avail & GROUP_SECURITY_INFORMATION) {
+			pnhead->group = cpu_to_le32(pos);
+			memcpy(&buf[pos],&attr[offgroup],gsidsz);
+			pos += gsidsz;
+		} else
+			pnhead->group = const_cpu_to_le32(0);
+		if (pos != size)
+			ntfs_log_error("Error in security descriptor size\n");
+		*psize = size;
+		ok = TRUE;
+	}
+
+	return (ok);
+}
+
+/*
+ *		Merge a new security descriptor into the old one
+ *	and assign to designated file
+ *
+ *	Returns TRUE if successful
+ */
+
+static BOOL mergesecurityattr(ntfs_volume *vol, const char *oldattr,
+		const char *newattr, u32 selection, ntfs_inode *ni)
+{
+	const SECURITY_DESCRIPTOR_RELATIVE *oldhead;
+	const SECURITY_DESCRIPTOR_RELATIVE *newhead;
+	SECURITY_DESCRIPTOR_RELATIVE *targhead;
+	const ACL *pdacl;
+	const ACL *psacl;
+	const SID *powner;
+	const SID *pgroup;
+	int offdacl;
+	int offsacl;
+	int offowner;
+	int offgroup;
+	unsigned int size;
+	le16 control;
+	char *target;
+	int pos;
+	int oldattrsz;
+	int newattrsz;
+	BOOL ok;
+
+	ok = FALSE; /* default return */
+	oldhead = (const SECURITY_DESCRIPTOR_RELATIVE*)oldattr;
+	newhead = (const SECURITY_DESCRIPTOR_RELATIVE*)newattr;
+	oldattrsz = ntfs_attr_size(oldattr);
+	newattrsz = ntfs_attr_size(newattr);
+	target = (char*)ntfs_malloc(oldattrsz + newattrsz);
+	if (target) {
+		targhead = (SECURITY_DESCRIPTOR_RELATIVE*)target;
+		pos = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
+		control = SE_SELF_RELATIVE;
+			/*
+			 * copy new DACL if selected
+			 * or keep old DACL if any
+			 */
+		if ((selection & DACL_SECURITY_INFORMATION) ?
+				newhead->dacl : oldhead->dacl) {
+			if (selection & DACL_SECURITY_INFORMATION) {
+				offdacl = le32_to_cpu(newhead->dacl);
+				pdacl = (const ACL*)&newattr[offdacl];
+			} else {
+				offdacl = le32_to_cpu(oldhead->dacl);
+				pdacl = (const ACL*)&oldattr[offdacl];
+			}
+			size = le16_to_cpu(pdacl->size);
+			memcpy(&target[pos], pdacl, size);
+			targhead->dacl = cpu_to_le32(pos);
+			pos += size;
+		} else
+			targhead->dacl = const_cpu_to_le32(0);
+		if (selection & DACL_SECURITY_INFORMATION) {
+			control |= newhead->control
+					& (SE_DACL_PRESENT
+					   | SE_DACL_DEFAULTED
+					   | SE_DACL_PROTECTED);
+			if (newhead->control & SE_DACL_AUTO_INHERIT_REQ)
+				control |= SE_DACL_AUTO_INHERITED;
+		} else
+			control |= oldhead->control
+					& (SE_DACL_PRESENT
+					   | SE_DACL_DEFAULTED
+					   | SE_DACL_AUTO_INHERITED
+					   | SE_DACL_PROTECTED);
+			/*
+			 * copy new SACL if selected
+			 * or keep old SACL if any
+			 */
+		if ((selection & SACL_SECURITY_INFORMATION) ?
+				newhead->sacl : oldhead->sacl) {
+			if (selection & SACL_SECURITY_INFORMATION) {
+				offsacl = le32_to_cpu(newhead->sacl);
+				psacl = (const ACL*)&newattr[offsacl];
+			} else {
+				offsacl = le32_to_cpu(oldhead->sacl);
+				psacl = (const ACL*)&oldattr[offsacl];
+			}
+			size = le16_to_cpu(psacl->size);
+			memcpy(&target[pos], psacl, size);
+			targhead->sacl = cpu_to_le32(pos);
+			pos += size;
+		} else
+			targhead->sacl = const_cpu_to_le32(0);
+		if (selection & SACL_SECURITY_INFORMATION) {
+			control |= newhead->control
+					& (SE_SACL_PRESENT
+					   | SE_SACL_DEFAULTED
+					   | SE_SACL_PROTECTED);
+			if (newhead->control & SE_SACL_AUTO_INHERIT_REQ)
+				control |= SE_SACL_AUTO_INHERITED;
+		} else
+			control |= oldhead->control
+					& (SE_SACL_PRESENT
+					   | SE_SACL_DEFAULTED
+					   | SE_SACL_AUTO_INHERITED
+					   | SE_SACL_PROTECTED);
+			/*
+			 * copy new OWNER if selected
+			 * or keep old OWNER if any
+			 */
+		if ((selection & OWNER_SECURITY_INFORMATION) ?
+				newhead->owner : oldhead->owner) {
+			if (selection & OWNER_SECURITY_INFORMATION) {
+				offowner = le32_to_cpu(newhead->owner);
+				powner = (const SID*)&newattr[offowner];
+			} else {
+				offowner = le32_to_cpu(oldhead->owner);
+				powner = (const SID*)&oldattr[offowner];
+			}
+			size = ntfs_sid_size(powner);
+			memcpy(&target[pos], powner, size);
+			targhead->owner = cpu_to_le32(pos);
+			pos += size;
+		} else
+			targhead->owner = const_cpu_to_le32(0);
+		if (selection & OWNER_SECURITY_INFORMATION)
+			control |= newhead->control & SE_OWNER_DEFAULTED;
+		else
+			control |= oldhead->control & SE_OWNER_DEFAULTED;
+			/*
+			 * copy new GROUP if selected
+			 * or keep old GROUP if any
+			 */
+		if ((selection & GROUP_SECURITY_INFORMATION) ?
+				newhead->group : oldhead->group) {
+			if (selection & GROUP_SECURITY_INFORMATION) {
+				offgroup = le32_to_cpu(newhead->group);
+				pgroup = (const SID*)&newattr[offgroup];
+				control |= newhead->control
+						 & SE_GROUP_DEFAULTED;
+			} else {
+				offgroup = le32_to_cpu(oldhead->group);
+				pgroup = (const SID*)&oldattr[offgroup];
+				control |= oldhead->control
+						 & SE_GROUP_DEFAULTED;
+			}
+			size = ntfs_sid_size(pgroup);
+			memcpy(&target[pos], pgroup, size);
+			targhead->group = cpu_to_le32(pos);
+			pos += size;
+		} else
+			targhead->group = const_cpu_to_le32(0);
+		if (selection & GROUP_SECURITY_INFORMATION)
+			control |= newhead->control & SE_GROUP_DEFAULTED;
+		else
+			control |= oldhead->control & SE_GROUP_DEFAULTED;
+		targhead->revision = SECURITY_DESCRIPTOR_REVISION;
+		targhead->alignment = 0;
+		targhead->control = control;
+		ok = !update_secur_descr(vol, target, ni);
+		free(target);
+	}
+	return (ok);
+}
+
+/*
+ *		Return the security descriptor of a file
+ *	This is intended to be similar to GetFileSecurity() from Win32
+ *	in order to facilitate the development of portable tools
+ *
+ *	returns zero if unsuccessful (following Win32 conventions)
+ *		-1 if no securid
+ *		the securid if any
+ *
+ *  The Win32 API is :
+ *
+ *  BOOL WINAPI GetFileSecurity(
+ *    __in          LPCTSTR lpFileName,
+ *    __in          SECURITY_INFORMATION RequestedInformation,
+ *    __out_opt     PSECURITY_DESCRIPTOR pSecurityDescriptor,
+ *    __in          DWORD nLength,
+ *    __out         LPDWORD lpnLengthNeeded
+ *  );
+ *
+ */
+
+int ntfs_get_file_security(struct SECURITY_API *scapi,
+		const char *path, u32 selection,
+		char *buf, u32 buflen, u32 *psize)
+{
+	ntfs_inode *ni;
+	char *attr;
+	int res;
+
+	res = 0; /* default return */
+	if (scapi && (scapi->magic == MAGIC_API)) {
+		ni = ntfs_pathname_to_inode(scapi->security.vol, NULL, path);
+		if (ni) {
+			attr = getsecurityattr(scapi->security.vol, ni);
+			if (attr) {
+				if (feedsecurityattr(attr,selection,
+						buf,buflen,psize)) {
+					if (test_nino_flag(ni, v3_Extensions)
+					    && ni->security_id)
+						res = le32_to_cpu(
+							ni->security_id);
+					else
+						res = -1;
+				}
+				free(attr);
+			}
+			ntfs_inode_close(ni);
+		} else
+			errno = ENOENT;
+		if (!res) *psize = 0;
+	} else
+		errno = EINVAL; /* do not clear *psize */
+	return (res);
+}
+
+
+/*
+ *		Set the security descriptor of a file or directory
+ *	This is intended to be similar to SetFileSecurity() from Win32
+ *	in order to facilitate the development of portable tools
+ *
+ *	returns zero if unsuccessful (following Win32 conventions)
+ *		-1 if no securid
+ *		the securid if any
+ *
+ *  The Win32 API is :
+ *
+ *  BOOL WINAPI SetFileSecurity(
+ *    __in          LPCTSTR lpFileName,
+ *    __in          SECURITY_INFORMATION SecurityInformation,
+ *    __in          PSECURITY_DESCRIPTOR pSecurityDescriptor
+ *  );
+ */
+
+int ntfs_set_file_security(struct SECURITY_API *scapi,
+		const char *path, u32 selection, const char *attr)
+{
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	ntfs_inode *ni;
+	int attrsz;
+	BOOL missing;
+	char *oldattr;
+	int res;
+
+	res = 0; /* default return */
+	if (scapi && (scapi->magic == MAGIC_API) && attr) {
+		phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr;
+		attrsz = ntfs_attr_size(attr);
+		/* if selected, owner and group must be present or defaulted */
+		missing = ((selection & OWNER_SECURITY_INFORMATION)
+				&& !phead->owner
+				&& !(phead->control & SE_OWNER_DEFAULTED))
+			|| ((selection & GROUP_SECURITY_INFORMATION)
+				&& !phead->group
+				&& !(phead->control & SE_GROUP_DEFAULTED));
+		if (!missing
+		    && (phead->control & SE_SELF_RELATIVE)
+		    && ntfs_valid_descr(attr, attrsz)) {
+			ni = ntfs_pathname_to_inode(scapi->security.vol,
+				NULL, path);
+			if (ni) {
+				oldattr = getsecurityattr(scapi->security.vol,
+						ni);
+				if (oldattr) {
+					if (mergesecurityattr(
+						scapi->security.vol,
+						oldattr, attr,
+						selection, ni)) {
+						if (test_nino_flag(ni,
+							    v3_Extensions))
+							res = le32_to_cpu(
+							    ni->security_id);
+						else
+							res = -1;
+					}
+					free(oldattr);
+				}
+				ntfs_inode_close(ni);
+			}
+		} else
+			errno = EINVAL;
+	} else
+		errno = EINVAL;
+	return (res);
+}
+
+
+/*
+ *		Return the attributes of a file
+ *	This is intended to be similar to GetFileAttributes() from Win32
+ *	in order to facilitate the development of portable tools
+ *
+ *	returns -1 if unsuccessful (Win32 : INVALID_FILE_ATTRIBUTES)
+ *
+ *  The Win32 API is :
+ *
+ *  DWORD WINAPI GetFileAttributes(
+ *   __in  LPCTSTR lpFileName
+ *  );
+ */
+
+int ntfs_get_file_attributes(struct SECURITY_API *scapi, const char *path)
+{
+	ntfs_inode *ni;
+	s32 attrib;
+
+	attrib = -1; /* default return */
+	if (scapi && (scapi->magic == MAGIC_API) && path) {
+		ni = ntfs_pathname_to_inode(scapi->security.vol, NULL, path);
+		if (ni) {
+			attrib = le32_to_cpu(ni->flags);
+			if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
+				attrib |= const_le32_to_cpu(FILE_ATTR_DIRECTORY);
+			else
+				attrib &= ~const_le32_to_cpu(FILE_ATTR_DIRECTORY);
+			if (!attrib)
+				attrib |= const_le32_to_cpu(FILE_ATTR_NORMAL);
+
+			ntfs_inode_close(ni);
+		} else
+			errno = ENOENT;
+	} else
+		errno = EINVAL; /* do not clear *psize */
+	return (attrib);
+}
+
+
+/*
+ *		Set attributes to a file or directory
+ *	This is intended to be similar to SetFileAttributes() from Win32
+ *	in order to facilitate the development of portable tools
+ *
+ *	Only a few flags can be set (same list as Win32)
+ *
+ *	returns zero if unsuccessful (following Win32 conventions)
+ *		nonzero if successful
+ *
+ *  The Win32 API is :
+ *
+ *  BOOL WINAPI SetFileAttributes(
+ *    __in  LPCTSTR lpFileName,
+ *    __in  DWORD dwFileAttributes
+ *  );
+ */
+
+BOOL ntfs_set_file_attributes(struct SECURITY_API *scapi,
+		const char *path, s32 attrib)
+{
+	ntfs_inode *ni;
+	le32 settable;
+	ATTR_FLAGS dirflags;
+	int res;
+
+	res = 0; /* default return */
+	if (scapi && (scapi->magic == MAGIC_API) && path) {
+		ni = ntfs_pathname_to_inode(scapi->security.vol, NULL, path);
+		if (ni) {
+			settable = FILE_ATTR_SETTABLE;
+			if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
+				/*
+				 * Accept changing compression for a directory
+				 * and set index root accordingly
+				 */
+				settable |= FILE_ATTR_COMPRESSED;
+				if ((ni->flags ^ cpu_to_le32(attrib))
+				             & FILE_ATTR_COMPRESSED) {
+					if (ni->flags & FILE_ATTR_COMPRESSED)
+						dirflags = const_cpu_to_le16(0);
+					else
+						dirflags = ATTR_IS_COMPRESSED;
+					res = ntfs_attr_set_flags(ni,
+						AT_INDEX_ROOT,
+					        NTFS_INDEX_I30, 4,
+						dirflags,
+						ATTR_COMPRESSION_MASK);
+				}
+			}
+			if (!res) {
+				ni->flags = (ni->flags & ~settable)
+					 | (cpu_to_le32(attrib) & settable);
+				NInoSetDirty(ni);
+				NInoFileNameSetDirty(ni);
+			}
+			if (!ntfs_inode_close(ni))
+				res = -1;
+		} else
+			errno = ENOENT;
+	}
+	return (res);
+}
+
+
+BOOL ntfs_read_directory(struct SECURITY_API *scapi,
+		const char *path, ntfs_filldir_t callback, void *context)
+{
+	ntfs_inode *ni;
+	BOOL ok;
+	s64 pos;
+
+	ok = FALSE; /* default return */
+	if (scapi && (scapi->magic == MAGIC_API) && callback) {
+		ni = ntfs_pathname_to_inode(scapi->security.vol, NULL, path);
+		if (ni) {
+			if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
+				pos = 0;
+				ntfs_readdir(ni,&pos,context,callback);
+				ok = !ntfs_inode_close(ni);
+			} else {
+				ntfs_inode_close(ni);
+				errno = ENOTDIR;
+			}
+		} else
+			errno = ENOENT;
+	} else
+		errno = EINVAL; /* do not clear *psize */
+	return (ok);
+}
+
+/*
+ *		read $SDS (for auditing security data)
+ *
+ *	Returns the number or read bytes, or -1 if there is an error
+ */
+
+int ntfs_read_sds(struct SECURITY_API *scapi,
+		char *buf, u32 size, u32 offset)
+{
+	int got;
+
+	got = -1; /* default return */
+	if (scapi && (scapi->magic == MAGIC_API)) {
+		if (scapi->security.vol->secure_ni)
+			got = ntfs_attr_data_read(scapi->security.vol->secure_ni,
+				STREAM_SDS, 4, buf, size, offset);
+		else
+			errno = EOPNOTSUPP;
+	} else
+		errno = EINVAL;
+	return (got);
+}
+
+/*
+ *		read $SII (for auditing security data)
+ *
+ *	Returns next entry, or NULL if there is an error
+ */
+
+INDEX_ENTRY *ntfs_read_sii(struct SECURITY_API *scapi,
+		INDEX_ENTRY *entry)
+{
+	SII_INDEX_KEY key;
+	INDEX_ENTRY *ret;
+	BOOL found;
+	ntfs_index_context *xsii;
+
+	ret = (INDEX_ENTRY*)NULL; /* default return */
+	if (scapi && (scapi->magic == MAGIC_API)) {
+		xsii = scapi->security.vol->secure_xsii;
+		if (xsii) {
+			if (!entry) {
+				key.security_id = const_cpu_to_le32(0);
+				found = !ntfs_index_lookup((char*)&key,
+						sizeof(SII_INDEX_KEY), xsii);
+				/* not supposed to find */
+				if (!found && (errno == ENOENT))
+					ret = xsii->entry;
+			} else
+				ret = ntfs_index_next(entry,xsii);
+			if (!ret)
+				errno = ENODATA;
+		} else
+			errno = EOPNOTSUPP;
+	} else
+		errno = EINVAL;
+	return (ret);
+}
+
+/*
+ *		read $SDH (for auditing security data)
+ *
+ *	Returns next entry, or NULL if there is an error
+ */
+
+INDEX_ENTRY *ntfs_read_sdh(struct SECURITY_API *scapi,
+		INDEX_ENTRY *entry)
+{
+	SDH_INDEX_KEY key;
+	INDEX_ENTRY *ret;
+	BOOL found;
+	ntfs_index_context *xsdh;
+
+	ret = (INDEX_ENTRY*)NULL; /* default return */
+	if (scapi && (scapi->magic == MAGIC_API)) {
+		xsdh = scapi->security.vol->secure_xsdh;
+		if (xsdh) {
+			if (!entry) {
+				key.hash = const_cpu_to_le32(0);
+				key.security_id = const_cpu_to_le32(0);
+				found = !ntfs_index_lookup((char*)&key,
+						sizeof(SDH_INDEX_KEY), xsdh);
+				/* not supposed to find */
+				if (!found && (errno == ENOENT))
+					ret = xsdh->entry;
+			} else
+				ret = ntfs_index_next(entry,xsdh);
+			if (!ret)
+				errno = ENODATA;
+		} else errno = ENOTSUP;
+	} else
+		errno = EINVAL;
+	return (ret);
+}
+
+/*
+ *		Get the mapped user SID
+ *	A buffer of 40 bytes has to be supplied
+ *
+ *	returns the size of the SID, or zero and errno set if not found
+ */
+
+int ntfs_get_usid(struct SECURITY_API *scapi, uid_t uid, char *buf)
+{
+	const SID *usid;
+	BIGSID defusid;
+	int size;
+
+	size = 0;
+	if (scapi && (scapi->magic == MAGIC_API)) {
+		usid = ntfs_find_usid(scapi->security.mapping[MAPUSERS], uid, (SID*)&defusid);
+		if (usid) {
+			size = ntfs_sid_size(usid);
+			memcpy(buf,usid,size);
+		} else
+			errno = ENODATA;
+	} else
+		errno = EINVAL;
+	return (size);
+}
+
+/*
+ *		Get the mapped group SID
+ *	A buffer of 40 bytes has to be supplied
+ *
+ *	returns the size of the SID, or zero and errno set if not found
+ */
+
+int ntfs_get_gsid(struct SECURITY_API *scapi, gid_t gid, char *buf)
+{
+	const SID *gsid;
+	BIGSID defgsid;
+	int size;
+
+	size = 0;
+	if (scapi && (scapi->magic == MAGIC_API)) {
+		gsid = ntfs_find_gsid(scapi->security.mapping[MAPGROUPS], gid, (SID*)&defgsid);
+		if (gsid) {
+			size = ntfs_sid_size(gsid);
+			memcpy(buf,gsid,size);
+		} else
+			errno = ENODATA;
+	} else
+		errno = EINVAL;
+	return (size);
+}
+
+/*
+ *		Get the user mapped to a SID
+ *
+ *	returns the uid, or -1 if not found
+ */
+
+int ntfs_get_user(struct SECURITY_API *scapi, const SID *usid)
+{
+	int uid;
+
+	uid = -1;
+	if (scapi && (scapi->magic == MAGIC_API) && ntfs_valid_sid(usid)) {
+		if (ntfs_same_sid(usid,adminsid))
+			uid = 0;
+		else {
+			uid = ntfs_find_user(scapi->security.mapping[MAPUSERS], usid);
+			if (!uid) {
+				uid = -1;
+				errno = ENODATA;
+			}
+		}
+	} else
+		errno = EINVAL;
+	return (uid);
+}
+
+/*
+ *		Get the group mapped to a SID
+ *
+ *	returns the uid, or -1 if not found
+ */
+
+int ntfs_get_group(struct SECURITY_API *scapi, const SID *gsid)
+{
+	int gid;
+
+	gid = -1;
+	if (scapi && (scapi->magic == MAGIC_API) && ntfs_valid_sid(gsid)) {
+		if (ntfs_same_sid(gsid,adminsid))
+			gid = 0;
+		else {
+			gid = ntfs_find_group(scapi->security.mapping[MAPGROUPS], gsid);
+			if (!gid) {
+				gid = -1;
+				errno = ENODATA;
+			}
+		}
+	} else
+		errno = EINVAL;
+	return (gid);
+}
+
+/*
+ *		Initializations before calling ntfs_get_file_security()
+ *	ntfs_set_file_security() and ntfs_read_directory()
+ *
+ *	Only allowed for root
+ *
+ *	Returns an (obscured) struct SECURITY_API* needed for further calls
+ *		NULL if not root (EPERM) or device is mounted (EBUSY)
+ */
+
+struct SECURITY_API *ntfs_initialize_file_security(const char *device,
+				unsigned long flags)
+{
+	ntfs_volume *vol;
+	unsigned long mntflag;
+	int mnt;
+	struct SECURITY_API *scapi;
+	struct SECURITY_CONTEXT *scx;
+
+	scapi = (struct SECURITY_API*)NULL;
+	mnt = ntfs_check_if_mounted(device, &mntflag);
+	if (!mnt && !(mntflag & NTFS_MF_MOUNTED) && !getuid()) {
+		vol = ntfs_mount(device, flags);
+		if (vol) {
+			scapi = (struct SECURITY_API*)
+				ntfs_malloc(sizeof(struct SECURITY_API));
+			if (!ntfs_volume_get_free_space(vol)
+			    && scapi) {
+				scapi->magic = MAGIC_API;
+				scapi->seccache = (struct PERMISSIONS_CACHE*)NULL;
+				scx = &scapi->security;
+				scx->vol = vol;
+				scx->uid = getuid();
+				scx->gid = getgid();
+				scx->pseccache = &scapi->seccache;
+				scx->vol->secure_flags = 0;
+					/* accept no mapping and no $Secure */
+				ntfs_build_mapping(scx,(const char*)NULL,TRUE);
+				ntfs_open_secure(vol);
+			} else {
+				if (scapi)
+					free(scapi);
+				else
+					errno = ENOMEM;
+				mnt = ntfs_umount(vol,FALSE);
+				scapi = (struct SECURITY_API*)NULL;
+			}
+		}
+	} else
+		if (getuid())
+			errno = EPERM;
+		else
+			errno = EBUSY;
+	return (scapi);
+}
+
+/*
+ *		Leaving after ntfs_initialize_file_security()
+ *
+ *	Returns FALSE if FAILED
+ */
+
+BOOL ntfs_leave_file_security(struct SECURITY_API *scapi)
+{
+	int ok;
+	ntfs_volume *vol;
+
+	ok = FALSE;
+	if (scapi && (scapi->magic == MAGIC_API) && scapi->security.vol) {
+		vol = scapi->security.vol;
+		ntfs_close_secure(&scapi->security);
+		free(scapi);
+ 		if (!ntfs_umount(vol, 0))
+			ok = TRUE;
+	}
+	return (ok);
+}
+
diff --git a/libntfs-3g/unistr.c b/libntfs-3g/unistr.c
new file mode 100755
index 0000000000000000000000000000000000000000..e12d21e75dd2117725d8f9781e8395f8c5afba72
--- /dev/null
+++ b/libntfs-3g/unistr.c
@@ -0,0 +1,1609 @@
+/**
+ * unistr.c - Unicode string handling. Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2000-2004 Anton Altaparmakov
+ * Copyright (c) 2002-2009 Szabolcs Szakacsits
+ * Copyright (c) 2008-2014 Jean-Pierre Andre
+ * Copyright (c) 2008      Bernhard Kaindl
+ *
+ * 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_WCHAR_H
+#include <wchar.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+#if defined(__APPLE__) || defined(__DARWIN__)
+#ifdef ENABLE_NFCONV
+#include <CoreFoundation/CoreFoundation.h>
+#endif /* ENABLE_NFCONV */
+#endif /* defined(__APPLE__) || defined(__DARWIN__) */
+
+#include "compat.h"
+#include "attrib.h"
+#include "types.h"
+#include "unistr.h"
+#include "debug.h"
+#include "logging.h"
+#include "misc.h"
+
+#define NOREVBOM 0  /* JPA rejecting U+FFFE and U+FFFF, open to debate */
+
+/*
+ * IMPORTANT
+ * =========
+ *
+ * All these routines assume that the Unicode characters are in little endian
+ * encoding inside the strings!!!
+ */
+
+static int use_utf8 = 1; /* use UTF-8 encoding for file names */
+
+#if defined(__APPLE__) || defined(__DARWIN__)
+#ifdef ENABLE_NFCONV
+/**
+ * This variable controls whether or not automatic normalization form conversion
+ * should be performed when translating NTFS unicode file names to UTF-8.
+ * Defaults to on, but can be controlled from the outside using the function
+ *   int ntfs_macosx_normalize_filenames(int normalize);
+ */
+static int nfconvert_utf8 = 1;
+#endif /* ENABLE_NFCONV */
+#endif /* defined(__APPLE__) || defined(__DARWIN__) */
+
+/*
+ * This is used by the name collation functions to quickly determine what
+ * characters are (in)valid.
+ */
+#if 0
+static const u8 legal_ansi_char_array[0x40] = {
+	0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+
+	0x17, 0x07, 0x18, 0x17, 0x17, 0x17, 0x17, 0x17,
+	0x17, 0x17, 0x18, 0x16, 0x16, 0x17, 0x07, 0x00,
+
+	0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
+	0x17, 0x17, 0x04, 0x16, 0x18, 0x16, 0x18, 0x18,
+};
+#endif
+
+/**
+ * ntfs_names_are_equal - compare two Unicode names for equality
+ * @s1:			name to compare to @s2
+ * @s1_len:		length in Unicode characters of @s1
+ * @s2:			name to compare to @s1
+ * @s2_len:		length in Unicode characters of @s2
+ * @ic:			ignore case bool
+ * @upcase:		upcase table (only if @ic == IGNORE_CASE)
+ * @upcase_size:	length in Unicode characters of @upcase (if present)
+ *
+ * Compare the names @s1 and @s2 and return TRUE (1) if the names are
+ * identical, or FALSE (0) if they are not identical. If @ic is IGNORE_CASE,
+ * the @upcase table is used to perform a case insensitive comparison.
+ */
+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)
+{
+	if (s1_len != s2_len)
+		return FALSE;
+	if (!s1_len)
+		return TRUE;
+	if (ic == CASE_SENSITIVE)
+		return ntfs_ucsncmp(s1, s2, s1_len) ? FALSE: TRUE;
+	return ntfs_ucsncasecmp(s1, s2, s1_len, upcase, upcase_size) ? FALSE:
+								       TRUE;
+}
+
+/*
+ * ntfs_names_full_collate() fully collate two Unicode names
+ *
+ * @name1:	first Unicode name to compare
+ * @name1_len:	length of first Unicode name to compare
+ * @name2:	second Unicode name to compare
+ * @name2_len:	length of second Unicode name to compare
+ * @ic:		either CASE_SENSITIVE or IGNORE_CASE
+ * @upcase:	upcase table (ignored if @ic is CASE_SENSITIVE)
+ * @upcase_len:	upcase table size (ignored if @ic is CASE_SENSITIVE)
+ *
+ *  -1 if the first name collates before the second one,
+ *   0 if the names match,
+ *   1 if the second name collates before the first one, or
+ *
+ */
+int ntfs_names_full_collate(const ntfschar *name1, const u32 name1_len,
+		const ntfschar *name2, const u32 name2_len,
+		const IGNORE_CASE_BOOL ic, const ntfschar *upcase,
+		const u32 upcase_len)
+{
+	u32 cnt;
+	u16 c1, c2;
+	u16 u1, u2;
+
+#ifdef DEBUG
+	if (!name1 || !name2 || (ic && (!upcase || !upcase_len))) {
+		ntfs_log_debug("ntfs_names_collate received NULL pointer!\n");
+		exit(1);
+	}
+#endif
+	cnt = min(name1_len, name2_len);
+	if (cnt > 0) {
+		if (ic == CASE_SENSITIVE) {
+			while (--cnt && (*name1 == *name2)) {
+				name1++;
+				name2++;
+			}
+			u1 = c1 = le16_to_cpu(*name1);
+			u2 = c2 = le16_to_cpu(*name2);
+			if (u1 < upcase_len)
+				u1 = le16_to_cpu(upcase[u1]);
+			if (u2 < upcase_len)
+				u2 = le16_to_cpu(upcase[u2]);
+			if ((u1 == u2) && cnt)
+				do {
+					name1++;
+					u1 = le16_to_cpu(*name1);
+					name2++;
+					u2 = le16_to_cpu(*name2);
+					if (u1 < upcase_len)
+						u1 = le16_to_cpu(upcase[u1]);
+					if (u2 < upcase_len)
+						u2 = le16_to_cpu(upcase[u2]);
+				} while ((u1 == u2) && --cnt);
+			if (u1 < u2)
+				return -1;
+			if (u1 > u2)
+				return 1;
+			if (name1_len < name2_len)
+				return -1;
+			if (name1_len > name2_len)
+				return 1;
+			if (c1 < c2)
+				return -1;
+			if (c1 > c2)
+				return 1;
+		} else {
+			do {
+				u1 = c1 = le16_to_cpu(*name1);
+				name1++;
+				u2 = c2 = le16_to_cpu(*name2);
+				name2++;
+				if (u1 < upcase_len)
+					u1 = le16_to_cpu(upcase[u1]);
+				if (u2 < upcase_len)
+					u2 = le16_to_cpu(upcase[u2]);
+			} while ((u1 == u2) && --cnt);
+			if (u1 < u2)
+				return -1;
+			if (u1 > u2)
+				return 1;
+			if (name1_len < name2_len)
+				return -1;
+			if (name1_len > name2_len)
+				return 1;
+		}
+	} else {
+		if (name1_len < name2_len)
+			return -1;
+		if (name1_len > name2_len)
+			return 1;
+	}
+	return 0;
+}
+
+/**
+ * ntfs_ucsncmp - compare two little endian Unicode strings
+ * @s1:		first string
+ * @s2:		second string
+ * @n:		maximum unicode characters to compare
+ *
+ * Compare the first @n characters of the Unicode strings @s1 and @s2,
+ * The strings in little endian format and appropriate le16_to_cpu()
+ * conversion is performed on non-little endian machines.
+ *
+ * The function returns an integer less than, equal to, or greater than zero
+ * if @s1 (or the first @n Unicode characters thereof) is found, respectively,
+ * to be less than, to match, or be greater than @s2.
+ */
+int ntfs_ucsncmp(const ntfschar *s1, const ntfschar *s2, size_t n)
+{
+	ntfschar c1, c2;
+	size_t i;
+
+#ifdef DEBUG
+	if (!s1 || !s2) {
+		ntfs_log_debug("ntfs_wcsncmp() received NULL pointer!\n");
+		exit(1);
+	}
+#endif
+	for (i = 0; i < n; ++i) {
+		c1 = le16_to_cpu(s1[i]);
+		c2 = le16_to_cpu(s2[i]);
+		if (c1 < c2)
+			return -1;
+		if (c1 > c2)
+			return 1;
+		if (!c1)
+			break;
+	}
+	return 0;
+}
+
+/**
+ * ntfs_ucsncasecmp - compare two little endian Unicode strings, ignoring case
+ * @s1:			first string
+ * @s2:			second string
+ * @n:			maximum unicode characters to compare
+ * @upcase:		upcase table
+ * @upcase_size:	upcase table size in Unicode characters
+ *
+ * Compare the first @n characters of the Unicode strings @s1 and @s2,
+ * ignoring case. The strings in little endian format and appropriate
+ * le16_to_cpu() conversion is performed on non-little endian machines.
+ *
+ * Each character is uppercased using the @upcase table before the comparison.
+ *
+ * The function returns an integer less than, equal to, or greater than zero
+ * if @s1 (or the first @n Unicode characters thereof) is found, respectively,
+ * to be less than, to match, or be greater than @s2.
+ */
+int ntfs_ucsncasecmp(const ntfschar *s1, const ntfschar *s2, size_t n,
+		const ntfschar *upcase, const u32 upcase_size)
+{
+	u16 c1, c2;
+	size_t i;
+
+#ifdef DEBUG
+	if (!s1 || !s2 || !upcase) {
+		ntfs_log_debug("ntfs_wcsncasecmp() received NULL pointer!\n");
+		exit(1);
+	}
+#endif
+	for (i = 0; i < n; ++i) {
+		if ((c1 = le16_to_cpu(s1[i])) < upcase_size)
+			c1 = le16_to_cpu(upcase[c1]);
+		if ((c2 = le16_to_cpu(s2[i])) < upcase_size)
+			c2 = le16_to_cpu(upcase[c2]);
+		if (c1 < c2)
+			return -1;
+		if (c1 > c2)
+			return 1;
+		if (!c1)
+			break;
+	}
+	return 0;
+}
+
+/**
+ * ntfs_ucsnlen - determine the length of a little endian Unicode string
+ * @s:		pointer to Unicode string
+ * @maxlen:	maximum length of string @s
+ *
+ * Return the number of Unicode characters in the little endian Unicode
+ * string @s up to a maximum of maxlen Unicode characters, not including
+ * the terminating (ntfschar)'\0'. If there is no (ntfschar)'\0' between @s
+ * and @s + @maxlen, @maxlen is returned.
+ *
+ * This function never looks beyond @s + @maxlen.
+ */
+u32 ntfs_ucsnlen(const ntfschar *s, u32 maxlen)
+{
+	u32 i;
+
+	for (i = 0; i < maxlen; i++) {
+		if (!le16_to_cpu(s[i]))
+			break;
+	}
+	return i;
+}
+
+/**
+ * ntfs_ucsndup - duplicate little endian Unicode string
+ * @s:		pointer to Unicode string
+ * @maxlen:	maximum length of string @s
+ *
+ * Return a pointer to a new little endian Unicode string which is a duplicate
+ * of the string s.  Memory for the new string is obtained with ntfs_malloc(3),
+ * and can be freed with free(3).
+ *
+ * A maximum of @maxlen Unicode characters are copied and a terminating
+ * (ntfschar)'\0' little endian Unicode character is added.
+ *
+ * This function never looks beyond @s + @maxlen.
+ *
+ * Return a pointer to the new little endian Unicode string on success and NULL
+ * on failure with errno set to the error code.
+ */
+ntfschar *ntfs_ucsndup(const ntfschar *s, u32 maxlen)
+{
+	ntfschar *dst;
+	u32 len;
+
+	len = ntfs_ucsnlen(s, maxlen);
+	dst = ntfs_malloc((len + 1) * sizeof(ntfschar));
+	if (dst) {
+		memcpy(dst, s, len * sizeof(ntfschar));
+		dst[len] = cpu_to_le16(L'\0');
+	}
+	return dst;
+}
+
+/**
+ * ntfs_name_upcase - Map an Unicode name to its uppercase equivalent
+ * @name:
+ * @name_len:
+ * @upcase:
+ * @upcase_len:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+void ntfs_name_upcase(ntfschar *name, u32 name_len, const ntfschar *upcase,
+		const u32 upcase_len)
+{
+	u32 i;
+	u16 u;
+
+	for (i = 0; i < name_len; i++)
+		if ((u = le16_to_cpu(name[i])) < upcase_len)
+			name[i] = upcase[u];
+}
+
+/**
+ * ntfs_name_locase - Map a Unicode name to its lowercase equivalent
+ */
+void ntfs_name_locase(ntfschar *name, u32 name_len, const ntfschar *locase,
+		const u32 locase_len)
+{
+	u32 i;
+	u16 u;
+
+	if (locase)
+		for (i = 0; i < name_len; i++)
+			if ((u = le16_to_cpu(name[i])) < locase_len)
+				name[i] = locase[u];
+}
+
+/**
+ * ntfs_file_value_upcase - Convert a filename to upper case
+ * @file_name_attr:
+ * @upcase:
+ * @upcase_len:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+void ntfs_file_value_upcase(FILE_NAME_ATTR *file_name_attr,
+		const ntfschar *upcase, const u32 upcase_len)
+{
+	ntfs_name_upcase((ntfschar*)&file_name_attr->file_name,
+			file_name_attr->file_name_length, upcase, upcase_len);
+}
+
+/*
+   NTFS uses Unicode (UTF-16LE [NTFS-3G uses UCS-2LE, which is enough
+   for now]) for path names, but the Unicode code points need to be
+   converted before a path can be accessed under NTFS. For 7 bit ASCII/ANSI,
+   glibc does this even without a locale in a hard-coded fashion as that
+   appears to be is easy because the low 7-bit ASCII range appears to be
+   available in all charsets but it does not convert anything if
+   there was some error with the locale setup or none set up like
+   when mount is called during early boot where he (by policy) do
+   not use locales (and may be not available if /usr is not yet mounted),
+   so this patch fixes the resulting issues for systems which use
+   UTF-8 and for others, specifying the locale in fstab brings them
+   the encoding which they want.
+  
+   If no locale is defined or there was a problem with setting one
+   up and whenever nl_langinfo(CODESET) returns a sting starting with
+   "ANSI", use an internal UCS-2LE <-> UTF-8 codeset converter to fix
+   the bug where NTFS-3G does not show any path names which include
+   international characters!!! (and also fails on creating them) as result.
+  
+   Author: Bernhard Kaindl <bk@suse.de>
+   Jean-Pierre Andre made it compliant with RFC3629/RFC2781.
+*/
+ 
+/* 
+ * Return the amount of 8-bit elements in UTF-8 needed (without the terminating
+ * null) to store a given UTF-16LE string.
+ *
+ * Return -1 with errno set if string has invalid byte sequence or too long.
+ */
+static int utf16_to_utf8_size(const ntfschar *ins, const int ins_len, int outs_len)
+{
+	int i, ret = -1;
+	int count = 0;
+	BOOL surrog;
+
+	surrog = FALSE;
+	for (i = 0; i < ins_len && ins[i]; i++) {
+		unsigned short c = le16_to_cpu(ins[i]);
+		if (surrog) {
+			if ((c >= 0xdc00) && (c < 0xe000)) {
+				surrog = FALSE;
+				count += 4;
+			} else 
+				goto fail;
+		} else
+			if (c < 0x80)
+				count++;
+			else if (c < 0x800)
+				count += 2;
+			else if (c < 0xd800)
+				count += 3;
+			else if (c < 0xdc00)
+				surrog = TRUE;
+#if NOREVBOM
+			else if ((c >= 0xe000) && (c < 0xfffe))
+#else
+			else if (c >= 0xe000)
+#endif
+				count += 3;
+			else 
+				goto fail;
+		if (count > outs_len) {
+			errno = ENAMETOOLONG;
+			goto out;
+		}
+	}
+	if (surrog) 
+		goto fail;
+
+	ret = count;
+out:
+	return ret;
+fail:
+	errno = EILSEQ;
+	goto out;
+}
+
+/*
+ * ntfs_utf16_to_utf8 - convert a little endian UTF16LE string to an UTF-8 string
+ * @ins:	input utf16 string buffer
+ * @ins_len:	length of input string in utf16 characters
+ * @outs:	on return contains the (allocated) output multibyte string
+ * @outs_len:	length of output buffer in bytes
+ *
+ * Return -1 with errno set if string has invalid byte sequence or too long.
+ */
+static int ntfs_utf16_to_utf8(const ntfschar *ins, const int ins_len,
+			      char **outs, int outs_len)
+{
+#if defined(__APPLE__) || defined(__DARWIN__)
+#ifdef ENABLE_NFCONV
+	char *original_outs_value = *outs;
+	int original_outs_len = outs_len;
+#endif /* ENABLE_NFCONV */
+#endif /* defined(__APPLE__) || defined(__DARWIN__) */
+
+	char *t;
+	int i, size, ret = -1;
+	int halfpair;
+
+	halfpair = 0;
+	if (!*outs)
+		outs_len = PATH_MAX;
+
+	size = utf16_to_utf8_size(ins, ins_len, outs_len);
+
+	if (size < 0)
+		goto out;
+
+	if (!*outs) {
+		outs_len = size + 1;
+		*outs = ntfs_malloc(outs_len);
+		if (!*outs)
+			goto out;
+	}
+
+	t = *outs;
+
+	for (i = 0; i < ins_len && ins[i]; i++) {
+	    unsigned short c = le16_to_cpu(ins[i]);
+			/* size not double-checked */
+		if (halfpair) {
+			if ((c >= 0xdc00) && (c < 0xe000)) {
+				*t++ = 0xf0 + (((halfpair + 64) >> 8) & 7);
+				*t++ = 0x80 + (((halfpair + 64) >> 2) & 63);
+				*t++ = 0x80 + ((c >> 6) & 15) + ((halfpair & 3) << 4);
+				*t++ = 0x80 + (c & 63);
+				halfpair = 0;
+			} else 
+				goto fail;
+		} else if (c < 0x80) {
+			*t++ = c;
+	    	} else {
+			if (c < 0x800) {
+			   	*t++ = (0xc0 | ((c >> 6) & 0x3f));
+			        *t++ = 0x80 | (c & 0x3f);
+			} else if (c < 0xd800) {
+			   	*t++ = 0xe0 | (c >> 12);
+			   	*t++ = 0x80 | ((c >> 6) & 0x3f);
+		        	*t++ = 0x80 | (c & 0x3f);
+			} else if (c < 0xdc00)
+				halfpair = c;
+			else if (c >= 0xe000) {
+				*t++ = 0xe0 | (c >> 12);
+				*t++ = 0x80 | ((c >> 6) & 0x3f);
+			        *t++ = 0x80 | (c & 0x3f);
+			} else 
+				goto fail;
+	        }
+	}
+	*t = '\0';
+	
+#if defined(__APPLE__) || defined(__DARWIN__)
+#ifdef ENABLE_NFCONV
+	if(nfconvert_utf8 && (t - *outs) > 0) {
+		char *new_outs = NULL;
+		int new_outs_len = ntfs_macosx_normalize_utf8(*outs, &new_outs, 0); // Normalize to decomposed form
+		if(new_outs_len >= 0 && new_outs != NULL) {
+			if(original_outs_value != *outs) {
+				// We have allocated outs ourselves.
+				free(*outs);
+				*outs = new_outs;
+				t = *outs + new_outs_len;
+			}
+			else {
+				// We need to copy new_outs into the fixed outs buffer.
+				memset(*outs, 0, original_outs_len);
+				strncpy(*outs, new_outs, original_outs_len-1);
+				t = *outs + original_outs_len;
+				free(new_outs);
+			}
+		}
+		else {
+			ntfs_log_error("Failed to normalize NTFS string to UTF-8 NFD: %s\n", *outs);
+			ntfs_log_error("  new_outs=0x%p\n", new_outs);
+			ntfs_log_error("  new_outs_len=%d\n", new_outs_len);
+		}
+	}
+#endif /* ENABLE_NFCONV */
+#endif /* defined(__APPLE__) || defined(__DARWIN__) */
+	
+	ret = t - *outs;
+out:
+	return ret;
+fail:
+	errno = EILSEQ;
+	goto out;
+}
+
+/* 
+ * Return the amount of 16-bit elements in UTF-16LE needed 
+ * (without the terminating null) to store given UTF-8 string.
+ *
+ * Return -1 with errno set if it's longer than PATH_MAX or string is invalid.
+ *
+ * Note: This does not check whether the input sequence is a valid utf8 string,
+ *	 and should be used only in context where such check is made!
+ */
+static int utf8_to_utf16_size(const char *s)
+{
+	int ret = -1;
+	unsigned int byte;
+	size_t count = 0;
+
+	while ((byte = *((const unsigned char *)s++))) {
+		if (++count >= PATH_MAX) 
+			goto fail;
+		if (byte >= 0xc0) {
+			if (byte >= 0xF5) {
+				errno = EILSEQ;
+				goto out;
+			}
+			if (!*s) 
+				break;
+			if (byte >= 0xC0) 
+				s++;
+			if (!*s) 
+				break;
+			if (byte >= 0xE0) 
+				s++;
+			if (!*s) 
+				break;
+			if (byte >= 0xF0) {
+				s++;
+				if (++count >= PATH_MAX)
+					goto fail;
+			}
+		}
+	}
+	ret = count;
+out:
+	return ret;
+fail:
+	errno = ENAMETOOLONG;
+	goto out;
+}
+/* 
+ * This converts one UTF-8 sequence to cpu-endian Unicode value
+ * within range U+0 .. U+10ffff and excluding U+D800 .. U+DFFF
+ *
+ * Return the number of used utf8 bytes or -1 with errno set 
+ * if sequence is invalid.
+ */
+static int utf8_to_unicode(u32 *wc, const char *s)
+{
+    	unsigned int byte = *((const unsigned char *)s);
+
+					/* single byte */
+	if (byte == 0) {
+		*wc = (u32) 0;
+		return 0;
+	} else if (byte < 0x80) {
+		*wc = (u32) byte;
+		return 1;
+					/* double byte */
+	} else if (byte < 0xc2) {
+		goto fail;
+	} else if (byte < 0xE0) {
+		if ((s[1] & 0xC0) == 0x80) {
+			*wc = ((u32)(byte & 0x1F) << 6)
+			    | ((u32)(s[1] & 0x3F));
+			return 2;
+		} else
+			goto fail;
+					/* three-byte */
+	} else if (byte < 0xF0) {
+		if (((s[1] & 0xC0) == 0x80) && ((s[2] & 0xC0) == 0x80)) {
+			*wc = ((u32)(byte & 0x0F) << 12)
+			    | ((u32)(s[1] & 0x3F) << 6)
+			    | ((u32)(s[2] & 0x3F));
+			/* Check valid ranges */
+#if NOREVBOM
+			if (((*wc >= 0x800) && (*wc <= 0xD7FF))
+			  || ((*wc >= 0xe000) && (*wc <= 0xFFFD)))
+				return 3;
+#else
+			if (((*wc >= 0x800) && (*wc <= 0xD7FF))
+			  || ((*wc >= 0xe000) && (*wc <= 0xFFFF)))
+				return 3;
+#endif
+		}
+		goto fail;
+					/* four-byte */
+	} else if (byte < 0xF5) {
+		if (((s[1] & 0xC0) == 0x80) && ((s[2] & 0xC0) == 0x80)
+		  && ((s[3] & 0xC0) == 0x80)) {
+			*wc = ((u32)(byte & 0x07) << 18)
+			    | ((u32)(s[1] & 0x3F) << 12)
+			    | ((u32)(s[2] & 0x3F) << 6)
+			    | ((u32)(s[3] & 0x3F));
+			/* Check valid ranges */
+			if ((*wc <= 0x10ffff) && (*wc >= 0x10000))
+				return 4;
+		}
+		goto fail;
+	}
+fail:
+	errno = EILSEQ;
+	return -1;
+}
+
+/**
+ * ntfs_utf8_to_utf16 - convert a UTF-8 string to a UTF-16LE string
+ * @ins:	input multibyte string buffer
+ * @outs:	on return contains the (allocated) output utf16 string
+ * @outs_len:	length of output buffer in utf16 characters
+ * 
+ * Return -1 with errno set.
+ */
+static int ntfs_utf8_to_utf16(const char *ins, ntfschar **outs)
+{
+#if defined(__APPLE__) || defined(__DARWIN__)
+#ifdef ENABLE_NFCONV
+	char *new_ins = NULL;
+	if(nfconvert_utf8) {
+		int new_ins_len;
+		new_ins_len = ntfs_macosx_normalize_utf8(ins, &new_ins, 1); // Normalize to composed form
+		if(new_ins_len >= 0)
+			ins = new_ins;
+		else
+			ntfs_log_error("Failed to normalize NTFS string to UTF-8 NFC: %s\n", ins);
+	}
+#endif /* ENABLE_NFCONV */
+#endif /* defined(__APPLE__) || defined(__DARWIN__) */
+	const char *t = ins;
+	u32 wc;
+	BOOL allocated;
+	ntfschar *outpos;
+	int shorts, ret = -1;
+
+	shorts = utf8_to_utf16_size(ins);
+	if (shorts < 0)
+		goto fail;
+
+	allocated = FALSE;
+	if (!*outs) {
+		*outs = ntfs_malloc((shorts + 1) * sizeof(ntfschar));
+		if (!*outs)
+			goto fail;
+		allocated = TRUE;
+	}
+
+	outpos = *outs;
+
+	while(1) {
+		int m  = utf8_to_unicode(&wc, t);
+		if (m <= 0) {
+			if (m < 0) {
+				/* do not leave space allocated if failed */
+				if (allocated) {
+					free(*outs);
+					*outs = (ntfschar*)NULL;
+				}
+				goto fail;
+			}
+			*outpos++ = const_cpu_to_le16(0);
+			break;
+		}
+		if (wc < 0x10000)
+			*outpos++ = cpu_to_le16(wc);
+		else {
+			wc -= 0x10000;
+			*outpos++ = cpu_to_le16((wc >> 10) + 0xd800);
+			*outpos++ = cpu_to_le16((wc & 0x3ff) + 0xdc00);
+		}
+		t += m;
+	}
+	
+	ret = --outpos - *outs;
+fail:
+#if defined(__APPLE__) || defined(__DARWIN__)
+#ifdef ENABLE_NFCONV
+	if(new_ins != NULL)
+		free(new_ins);
+#endif /* ENABLE_NFCONV */
+#endif /* defined(__APPLE__) || defined(__DARWIN__) */
+	return ret;
+}
+
+/**
+ * ntfs_ucstombs - convert a little endian Unicode string to a multibyte string
+ * @ins:	input Unicode string buffer
+ * @ins_len:	length of input string in Unicode characters
+ * @outs:	on return contains the (allocated) output multibyte string
+ * @outs_len:	length of output buffer in bytes
+ *
+ * Convert the input little endian, 2-byte Unicode string @ins, of length
+ * @ins_len into the multibyte string format dictated by the current locale.
+ *
+ * If *@outs is NULL, the function allocates the string and the caller is
+ * responsible for calling free(*@outs); when finished with it.
+ *
+ * On success the function returns the number of bytes written to the output
+ * string *@outs (>= 0), not counting the terminating NULL byte. If the output
+ * string buffer was allocated, *@outs is set to it.
+ *
+ * On error, -1 is returned, and errno is set to the error code. The following
+ * error codes can be expected:
+ *	EINVAL		Invalid arguments (e.g. @ins or @outs is NULL).
+ *	EILSEQ		The input string cannot be represented as a multibyte
+ *			sequence according to the current locale.
+ *	ENAMETOOLONG	Destination buffer is too small for input string.
+ *	ENOMEM		Not enough memory to allocate destination buffer.
+ */
+int ntfs_ucstombs(const ntfschar *ins, const int ins_len, char **outs,
+		int outs_len)
+{
+	char *mbs;
+	int mbs_len;
+#ifdef MB_CUR_MAX
+	wchar_t wc;
+	int i, o;
+	int cnt = 0;
+#ifdef HAVE_MBSINIT
+	mbstate_t mbstate;
+#endif
+#endif /* MB_CUR_MAX */
+
+	if (!ins || !outs) {
+		errno = EINVAL;
+		return -1;
+	}
+	mbs = *outs;
+	mbs_len = outs_len;
+	if (mbs && !mbs_len) {
+		errno = ENAMETOOLONG;
+		return -1;
+	}
+	if (use_utf8)
+		return ntfs_utf16_to_utf8(ins, ins_len, outs, outs_len);
+#ifdef MB_CUR_MAX
+	if (!mbs) {
+		mbs_len = (ins_len + 1) * MB_CUR_MAX;
+		mbs = ntfs_malloc(mbs_len);
+		if (!mbs)
+			return -1;
+	}
+#ifdef HAVE_MBSINIT
+	memset(&mbstate, 0, sizeof(mbstate));
+#else
+	wctomb(NULL, 0);
+#endif
+	for (i = o = 0; i < ins_len; i++) {
+		/* Reallocate memory if necessary or abort. */
+		if ((int)(o + MB_CUR_MAX) > mbs_len) {
+			char *tc;
+			if (mbs == *outs) {
+				errno = ENAMETOOLONG;
+				return -1;
+			}
+			tc = ntfs_malloc((mbs_len + 64) & ~63);
+			if (!tc)
+				goto err_out;
+			memcpy(tc, mbs, mbs_len);
+			mbs_len = (mbs_len + 64) & ~63;
+			free(mbs);
+			mbs = tc;
+		}
+		/* Convert the LE Unicode character to a CPU wide character. */
+		wc = (wchar_t)le16_to_cpu(ins[i]);
+		if (!wc)
+			break;
+		/* Convert the CPU endian wide character to multibyte. */
+#ifdef HAVE_MBSINIT
+		cnt = wcrtomb(mbs + o, wc, &mbstate);
+#else
+		cnt = wctomb(mbs + o, wc);
+#endif
+		if (cnt == -1)
+			goto err_out;
+		if (cnt <= 0) {
+			ntfs_log_debug("Eeek. cnt <= 0, cnt = %i\n", cnt);
+			errno = EINVAL;
+			goto err_out;
+		}
+		o += cnt;
+	}
+#ifdef HAVE_MBSINIT
+	/* Make sure we are back in the initial state. */
+	if (!mbsinit(&mbstate)) {
+		ntfs_log_debug("Eeek. mbstate not in initial state!\n");
+		errno = EILSEQ;
+		goto err_out;
+	}
+#endif
+	/* Now write the NULL character. */
+	mbs[o] = '\0';
+	if (*outs != mbs)
+		*outs = mbs;
+	return o;
+err_out:
+	if (mbs != *outs) {
+		int eo = errno;
+		free(mbs);
+		errno = eo;
+	}
+#else /* MB_CUR_MAX */
+	errno = EILSEQ;
+#endif /* MB_CUR_MAX */
+	return -1;
+}
+
+/**
+ * ntfs_mbstoucs - convert a multibyte string to a little endian Unicode string
+ * @ins:	input multibyte string buffer
+ * @outs:	on return contains the (allocated) output Unicode string
+ *
+ * Convert the input multibyte string @ins, from the current locale into the
+ * corresponding little endian, 2-byte Unicode string.
+ *
+ * The function allocates the string and the caller is responsible for calling 
+ * free(*@outs); when finished with it.
+ *
+ * On success the function returns the number of Unicode characters written to
+ * the output string *@outs (>= 0), not counting the terminating Unicode NULL
+ * character.
+ *
+ * On error, -1 is returned, and errno is set to the error code. The following
+ * error codes can be expected:
+ *	EINVAL		Invalid arguments (e.g. @ins or @outs is NULL).
+ *	EILSEQ		The input string cannot be represented as a Unicode
+ *			string according to the current locale.
+ *	ENAMETOOLONG	Destination buffer is too small for input string.
+ *	ENOMEM		Not enough memory to allocate destination buffer.
+ */
+int ntfs_mbstoucs(const char *ins, ntfschar **outs)
+{
+#ifdef MB_CUR_MAX
+	ntfschar *ucs;
+	const char *s;
+	wchar_t wc;
+	int i, o, cnt, ins_len, ucs_len, ins_size;
+#ifdef HAVE_MBSINIT
+	mbstate_t mbstate;
+#endif
+#endif /* MB_CUR_MAX */
+
+	if (!ins || !outs) {
+		errno = EINVAL;
+		return -1;
+	}
+	
+	if (use_utf8)
+		return ntfs_utf8_to_utf16(ins, outs);
+
+#ifdef MB_CUR_MAX
+	/* Determine the size of the multi-byte string in bytes. */
+	ins_size = strlen(ins);
+	/* Determine the length of the multi-byte string. */
+	s = ins;
+#if defined(HAVE_MBSINIT)
+	memset(&mbstate, 0, sizeof(mbstate));
+	ins_len = mbsrtowcs(NULL, (const char **)&s, 0, &mbstate);
+#ifdef __CYGWIN32__
+	if (!ins_len && *ins) {
+		/* Older Cygwin had broken mbsrtowcs() implementation. */
+		ins_len = strlen(ins);
+	}
+#endif
+#elif !defined(DJGPP)
+	ins_len = mbstowcs(NULL, s, 0);
+#else
+	/* Eeek!!! DJGPP has broken mbstowcs() implementation!!! */
+	ins_len = strlen(ins);
+#endif
+	if (ins_len == -1)
+		return ins_len;
+#ifdef HAVE_MBSINIT
+	if ((s != ins) || !mbsinit(&mbstate)) {
+#else
+	if (s != ins) {
+#endif
+		errno = EILSEQ;
+		return -1;
+	}
+	/* Add the NULL terminator. */
+	ins_len++;
+	ucs_len = ins_len;
+	ucs = ntfs_malloc(ucs_len * sizeof(ntfschar));
+	if (!ucs)
+		return -1;
+#ifdef HAVE_MBSINIT
+	memset(&mbstate, 0, sizeof(mbstate));
+#else
+	mbtowc(NULL, NULL, 0);
+#endif
+	for (i = o = cnt = 0; i < ins_size; i += cnt, o++) {
+		/* Reallocate memory if necessary. */
+		if (o >= ucs_len) {
+			ntfschar *tc;
+			ucs_len = (ucs_len * sizeof(ntfschar) + 64) & ~63;
+			tc = realloc(ucs, ucs_len);
+			if (!tc)
+				goto err_out;
+			ucs = tc;
+			ucs_len /= sizeof(ntfschar);
+		}
+		/* Convert the multibyte character to a wide character. */
+#ifdef HAVE_MBSINIT
+		cnt = mbrtowc(&wc, ins + i, ins_size - i, &mbstate);
+#else
+		cnt = mbtowc(&wc, ins + i, ins_size - i);
+#endif
+		if (!cnt)
+			break;
+		if (cnt == -1)
+			goto err_out;
+		if (cnt < -1) {
+			ntfs_log_trace("Eeek. cnt = %i\n", cnt);
+			errno = EINVAL;
+			goto err_out;
+		}
+		/* Make sure we are not overflowing the NTFS Unicode set. */
+		if ((unsigned long)wc >= (unsigned long)(1 <<
+				(8 * sizeof(ntfschar)))) {
+			errno = EILSEQ;
+			goto err_out;
+		}
+		/* Convert the CPU wide character to a LE Unicode character. */
+		ucs[o] = cpu_to_le16(wc);
+	}
+#ifdef HAVE_MBSINIT
+	/* Make sure we are back in the initial state. */
+	if (!mbsinit(&mbstate)) {
+		ntfs_log_trace("Eeek. mbstate not in initial state!\n");
+		errno = EILSEQ;
+		goto err_out;
+	}
+#endif
+	/* Now write the NULL character. */
+	ucs[o] = cpu_to_le16(L'\0');
+	*outs = ucs;
+	return o;
+err_out:
+	free(ucs);
+#else /* MB_CUR_MAX */
+	errno = EILSEQ;
+#endif /* MB_CUR_MAX */
+	return -1;
+}
+
+/*
+ *		Turn a UTF8 name uppercase
+ *
+ *	Returns an allocated uppercase name which has to be freed by caller
+ *	or NULL if there is an error (described by errno)
+ */
+
+char *ntfs_uppercase_mbs(const char *low,
+			const ntfschar *upcase, u32 upcase_size)
+{
+	int size;
+	char *upp;
+	u32 wc;
+	int n;
+	const char *s;
+	char *t;
+
+	size = strlen(low);
+	upp = (char*)ntfs_malloc(3*size + 1);
+	if (upp) {
+		s = low;
+		t = upp;
+		do {
+			n = utf8_to_unicode(&wc, s);
+			if (n > 0) {
+				if (wc < upcase_size)
+					wc = le16_to_cpu(upcase[wc]);
+				if (wc < 0x80)
+					*t++ = wc;
+				else if (wc < 0x800) {
+					*t++ = (0xc0 | ((wc >> 6) & 0x3f));
+					*t++ = 0x80 | (wc & 0x3f);
+				} else if (wc < 0x10000) {
+					*t++ = 0xe0 | (wc >> 12);
+					*t++ = 0x80 | ((wc >> 6) & 0x3f);
+					*t++ = 0x80 | (wc & 0x3f);
+				} else {
+					*t++ = 0xf0 | ((wc >> 18) & 7);
+					*t++ = 0x80 | ((wc >> 12) & 63);
+					*t++ = 0x80 | ((wc >> 6) & 0x3f);
+					*t++ = 0x80 | (wc & 0x3f);
+				}
+			s += n;
+			}
+		} while (n > 0);
+		if (n < 0) {
+			free(upp);
+			upp = (char*)NULL;
+			errno = EILSEQ;
+		}
+		*t = 0;
+	}
+	return (upp);
+}
+
+/**
+ * ntfs_upcase_table_build - build the default upcase table for NTFS
+ * @uc:		destination buffer where to store the built table
+ * @uc_len:	size of destination buffer in bytes
+ *
+ * ntfs_upcase_table_build() builds the default upcase table for NTFS and
+ * stores it in the caller supplied buffer @uc of size @uc_len.
+ *
+ * Note, @uc_len must be at least 128kiB in size or bad things will happen!
+ */
+void ntfs_upcase_table_build(ntfschar *uc, u32 uc_len)
+{
+#if 1 /* Vista */
+	/*
+	 *	This is the table as defined by Vista
+	 */
+	/*
+	 * "Start" is inclusive and "End" is exclusive, every value has the
+	 * value of "Add" added to it.
+	 */
+	static int uc_run_table[][3] = { /* Start, End, Add */
+	{0x0061, 0x007b,   -32}, {0x00e0, 0x00f7,  -32}, {0x00f8, 0x00ff, -32}, 
+	{0x0256, 0x0258,  -205}, {0x028a, 0x028c, -217}, {0x037b, 0x037e, 130}, 
+	{0x03ac, 0x03ad,   -38}, {0x03ad, 0x03b0,  -37}, {0x03b1, 0x03c2, -32},
+	{0x03c2, 0x03c3,   -31}, {0x03c3, 0x03cc,  -32}, {0x03cc, 0x03cd, -64},
+	{0x03cd, 0x03cf,   -63}, {0x0430, 0x0450,  -32}, {0x0450, 0x0460, -80},
+	{0x0561, 0x0587,   -48}, {0x1f00, 0x1f08,    8}, {0x1f10, 0x1f16,   8},
+	{0x1f20, 0x1f28,     8}, {0x1f30, 0x1f38,    8}, {0x1f40, 0x1f46,   8},
+	{0x1f51, 0x1f52,     8}, {0x1f53, 0x1f54,    8}, {0x1f55, 0x1f56,   8},
+	{0x1f57, 0x1f58,     8}, {0x1f60, 0x1f68,    8}, {0x1f70, 0x1f72,  74},
+	{0x1f72, 0x1f76,    86}, {0x1f76, 0x1f78,  100}, {0x1f78, 0x1f7a, 128},
+	{0x1f7a, 0x1f7c,   112}, {0x1f7c, 0x1f7e,  126}, {0x1f80, 0x1f88,   8},
+	{0x1f90, 0x1f98,     8}, {0x1fa0, 0x1fa8,    8}, {0x1fb0, 0x1fb2,   8},
+	{0x1fb3, 0x1fb4,     9}, {0x1fcc, 0x1fcd,   -9}, {0x1fd0, 0x1fd2,   8},
+	{0x1fe0, 0x1fe2,     8}, {0x1fe5, 0x1fe6,    7}, {0x1ffc, 0x1ffd,  -9},
+	{0x2170, 0x2180,   -16}, {0x24d0, 0x24ea,  -26}, {0x2c30, 0x2c5f, -48},
+	{0x2d00, 0x2d26, -7264}, {0xff41, 0xff5b,  -32}, {0}
+	};
+	/*
+	 * "Start" is exclusive and "End" is inclusive, every second value is
+	 * decremented by one.
+	 */
+	static int uc_dup_table[][2] = { /* Start, End */
+	{0x0100, 0x012f}, {0x0132, 0x0137}, {0x0139, 0x0149}, {0x014a, 0x0178},
+	{0x0179, 0x017e}, {0x01a0, 0x01a6}, {0x01b3, 0x01b7}, {0x01cd, 0x01dd},
+	{0x01de, 0x01ef}, {0x01f4, 0x01f5}, {0x01f8, 0x01f9}, {0x01fa, 0x0220},
+	{0x0222, 0x0234}, {0x023b, 0x023c}, {0x0241, 0x0242}, {0x0246, 0x024f},
+	{0x03d8, 0x03ef}, {0x03f7, 0x03f8}, {0x03fa, 0x03fb}, {0x0460, 0x0481},
+	{0x048a, 0x04bf}, {0x04c1, 0x04c4}, {0x04c5, 0x04c8}, {0x04c9, 0x04ce},
+	{0x04ec, 0x04ed}, {0x04d0, 0x04eb}, {0x04ee, 0x04f5}, {0x04f6, 0x0513},
+	{0x1e00, 0x1e95}, {0x1ea0, 0x1ef9}, {0x2183, 0x2184}, {0x2c60, 0x2c61},
+	{0x2c67, 0x2c6c}, {0x2c75, 0x2c76}, {0x2c80, 0x2ce3}, {0}
+	};
+	/*
+	 * Set the Unicode character at offset "Offset" to "Value".  Note,
+	 * "Value" is host endian.
+	 */
+	static int uc_byte_table[][2] = { /* Offset, Value */
+	{0x00ff, 0x0178}, {0x0180, 0x0243}, {0x0183, 0x0182}, {0x0185, 0x0184},
+	{0x0188, 0x0187}, {0x018c, 0x018b}, {0x0192, 0x0191}, {0x0195, 0x01f6},
+	{0x0199, 0x0198}, {0x019a, 0x023d}, {0x019e, 0x0220}, {0x01a8, 0x01a7},
+	{0x01ad, 0x01ac}, {0x01b0, 0x01af}, {0x01b9, 0x01b8}, {0x01bd, 0x01bc},
+	{0x01bf, 0x01f7}, {0x01c6, 0x01c4}, {0x01c9, 0x01c7}, {0x01cc, 0x01ca},
+	{0x01dd, 0x018e}, {0x01f3, 0x01f1}, {0x023a, 0x2c65}, {0x023e, 0x2c66},
+	{0x0253, 0x0181}, {0x0254, 0x0186}, {0x0259, 0x018f}, {0x025b, 0x0190},
+	{0x0260, 0x0193}, {0x0263, 0x0194}, {0x0268, 0x0197}, {0x0269, 0x0196},
+	{0x026b, 0x2c62}, {0x026f, 0x019c}, {0x0272, 0x019d}, {0x0275, 0x019f},
+	{0x027d, 0x2c64}, {0x0280, 0x01a6}, {0x0283, 0x01a9}, {0x0288, 0x01ae},
+	{0x0289, 0x0244}, {0x028c, 0x0245}, {0x0292, 0x01b7}, {0x03f2, 0x03f9},
+	{0x04cf, 0x04c0}, {0x1d7d, 0x2c63}, {0x214e, 0x2132}, {0}
+	};
+#else /* Vista */
+	/*
+	 *	This is the table as defined by Windows XP
+	 */
+	static int uc_run_table[][3] = { /* Start, End, Add */
+	{0x0061, 0x007B,  -32}, {0x0451, 0x045D, -80}, {0x1F70, 0x1F72,  74},
+	{0x00E0, 0x00F7,  -32}, {0x045E, 0x0460, -80}, {0x1F72, 0x1F76,  86},
+	{0x00F8, 0x00FF,  -32}, {0x0561, 0x0587, -48}, {0x1F76, 0x1F78, 100},
+	{0x0256, 0x0258, -205}, {0x1F00, 0x1F08,   8}, {0x1F78, 0x1F7A, 128},
+	{0x028A, 0x028C, -217}, {0x1F10, 0x1F16,   8}, {0x1F7A, 0x1F7C, 112},
+	{0x03AC, 0x03AD,  -38}, {0x1F20, 0x1F28,   8}, {0x1F7C, 0x1F7E, 126},
+	{0x03AD, 0x03B0,  -37}, {0x1F30, 0x1F38,   8}, {0x1FB0, 0x1FB2,   8},
+	{0x03B1, 0x03C2,  -32}, {0x1F40, 0x1F46,   8}, {0x1FD0, 0x1FD2,   8},
+	{0x03C2, 0x03C3,  -31}, {0x1F51, 0x1F52,   8}, {0x1FE0, 0x1FE2,   8},
+	{0x03C3, 0x03CC,  -32}, {0x1F53, 0x1F54,   8}, {0x1FE5, 0x1FE6,   7},
+	{0x03CC, 0x03CD,  -64}, {0x1F55, 0x1F56,   8}, {0x2170, 0x2180, -16},
+	{0x03CD, 0x03CF,  -63}, {0x1F57, 0x1F58,   8}, {0x24D0, 0x24EA, -26},
+	{0x0430, 0x0450,  -32}, {0x1F60, 0x1F68,   8}, {0xFF41, 0xFF5B, -32},
+	{0}
+	};
+	static int uc_dup_table[][2] = { /* Start, End */
+	{0x0100, 0x012F}, {0x01A0, 0x01A6}, {0x03E2, 0x03EF}, {0x04CB, 0x04CC},
+	{0x0132, 0x0137}, {0x01B3, 0x01B7}, {0x0460, 0x0481}, {0x04D0, 0x04EB},
+	{0x0139, 0x0149}, {0x01CD, 0x01DD}, {0x0490, 0x04BF}, {0x04EE, 0x04F5},
+	{0x014A, 0x0178}, {0x01DE, 0x01EF}, {0x04BF, 0x04BF}, {0x04F8, 0x04F9},
+	{0x0179, 0x017E}, {0x01F4, 0x01F5}, {0x04C1, 0x04C4}, {0x1E00, 0x1E95},
+	{0x018B, 0x018B}, {0x01FA, 0x0218}, {0x04C7, 0x04C8}, {0x1EA0, 0x1EF9},
+	{0}
+	};
+	static int uc_byte_table[][2] = { /* Offset, Value */
+	{0x00FF, 0x0178}, {0x01AD, 0x01AC}, {0x01F3, 0x01F1}, {0x0269, 0x0196},
+	{0x0183, 0x0182}, {0x01B0, 0x01AF}, {0x0253, 0x0181}, {0x026F, 0x019C},
+	{0x0185, 0x0184}, {0x01B9, 0x01B8}, {0x0254, 0x0186}, {0x0272, 0x019D},
+	{0x0188, 0x0187}, {0x01BD, 0x01BC}, {0x0259, 0x018F}, {0x0275, 0x019F},
+	{0x018C, 0x018B}, {0x01C6, 0x01C4}, {0x025B, 0x0190}, {0x0283, 0x01A9},
+	{0x0192, 0x0191}, {0x01C9, 0x01C7}, {0x0260, 0x0193}, {0x0288, 0x01AE},
+	{0x0199, 0x0198}, {0x01CC, 0x01CA}, {0x0263, 0x0194}, {0x0292, 0x01B7},
+	{0x01A8, 0x01A7}, {0x01DD, 0x018E}, {0x0268, 0x0197},
+	{0}
+	};
+#endif /* Vista */
+	int i, r;
+	int k, off;
+
+	memset((char*)uc, 0, uc_len);
+	uc_len >>= 1;
+	if (uc_len > 65536)
+		uc_len = 65536;
+	for (i = 0; (u32)i < uc_len; i++)
+		uc[i] = cpu_to_le16(i);
+	for (r = 0; uc_run_table[r][0]; r++) {
+		off = uc_run_table[r][2];
+		for (i = uc_run_table[r][0]; i < uc_run_table[r][1]; i++)
+			uc[i] = cpu_to_le16(i + off);
+	}
+	for (r = 0; uc_dup_table[r][0]; r++)
+		for (i = uc_dup_table[r][0]; i < uc_dup_table[r][1]; i += 2)
+			uc[i + 1] = cpu_to_le16(i);
+	for (r = 0; uc_byte_table[r][0]; r++) {
+		k = uc_byte_table[r][1];
+		uc[uc_byte_table[r][0]] = cpu_to_le16(k);
+	}
+}
+
+/*
+ *		Allocate and build the default upcase table
+ *
+ *	Returns the number of entries
+ *		0 if failed
+ */
+
+#define UPCASE_LEN 65536 /* default number of entries in upcase */
+
+u32 ntfs_upcase_build_default(ntfschar **upcase)
+{
+	u32 upcase_len = 0;
+
+	*upcase = (ntfschar*)ntfs_malloc(UPCASE_LEN*2);
+	if (*upcase) {
+		ntfs_upcase_table_build(*upcase, UPCASE_LEN*2);
+		upcase_len = UPCASE_LEN;
+	}
+	return (upcase_len);
+}
+
+/*
+ *		Build a table for converting to lower case
+ *
+ *	This is only meaningful when there is a single lower case
+ *	character leading to an upper case one, and currently the
+ *	only exception is the greek letter sigma which has a single
+ *	upper case glyph (code U+03A3), but two lower case glyphs
+ *	(code U+03C3 and U+03C2, the latter to be used at the end
+ *	of a word). In the following implementation the upper case
+ *	sigma will be lowercased as U+03C3.
+ */
+
+ntfschar *ntfs_locase_table_build(const ntfschar *uc, u32 uc_cnt)
+{
+	ntfschar *lc;
+	u32 upp;
+	u32 i;
+
+	lc = (ntfschar*)ntfs_malloc(uc_cnt*sizeof(ntfschar));
+	if (lc) {
+		for (i=0; i<uc_cnt; i++)
+			lc[i] = cpu_to_le16(i);
+		for (i=0; i<uc_cnt; i++) {
+			upp = le16_to_cpu(uc[i]);
+			if ((upp != i) && (upp < uc_cnt))
+				lc[upp] = cpu_to_le16(i);
+		}
+	} else
+		ntfs_log_error("Could not build the locase table\n");
+	return (lc);
+}
+
+/**
+ * ntfs_str2ucs - convert a string to a valid NTFS file name
+ * @s:		input string
+ * @len:	length of output buffer in Unicode characters
+ *
+ * Convert the input @s string into the corresponding little endian,
+ * 2-byte Unicode string. The length of the converted string is less 
+ * or equal to the maximum length allowed by the NTFS format (255).
+ *
+ * If @s is NULL then return AT_UNNAMED.
+ *
+ * On success the function returns the Unicode string in an allocated 
+ * buffer and the caller is responsible to free it when it's not needed
+ * anymore.
+ *
+ * On error NULL is returned and errno is set to the error code.
+ */
+ntfschar *ntfs_str2ucs(const char *s, int *len)
+{
+	ntfschar *ucs = NULL;
+
+	if (s && ((*len = ntfs_mbstoucs(s, &ucs)) == -1)) {
+		ntfs_log_perror("Couldn't convert '%s' to Unicode", s);
+		return NULL;
+	}
+	if (*len > NTFS_MAX_NAME_LEN) {
+		free(ucs);
+		errno = ENAMETOOLONG;
+		return NULL;
+	}
+	if (!ucs || !*len) {
+		ucs  = AT_UNNAMED;
+		*len = 0;
+	}
+	return ucs;
+}
+
+/**
+ * ntfs_ucsfree - free memory allocated by ntfs_str2ucs()
+ * @ucs		input string to be freed
+ *
+ * Free memory at @ucs and which was allocated by ntfs_str2ucs.
+ *
+ * Return value: none.
+ */
+void ntfs_ucsfree(ntfschar *ucs)
+{
+	if (ucs && (ucs != AT_UNNAMED))
+		free(ucs);
+}
+
+/*
+ *		Check whether a name contains no chars forbidden
+ *	for DOS or Win32 use
+ *
+ *	If there is a bad char, errno is set to EINVAL
+ */
+
+BOOL ntfs_forbidden_chars(const ntfschar *name, int len)
+{
+	BOOL forbidden;
+	int ch;
+	int i;
+	static const u32 mainset = (1L << ('\"' - 0x20))
+			| (1L << ('*' - 0x20))
+			| (1L << ('/' - 0x20))
+			| (1L << (':' - 0x20))
+			| (1L << ('<' - 0x20))
+			| (1L << ('>' - 0x20))
+			| (1L << ('?' - 0x20));
+
+	forbidden = (len == 0)
+			|| (name[len-1] == const_cpu_to_le16(' '))
+			|| (name[len-1] == const_cpu_to_le16('.'));
+	for (i=0; i<len; i++) {
+		ch = le16_to_cpu(name[i]);
+		if ((ch < 0x20)
+		    || ((ch < 0x40)
+			&& ((1L << (ch - 0x20)) & mainset))
+		    || (ch == '\\')
+		    || (ch == '|'))
+			forbidden = TRUE;
+	}
+	if (forbidden)
+		errno = EINVAL;
+	return (forbidden);
+}
+
+/*
+ *		Check whether a name contains no forbidden chars and
+ *	is not a reserved name for DOS or Win32 use
+ *
+ *	The reserved names are CON, PRN, AUX, NUL, COM1..COM9, LPT1..LPT9
+ *	with no suffix or any suffix.
+ *
+ *	If the name is forbidden, errno is set to EINVAL
+ */
+
+BOOL ntfs_forbidden_names(ntfs_volume *vol, const ntfschar *name, int len)
+{
+	BOOL forbidden;
+	int h;
+	static const ntfschar dot = const_cpu_to_le16('.');
+	static const ntfschar con[] = { const_cpu_to_le16('c'),
+			const_cpu_to_le16('o'), const_cpu_to_le16('n') };
+	static const ntfschar prn[] = { const_cpu_to_le16('p'),
+			const_cpu_to_le16('r'), const_cpu_to_le16('n') };
+	static const ntfschar aux[] = { const_cpu_to_le16('a'),
+			const_cpu_to_le16('u'), const_cpu_to_le16('x') };
+	static const ntfschar nul[] = { const_cpu_to_le16('n'),
+			const_cpu_to_le16('u'), const_cpu_to_le16('l') };
+	static const ntfschar com[] = { const_cpu_to_le16('c'),
+			const_cpu_to_le16('o'), const_cpu_to_le16('m') };
+	static const ntfschar lpt[] = { const_cpu_to_le16('l'),
+			const_cpu_to_le16('p'), const_cpu_to_le16('t') };
+
+	forbidden = ntfs_forbidden_chars(name, len);
+	if (!forbidden && (len >= 3)) {
+		/*
+		 * Rough hash check to tell whether the first couple of chars
+		 * may be one of CO PR AU NU LP or lowercase variants.
+		 */
+		h = ((le16_to_cpu(name[0]) & 31)*48)
+				^ ((le16_to_cpu(name[1]) & 31)*165);
+		if ((h % 23) == 17) {
+			/* do a full check, depending on the third char */
+			switch (le16_to_cpu(name[2]) & ~0x20) {
+			case 'N' :
+				if (((len == 3) || (name[3] == dot))
+				    && (!ntfs_ucsncasecmp(name, con, 3,
+						vol->upcase, vol->upcase_len)
+					|| !ntfs_ucsncasecmp(name, prn, 3,
+						vol->upcase, vol->upcase_len)))
+					forbidden = TRUE;
+				break;
+			case 'X' :
+				if (((len == 3) || (name[3] == dot))
+				    && !ntfs_ucsncasecmp(name, aux, 3,
+						vol->upcase, vol->upcase_len))
+					forbidden = TRUE;
+				break;
+			case 'L' :
+				if (((len == 3) || (name[3] == dot))
+				    && !ntfs_ucsncasecmp(name, nul, 3,
+						vol->upcase, vol->upcase_len))
+					forbidden = TRUE;
+				break;
+			case 'M' :
+				if ((len > 3)
+				    && (le16_to_cpu(name[3]) >= '1')
+				    && (le16_to_cpu(name[3]) <= '9')
+				    && ((len == 4) || (name[4] == dot))
+				    && !ntfs_ucsncasecmp(name, com, 3,
+						vol->upcase, vol->upcase_len))
+					forbidden = TRUE;
+				break;
+			case 'T' :
+				if ((len > 3)
+				    && (le16_to_cpu(name[3]) >= '1')
+				    && (le16_to_cpu(name[3]) <= '9')
+				    && ((len == 4) || (name[4] == dot))
+				    && !ntfs_ucsncasecmp(name, lpt, 3,
+						vol->upcase, vol->upcase_len))
+					forbidden = TRUE;
+				break;
+			}
+		}
+	}
+
+	if (forbidden)
+		errno = EINVAL;
+	return (forbidden);
+}
+
+/*
+ *		Check whether the same name can be used as a DOS and
+ *	a Win32 name
+ *
+ *	The names must be the same, or the short name the uppercase
+ *	variant of the long name
+ */
+
+BOOL ntfs_collapsible_chars(ntfs_volume *vol,
+			const ntfschar *shortname, int shortlen,
+			const ntfschar *longname, int longlen)
+{
+	BOOL collapsible;
+	unsigned int ch;
+	unsigned int cs;
+	int i;
+
+	collapsible = shortlen == longlen;
+	for (i=0; collapsible && (i<shortlen); i++) {
+		ch = le16_to_cpu(longname[i]);
+		cs = le16_to_cpu(shortname[i]);
+		if ((cs != ch)
+		    && ((ch >= vol->upcase_len)
+			|| (cs >= vol->upcase_len)
+			|| (vol->upcase[cs] != vol->upcase[ch])))
+				collapsible = FALSE;
+	}
+	return (collapsible);
+}
+
+/*
+ * Define the character encoding to be used.
+ * Use UTF-8 unless specified otherwise.
+ */
+
+int ntfs_set_char_encoding(const char *locale)
+{
+	use_utf8 = 0;
+	if (!locale || strstr(locale,"utf8") || strstr(locale,"UTF8")
+	    || strstr(locale,"utf-8") || strstr(locale,"UTF-8"))
+		use_utf8 = 1;
+	else
+		if (setlocale(LC_ALL, locale))
+			use_utf8 = 0;
+		else {
+			ntfs_log_error("Invalid locale, encoding to UTF-8\n");
+			use_utf8 = 1;
+	 	}
+	return 0; /* always successful */
+}
+
+#if defined(__APPLE__) || defined(__DARWIN__)
+
+int ntfs_macosx_normalize_filenames(int normalize) {
+#ifdef ENABLE_NFCONV
+	if(normalize == 0 || normalize == 1) {
+		nfconvert_utf8 = normalize;
+		return 0;
+	}
+	else
+		return -1;
+#else
+	return -1;
+#endif /* ENABLE_NFCONV */
+} 
+
+int ntfs_macosx_normalize_utf8(const char *utf8_string, char **target,
+ int composed) {
+#ifdef ENABLE_NFCONV
+	/* For this code to compile, the CoreFoundation framework must be fed to the linker. */
+	CFStringRef cfSourceString;
+	CFMutableStringRef cfMutableString;
+	CFRange rangeToProcess;
+	CFIndex requiredBufferLength;
+	char *result = NULL;
+	int resultLength = -1;
+	
+	/* Convert the UTF-8 string to a CFString. */
+	cfSourceString = CFStringCreateWithCString(kCFAllocatorDefault, utf8_string, kCFStringEncodingUTF8);
+	if(cfSourceString == NULL) {
+		ntfs_log_error("CFStringCreateWithCString failed!\n");
+		return -2;
+	}
+	
+	/* Create a mutable string from cfSourceString that we are free to modify. */
+	cfMutableString = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, cfSourceString);
+	CFRelease(cfSourceString); /* End-of-life. */
+	if(cfMutableString == NULL) {
+		ntfs_log_error("CFStringCreateMutableCopy failed!\n");
+		return -3;
+	}
+  
+	/* Normalize the mutable string to the desired normalization form. */
+	CFStringNormalize(cfMutableString, (composed != 0 ? kCFStringNormalizationFormC : kCFStringNormalizationFormD));
+	
+	/* Store the resulting string in a '\0'-terminated UTF-8 encoded char* buffer. */
+	rangeToProcess = CFRangeMake(0, CFStringGetLength(cfMutableString));
+	if(CFStringGetBytes(cfMutableString, rangeToProcess, kCFStringEncodingUTF8, 0, false, NULL, 0, &requiredBufferLength) > 0) {
+		resultLength = sizeof(char)*(requiredBufferLength + 1);
+		result = ntfs_calloc(resultLength);
+		
+		if(result != NULL) {
+			if(CFStringGetBytes(cfMutableString, rangeToProcess, kCFStringEncodingUTF8,
+					    0, false, (UInt8*)result, resultLength-1, &requiredBufferLength) <= 0) {
+				ntfs_log_error("Could not perform UTF-8 conversion of normalized CFMutableString.\n");
+				free(result);
+				result = NULL;
+			}
+		}
+		else
+			ntfs_log_error("Could not perform a ntfs_calloc of %d bytes for char *result.\n", resultLength);
+	}
+	else
+		ntfs_log_error("Could not perform check for required length of UTF-8 conversion of normalized CFMutableString.\n");
+
+	
+	CFRelease(cfMutableString);
+	
+	if(result != NULL) {
+	 	*target = result;
+		return resultLength - 1;
+	}
+	else
+		return -1;
+#else
+	return -1;
+#endif /* ENABLE_NFCONV */
+}
+#endif /* defined(__APPLE__) || defined(__DARWIN__) */
diff --git a/libntfs-3g/unix_io.c b/libntfs-3g/unix_io.c
new file mode 100755
index 0000000000000000000000000000000000000000..17c2899deba3710d84d97f1dadc4999eee2deb41
--- /dev/null
+++ b/libntfs-3g/unix_io.c
@@ -0,0 +1,371 @@
+/**
+ * unix_io.c - Unix style disk io functions. Originated from the Linux-NTFS project.
+ *
+ * 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
+ * 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_UNISTD_H
+#include <unistd.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
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_LINUX_FD_H
+#include <linux/fd.h>
+#endif
+
+#include "types.h"
+#include "mst.h"
+#include "debug.h"
+#include "device.h"
+#include "logging.h"
+#include "misc.h"
+
+#define DEV_FD(dev)	(*(int *)dev->d_private)
+
+/* Define to nothing if not present on this system. */
+#ifndef O_EXCL
+#	define O_EXCL 0
+#endif
+
+/**
+ * fsync replacement which makes every effort to try to get the data down to
+ * disk, using different means for different operating systems. Specifically,
+ * it issues the proper fcntl for Mac OS X or does fsync where it is available
+ * or as a last resort calls the fsync function. Information on this problem
+ * was retrieved from:
+ *   http://mirror.linux.org.au/pub/linux.conf.au/2007/video/talks/278.pdf
+ */
+static int ntfs_fsync(int fildes)
+{
+	int ret = -1;
+#if defined(__APPLE__) || defined(__DARWIN__)
+# ifndef F_FULLFSYNC
+#  error "Mac OS X: F_FULLFSYNC is not defined. Either you didn't include fcntl.h or you're using an older, unsupported version of Mac OS X (pre-10.3)."
+# endif
+	/* 
+	 * Apple has disabled fsync() for internal disk drives in OS X.
+	 * To force a synchronization of disk contents, we use a Mac OS X
+	 * specific fcntl, F_FULLFSYNC. 
+	 */
+	ret = fcntl(fildes, F_FULLFSYNC, NULL);
+	if (ret) {
+		/* 
+		 * If we are not on a file system that supports this,
+		 * then fall back to a plain fsync. 
+		 */
+		ret = fsync(fildes);
+	}
+#else
+	ret = fsync(fildes);
+#endif
+	return ret;
+}
+
+/**
+ * ntfs_device_unix_io_open - Open a device and lock it exclusively
+ * @dev:
+ * @flags:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static int ntfs_device_unix_io_open(struct ntfs_device *dev, int flags)
+{
+	struct flock flk;
+	struct stat sbuf;
+	int err;
+
+	if (NDevOpen(dev)) {
+		errno = EBUSY;
+		return -1;
+	}
+	if (stat(dev->d_name, &sbuf)) {
+		ntfs_log_perror("Failed to access '%s'", dev->d_name);
+		return -1;
+	}
+	if (S_ISBLK(sbuf.st_mode))
+		NDevSetBlock(dev);
+	
+	dev->d_private = ntfs_malloc(sizeof(int));
+	if (!dev->d_private)
+		return -1;
+	/*
+	 * Open file for exclusive access if mounting r/w.
+	 * Fuseblk takes care about block devices.
+	 */ 
+	if (!NDevBlock(dev) && (flags & O_RDWR) == O_RDWR)
+		flags |= O_EXCL;
+	*(int*)dev->d_private = open(dev->d_name, flags);
+	if (*(int*)dev->d_private == -1) {
+		err = errno;
+		goto err_out;
+	}
+	
+	if ((flags & O_RDWR) != O_RDWR)
+		NDevSetReadOnly(dev);
+	
+	memset(&flk, 0, sizeof(flk));
+	if (NDevReadOnly(dev))
+		flk.l_type = F_RDLCK;
+	else
+		flk.l_type = F_WRLCK;
+	flk.l_whence = SEEK_SET;
+	flk.l_start = flk.l_len = 0LL;
+	if (fcntl(DEV_FD(dev), F_SETLK, &flk)) {
+		err = errno;
+		ntfs_log_perror("Failed to %s lock '%s'", NDevReadOnly(dev) ? 
+				"read" : "write", dev->d_name);
+		if (close(DEV_FD(dev)))
+			ntfs_log_perror("Failed to close '%s'", dev->d_name);
+		goto err_out;
+	}
+	
+	NDevSetOpen(dev);
+	return 0;
+err_out:
+	free(dev->d_private);
+	dev->d_private = NULL;
+	errno = err;
+	return -1;
+}
+
+/**
+ * ntfs_device_unix_io_close - Close the device, releasing the lock
+ * @dev:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static int ntfs_device_unix_io_close(struct ntfs_device *dev)
+{
+	struct flock flk;
+
+	if (!NDevOpen(dev)) {
+		errno = EBADF;
+		ntfs_log_perror("Device %s is not open", dev->d_name);
+		return -1;
+	}
+	if (NDevDirty(dev))
+		if (ntfs_fsync(DEV_FD(dev))) {
+			ntfs_log_perror("Failed to fsync device %s", dev->d_name);
+			return -1;
+		}
+
+	memset(&flk, 0, sizeof(flk));
+	flk.l_type = F_UNLCK;
+	flk.l_whence = SEEK_SET;
+	flk.l_start = flk.l_len = 0LL;
+	if (fcntl(DEV_FD(dev), F_SETLK, &flk))
+		ntfs_log_perror("Could not unlock %s", dev->d_name);
+	if (close(DEV_FD(dev))) {
+		ntfs_log_perror("Failed to close device %s", dev->d_name);
+		return -1;
+	}
+	NDevClearOpen(dev);
+	free(dev->d_private);
+	dev->d_private = NULL;
+	return 0;
+}
+
+/**
+ * ntfs_device_unix_io_seek - Seek to a place on the device
+ * @dev:
+ * @offset:
+ * @whence:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static s64 ntfs_device_unix_io_seek(struct ntfs_device *dev, s64 offset,
+		int whence)
+{
+	return lseek64(DEV_FD(dev), offset, whence);
+}
+
+/**
+ * ntfs_device_unix_io_read - Read from the device, from the current location
+ * @dev:
+ * @buf:
+ * @count:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static s64 ntfs_device_unix_io_read(struct ntfs_device *dev, void *buf,
+		s64 count)
+{
+	return read(DEV_FD(dev), buf, count);
+}
+
+/**
+ * ntfs_device_unix_io_write - Write to the device, at the current location
+ * @dev:
+ * @buf:
+ * @count:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static s64 ntfs_device_unix_io_write(struct ntfs_device *dev, const void *buf,
+		s64 count)
+{
+	if (NDevReadOnly(dev)) {
+		errno = EROFS;
+		return -1;
+	}
+	NDevSetDirty(dev);
+	return write(DEV_FD(dev), buf, count);
+}
+
+/**
+ * ntfs_device_unix_io_pread - Perform a positioned read from the device
+ * @dev:
+ * @buf:
+ * @count:
+ * @offset:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static s64 ntfs_device_unix_io_pread(struct ntfs_device *dev, void *buf,
+		s64 count, s64 offset)
+{
+	return pread64(DEV_FD(dev), buf, count, offset);
+}
+
+/**
+ * ntfs_device_unix_io_pwrite - Perform a positioned write to the device
+ * @dev:
+ * @buf:
+ * @count:
+ * @offset:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static s64 ntfs_device_unix_io_pwrite(struct ntfs_device *dev, const void *buf,
+		s64 count, s64 offset)
+{
+	if (NDevReadOnly(dev)) {
+		errno = EROFS;
+		return -1;
+	}
+	NDevSetDirty(dev);
+	return pwrite64(DEV_FD(dev), buf, count, offset);
+}
+
+/**
+ * ntfs_device_unix_io_sync - Flush any buffered changes to the device
+ * @dev:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static int ntfs_device_unix_io_sync(struct ntfs_device *dev)
+{
+	int res = 0;
+	
+	if (!NDevReadOnly(dev)) {
+		res = ntfs_fsync(DEV_FD(dev));
+		if (res)
+			ntfs_log_perror("Failed to sync device %s", dev->d_name);
+		else
+			NDevClearDirty(dev);
+	}
+	return res;
+}
+
+/**
+ * ntfs_device_unix_io_stat - Get information about the device
+ * @dev:
+ * @buf:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static int ntfs_device_unix_io_stat(struct ntfs_device *dev, struct stat *buf)
+{
+	return fstat(DEV_FD(dev), buf);
+}
+
+/**
+ * ntfs_device_unix_io_ioctl - Perform an ioctl on the device
+ * @dev:
+ * @request:
+ * @argp:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static int ntfs_device_unix_io_ioctl(struct ntfs_device *dev, int request,
+		void *argp)
+{
+	return ioctl(DEV_FD(dev), request, argp);
+}
+
+/**
+ * Device operations for working with unix style devices and files.
+ */
+struct ntfs_device_operations ntfs_device_unix_io_ops = {
+	.open		= ntfs_device_unix_io_open,
+	.close		= ntfs_device_unix_io_close,
+	.seek		= ntfs_device_unix_io_seek,
+	.read		= ntfs_device_unix_io_read,
+	.write		= ntfs_device_unix_io_write,
+	.pread		= ntfs_device_unix_io_pread,
+	.pwrite		= ntfs_device_unix_io_pwrite,
+	.sync		= ntfs_device_unix_io_sync,
+	.stat		= ntfs_device_unix_io_stat,
+	.ioctl		= ntfs_device_unix_io_ioctl,
+};
diff --git a/libntfs-3g/volume.c b/libntfs-3g/volume.c
new file mode 100755
index 0000000000000000000000000000000000000000..edd769796e8743d8b81a5a449cb34a913a9db4a7
--- /dev/null
+++ b/libntfs-3g/volume.c
@@ -0,0 +1,1936 @@
+/**
+ * volume.c - NTFS volume handling code. Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2000-2006 Anton Altaparmakov
+ * Copyright (c) 2002-2009 Szabolcs Szakacsits
+ * Copyright (c) 2004-2005 Richard Russon
+ * 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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.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 HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+#if defined(__sun) && defined (__SVR4)
+#include <sys/mnttab.h>
+#endif
+
+#include "param.h"
+#include "compat.h"
+#include "volume.h"
+#include "attrib.h"
+#include "mft.h"
+#include "bootsect.h"
+#include "device.h"
+#include "debug.h"
+#include "inode.h"
+#include "runlist.h"
+#include "logfile.h"
+#include "dir.h"
+#include "logging.h"
+#include "cache.h"
+#include "realpath.h"
+#include "misc.h"
+
+const char *ntfs_home = 
+"News, support and information:  http://tuxera.com\n";
+
+static const char *invalid_ntfs_msg =
+"The device '%s' doesn't seem to have a valid NTFS.\n"
+"Maybe the wrong device is used? Or the whole disk instead of a\n"
+"partition (e.g. /dev/sda, not /dev/sda1)? Or the other way around?\n";
+
+static const char *corrupt_volume_msg =
+"NTFS is either inconsistent, or there is a hardware fault, or it's a\n"
+"SoftRAID/FakeRAID hardware. In the first case run chkdsk /f on Windows\n"
+"then reboot into Windows twice. The usage of the /f parameter is very\n"
+"important! If the device is a SoftRAID/FakeRAID then first activate\n"
+"it and mount a different device under the /dev/mapper/ directory, (e.g.\n"
+"/dev/mapper/nvidia_eahaabcc1). Please see the 'dmraid' documentation\n"
+"for more details.\n";
+
+static const char *hibernated_volume_msg =
+"The NTFS partition is in an unsafe state. Please resume and shutdown\n"
+"Windows fully (no hibernation or fast restarting), or mount the volume\n"
+"read-only with the 'ro' mount option.\n";
+
+static const char *unclean_journal_msg =
+"Write access is denied because the disk wasn't safely powered\n"
+"off and the 'norecover' mount option was specified.\n";
+
+static const char *opened_volume_msg =
+"Mount is denied because the NTFS volume is already exclusively opened.\n"
+"The volume may be already mounted, or another software may use it which\n"
+"could be identified for example by the help of the 'fuser' command.\n";
+
+static const char *fakeraid_msg =
+"Either the device is missing or it's powered down, or you have\n"
+"SoftRAID hardware and must use an activated, different device under\n" 
+"/dev/mapper/, (e.g. /dev/mapper/nvidia_eahaabcc1) to mount NTFS.\n"
+"Please see the 'dmraid' documentation for help.\n";
+
+static const char *access_denied_msg =
+"Please check '%s' and the ntfs-3g binary permissions,\n"
+"and the mounting user ID. More explanation is provided at\n"
+"http://tuxera.com/community/ntfs-3g-faq/#unprivileged\n";
+
+/**
+ * ntfs_volume_alloc - Create an NTFS volume object and initialise it
+ *
+ * Description...
+ *
+ * Returns:
+ */
+ntfs_volume *ntfs_volume_alloc(void)
+{
+	return ntfs_calloc(sizeof(ntfs_volume));
+}
+
+static void ntfs_attr_free(ntfs_attr **na)
+{
+	if (na && *na) {
+		ntfs_attr_close(*na);
+		*na = NULL;
+	}
+}
+
+static int ntfs_inode_free(ntfs_inode **ni)
+{
+	int ret = -1;
+
+	if (ni && *ni) {
+		ret = ntfs_inode_close(*ni);
+		*ni = NULL;
+	} 
+	
+	return ret;
+}
+
+static void ntfs_error_set(int *err)
+{
+	if (!*err)
+		*err = errno;
+}
+
+/**
+ * __ntfs_volume_release - Destroy an NTFS volume object
+ * @v:
+ *
+ * Description...
+ *
+ * Returns:
+ */
+static int __ntfs_volume_release(ntfs_volume *v)
+{
+	int err = 0;
+
+	if (ntfs_inode_free(&v->vol_ni))
+		ntfs_error_set(&err);
+	/* 
+	 * FIXME: Inodes must be synced before closing
+	 * attributes, otherwise unmount could fail.
+	 */
+	if (v->lcnbmp_ni && NInoDirty(v->lcnbmp_ni))
+		ntfs_inode_sync(v->lcnbmp_ni);
+	ntfs_attr_free(&v->lcnbmp_na);
+	if (ntfs_inode_free(&v->lcnbmp_ni))
+		ntfs_error_set(&err);
+	
+	if (v->mft_ni && NInoDirty(v->mft_ni))
+		ntfs_inode_sync(v->mft_ni);
+	ntfs_attr_free(&v->mftbmp_na);
+	ntfs_attr_free(&v->mft_na);
+	if (ntfs_inode_free(&v->mft_ni))
+		ntfs_error_set(&err);
+	
+	if (v->mftmirr_ni && NInoDirty(v->mftmirr_ni))
+		ntfs_inode_sync(v->mftmirr_ni);
+	ntfs_attr_free(&v->mftmirr_na);
+	if (ntfs_inode_free(&v->mftmirr_ni))
+		ntfs_error_set(&err);
+	
+	if (v->dev) {
+		struct ntfs_device *dev = v->dev;
+
+		if (dev->d_ops->sync(dev))
+			ntfs_error_set(&err);
+		if (dev->d_ops->close(dev))
+			ntfs_error_set(&err);
+	}
+
+	ntfs_free_lru_caches(v);
+	free(v->vol_name);
+	free(v->upcase);
+	if (v->locase) free(v->locase);
+	free(v->attrdef);
+	free(v);
+
+	errno = err;
+	return errno ? -1 : 0;
+}
+
+static void ntfs_attr_setup_flag(ntfs_inode *ni)
+{
+	STANDARD_INFORMATION *si;
+
+	si = ntfs_attr_readall(ni, AT_STANDARD_INFORMATION, AT_UNNAMED, 0, NULL);
+	if (si) {
+		ni->flags = si->file_attributes;
+		free(si);
+	}
+}
+
+/**
+ * ntfs_mft_load - load the $MFT and setup the ntfs volume with it
+ * @vol:	ntfs volume whose $MFT to load
+ *
+ * Load $MFT from @vol and setup @vol with it. After calling this function the
+ * volume @vol is ready for use by all read access functions provided by the
+ * ntfs library.
+ *
+ * Return 0 on success and -1 on error with errno set to the error code.
+ */
+static int ntfs_mft_load(ntfs_volume *vol)
+{
+	VCN next_vcn, last_vcn, highest_vcn;
+	s64 l;
+	MFT_RECORD *mb = NULL;
+	ntfs_attr_search_ctx *ctx = NULL;
+	ATTR_RECORD *a;
+	int eo;
+
+	/* Manually setup an ntfs_inode. */
+	vol->mft_ni = ntfs_inode_allocate(vol);
+	mb = ntfs_malloc(vol->mft_record_size);
+	if (!vol->mft_ni || !mb) {
+		ntfs_log_perror("Error allocating memory for $MFT");
+		goto error_exit;
+	}
+	vol->mft_ni->mft_no = 0;
+	vol->mft_ni->mrec = mb;
+	/* Can't use any of the higher level functions yet! */
+	l = ntfs_mst_pread(vol->dev, vol->mft_lcn << vol->cluster_size_bits, 1,
+			vol->mft_record_size, mb);
+	if (l != 1) {
+		if (l != -1)
+			errno = EIO;
+		ntfs_log_perror("Error reading $MFT");
+		goto error_exit;
+	}
+	
+	if (ntfs_mft_record_check(vol, 0, mb))
+		goto error_exit;
+	
+	ctx = ntfs_attr_get_search_ctx(vol->mft_ni, NULL);
+	if (!ctx)
+		goto error_exit;
+
+	/* Find the $ATTRIBUTE_LIST attribute in $MFT if present. */
+	if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0, 0, 0, NULL, 0,
+			ctx)) {
+		if (errno != ENOENT) {
+			ntfs_log_error("$MFT has corrupt attribute list.\n");
+			goto io_error_exit;
+		}
+		goto mft_has_no_attr_list;
+	}
+	NInoSetAttrList(vol->mft_ni);
+	l = ntfs_get_attribute_value_length(ctx->attr);
+	if (l <= 0 || l > 0x40000) {
+		ntfs_log_error("$MFT/$ATTR_LIST invalid length (%lld).\n",
+			       (long long)l);
+		goto io_error_exit;
+	}
+	vol->mft_ni->attr_list_size = l;
+	vol->mft_ni->attr_list = ntfs_malloc(l);
+	if (!vol->mft_ni->attr_list)
+		goto error_exit;
+	
+	l = ntfs_get_attribute_value(vol, ctx->attr, vol->mft_ni->attr_list);
+	if (!l) {
+		ntfs_log_error("Failed to get value of $MFT/$ATTR_LIST.\n");
+		goto io_error_exit;
+	}
+	if (l != vol->mft_ni->attr_list_size) {
+		ntfs_log_error("Partial read of $MFT/$ATTR_LIST (%lld != "
+			       "%u).\n", (long long)l,
+			       vol->mft_ni->attr_list_size);
+		goto io_error_exit;
+	}
+
+mft_has_no_attr_list:
+
+	ntfs_attr_setup_flag(vol->mft_ni);
+	
+	/* We now have a fully setup ntfs inode for $MFT in vol->mft_ni. */
+	
+	/* Get an ntfs attribute for $MFT/$DATA and set it up, too. */
+	vol->mft_na = ntfs_attr_open(vol->mft_ni, AT_DATA, AT_UNNAMED, 0);
+	if (!vol->mft_na) {
+		ntfs_log_perror("Failed to open ntfs attribute");
+		goto error_exit;
+	}
+	/* Read all extents from the $DATA attribute in $MFT. */
+	ntfs_attr_reinit_search_ctx(ctx);
+	last_vcn = vol->mft_na->allocated_size >> vol->cluster_size_bits;
+	highest_vcn = next_vcn = 0;
+	a = NULL;
+	while (!ntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, next_vcn, NULL, 0,
+			ctx)) {
+		runlist_element *nrl;
+
+		a = ctx->attr;
+		/* $MFT must be non-resident. */
+		if (!a->non_resident) {
+			ntfs_log_error("$MFT must be non-resident.\n");
+			goto io_error_exit;
+		}
+		/* $MFT must be uncompressed and unencrypted. */
+		if (a->flags & ATTR_COMPRESSION_MASK ||
+				a->flags & ATTR_IS_ENCRYPTED) {
+			ntfs_log_error("$MFT must be uncompressed and "
+				       "unencrypted.\n");
+			goto io_error_exit;
+		}
+		/*
+		 * Decompress the mapping pairs array of this extent and merge
+		 * the result into the existing runlist. No need for locking
+		 * as we have exclusive access to the inode at this time and we
+		 * are a mount in progress task, too.
+		 */
+		nrl = ntfs_mapping_pairs_decompress(vol, a, vol->mft_na->rl);
+		if (!nrl) {
+			ntfs_log_perror("ntfs_mapping_pairs_decompress() failed");
+			goto error_exit;
+		}
+		vol->mft_na->rl = nrl;
+
+		/* Get the lowest vcn for the next extent. */
+		highest_vcn = sle64_to_cpu(a->highest_vcn);
+		next_vcn = highest_vcn + 1;
+
+		/* Only one extent or error, which we catch below. */
+		if (next_vcn <= 0)
+			break;
+
+		/* Avoid endless loops due to corruption. */
+		if (next_vcn < sle64_to_cpu(a->lowest_vcn)) {
+			ntfs_log_error("$MFT has corrupt attribute list.\n");
+			goto io_error_exit;
+		}
+	}
+	if (!a) {
+		ntfs_log_error("$MFT/$DATA attribute not found.\n");
+		goto io_error_exit;
+	}
+	if (highest_vcn && highest_vcn != last_vcn - 1) {
+		ntfs_log_error("Failed to load runlist for $MFT/$DATA.\n");
+		ntfs_log_error("highest_vcn = 0x%llx, last_vcn - 1 = 0x%llx\n",
+			       (long long)highest_vcn, (long long)last_vcn - 1);
+		goto io_error_exit;
+	}
+	/* Done with the $Mft mft record. */
+	ntfs_attr_put_search_ctx(ctx);
+	ctx = NULL;
+
+	/* Update the size fields in the inode. */
+	vol->mft_ni->data_size = vol->mft_na->data_size;
+	vol->mft_ni->allocated_size = vol->mft_na->allocated_size;
+	set_nino_flag(vol->mft_ni, KnownSize);
+
+	/*
+	 * The volume is now setup so we can use all read access functions.
+	 */
+	vol->mftbmp_na = ntfs_attr_open(vol->mft_ni, AT_BITMAP, AT_UNNAMED, 0);
+	if (!vol->mftbmp_na) {
+		ntfs_log_perror("Failed to open $MFT/$BITMAP");
+		goto error_exit;
+	}
+	return 0;
+io_error_exit:
+	errno = EIO;
+error_exit:
+	eo = errno;
+	if (ctx)
+		ntfs_attr_put_search_ctx(ctx);
+	if (vol->mft_na) {
+		ntfs_attr_close(vol->mft_na);
+		vol->mft_na = NULL;
+	}
+	if (vol->mft_ni) {
+		ntfs_inode_close(vol->mft_ni);
+		vol->mft_ni = NULL;
+	}
+	errno = eo;
+	return -1;
+}
+
+/**
+ * ntfs_mftmirr_load - load the $MFTMirr and setup the ntfs volume with it
+ * @vol:	ntfs volume whose $MFTMirr to load
+ *
+ * Load $MFTMirr from @vol and setup @vol with it. After calling this function
+ * the volume @vol is ready for use by all write access functions provided by
+ * the ntfs library (assuming ntfs_mft_load() has been called successfully
+ * beforehand).
+ *
+ * Return 0 on success and -1 on error with errno set to the error code.
+ */
+static int ntfs_mftmirr_load(ntfs_volume *vol)
+{
+	int err;
+
+	vol->mftmirr_ni = ntfs_inode_open(vol, FILE_MFTMirr);
+	if (!vol->mftmirr_ni) {
+		ntfs_log_perror("Failed to open inode $MFTMirr");
+		return -1;
+	}
+	
+	vol->mftmirr_na = ntfs_attr_open(vol->mftmirr_ni, AT_DATA, AT_UNNAMED, 0);
+	if (!vol->mftmirr_na) {
+		ntfs_log_perror("Failed to open $MFTMirr/$DATA");
+		goto error_exit;
+	}
+	
+	if (ntfs_attr_map_runlist(vol->mftmirr_na, 0) < 0) {
+		ntfs_log_perror("Failed to map runlist of $MFTMirr/$DATA");
+		goto error_exit;
+	}
+	
+	return 0;
+
+error_exit:
+	err = errno;
+	if (vol->mftmirr_na) {
+		ntfs_attr_close(vol->mftmirr_na);
+		vol->mftmirr_na = NULL;
+	}
+	ntfs_inode_close(vol->mftmirr_ni);
+	vol->mftmirr_ni = NULL;
+	errno = err;
+	return -1;
+}
+
+/**
+ * ntfs_volume_startup - allocate and setup an ntfs volume
+ * @dev:	device to open
+ * @flags:	optional mount flags
+ *
+ * Load, verify, and parse bootsector; load and setup $MFT and $MFTMirr. After
+ * calling this function, the volume is setup sufficiently to call all read
+ * and write access functions provided by the library.
+ *
+ * Return the allocated volume structure on success and NULL on error with
+ * errno set to the error code.
+ */
+ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev,
+		ntfs_mount_flags flags)
+{
+	LCN mft_zone_size, mft_lcn;
+	s64 br;
+	ntfs_volume *vol;
+	NTFS_BOOT_SECTOR *bs;
+	int eo;
+
+	if (!dev || !dev->d_ops || !dev->d_name) {
+		errno = EINVAL;
+		ntfs_log_perror("%s: dev = %p", __FUNCTION__, dev);
+		return NULL;
+	}
+
+	bs = ntfs_malloc(sizeof(NTFS_BOOT_SECTOR));
+	if (!bs)
+		return NULL;
+	
+	/* Allocate the volume structure. */
+	vol = ntfs_volume_alloc();
+	if (!vol)
+		goto error_exit;
+	
+	/* Create the default upcase table. */
+	vol->upcase_len = ntfs_upcase_build_default(&vol->upcase);
+	if (!vol->upcase_len || !vol->upcase)
+		goto error_exit;
+
+	/* Default with no locase table and case sensitive file names */
+	vol->locase = (ntfschar*)NULL;
+	NVolSetCaseSensitive(vol);
+	
+		/* by default, all files are shown and not marked hidden */
+	NVolSetShowSysFiles(vol);
+	NVolSetShowHidFiles(vol);
+	NVolClearHideDotFiles(vol);
+		/* set default compression */
+#if DEFAULT_COMPRESSION
+	NVolSetCompression(vol);
+#else
+	NVolClearCompression(vol);
+#endif
+	if (flags & NTFS_MNT_RDONLY)
+		NVolSetReadOnly(vol);
+	
+	/* ...->open needs bracketing to compile with glibc 2.7 */
+	if ((dev->d_ops->open)(dev, NVolReadOnly(vol) ? O_RDONLY: O_RDWR)) {
+		if (!NVolReadOnly(vol) && (errno == EROFS)) {
+			if ((dev->d_ops->open)(dev, O_RDONLY)) {
+				ntfs_log_perror("Error opening read-only '%s'",
+						dev->d_name);
+				goto error_exit;
+			} else {
+				ntfs_log_info("Can only open '%s' as read-only\n",
+						dev->d_name);
+				NVolSetReadOnly(vol);
+			}
+		} else {
+			ntfs_log_perror("Error opening '%s'", dev->d_name);
+			goto error_exit;
+		}
+	}
+	/* Attach the device to the volume. */
+	vol->dev = dev;
+	
+	/* Now read the bootsector. */
+	br = ntfs_pread(dev, 0, sizeof(NTFS_BOOT_SECTOR), bs);
+	if (br != sizeof(NTFS_BOOT_SECTOR)) {
+		if (br != -1)
+			errno = EINVAL;
+		if (!br)
+			ntfs_log_error("Failed to read bootsector (size=0)\n");
+		else
+			ntfs_log_perror("Error reading bootsector");
+		goto error_exit;
+	}
+	if (!ntfs_boot_sector_is_ntfs(bs)) {
+		errno = EINVAL;
+		goto error_exit;
+	}
+	if (ntfs_boot_sector_parse(vol, bs) < 0)
+		goto error_exit;
+	
+	free(bs);
+	bs = NULL;
+	/* Now set the device block size to the sector size. */
+	if (ntfs_device_block_size_set(vol->dev, vol->sector_size))
+		ntfs_log_debug("Failed to set the device block size to the "
+				"sector size.  This may affect performance "
+				"but should be harmless otherwise.  Error: "
+				"%s\n", strerror(errno));
+	
+	/* We now initialize the cluster allocator. */
+	vol->full_zones = 0;
+	mft_zone_size = vol->nr_clusters >> 3;      /* 12.5% */
+
+	/* Setup the mft zone. */
+	vol->mft_zone_start = vol->mft_zone_pos = vol->mft_lcn;
+	ntfs_log_debug("mft_zone_pos = 0x%llx\n", (long long)vol->mft_zone_pos);
+
+	/*
+	 * Calculate the mft_lcn for an unmodified NTFS volume (see mkntfs
+	 * source) and if the actual mft_lcn is in the expected place or even
+	 * further to the front of the volume, extend the mft_zone to cover the
+	 * beginning of the volume as well. This is in order to protect the
+	 * area reserved for the mft bitmap as well within the mft_zone itself.
+	 * On non-standard volumes we don't protect it as the overhead would be
+	 * higher than the speed increase we would get by doing it.
+	 */
+	mft_lcn = (8192 + 2 * vol->cluster_size - 1) / vol->cluster_size;
+	if (mft_lcn * vol->cluster_size < 16 * 1024)
+		mft_lcn = (16 * 1024 + vol->cluster_size - 1) /
+				vol->cluster_size;
+	if (vol->mft_zone_start <= mft_lcn)
+		vol->mft_zone_start = 0;
+	ntfs_log_debug("mft_zone_start = 0x%llx\n", (long long)vol->mft_zone_start);
+
+	/*
+	 * Need to cap the mft zone on non-standard volumes so that it does
+	 * not point outside the boundaries of the volume. We do this by
+	 * halving the zone size until we are inside the volume.
+	 */
+	vol->mft_zone_end = vol->mft_lcn + mft_zone_size;
+	while (vol->mft_zone_end >= vol->nr_clusters) {
+		mft_zone_size >>= 1;
+		vol->mft_zone_end = vol->mft_lcn + mft_zone_size;
+	}
+	ntfs_log_debug("mft_zone_end = 0x%llx\n", (long long)vol->mft_zone_end);
+
+	/*
+	 * Set the current position within each data zone to the start of the
+	 * respective zone.
+	 */
+	vol->data1_zone_pos = vol->mft_zone_end;
+	ntfs_log_debug("data1_zone_pos = %lld\n", (long long)vol->data1_zone_pos);
+	vol->data2_zone_pos = 0;
+	ntfs_log_debug("data2_zone_pos = %lld\n", (long long)vol->data2_zone_pos);
+
+	/* Set the mft data allocation position to mft record 24. */
+	vol->mft_data_pos = 24;
+
+	/*
+	 * The cluster allocator is now fully operational.
+	 */
+
+	/* Need to setup $MFT so we can use the library read functions. */
+	if (ntfs_mft_load(vol) < 0) {
+		ntfs_log_perror("Failed to load $MFT");
+		goto error_exit;
+	}
+
+	/* Need to setup $MFTMirr so we can use the write functions, too. */
+	if (ntfs_mftmirr_load(vol) < 0) {
+		ntfs_log_perror("Failed to load $MFTMirr");
+		goto error_exit;
+	}
+	return vol;
+error_exit:
+	eo = errno;
+	free(bs);
+	if (vol)
+		__ntfs_volume_release(vol);
+	errno = eo;
+	return NULL;
+}
+
+/**
+ * ntfs_volume_check_logfile - check logfile on target volume
+ * @vol:	volume on which to check logfile
+ *
+ * Return 0 on success and -1 on error with errno set error code.
+ */
+static int ntfs_volume_check_logfile(ntfs_volume *vol)
+{
+	ntfs_inode *ni;
+	ntfs_attr *na = NULL;
+	RESTART_PAGE_HEADER *rp = NULL;
+	int err = 0;
+
+	ni = ntfs_inode_open(vol, FILE_LogFile);
+	if (!ni) {
+		ntfs_log_perror("Failed to open inode FILE_LogFile");
+		errno = EIO;
+		return -1;
+	}
+	
+	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
+	if (!na) {
+		ntfs_log_perror("Failed to open $FILE_LogFile/$DATA");
+		err = EIO;
+		goto out;
+	}
+	
+	if (!ntfs_check_logfile(na, &rp) || !ntfs_is_logfile_clean(na, rp))
+		err = EOPNOTSUPP;
+		/*
+		 * If the latest restart page was identified as version
+		 * 2.0, then Windows may have kept a cached copy of
+		 * metadata for fast restarting, and we should not mount.
+		 * Hibernation will be seen the same way on a non
+		 * Windows-system partition, so we have to use the same
+		 * error code (EPERM).
+		 * The restart page may also be identified as version 2.0
+		 * when access to the file system is terminated abruptly
+		 * by unplugging or power cut, so mounting is also rejected
+		 * after such an event.
+		 */
+	if (rp
+	    && (rp->major_ver == const_cpu_to_le16(2))
+	    && (rp->minor_ver == const_cpu_to_le16(0))) {
+		ntfs_log_error("Metadata kept in Windows cache, refused to mount.\n");
+		err = EPERM;
+	}
+	free(rp);
+	ntfs_attr_close(na);
+out:	
+	if (ntfs_inode_close(ni))
+		ntfs_error_set(&err);
+	if (err) {
+		errno = err;
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * ntfs_hiberfile_open - Find and open '/hiberfil.sys'
+ * @vol:    An ntfs volume obtained from ntfs_mount
+ *
+ * Return:  inode  Success, hiberfil.sys is valid
+ *	    NULL   hiberfil.sys doesn't exist or some other error occurred
+ */
+static ntfs_inode *ntfs_hiberfile_open(ntfs_volume *vol)
+{
+	u64 inode;
+	ntfs_inode *ni_root;
+	ntfs_inode *ni_hibr = NULL;
+	ntfschar   *unicode = NULL;
+	int unicode_len;
+	const char *hiberfile = "hiberfil.sys";
+
+	if (!vol) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	ni_root = ntfs_inode_open(vol, FILE_root);
+	if (!ni_root) {
+		ntfs_log_debug("Couldn't open the root directory.\n");
+		return NULL;
+	}
+
+	unicode_len = ntfs_mbstoucs(hiberfile, &unicode);
+	if (unicode_len < 0) {
+		ntfs_log_perror("Couldn't convert 'hiberfil.sys' to Unicode");
+		goto out;
+	}
+
+	inode = ntfs_inode_lookup_by_name(ni_root, unicode, unicode_len);
+	if (inode == (u64)-1) {
+		ntfs_log_debug("Couldn't find file '%s'.\n", hiberfile);
+		goto out;
+	}
+
+	inode = MREF(inode);
+	ni_hibr = ntfs_inode_open(vol, inode);
+	if (!ni_hibr) {
+		ntfs_log_debug("Couldn't open inode %lld.\n", (long long)inode);
+		goto out;
+	}
+out:
+	if (ntfs_inode_close(ni_root)) {
+		ntfs_inode_close(ni_hibr);
+		ni_hibr = NULL;
+	}
+	free(unicode);
+	return ni_hibr;
+}
+
+
+#define NTFS_HIBERFILE_HEADER_SIZE	4096
+
+/**
+ * ntfs_volume_check_hiberfile - check hiberfil.sys whether Windows is
+ *                               hibernated on the target volume
+ * @vol:    volume on which to check hiberfil.sys
+ *
+ * Return:  0 if Windows isn't hibernated for sure
+ *         -1 otherwise and errno is set to the appropriate value
+ */
+int ntfs_volume_check_hiberfile(ntfs_volume *vol, int verbose)
+{
+	ntfs_inode *ni;
+	ntfs_attr *na = NULL;
+	int bytes_read, err;
+	char *buf = NULL;
+
+	ni = ntfs_hiberfile_open(vol);
+	if (!ni) {
+		if (errno == ENOENT)
+			return 0;
+		return -1;
+	}
+
+	buf = ntfs_malloc(NTFS_HIBERFILE_HEADER_SIZE);
+	if (!buf)
+		goto out;
+
+	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
+	if (!na) {
+		ntfs_log_perror("Failed to open hiberfil.sys data attribute");
+		goto out;
+	}
+
+	bytes_read = ntfs_attr_pread(na, 0, NTFS_HIBERFILE_HEADER_SIZE, buf);
+	if (bytes_read == -1) {
+		ntfs_log_perror("Failed to read hiberfil.sys");
+		goto out;
+	}
+	if (bytes_read < NTFS_HIBERFILE_HEADER_SIZE) {
+		if (verbose)
+			ntfs_log_error("Hibernated non-system partition, "
+				       "refused to mount.\n");
+		errno = EPERM;
+		goto out;
+	}
+	if ((memcmp(buf, "hibr", 4) == 0)
+	   ||  (memcmp(buf, "HIBR", 4) == 0)) {
+		if (verbose)
+			ntfs_log_error("Windows is hibernated, refused to mount.\n");
+		errno = EPERM;
+		goto out;
+	}
+        /* All right, all header bytes are zero */
+	errno = 0;
+out:
+	if (na)
+		ntfs_attr_close(na);
+	free(buf);
+	err = errno;
+	if (ntfs_inode_close(ni))
+		ntfs_error_set(&err);
+	errno = err;
+	return errno ? -1 : 0;
+}
+
+/*
+ *		Make sure a LOGGED_UTILITY_STREAM attribute named "$TXF_DATA"
+ *	on the root directory is resident.
+ *	When it is non-resident, the partition cannot be mounted on Vista
+ *	(see http://support.microsoft.com/kb/974729)
+ *
+ *	We take care to avoid this situation, however this can be a
+ *	consequence of having used an older version (including older
+ *	Windows version), so we had better fix it.
+ *
+ *	Returns 0 if unneeded or successful
+ *		-1 if there was an error, explained by errno
+ */
+
+static int fix_txf_data(ntfs_volume *vol)
+{
+	void *txf_data;
+	s64 txf_data_size;
+	ntfs_inode *ni;
+	ntfs_attr *na;
+	int res;
+
+	res = 0;
+	ntfs_log_debug("Loading root directory\n");
+	ni = ntfs_inode_open(vol, FILE_root);
+	if (!ni) {
+		ntfs_log_perror("Failed to open root directory");
+		res = -1;
+	} else {
+		/* Get the $TXF_DATA attribute */
+		na = ntfs_attr_open(ni, AT_LOGGED_UTILITY_STREAM, TXF_DATA, 9);
+		if (na) {
+			if (NAttrNonResident(na)) {
+				/*
+				 * Fix the attribute by truncating, then
+				 * rewriting it.
+				 */
+				ntfs_log_debug("Making $TXF_DATA resident\n");
+				txf_data = ntfs_attr_readall(ni,
+						AT_LOGGED_UTILITY_STREAM,
+						TXF_DATA, 9, &txf_data_size);
+				if (txf_data) {
+					if (ntfs_attr_truncate(na, 0)
+					    || (ntfs_attr_pwrite(na, 0,
+						 txf_data_size, txf_data)
+							!= txf_data_size))
+						res = -1;
+					free(txf_data);
+				}
+			if (res)
+				ntfs_log_error("Failed to make $TXF_DATA resident\n");
+			else
+				ntfs_log_error("$TXF_DATA made resident\n");
+			}
+			ntfs_attr_close(na);
+		}
+		if (ntfs_inode_close(ni)) {
+			ntfs_log_perror("Failed to close root");
+			res = -1;
+		}
+	}
+	return (res);
+}
+
+/**
+ * ntfs_device_mount - open ntfs volume
+ * @dev:	device to open
+ * @flags:	optional mount flags
+ *
+ * This function mounts an ntfs volume. @dev should describe the device which
+ * to mount as the ntfs volume.
+ *
+ * @flags is an optional second parameter. The same flags are used as for
+ * the mount system call (man 2 mount). Currently only the following flag
+ * is implemented:
+ *	NTFS_MNT_RDONLY	- mount volume read-only
+ *
+ * The function opens the device @dev and verifies that it contains a valid
+ * bootsector. Then, it allocates an ntfs_volume structure and initializes
+ * some of the values inside the structure from the information stored in the
+ * bootsector. It proceeds to load the necessary system files and completes
+ * setting up the structure.
+ *
+ * Return the allocated volume structure on success and NULL on error with
+ * errno set to the error code.
+ */
+ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, ntfs_mount_flags flags)
+{
+	s64 l;
+	ntfs_volume *vol;
+	u8 *m = NULL, *m2 = NULL;
+	ntfs_attr_search_ctx *ctx = NULL;
+	ntfs_inode *ni;
+	ntfs_attr *na;
+	ATTR_RECORD *a;
+	VOLUME_INFORMATION *vinf;
+	ntfschar *vname;
+	int i, j, eo;
+	unsigned int k;
+	u32 u;
+
+	vol = ntfs_volume_startup(dev, flags);
+	if (!vol)
+		return NULL;
+
+	/* Load data from $MFT and $MFTMirr and compare the contents. */
+	m  = ntfs_malloc(vol->mftmirr_size << vol->mft_record_size_bits);
+	m2 = ntfs_malloc(vol->mftmirr_size << vol->mft_record_size_bits);
+	if (!m || !m2)
+		goto error_exit;
+
+	l = ntfs_attr_mst_pread(vol->mft_na, 0, vol->mftmirr_size,
+			vol->mft_record_size, m);
+	if (l != vol->mftmirr_size) {
+		if (l == -1)
+			ntfs_log_perror("Failed to read $MFT");
+		else {
+			ntfs_log_error("Failed to read $MFT, unexpected length "
+				       "(%lld != %d).\n", (long long)l,
+				       vol->mftmirr_size);
+			errno = EIO;
+		}
+		goto error_exit;
+	}
+	l = ntfs_attr_mst_pread(vol->mftmirr_na, 0, vol->mftmirr_size,
+			vol->mft_record_size, m2);
+	if (l != vol->mftmirr_size) {
+		if (l == -1) {
+			ntfs_log_perror("Failed to read $MFTMirr");
+			goto error_exit;
+		}
+		vol->mftmirr_size = l;
+	}
+	ntfs_log_debug("Comparing $MFTMirr to $MFT...\n");
+	for (i = 0; i < vol->mftmirr_size; ++i) {
+		MFT_RECORD *mrec, *mrec2;
+		const char *ESTR[12] = { "$MFT", "$MFTMirr", "$LogFile",
+			"$Volume", "$AttrDef", "root directory", "$Bitmap",
+			"$Boot", "$BadClus", "$Secure", "$UpCase", "$Extend" };
+		const char *s;
+
+		if (i < 12)
+			s = ESTR[i];
+		else if (i < 16)
+			s = "system file";
+		else
+			s = "mft record";
+
+		mrec = (MFT_RECORD*)(m + i * vol->mft_record_size);
+		if (mrec->flags & MFT_RECORD_IN_USE) {
+			if (ntfs_is_baad_recordp(mrec)) {
+				ntfs_log_error("$MFT error: Incomplete multi "
+					       "sector transfer detected in "
+					       "'%s'.\n", s);
+				goto io_error_exit;
+			}
+			if (!ntfs_is_mft_recordp(mrec)) {
+				ntfs_log_error("$MFT error: Invalid mft "
+						"record for '%s'.\n", s);
+				goto io_error_exit;
+			}
+		}
+		mrec2 = (MFT_RECORD*)(m2 + i * vol->mft_record_size);
+		if (mrec2->flags & MFT_RECORD_IN_USE) {
+			if (ntfs_is_baad_recordp(mrec2)) {
+				ntfs_log_error("$MFTMirr error: Incomplete "
+						"multi sector transfer "
+						"detected in '%s'.\n", s);
+				goto io_error_exit;
+			}
+			if (!ntfs_is_mft_recordp(mrec2)) {
+				ntfs_log_error("$MFTMirr error: Invalid mft "
+						"record for '%s'.\n", s);
+				goto io_error_exit;
+			}
+		}
+		if (memcmp(mrec, mrec2, ntfs_mft_record_get_data_size(mrec))) {
+			ntfs_log_error("$MFTMirr does not match $MFT (record "
+				       "%d).\n", i);
+			goto io_error_exit;
+		}
+	}
+
+	free(m2);
+	free(m);
+	m = m2 = NULL;
+
+	/* Now load the bitmap from $Bitmap. */
+	ntfs_log_debug("Loading $Bitmap...\n");
+	vol->lcnbmp_ni = ntfs_inode_open(vol, FILE_Bitmap);
+	if (!vol->lcnbmp_ni) {
+		ntfs_log_perror("Failed to open inode FILE_Bitmap");
+		goto error_exit;
+	}
+	
+	vol->lcnbmp_na = ntfs_attr_open(vol->lcnbmp_ni, AT_DATA, AT_UNNAMED, 0);
+	if (!vol->lcnbmp_na) {
+		ntfs_log_perror("Failed to open ntfs attribute");
+		goto error_exit;
+	}
+	
+	if (vol->lcnbmp_na->data_size > vol->lcnbmp_na->allocated_size) {
+		ntfs_log_error("Corrupt cluster map size (%lld > %lld)\n",
+				(long long)vol->lcnbmp_na->data_size, 
+				(long long)vol->lcnbmp_na->allocated_size);
+		goto io_error_exit;
+	}
+
+	/* Now load the upcase table from $UpCase. */
+	ntfs_log_debug("Loading $UpCase...\n");
+	ni = ntfs_inode_open(vol, FILE_UpCase);
+	if (!ni) {
+		ntfs_log_perror("Failed to open inode FILE_UpCase");
+		goto error_exit;
+	}
+	/* Get an ntfs attribute for $UpCase/$DATA. */
+	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
+	if (!na) {
+		ntfs_log_perror("Failed to open ntfs attribute");
+		goto error_exit;
+	}
+	/*
+	 * Note: Normally, the upcase table has a length equal to 65536
+	 * 2-byte Unicode characters but allow for different cases, so no
+	 * checks done. Just check we don't overflow 32-bits worth of Unicode
+	 * characters.
+	 */
+	if (na->data_size & ~0x1ffffffffULL) {
+		ntfs_log_error("Error: Upcase table is too big (max 32-bit "
+				"allowed).\n");
+		errno = EINVAL;
+		goto error_exit;
+	}
+	if (vol->upcase_len != na->data_size >> 1) {
+		vol->upcase_len = na->data_size >> 1;
+		/* Throw away default table. */
+		free(vol->upcase);
+		vol->upcase = ntfs_malloc(na->data_size);
+		if (!vol->upcase)
+			goto error_exit;
+	}
+	/* Read in the $DATA attribute value into the buffer. */
+	l = ntfs_attr_pread(na, 0, na->data_size, vol->upcase);
+	if (l != na->data_size) {
+		ntfs_log_error("Failed to read $UpCase, unexpected length "
+			       "(%lld != %lld).\n", (long long)l,
+			       (long long)na->data_size);
+		errno = EIO;
+		goto error_exit;
+	}
+	/* Done with the $UpCase mft record. */
+	ntfs_attr_close(na);
+	if (ntfs_inode_close(ni)) {
+		ntfs_log_perror("Failed to close $UpCase");
+		goto error_exit;
+	}
+	/* Consistency check of $UpCase, restricted to plain ASCII chars */
+	k = 0x20;
+	while ((k < vol->upcase_len)
+	    && (k < 0x7f)
+	    && (le16_to_cpu(vol->upcase[k])
+			== ((k < 'a') || (k > 'z') ? k : k + 'A' - 'a')))
+		k++;
+	if (k < 0x7f) {
+		ntfs_log_error("Corrupted file $UpCase\n");
+		goto io_error_exit;
+	}
+
+	/*
+	 * Now load $Volume and set the version information and flags in the
+	 * vol structure accordingly.
+	 */
+	ntfs_log_debug("Loading $Volume...\n");
+	vol->vol_ni = ntfs_inode_open(vol, FILE_Volume);
+	if (!vol->vol_ni) {
+		ntfs_log_perror("Failed to open inode FILE_Volume");
+		goto error_exit;
+	}
+	/* Get a search context for the $Volume/$VOLUME_INFORMATION lookup. */
+	ctx = ntfs_attr_get_search_ctx(vol->vol_ni, NULL);
+	if (!ctx)
+		goto error_exit;
+
+	/* Find the $VOLUME_INFORMATION attribute. */
+	if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, AT_UNNAMED, 0, 0, 0, NULL,
+			0, ctx)) {
+		ntfs_log_perror("$VOLUME_INFORMATION attribute not found in "
+				"$Volume");
+		goto error_exit;
+	}
+	a = ctx->attr;
+	/* Has to be resident. */
+	if (a->non_resident) {
+		ntfs_log_error("Attribute $VOLUME_INFORMATION must be "
+			       "resident but it isn't.\n");
+		errno = EIO;
+		goto error_exit;
+	}
+	/* Get a pointer to the value of the attribute. */
+	vinf = (VOLUME_INFORMATION*)(le16_to_cpu(a->value_offset) + (char*)a);
+	/* Sanity checks. */
+	if ((char*)vinf + le32_to_cpu(a->value_length) > (char*)ctx->mrec +
+			le32_to_cpu(ctx->mrec->bytes_in_use) ||
+			le16_to_cpu(a->value_offset) + le32_to_cpu(
+			a->value_length) > le32_to_cpu(a->length)) {
+		ntfs_log_error("$VOLUME_INFORMATION in $Volume is corrupt.\n");
+		errno = EIO;
+		goto error_exit;
+	}
+	/* Setup vol from the volume information attribute value. */
+	vol->major_ver = vinf->major_ver;
+	vol->minor_ver = vinf->minor_ver;
+	/* Do not use le16_to_cpu() macro here as our VOLUME_FLAGS are
+	   defined using cpu_to_le16() macro and hence are consistent. */
+	vol->flags = vinf->flags;
+	/*
+	 * Reinitialize the search context for the $Volume/$VOLUME_NAME lookup.
+	 */
+	ntfs_attr_reinit_search_ctx(ctx);
+	if (ntfs_attr_lookup(AT_VOLUME_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0,
+			ctx)) {
+		if (errno != ENOENT) {
+			ntfs_log_perror("Failed to lookup of $VOLUME_NAME in "
+					"$Volume failed");
+			goto error_exit;
+		}
+		/*
+		 * Attribute not present.  This has been seen in the field.
+		 * Treat this the same way as if the attribute was present but
+		 * had zero length.
+		 */
+		vol->vol_name = ntfs_malloc(1);
+		if (!vol->vol_name)
+			goto error_exit;
+		vol->vol_name[0] = '\0';
+	} else {
+		a = ctx->attr;
+		/* Has to be resident. */
+		if (a->non_resident) {
+			ntfs_log_error("$VOLUME_NAME must be resident.\n");
+			errno = EIO;
+			goto error_exit;
+		}
+		/* Get a pointer to the value of the attribute. */
+		vname = (ntfschar*)(le16_to_cpu(a->value_offset) + (char*)a);
+		u = le32_to_cpu(a->value_length) / 2;
+		/*
+		 * Convert Unicode volume name to current locale multibyte
+		 * format.
+		 */
+		vol->vol_name = NULL;
+		if (ntfs_ucstombs(vname, u, &vol->vol_name, 0) == -1) {
+			ntfs_log_perror("Volume name could not be converted "
+					"to current locale");
+			ntfs_log_debug("Forcing name into ASCII by replacing "
+				"non-ASCII characters with underscores.\n");
+			vol->vol_name = ntfs_malloc(u + 1);
+			if (!vol->vol_name)
+				goto error_exit;
+			
+			for (j = 0; j < (s32)u; j++) {
+				u16 uc = le16_to_cpu(vname[j]);
+				if (uc > 0xff)
+					uc = (u16)'_';
+				vol->vol_name[j] = (char)uc;
+			}
+			vol->vol_name[u] = '\0';
+		}
+	}
+	ntfs_attr_put_search_ctx(ctx);
+	ctx = NULL;
+	/* Now load the attribute definitions from $AttrDef. */
+	ntfs_log_debug("Loading $AttrDef...\n");
+	ni = ntfs_inode_open(vol, FILE_AttrDef);
+	if (!ni) {
+		ntfs_log_perror("Failed to open $AttrDef");
+		goto error_exit;
+	}
+	/* Get an ntfs attribute for $AttrDef/$DATA. */
+	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
+	if (!na) {
+		ntfs_log_perror("Failed to open ntfs attribute");
+		goto error_exit;
+	}
+	/* Check we don't overflow 32-bits. */
+	if (na->data_size > 0xffffffffLL) {
+		ntfs_log_error("Attribute definition table is too big (max "
+			       "32-bit allowed).\n");
+		errno = EINVAL;
+		goto error_exit;
+	}
+	vol->attrdef_len = na->data_size;
+	vol->attrdef = ntfs_malloc(na->data_size);
+	if (!vol->attrdef)
+		goto error_exit;
+	/* Read in the $DATA attribute value into the buffer. */
+	l = ntfs_attr_pread(na, 0, na->data_size, vol->attrdef);
+	if (l != na->data_size) {
+		ntfs_log_error("Failed to read $AttrDef, unexpected length "
+			       "(%lld != %lld).\n", (long long)l,
+			       (long long)na->data_size);
+		errno = EIO;
+		goto error_exit;
+	}
+	/* Done with the $AttrDef mft record. */
+	ntfs_attr_close(na);
+	if (ntfs_inode_close(ni)) {
+		ntfs_log_perror("Failed to close $AttrDef");
+		goto error_exit;
+	}
+	/*
+	 * Check for dirty logfile and hibernated Windows.
+	 * We care only about read-write mounts.
+	 */
+	if (!(flags & (NTFS_MNT_RDONLY | NTFS_MNT_FORENSIC))) {
+		if (!(flags & NTFS_MNT_IGNORE_HIBERFILE) &&
+		    ntfs_volume_check_hiberfile(vol, 1) < 0)
+			goto error_exit;
+		if (ntfs_volume_check_logfile(vol) < 0) {
+			/* Always reject cached metadata for now */
+			if (!(flags & NTFS_MNT_RECOVER) || (errno == EPERM))
+				goto error_exit;
+			ntfs_log_info("The file system wasn't safely "
+				      "closed on Windows. Fixing.\n");
+			if (ntfs_logfile_reset(vol))
+				goto error_exit;
+		}
+		/* make $TXF_DATA resident if present on the root directory */
+		if (fix_txf_data(vol))
+			goto error_exit;
+	}
+
+	return vol;
+io_error_exit:
+	errno = EIO;
+error_exit:
+	eo = errno;
+	if (ctx)
+		ntfs_attr_put_search_ctx(ctx);
+	free(m);
+	free(m2);
+	__ntfs_volume_release(vol);
+	errno = eo;
+	return NULL;
+}
+
+/*
+ *		Set appropriate flags for showing NTFS metafiles
+ *	or files marked as hidden.
+ *	Not set in ntfs_mount() to avoid breaking existing tools.
+ */
+
+int ntfs_set_shown_files(ntfs_volume *vol,
+			BOOL show_sys_files, BOOL show_hid_files,
+			BOOL hide_dot_files)
+{
+	int res;
+
+	res = -1;
+	if (vol) {
+		NVolClearShowSysFiles(vol);
+		NVolClearShowHidFiles(vol);
+		NVolClearHideDotFiles(vol);
+		if (show_sys_files)
+			NVolSetShowSysFiles(vol);
+		if (show_hid_files)
+			NVolSetShowHidFiles(vol);
+		if (hide_dot_files)
+			NVolSetHideDotFiles(vol);
+		res = 0;
+	}
+	if (res)
+		ntfs_log_error("Failed to set file visibility\n");
+	return (res);
+}
+
+/*
+ *		Set ignore case mode
+ */
+
+int ntfs_set_ignore_case(ntfs_volume *vol)
+{
+	int res;
+
+	res = -1;
+	if (vol && vol->upcase) {
+		vol->locase = ntfs_locase_table_build(vol->upcase,
+					vol->upcase_len);
+		if (vol->locase) {
+			NVolClearCaseSensitive(vol);
+			res = 0;
+		}
+	}
+	if (res)
+		ntfs_log_error("Failed to set ignore_case mode\n");
+	return (res);
+}
+
+/**
+ * ntfs_mount - open ntfs volume
+ * @name:	name of device/file to open
+ * @flags:	optional mount flags
+ *
+ * This function mounts an ntfs volume. @name should contain the name of the
+ * device/file to mount as the ntfs volume.
+ *
+ * @flags is an optional second parameter. The same flags are used as for
+ * the mount system call (man 2 mount). Currently only the following flags
+ * is implemented:
+ *	NTFS_MNT_RDONLY	- mount volume read-only
+ *
+ * The function opens the device or file @name and verifies that it contains a
+ * valid bootsector. Then, it allocates an ntfs_volume structure and initializes
+ * some of the values inside the structure from the information stored in the
+ * bootsector. It proceeds to load the necessary system files and completes
+ * setting up the structure.
+ *
+ * Return the allocated volume structure on success and NULL on error with
+ * errno set to the error code.
+ *
+ * Note, that a copy is made of @name, and hence it can be discarded as
+ * soon as the function returns.
+ */
+ntfs_volume *ntfs_mount(const char *name __attribute__((unused)),
+		ntfs_mount_flags flags __attribute__((unused)))
+{
+#ifndef NO_NTFS_DEVICE_DEFAULT_IO_OPS
+	struct ntfs_device *dev;
+	ntfs_volume *vol;
+
+	/* Allocate an ntfs_device structure. */
+	dev = ntfs_device_alloc(name, 0, &ntfs_device_default_io_ops, NULL);
+	if (!dev)
+		return NULL;
+	/* Call ntfs_device_mount() to do the actual mount. */
+	vol = ntfs_device_mount(dev, flags);
+	if (!vol) {
+		int eo = errno;
+		ntfs_device_free(dev);
+		errno = eo;
+	} else
+		ntfs_create_lru_caches(vol);
+	return vol;
+#else
+	/*
+	 * ntfs_mount() makes no sense if NO_NTFS_DEVICE_DEFAULT_IO_OPS is
+	 * defined as there are no device operations available in libntfs in
+	 * this case.
+	 */
+	errno = EOPNOTSUPP;
+	return NULL;
+#endif
+}
+
+/**
+ * ntfs_umount - close ntfs volume
+ * @vol: address of ntfs_volume structure of volume to close
+ * @force: if true force close the volume even if it is busy
+ *
+ * Deallocate all structures (including @vol itself) associated with the ntfs
+ * volume @vol.
+ *
+ * Return 0 on success. On error return -1 with errno set appropriately
+ * (most likely to one of EAGAIN, EBUSY or EINVAL). The EAGAIN error means that
+ * an operation is in progress and if you try the close later the operation
+ * might be completed and the close succeed.
+ *
+ * If @force is true (i.e. not zero) this function will close the volume even
+ * if this means that data might be lost.
+ *
+ * @vol must have previously been returned by a call to ntfs_mount().
+ *
+ * @vol itself is deallocated and should no longer be dereferenced after this
+ * function returns success. If it returns an error then nothing has been done
+ * so it is safe to continue using @vol.
+ */
+int ntfs_umount(ntfs_volume *vol, const BOOL force __attribute__((unused)))
+{
+	struct ntfs_device *dev;
+	int ret;
+
+	if (!vol) {
+		errno = EINVAL;
+		return -1;
+	}
+	dev = vol->dev;
+	ret = __ntfs_volume_release(vol);
+	ntfs_device_free(dev);
+	return ret;
+}
+
+#ifdef HAVE_MNTENT_H
+
+/**
+ * ntfs_mntent_check - desc
+ *
+ * If you are wanting to use this, you actually wanted to use
+ * ntfs_check_if_mounted(), you just didn't realize. (-:
+ *
+ * See description of ntfs_check_if_mounted(), below.
+ */
+static int ntfs_mntent_check(const char *file, unsigned long *mnt_flags)
+{
+	struct mntent *mnt;
+	char *real_file = NULL, *real_fsname = NULL;
+	FILE *f;
+	int err = 0;
+
+	real_file = ntfs_malloc(PATH_MAX + 1);
+	if (!real_file)
+		return -1;
+	real_fsname = ntfs_malloc(PATH_MAX + 1);
+	if (!real_fsname) {
+		err = errno;
+		goto exit;
+	}
+	if (!ntfs_realpath_canonicalize(file, real_file)) {
+		err = errno;
+		goto exit;
+	}
+	f = setmntent("/proc/mounts", "r");
+	if (!f && !(f = setmntent(MOUNTED, "r"))) {
+		err = errno;
+		goto exit;
+	}
+	while ((mnt = getmntent(f))) {
+		if (!ntfs_realpath_canonicalize(mnt->mnt_fsname, real_fsname))
+			continue;
+		if (!strcmp(real_file, real_fsname))
+			break;
+	}
+	endmntent(f);
+	if (!mnt)
+		goto exit;
+	*mnt_flags = NTFS_MF_MOUNTED;
+	if (!strcmp(mnt->mnt_dir, "/"))
+		*mnt_flags |= NTFS_MF_ISROOT;
+#ifdef HAVE_HASMNTOPT
+	if (hasmntopt(mnt, "ro") && !hasmntopt(mnt, "rw"))
+		*mnt_flags |= NTFS_MF_READONLY;
+#endif
+exit:
+	free(real_file);
+	free(real_fsname);
+	if (err) {
+		errno = err;
+		return -1;
+	}
+	return 0;
+}
+
+#else /* HAVE_MNTENT_H */
+
+#if defined(__sun) && defined (__SVR4)
+
+static int ntfs_mntent_check(const char *file, unsigned long *mnt_flags)
+{
+	struct mnttab *mnt = NULL;
+	char *real_file = NULL, *real_fsname = NULL;
+	FILE *f;
+	int err = 0;
+
+	real_file = (char*)ntfs_malloc(PATH_MAX + 1);
+	if (!real_file)
+		return -1;
+	real_fsname = (char*)ntfs_malloc(PATH_MAX + 1);
+	mnt = (struct mnttab*)ntfs_malloc(MNT_LINE_MAX + 1);
+	if (!real_fsname || !mnt) {
+		err = errno;
+		goto exit;
+	}
+	if (!ntfs_realpath_canonicalize(file, real_file)) {
+		err = errno;
+		goto exit;
+	}
+	if (!(f = fopen(MNTTAB, "r"))) {
+		err = errno;
+		goto exit;
+	}
+	while (!getmntent(f, mnt)) {
+		if (!ntfs_realpath_canonicalize(mnt->mnt_special, real_fsname))
+			continue;
+		if (!strcmp(real_file, real_fsname)) {
+			*mnt_flags = NTFS_MF_MOUNTED;
+			if (!strcmp(mnt->mnt_mountp, "/"))
+				*mnt_flags |= NTFS_MF_ISROOT;
+			if (hasmntopt(mnt, "ro") && !hasmntopt(mnt, "rw"))
+				*mnt_flags |= NTFS_MF_READONLY;
+			break;
+		}
+	}
+	fclose(f);
+exit:
+	free(mnt);
+	free(real_file);
+	free(real_fsname);
+	if (err) {
+		errno = err;
+		return -1;
+	}
+	return 0;
+}
+
+#endif /* defined(__sun) && defined (__SVR4) */
+#endif /* HAVE_MNTENT_H */
+
+/**
+ * ntfs_check_if_mounted - check if an ntfs volume is currently mounted
+ * @file:	device file to check
+ * @mnt_flags:	pointer into which to return the ntfs mount flags (see volume.h)
+ *
+ * If the running system does not support the {set,get,end}mntent() calls,
+ * just return 0 and set *@mnt_flags to zero.
+ *
+ * When the system does support the calls, ntfs_check_if_mounted() first tries
+ * to find the device @file in /etc/mtab (or wherever this is kept on the
+ * running system). If it is not found, assume the device is not mounted and
+ * return 0 and set *@mnt_flags to zero.
+ *
+ * If the device @file is found, set the NTFS_MF_MOUNTED flags in *@mnt_flags.
+ *
+ * Further if @file is mounted as the file system root ("/"), set the flag
+ * NTFS_MF_ISROOT in *@mnt_flags.
+ *
+ * Finally, check if the file system is mounted read-only, and if so set the
+ * NTFS_MF_READONLY flag in *@mnt_flags.
+ *
+ * On success return 0 with *@mnt_flags set to the ntfs mount flags.
+ *
+ * On error return -1 with errno set to the error code.
+ */
+int ntfs_check_if_mounted(const char *file __attribute__((unused)),
+		unsigned long *mnt_flags)
+{
+	*mnt_flags = 0;
+#if defined(HAVE_MNTENT_H) || (defined(__sun) && defined (__SVR4))
+	return ntfs_mntent_check(file, mnt_flags);
+#else
+	return 0;
+#endif
+}
+
+/**
+ * ntfs_version_is_supported - check if NTFS version is supported.
+ * @vol:	ntfs volume whose version we're interested in.
+ *
+ * The function checks if the NTFS volume version is known or not.
+ * Version 1.1 and 1.2 are used by Windows NT3.x and NT4.
+ * Version 2.x is used by Windows 2000 Betas.
+ * Version 3.0 is used by Windows 2000.
+ * Version 3.1 is used by Windows XP, Windows Server 2003 and Longhorn.
+ *
+ * Return 0 if NTFS version is supported otherwise -1 with errno set.
+ *
+ * The following error codes are defined:
+ *	EOPNOTSUPP - Unknown NTFS version
+ *	EINVAL	   - Invalid argument
+ */
+int ntfs_version_is_supported(ntfs_volume *vol)
+{
+	u8 major, minor;
+
+	if (!vol) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	major = vol->major_ver;
+	minor = vol->minor_ver;
+
+	if (NTFS_V1_1(major, minor) || NTFS_V1_2(major, minor))
+		return 0;
+
+	if (NTFS_V2_X(major, minor))
+		return 0;
+
+	if (NTFS_V3_0(major, minor) || NTFS_V3_1(major, minor))
+		return 0;
+
+	errno = EOPNOTSUPP;
+	return -1;
+}
+
+/**
+ * ntfs_logfile_reset - "empty" $LogFile data attribute value
+ * @vol:	ntfs volume whose $LogFile we intend to reset.
+ *
+ * Fill the value of the $LogFile data attribute, i.e. the contents of
+ * the file, with 0xff's, thus marking the journal as empty.
+ *
+ * FIXME(?): We might need to zero the LSN field of every single mft
+ * record as well. (But, first try without doing that and see what
+ * happens, since chkdsk might pickup the pieces and do it for us...)
+ *
+ * On success return 0.
+ *
+ * On error return -1 with errno set to the error code.
+ */
+int ntfs_logfile_reset(ntfs_volume *vol)
+{
+	ntfs_inode *ni;
+	ntfs_attr *na;
+	int eo;
+
+	if (!vol) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	ni = ntfs_inode_open(vol, FILE_LogFile);
+	if (!ni) {
+		ntfs_log_perror("Failed to open inode FILE_LogFile");
+		return -1;
+	}
+
+	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
+	if (!na) {
+		eo = errno;
+		ntfs_log_perror("Failed to open $FILE_LogFile/$DATA");
+		goto error_exit;
+	}
+
+	if (ntfs_empty_logfile(na)) {
+		eo = errno;
+		ntfs_attr_close(na);
+		goto error_exit;
+	}
+	
+	ntfs_attr_close(na);
+	return ntfs_inode_close(ni);
+
+error_exit:
+	ntfs_inode_close(ni);
+	errno = eo;
+	return -1;
+}
+
+/**
+ * ntfs_volume_write_flags - set the flags of an ntfs volume
+ * @vol:	ntfs volume where we set the volume flags
+ * @flags:	new flags
+ *
+ * Set the on-disk volume flags in the mft record of $Volume and
+ * on volume @vol to @flags.
+ *
+ * Return 0 if successful and -1 if not with errno set to the error code.
+ */
+int ntfs_volume_write_flags(ntfs_volume *vol, const le16 flags)
+{
+	ATTR_RECORD *a;
+	VOLUME_INFORMATION *c;
+	ntfs_attr_search_ctx *ctx;
+	int ret = -1;	/* failure */
+
+	if (!vol || !vol->vol_ni) {
+		errno = EINVAL;
+		return -1;
+	}
+	/* Get a pointer to the volume information attribute. */
+	ctx = ntfs_attr_get_search_ctx(vol->vol_ni, NULL);
+	if (!ctx)
+		return -1;
+
+	if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, AT_UNNAMED, 0, 0, 0, NULL,
+			0, ctx)) {
+		ntfs_log_error("Attribute $VOLUME_INFORMATION was not found "
+			       "in $Volume!\n");
+		goto err_out;
+	}
+	a = ctx->attr;
+	/* Sanity check. */
+	if (a->non_resident) {
+		ntfs_log_error("Attribute $VOLUME_INFORMATION must be resident "
+			       "but it isn't.\n");
+		errno = EIO;
+		goto err_out;
+	}
+	/* Get a pointer to the value of the attribute. */
+	c = (VOLUME_INFORMATION*)(le16_to_cpu(a->value_offset) + (char*)a);
+	/* Sanity checks. */
+	if ((char*)c + le32_to_cpu(a->value_length) > (char*)ctx->mrec +
+			le32_to_cpu(ctx->mrec->bytes_in_use) ||
+			le16_to_cpu(a->value_offset) +
+			le32_to_cpu(a->value_length) > le32_to_cpu(a->length)) {
+		ntfs_log_error("Attribute $VOLUME_INFORMATION in $Volume is "
+			       "corrupt!\n");
+		errno = EIO;
+		goto err_out;
+	}
+	/* Set the volume flags. */
+	vol->flags = c->flags = flags & VOLUME_FLAGS_MASK;
+	/* Write them to disk. */
+	ntfs_inode_mark_dirty(vol->vol_ni);
+	if (ntfs_inode_sync(vol->vol_ni))
+		goto err_out;
+
+	ret = 0; /* success */
+err_out:
+	ntfs_attr_put_search_ctx(ctx);
+	return ret;
+}
+
+int ntfs_volume_error(int err)
+{
+	int ret;
+
+	switch (err) {
+		case 0:
+			ret = NTFS_VOLUME_OK;
+			break;
+		case EINVAL:
+			ret = NTFS_VOLUME_NOT_NTFS;
+			break;
+		case EIO:
+			ret = NTFS_VOLUME_CORRUPT;
+			break;
+		case EPERM:
+			/*
+			 * Hibernation and fast restarting are seen the
+			 * same way on a non Windows-system partition.
+			 */
+			ret = NTFS_VOLUME_HIBERNATED;
+			break;
+		case EOPNOTSUPP:
+			ret = NTFS_VOLUME_UNCLEAN_UNMOUNT;
+			break;
+		case EBUSY:
+			ret = NTFS_VOLUME_LOCKED;
+			break;
+		case ENXIO:
+			ret = NTFS_VOLUME_RAID;
+			break;
+		case EACCES:
+			ret = NTFS_VOLUME_NO_PRIVILEGE;
+			break;
+		default:
+			ret = NTFS_VOLUME_UNKNOWN_REASON;
+			break;
+	}
+	return ret;
+}
+
+
+void ntfs_mount_error(const char *volume, const char *mntpoint, int err)
+{
+	switch (err) {
+		case NTFS_VOLUME_NOT_NTFS:
+			ntfs_log_error(invalid_ntfs_msg, volume);
+			break;
+		case NTFS_VOLUME_CORRUPT:
+			ntfs_log_error("%s", corrupt_volume_msg);
+			break;
+		case NTFS_VOLUME_HIBERNATED:
+			ntfs_log_error(hibernated_volume_msg, volume, mntpoint);
+			break;
+		case NTFS_VOLUME_UNCLEAN_UNMOUNT:
+			ntfs_log_error("%s", unclean_journal_msg);
+			break;
+		case NTFS_VOLUME_LOCKED:
+			ntfs_log_error("%s", opened_volume_msg);
+			break;
+		case NTFS_VOLUME_RAID:
+			ntfs_log_error("%s", fakeraid_msg);
+			break;
+		case NTFS_VOLUME_NO_PRIVILEGE:
+			ntfs_log_error(access_denied_msg, volume);
+			break;
+	}
+}
+
+int ntfs_set_locale(void)
+{
+	const char *locale;
+
+	locale = setlocale(LC_ALL, "");
+	if (!locale) {
+		locale = setlocale(LC_ALL, NULL);
+		ntfs_log_error("Couldn't set local environment, using default "
+			       "'%s'.\n", locale);
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ *		Feed the counts of free clusters and free mft records
+ */
+
+int ntfs_volume_get_free_space(ntfs_volume *vol)
+{
+	ntfs_attr *na;
+	int ret;
+
+	ret = -1; /* default return */
+	vol->free_clusters = ntfs_attr_get_free_bits(vol->lcnbmp_na);
+	if (vol->free_clusters < 0) {
+		ntfs_log_perror("Failed to read NTFS $Bitmap");
+	} else {
+		na = vol->mftbmp_na;
+		vol->free_mft_records = ntfs_attr_get_free_bits(na);
+
+		if (vol->free_mft_records >= 0)
+			vol->free_mft_records += (na->allocated_size - na->data_size) << 3;
+
+		if (vol->free_mft_records < 0)
+			ntfs_log_perror("Failed to calculate free MFT records");
+		else
+			ret = 0;
+	}
+	return (ret);
+}
+
+/**
+ * ntfs_volume_rename - change the current label on a volume
+ * @vol:	volume to change the label on
+ * @label:	the new label
+ * @label_len:	the length of @label in ntfschars including the terminating NULL
+ *		character, which is mandatory (the value can not exceed 128)
+ *
+ * Change the label on the volume @vol to @label.
+ */
+int ntfs_volume_rename(ntfs_volume *vol, const ntfschar *label, int label_len)
+{
+	ntfs_attr *na;
+	char *old_vol_name;
+	char *new_vol_name = NULL;
+	int new_vol_name_len;
+	int err;
+
+	if (NVolReadOnly(vol)) {
+		ntfs_log_error("Refusing to change label on read-only mounted "
+			"volume.\n");
+		errno = EROFS;
+		return -1;
+	}
+
+	label_len *= sizeof(ntfschar);
+	if (label_len > 0x100) {
+		ntfs_log_error("New label is too long. Maximum %u characters "
+				"allowed.\n",
+				(unsigned)(0x100 / sizeof(ntfschar)));
+		errno = ERANGE;
+		return -1;
+	}
+
+	na = ntfs_attr_open(vol->vol_ni, AT_VOLUME_NAME, AT_UNNAMED, 0);
+	if (!na) {
+		if (errno != ENOENT) {
+			err = errno;
+			ntfs_log_perror("Lookup of $VOLUME_NAME attribute "
+				"failed");
+			goto err_out;
+		}
+
+		/* The volume name attribute does not exist.  Need to add it. */
+		if (ntfs_attr_add(vol->vol_ni, AT_VOLUME_NAME, AT_UNNAMED, 0,
+			(const u8*) label, label_len))
+		{
+			err = errno;
+			ntfs_log_perror("Encountered error while adding "
+				"$VOLUME_NAME attribute");
+			goto err_out;
+		}
+	}
+	else {
+		s64 written;
+
+		if (NAttrNonResident(na)) {
+			err = errno;
+			ntfs_log_error("Error: Attribute $VOLUME_NAME must be "
+					"resident.\n");
+			goto err_out;
+		}
+
+		if (na->data_size != label_len) {
+			if (ntfs_attr_truncate(na, label_len)) {
+				err = errno;
+				ntfs_log_perror("Error resizing resident "
+					"attribute");
+				goto err_out;
+			}
+		}
+
+		if (label_len) {
+			written = ntfs_attr_pwrite(na, 0, label_len, label);
+			if (written == -1) {
+				err = errno;
+				ntfs_log_perror("Error when writing "
+					"$VOLUME_NAME data");
+				goto err_out;
+			}
+			else if (written != label_len) {
+				err = EIO;
+				ntfs_log_error("Partial write when writing "
+					"$VOLUME_NAME data.");
+				goto err_out;
+
+			}
+		}
+	}
+
+	new_vol_name_len =
+		ntfs_ucstombs(label, label_len, &new_vol_name, 0);
+	if (new_vol_name_len == -1) {
+		err = errno;
+		ntfs_log_perror("Error while decoding new volume name");
+		goto err_out;
+	}
+
+	old_vol_name = vol->vol_name;
+	vol->vol_name = new_vol_name;
+	free(old_vol_name);
+
+	err = 0;
+err_out:
+	if (na)
+		ntfs_attr_close(na);
+	if (err)
+		errno = err;
+	return err ? -1 : 0;
+}
diff --git a/libntfs-3g/win32_io.c b/libntfs-3g/win32_io.c
new file mode 100755
index 0000000000000000000000000000000000000000..9c84ec677502d2a6c529039f44f53311cc92fd8b
--- /dev/null
+++ b/libntfs-3g/win32_io.c
@@ -0,0 +1,2033 @@
+/*
+ * win32_io.c - A stdio-like disk I/O implementation for low-level disk access
+ *		on Win32.  Can access an NTFS volume while it is mounted.
+ *		Originated from the Linux-NTFS project.
+ *
+ * Copyright (c) 2003-2004 Lode Leroy
+ * Copyright (c) 2003-2006 Anton Altaparmakov
+ * Copyright (c) 2004-2005 Yuval Fledel
+ * Copyright (c) 2012-2014 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
+ */
+
+#include "config.h"
+
+#ifdef HAVE_WINDOWS_H
+#define BOOL WINBOOL /* avoid conflicting definitions of BOOL */
+#include <windows.h>
+#undef BOOL
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+/*
+ *		Definitions needed for <winioctl.h>
+ */
+#ifndef _ANONYMOUS_UNION
+#define _ANONYMOUS_UNION
+#define _ANONYMOUS_STRUCT
+typedef unsigned long long DWORD64;
+#endif
+
+typedef struct {
+        DWORD data1;     /* The first eight hexadecimal digits of the GUID. */
+        WORD data2;     /* The first group of four hexadecimal digits. */
+        WORD data3;     /* The second group of four hexadecimal digits. */ 
+        char data4[8];    /* The first two bytes are the third group of four
+                           hexadecimal digits. The remaining six bytes are the
+                           final 12 hexadecimal digits. */
+} GUID;
+
+#include <winioctl.h>
+
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#define stat stat64
+#define st_blocks  st_rdev /* emulate st_blocks, missing in Windows */
+#endif
+
+/* Prevent volume.h from being be loaded, as it conflicts with winnt.h. */
+#define _NTFS_VOLUME_H
+struct ntfs_volume;
+typedef struct ntfs_volume ntfs_volume;
+
+#include "debug.h"
+#include "types.h"
+#include "device.h"
+#include "misc.h"
+
+#define cpu_to_le16(x) (x)
+#define const_cpu_to_le16(x) (x)
+
+#ifndef MAX_PATH
+#define MAX_PATH 1024
+#endif
+
+#ifndef NTFS_BLOCK_SIZE
+#define NTFS_BLOCK_SIZE		512
+#define NTFS_BLOCK_SIZE_BITS	9
+#endif
+
+#ifndef INVALID_SET_FILE_POINTER
+#define INVALID_SET_FILE_POINTER ((DWORD)-1)
+#endif
+
+#ifndef IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
+#define IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS 5636096
+#endif
+
+#ifndef IOCTL_DISK_GET_DRIVE_GEOMETRY
+#define IOCTL_DISK_GET_DRIVE_GEOMETRY 0x70000
+#endif
+
+#ifndef IOCTL_GET_DISK_LENGTH_INFO
+#define IOCTL_GET_DISK_LENGTH_INFO 0x7405c
+#endif
+
+#ifndef FSCTL_ALLOW_EXTENDED_DASD_IO
+#define FSCTL_ALLOW_EXTENDED_DASD_IO 0x90083
+#endif
+
+/* Windows 2k+ imports. */
+typedef HANDLE (WINAPI *LPFN_FINDFIRSTVOLUME)(LPTSTR, DWORD);
+typedef BOOL (WINAPI *LPFN_FINDNEXTVOLUME)(HANDLE, LPTSTR, DWORD);
+typedef BOOL (WINAPI *LPFN_FINDVOLUMECLOSE)(HANDLE);
+typedef BOOL (WINAPI *LPFN_SETFILEPOINTEREX)(HANDLE, LARGE_INTEGER,
+		PLARGE_INTEGER, DWORD);
+
+static LPFN_FINDFIRSTVOLUME fnFindFirstVolume = NULL;
+static LPFN_FINDNEXTVOLUME fnFindNextVolume = NULL;
+static LPFN_FINDVOLUMECLOSE fnFindVolumeClose = NULL;
+static LPFN_SETFILEPOINTEREX fnSetFilePointerEx = NULL;
+
+#ifdef UNICODE
+#define FNPOSTFIX "W"
+#else
+#define FNPOSTFIX "A"
+#endif
+
+enum { /* see http://msdn.microsoft.com/en-us/library/cc704588(v=prot.10).aspx */
+   STATUS_UNKNOWN = -1,
+   STATUS_SUCCESS =              0x00000000,
+   STATUS_BUFFER_OVERFLOW =      0x80000005,
+   STATUS_INVALID_HANDLE =       0xC0000008,
+   STATUS_INVALID_PARAMETER =    0xC000000D,
+   STATUS_INVALID_DEVICE_REQUEST = 0xC0000010,
+   STATUS_END_OF_FILE =          0xC0000011,
+   STATUS_CONFLICTING_ADDRESSES = 0xC0000018,
+   STATUS_NO_MATCH =             0xC000001E,
+   STATUS_ACCESS_DENIED =        0xC0000022,
+   STATUS_BUFFER_TOO_SMALL =     0xC0000023,
+   STATUS_OBJECT_TYPE_MISMATCH = 0xC0000024,
+   STATUS_FILE_NOT_FOUND =       0xC0000028,
+   STATUS_OBJECT_NAME_INVALID =  0xC0000033,
+   STATUS_OBJECT_NAME_NOT_FOUND = 0xC0000034,
+   STATUS_INVALID_PARAMETER_1 =  0xC00000EF,
+   STATUS_IO_DEVICE_ERROR =      0xC0000185,
+   STATUS_GUARD_PAGE_VIOLATION = 0x80000001
+ } ;
+
+typedef u32 NTSTATUS; /* do not let the compiler choose the size */
+#ifdef __x86_64__
+typedef unsigned long long ULONG_PTR; /* an integer the same size as a pointer */
+#else
+typedef unsigned long ULONG_PTR; /* an integer the same size as a pointer */
+#endif
+
+HANDLE get_osfhandle(int); /* from msvcrt.dll */
+
+/*
+ *		A few needed definitions not included in <windows.h>
+ */
+
+typedef struct _IO_STATUS_BLOCK {
+	union {
+		NTSTATUS Status;
+		PVOID    Pointer;
+	};
+  	ULONG_PTR Information;
+} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
+
+typedef struct _UNICODE_STRING {
+	USHORT Length;
+	USHORT MaximumLength;
+#ifdef __x86_64__
+	u32    padding;
+#endif
+	PWSTR  Buffer;
+} UNICODE_STRING, *PUNICODE_STRING;
+
+typedef struct _OBJECT_ATTRIBUTES {
+	ULONG           Length;
+#ifdef __x86_64__
+	u32		padding1;
+	HANDLE          RootDirectory;
+	PUNICODE_STRING ObjectName;
+	ULONG           Attributes;
+	u32		padding2;
+#else
+	HANDLE          RootDirectory;
+	PUNICODE_STRING ObjectName;
+	ULONG           Attributes;
+#endif
+	PVOID           SecurityDescriptor;
+	PVOID           SecurityQualityOfService;
+}  OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
+
+#define FILE_OPEN 1
+#define FILE_CREATE 2
+#define FILE_OVERWRITE 4
+#define FILE_SYNCHRONOUS_IO_ALERT    0x10
+#define FILE_SYNCHRONOUS_IO_NONALERT 0x20
+#define OBJ_CASE_INSENSITIVE 0x40
+
+typedef void (WINAPI *PIO_APC_ROUTINE)(void*, PIO_STATUS_BLOCK, ULONG);
+
+extern WINAPI NTSTATUS NtOpenFile(
+	PHANDLE FileHandle,
+	ACCESS_MASK DesiredAccess,
+	POBJECT_ATTRIBUTES ObjectAttributes,
+	PIO_STATUS_BLOCK IoStatusBlock,
+	ULONG ShareAccess,
+	ULONG OpenOptions
+);
+
+extern WINAPI NTSTATUS NtReadFile(
+	HANDLE FileHandle,
+	HANDLE Event,
+	PIO_APC_ROUTINE ApcRoutine,
+	PVOID ApcContext,
+	PIO_STATUS_BLOCK IoStatusBlock,
+	PVOID Buffer,
+	ULONG Length,
+	PLARGE_INTEGER ByteOffset,
+	PULONG Key
+);
+
+extern WINAPI NTSTATUS NtWriteFile(
+	HANDLE FileHandle,
+	HANDLE Event,
+	PIO_APC_ROUTINE ApcRoutine,
+	PVOID ApcContext,
+	PIO_STATUS_BLOCK IoStatusBlock,
+	LPCVOID Buffer,
+	ULONG Length,
+	PLARGE_INTEGER ByteOffset,
+	PULONG Key
+);
+
+extern NTSTATUS WINAPI NtClose(
+	HANDLE Handle
+);
+
+extern NTSTATUS WINAPI NtDeviceIoControlFile(
+	HANDLE FileHandle,
+	HANDLE Event,
+	PIO_APC_ROUTINE ApcRoutine,
+	PVOID ApcContext,
+	PIO_STATUS_BLOCK IoStatusBlock,
+	ULONG IoControlCode,
+	PVOID InputBuffer,
+	ULONG InputBufferLength,
+	PVOID OutputBuffer,
+	ULONG OutputBufferLength
+);
+
+extern NTSTATUS	WINAPI NtFsControlFile(
+	HANDLE FileHandle,
+	HANDLE Event,
+	PIO_APC_ROUTINE ApcRoutine,
+	PVOID ApcContext,
+	PIO_STATUS_BLOCK IoStatusBlock,
+	ULONG FsControlCode,
+	PVOID InputBuffer,
+	ULONG InputBufferLength,
+	PVOID OutputBuffer,
+	ULONG OutputBufferLength
+);
+
+/**
+ * struct win32_fd -
+ */
+typedef struct {
+	HANDLE handle;
+	s64 pos;		/* Logical current position on the volume. */
+	s64 part_start;
+	s64 part_length;
+	int part_hidden_sectors;
+	s64 geo_size, geo_cylinders;
+	s32 geo_sector_size;
+	s64 volume_size;
+	DWORD geo_sectors, geo_heads;
+	HANDLE vol_handle;
+	BOOL ntdll;
+} win32_fd;
+
+/**
+ * ntfs_w32error_to_errno - convert a win32 error code to the unix one
+ * @w32error:	the win32 error code
+ *
+ * Limited to a relatively small but useful number of codes.
+ */
+static int ntfs_w32error_to_errno(unsigned int w32error)
+{
+	ntfs_log_trace("Converting w32error 0x%x.\n",w32error);
+	switch (w32error) {
+		case ERROR_INVALID_FUNCTION:
+			return EBADRQC;
+		case ERROR_FILE_NOT_FOUND:
+		case ERROR_PATH_NOT_FOUND:
+		case ERROR_INVALID_NAME:
+			return ENOENT;
+		case ERROR_TOO_MANY_OPEN_FILES:
+			return EMFILE;
+		case ERROR_ACCESS_DENIED:
+			return EACCES;
+		case ERROR_INVALID_HANDLE:
+			return EBADF;
+		case ERROR_NOT_ENOUGH_MEMORY:
+			return ENOMEM;
+		case ERROR_OUTOFMEMORY:
+			return ENOSPC;
+		case ERROR_INVALID_DRIVE:
+		case ERROR_BAD_UNIT:
+			return ENODEV;
+		case ERROR_WRITE_PROTECT:
+			return EROFS;
+		case ERROR_NOT_READY:
+		case ERROR_SHARING_VIOLATION:
+			return EBUSY;
+		case ERROR_BAD_COMMAND:
+			return EINVAL;
+		case ERROR_SEEK:
+		case ERROR_NEGATIVE_SEEK:
+			return ESPIPE;
+		case ERROR_NOT_SUPPORTED:
+			return EOPNOTSUPP;
+		case ERROR_BAD_NETPATH:
+			return ENOSHARE;
+		default:
+			/* generic message */
+			return ENOMSG;
+	}
+}
+
+static int ntfs_ntstatus_to_errno(NTSTATUS status)
+{
+	ntfs_log_trace("Converting w32error 0x%x.\n",w32error);
+	switch (status) {
+		case STATUS_INVALID_HANDLE :
+		case STATUS_INVALID_PARAMETER :
+		case STATUS_OBJECT_NAME_INVALID :
+		case STATUS_INVALID_DEVICE_REQUEST :
+			return (EINVAL);
+		case STATUS_ACCESS_DENIED :
+			return (EACCES);
+		case STATUS_IO_DEVICE_ERROR :
+		case STATUS_END_OF_FILE :
+			return (EIO);
+		default:
+			/* generic message */
+			return ENOMSG;
+	}
+}
+
+/**
+ * libntfs_SetFilePointerEx - emulation for SetFilePointerEx()
+ *
+ * We use this to emulate SetFilePointerEx() when it is not present.  This can
+ * happen since SetFilePointerEx() only exists in Win2k+.
+ */
+static BOOL WINAPI libntfs_SetFilePointerEx(HANDLE hFile,
+		LARGE_INTEGER liDistanceToMove,
+		PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod)
+{
+	liDistanceToMove.u.LowPart = SetFilePointer(hFile,
+			liDistanceToMove.u.LowPart,
+			&liDistanceToMove.u.HighPart, dwMoveMethod);
+	SetLastError(NO_ERROR);
+	if (liDistanceToMove.u.LowPart == INVALID_SET_FILE_POINTER &&
+			GetLastError() != NO_ERROR) {
+		if (lpNewFilePointer)
+			lpNewFilePointer->QuadPart = -1;
+		return FALSE;
+	}
+	if (lpNewFilePointer)
+		lpNewFilePointer->QuadPart = liDistanceToMove.QuadPart;
+	return TRUE;
+}
+
+/**
+ * ntfs_device_win32_init_imports - initialize the function pointers
+ *
+ * The Find*Volume and SetFilePointerEx functions exist only on win2k+, as such
+ * we cannot just staticly import them.
+ *
+ * This function initializes the imports if the functions do exist and in the
+ * SetFilePointerEx case, we emulate the function ourselves if it is not
+ * present.
+ *
+ * Note: The values are cached, do be afraid to run it more than once.
+ */
+static void ntfs_device_win32_init_imports(void)
+{
+	HMODULE kernel32 = GetModuleHandle("kernel32");
+	if (!kernel32) {
+		errno = ntfs_w32error_to_errno(GetLastError());
+		ntfs_log_trace("kernel32.dll could not be imported.\n");
+	}
+	if (!fnSetFilePointerEx) {
+		if (kernel32)
+			fnSetFilePointerEx = (LPFN_SETFILEPOINTEREX)
+					GetProcAddress(kernel32,
+					"SetFilePointerEx");
+		/*
+		 * If we did not get kernel32.dll or it is not Win2k+, emulate
+		 * SetFilePointerEx().
+		 */
+		if (!fnSetFilePointerEx) {
+			ntfs_log_debug("SetFilePointerEx() not found in "
+					"kernel32.dll: Enabling emulation.\n");
+			fnSetFilePointerEx = libntfs_SetFilePointerEx;
+		}
+	}
+	/* Cannot do lookups if we could not get kernel32.dll... */
+	if (!kernel32)
+		return;
+	if (!fnFindFirstVolume)
+		fnFindFirstVolume = (LPFN_FINDFIRSTVOLUME)
+				GetProcAddress(kernel32, "FindFirstVolume"
+				FNPOSTFIX);
+	if (!fnFindNextVolume)
+		fnFindNextVolume = (LPFN_FINDNEXTVOLUME)
+				GetProcAddress(kernel32, "FindNextVolume"
+				FNPOSTFIX);
+	if (!fnFindVolumeClose)
+		fnFindVolumeClose = (LPFN_FINDVOLUMECLOSE)
+				GetProcAddress(kernel32, "FindVolumeClose");
+}
+
+/**
+ * ntfs_device_unix_status_flags_to_win32 - convert unix->win32 open flags
+ * @flags:	unix open status flags
+ *
+ * Supported flags are O_RDONLY, O_WRONLY and O_RDWR.
+ */
+static __inline__ int ntfs_device_unix_status_flags_to_win32(int flags)
+{
+	int win_mode;
+
+	switch (flags & O_ACCMODE) {
+	case O_RDONLY:
+		win_mode = GENERIC_READ;
+		break;
+	case O_WRONLY:
+		win_mode = GENERIC_WRITE;
+		break;
+	case O_RDWR:
+		win_mode = GENERIC_READ | GENERIC_WRITE;
+		break;
+	default:
+		/* error */
+		ntfs_log_trace("Unknown status flags.\n");
+		win_mode = 0;
+	}
+	return win_mode;
+}
+
+
+/**
+ * ntfs_device_win32_simple_open_file - just open a file via win32 API
+ * @filename:	name of the file to open
+ * @handle:	pointer the a HANDLE in which to put the result
+ * @flags:	unix open status flags
+ * @locking:	will the function gain an exclusive lock on the file?
+ *
+ * Supported flags are O_RDONLY, O_WRONLY and O_RDWR.
+ *
+ * Return 0 if o.k.
+ *	 -1 if not, and errno set.  In this case handle is trashed.
+ */
+static int ntfs_device_win32_simple_open_file(const char *filename,
+		HANDLE *handle, int flags, BOOL locking)
+{
+	*handle = CreateFile(filename,
+			ntfs_device_unix_status_flags_to_win32(flags),
+			locking ? 0 : (FILE_SHARE_WRITE | FILE_SHARE_READ),
+			NULL, (flags & O_CREAT ? OPEN_ALWAYS : OPEN_EXISTING),
+			0, NULL);
+	if (*handle == INVALID_HANDLE_VALUE) {
+		errno = ntfs_w32error_to_errno(GetLastError());
+		ntfs_log_trace("CreateFile(%s) failed.\n", filename);
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * ntfs_device_win32_lock - lock the volume
+ * @handle:	a win32 HANDLE for a volume to lock
+ *
+ * Locking a volume means no one can access its contents.
+ * Exiting the process automatically unlocks the volume, except in old NT4s.
+ *
+ * Return 0 if o.k.
+ *	 -1 if not, and errno set.
+ */
+static int ntfs_device_win32_lock(HANDLE handle)
+{
+	DWORD i;
+
+	if (!DeviceIoControl(handle, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &i,
+			NULL)) {
+		errno = ntfs_w32error_to_errno(GetLastError());
+		ntfs_log_trace("Couldn't lock volume.\n");
+		return -1;
+	}
+	ntfs_log_debug("Volume locked.\n");
+	return 0;
+}
+
+/**
+ * ntfs_device_win32_unlock - unlock the volume
+ * @handle:	the win32 HANDLE which the volume was locked with
+ *
+ * Return 0 if o.k.
+ *	 -1 if not, and errno set.
+ */
+static int ntfs_device_win32_unlock(HANDLE handle)
+{
+	DWORD i;
+
+	if (!DeviceIoControl(handle, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &i,
+			NULL)) {
+		errno = ntfs_w32error_to_errno(GetLastError());
+		ntfs_log_trace("Couldn't unlock volume.\n");
+		return -1;
+	}
+	ntfs_log_debug("Volume unlocked.\n");
+	return 0;
+}
+
+static int ntfs_device_win32_setlock(HANDLE handle, ULONG code)
+{
+	IO_STATUS_BLOCK io_status;
+	NTSTATUS res;
+
+	io_status.Status = STATUS_SUCCESS;
+	io_status.Information = 0;
+	res = NtFsControlFile(handle,(HANDLE)NULL,
+				(PIO_APC_ROUTINE)NULL,(void*)NULL,
+				&io_status, code,
+				(char*)NULL,0,(char*)NULL,0);
+	if (res != STATUS_SUCCESS)
+		errno = ntfs_ntstatus_to_errno(res);
+	return (res == STATUS_SUCCESS ? 0 : -1);
+}
+
+/**
+ * ntfs_device_win32_dismount - dismount a volume
+ * @handle:	a win32 HANDLE for a volume to dismount
+ *
+ * Dismounting means the system will refresh the volume in the first change it
+ * gets.  Usefull after altering the file structures.
+ * The volume must be locked by the current process while dismounting.
+ * A side effect is that the volume is also unlocked, but you must not rely om
+ * this.
+ *
+ * Return 0 if o.k.
+ *	 -1 if not, and errno set.
+ */
+static int ntfs_device_win32_dismount(HANDLE handle)
+{
+	DWORD i;
+
+	if (!DeviceIoControl(handle, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0,
+			&i, NULL)) {
+		errno = ntfs_w32error_to_errno(GetLastError());
+		ntfs_log_trace("Couldn't dismount volume.\n");
+		return -1;
+	}
+	ntfs_log_debug("Volume dismounted.\n");
+	return 0;
+}
+
+/**
+ * ntfs_device_win32_getsize - get file size via win32 API
+ * @handle:	pointer the file HANDLE obtained via open
+ *
+ * Only works on ordinary files.
+ *
+ * Return The file size if o.k.
+ *	 -1 if not, and errno set.
+ */
+static s64 ntfs_device_win32_getsize(HANDLE handle)
+{
+	LONG loword, hiword;
+
+	SetLastError(NO_ERROR);
+	hiword = 0;
+	loword = SetFilePointer(handle, 0, &hiword, 2);
+	if ((loword == INVALID_SET_FILE_POINTER)
+	    && (GetLastError() != NO_ERROR)) {
+		errno = ntfs_w32error_to_errno(GetLastError());
+		ntfs_log_trace("Couldn't get file size.\n");
+		return -1;
+	}
+	return ((s64)hiword << 32) + (ULONG)loword;
+}
+
+/**
+ * ntfs_device_win32_getdisklength - get disk size via win32 API
+ * @handle:	pointer the file HANDLE obtained via open
+ * @argp:	pointer to result buffer
+ *
+ * Only works on PhysicalDriveX type handles.
+ *
+ * Return The disk size if o.k.
+ *	 -1 if not, and errno set.
+ */
+static s64 ntfs_device_win32_getdisklength(HANDLE handle)
+{
+	GET_LENGTH_INFORMATION buf;
+	DWORD i;
+
+	if (!DeviceIoControl(handle, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &buf,
+			sizeof(buf), &i, NULL)) {
+		errno = ntfs_w32error_to_errno(GetLastError());
+		ntfs_log_trace("Couldn't get disk length.\n");
+		return -1;
+	}
+	ntfs_log_debug("Disk length: %lld.\n", buf.Length.QuadPart);
+	return buf.Length.QuadPart;
+}
+
+/**
+ * ntfs_device_win32_getntfssize - get NTFS volume size via win32 API
+ * @handle:	pointer the file HANDLE obtained via open
+ * @argp:	pointer to result buffer
+ *
+ * Only works on NTFS volume handles.
+ * An annoying bug in windows is that an NTFS volume does not occupy the entire
+ * partition, namely not the last sector (which holds the backup boot sector,
+ * and normally not interesting).
+ * Use this function to get the length of the accessible space through a given
+ * volume handle.
+ *
+ * Return The volume size if o.k.
+ *	 -1 if not, and errno set.
+ */
+static s64 ntfs_device_win32_getntfssize(HANDLE handle)
+{
+	s64 rvl;
+#ifdef FSCTL_GET_NTFS_VOLUME_DATA
+	DWORD i;
+	NTFS_VOLUME_DATA_BUFFER buf;
+
+	if (!DeviceIoControl(handle, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, &buf,
+			sizeof(buf), &i, NULL)) {
+		errno = ntfs_w32error_to_errno(GetLastError());
+		ntfs_log_trace("Couldn't get NTFS volume length.\n");
+		return -1;
+	}
+	rvl = buf.NumberSectors.QuadPart * buf.BytesPerSector;
+	ntfs_log_debug("NTFS volume length: 0x%llx.\n", (long long)rvl);
+#else
+	errno = EINVAL;
+	rvl = -1;
+#endif
+	return rvl;
+}
+
+/**
+ * ntfs_device_win32_getgeo - get CHS information of a drive
+ * @handle:	an open handle to the PhysicalDevice
+ * @fd:		a win_fd structure that will be filled
+ *
+ * Return 0 if o.k.
+ *	 -1 if not, and errno  set.
+ *
+ * In Windows NT+: fills size, sectors, and cylinders and sets heads to -1.
+ * In Windows XP+: fills size, sectors, cylinders, and heads.
+ *
+ * Note: In pre XP, this requires write permission, even though nothing is
+ * actually written.
+ *
+ * If fails, sets sectors, cylinders, heads, and size to -1.
+ */
+static int ntfs_device_win32_getgeo(HANDLE handle, win32_fd *fd)
+{
+	DWORD i;
+	BOOL rvl;
+	BYTE b[sizeof(DISK_GEOMETRY) + sizeof(DISK_PARTITION_INFO) +
+			sizeof(DISK_DETECTION_INFO) + 512];
+
+	rvl = DeviceIoControl(handle, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL,
+			0, &b, sizeof(b), &i, NULL);
+	if (rvl) {
+		ntfs_log_debug("GET_DRIVE_GEOMETRY_EX detected.\n");
+		DISK_DETECTION_INFO *ddi = (PDISK_DETECTION_INFO)
+				(((PBYTE)(&((PDISK_GEOMETRY_EX)b)->Data)) +
+				(((PDISK_PARTITION_INFO)
+				(&((PDISK_GEOMETRY_EX)b)->Data))->
+				SizeOfPartitionInfo));
+		fd->geo_cylinders = ((DISK_GEOMETRY*)&b)->Cylinders.QuadPart;
+		fd->geo_sectors = ((DISK_GEOMETRY*)&b)->SectorsPerTrack;
+		fd->geo_size = ((DISK_GEOMETRY_EX*)&b)->DiskSize.QuadPart;
+		fd->geo_sector_size = NTFS_BLOCK_SIZE;
+		switch (ddi->DetectionType) {
+		case DetectInt13:
+			fd->geo_cylinders = ddi->Int13.MaxCylinders;
+			fd->geo_sectors = ddi->Int13.SectorsPerTrack;
+			fd->geo_heads = ddi->Int13.MaxHeads;
+			return 0;
+		case DetectExInt13:
+			fd->geo_cylinders = ddi->ExInt13.ExCylinders;
+			fd->geo_sectors = ddi->ExInt13.ExSectorsPerTrack;
+			fd->geo_heads = ddi->ExInt13.ExHeads;
+			return 0;
+		case DetectNone:
+		default:
+			break;
+		}
+	} else
+		fd->geo_heads = -1;
+	rvl = DeviceIoControl(handle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,
+			&b, sizeof(b), &i, NULL);
+	if (rvl) {
+		ntfs_log_debug("GET_DRIVE_GEOMETRY detected.\n");
+		fd->geo_cylinders = ((DISK_GEOMETRY*)&b)->Cylinders.QuadPart;
+		fd->geo_sectors = ((DISK_GEOMETRY*)&b)->SectorsPerTrack;
+		fd->geo_size = fd->geo_cylinders * fd->geo_sectors *
+				((DISK_GEOMETRY*)&b)->TracksPerCylinder *
+				((DISK_GEOMETRY*)&b)->BytesPerSector;
+		fd->geo_sector_size = ((DISK_GEOMETRY*)&b)->BytesPerSector;
+		return 0;
+	}
+	errno = ntfs_w32error_to_errno(GetLastError());
+	ntfs_log_trace("Couldn't retrieve disk geometry.\n");
+	fd->geo_cylinders = -1;
+	fd->geo_sectors = -1;
+	fd->geo_size = -1;
+	fd->geo_sector_size = NTFS_BLOCK_SIZE;
+	return -1;
+}
+
+static int ntfs_device_win32_getntgeo(HANDLE handle, win32_fd *fd)
+{
+	DISK_GEOMETRY geo;
+	NTSTATUS st;
+	IO_STATUS_BLOCK status;
+	u64 bytes;
+	int res;
+
+	res = -1;
+	fd->geo_cylinders = 0;
+	fd->geo_sectors = 0;
+	fd->geo_size = 1073741824;
+	fd->geo_sectors = fd->geo_size >> 9;
+	fd->geo_sector_size = NTFS_BLOCK_SIZE;
+
+	st = NtDeviceIoControlFile(handle, (HANDLE)NULL,
+			(PIO_APC_ROUTINE)NULL, (void*)NULL,
+			&status, IOCTL_DISK_GET_DRIVE_GEOMETRY, (void*)NULL, 0,
+			(void*)&geo, sizeof(geo));
+	if (st == STATUS_SUCCESS) {
+		/* over-estimate the (rounded) number of cylinders */
+		fd->geo_cylinders = geo.Cylinders.QuadPart + 1;
+		fd->geo_sectors = fd->geo_cylinders
+				*geo.TracksPerCylinder*geo.SectorsPerTrack;
+		fd->geo_size = fd->geo_sectors*geo.BytesPerSector;
+		fd->geo_sector_size = geo.BytesPerSector;
+		res = 0;
+			/* try to get the exact sector count */
+		st = NtDeviceIoControlFile(handle, (HANDLE)NULL,
+				(PIO_APC_ROUTINE)NULL, (void*)NULL,
+				&status, IOCTL_GET_DISK_LENGTH_INFO,
+				(void*)NULL, 0,
+				(void*)&bytes, sizeof(bytes));
+		if (st == STATUS_SUCCESS) {
+			fd->geo_size = bytes;
+			fd->geo_sectors = bytes/geo.BytesPerSector;
+		}
+	}
+	return (res);
+}
+
+/**
+ * ntfs_device_win32_open_file - open a file via win32 API
+ * @filename:	name of the file to open
+ * @fd:		pointer to win32 file device in which to put the result
+ * @flags:	unix open status flags
+ *
+ * Return 0 if o.k.
+ *	 -1 if not, and errno set.
+ */
+static __inline__ int ntfs_device_win32_open_file(char *filename, win32_fd *fd,
+		int flags)
+{
+	HANDLE handle;
+	int mode;
+
+	if (ntfs_device_win32_simple_open_file(filename, &handle, flags,
+			FALSE)) {
+		/* open error */
+		return -1;
+	}
+	mode = flags & O_ACCMODE;
+	if ((mode == O_RDWR) || (mode == O_WRONLY)) {
+		DWORD bytes;
+
+		/* try making sparse (but ignore errors) */
+		DeviceIoControl(handle, FSCTL_SET_SPARSE,
+				(void*)NULL, 0, (void*)NULL, 0,
+				&bytes, (LPOVERLAPPED)NULL);
+	}
+	/* fill fd */
+	fd->handle = handle;
+	fd->part_start = 0;
+	fd->part_length = ntfs_device_win32_getsize(handle);
+	fd->pos = 0;
+	fd->part_hidden_sectors = -1;
+	fd->geo_size = -1;	/* used as a marker that this is a file */
+	fd->vol_handle = INVALID_HANDLE_VALUE;
+	fd->geo_sector_size = 512;  /* will be adjusted from the boot sector */
+	fd->ntdll = FALSE;
+	return 0;
+}
+
+/**
+ * ntfs_device_win32_open_drive - open a drive via win32 API
+ * @drive_id:	drive to open
+ * @fd:		pointer to win32 file device in which to put the result
+ * @flags:	unix open status flags
+ *
+ * return 0 if o.k.
+ *        -1 if not, and errno set.
+ */
+static __inline__ int ntfs_device_win32_open_drive(int drive_id, win32_fd *fd,
+		int flags)
+{
+	HANDLE handle;
+	int err;
+	char filename[MAX_PATH];
+
+	sprintf(filename, "\\\\.\\PhysicalDrive%d", drive_id);
+	if ((err = ntfs_device_win32_simple_open_file(filename, &handle, flags,
+			TRUE))) {
+		/* open error */
+		return err;
+	}
+	/* store the drive geometry */
+	ntfs_device_win32_getgeo(handle, fd);
+	/* Just to be sure */
+	if (fd->geo_size == -1)
+		fd->geo_size = ntfs_device_win32_getdisklength(handle);
+	/* fill fd */
+	fd->ntdll = FALSE;
+	fd->handle = handle;
+	fd->part_start = 0;
+	fd->part_length = fd->geo_size;
+	fd->pos = 0;
+	fd->part_hidden_sectors = -1;
+	fd->vol_handle = INVALID_HANDLE_VALUE;
+	return 0;
+}
+
+/**
+ * ntfs_device_win32_open_lowlevel - open a drive via low level win32 API
+ * @drive_id:	drive to open
+ * @fd:		pointer to win32 file device in which to put the result
+ * @flags:	unix open status flags
+ *
+ * return 0 if o.k.
+ *        -1 if not, and errno set.
+ */
+static __inline__ int ntfs_device_win32_open_lowlevel(int drive_id,
+		win32_fd *fd, int flags)
+{
+	HANDLE handle;
+	NTSTATUS st;
+	ACCESS_MASK access;
+	ULONG share;
+	OBJECT_ATTRIBUTES attr;
+	IO_STATUS_BLOCK io_status;
+	UNICODE_STRING unicode_name;
+	ntfschar unicode_buffer[7];
+	int mode;
+	static const ntfschar unicode_init[] = {
+		const_cpu_to_le16('\\'), const_cpu_to_le16('?'),
+		const_cpu_to_le16('?'), const_cpu_to_le16('\\'),
+		const_cpu_to_le16(' '), const_cpu_to_le16(':'),
+		const_cpu_to_le16(0)
+	};
+
+	memcpy(unicode_buffer, unicode_init, sizeof(unicode_buffer));
+	unicode_buffer[4] = cpu_to_le16(drive_id + 'A');
+	unicode_name.Buffer = unicode_buffer;
+	unicode_name.Length = 6*sizeof(ntfschar);
+	unicode_name.MaximumLength = 6*sizeof(ntfschar);
+
+	attr.Length = sizeof(OBJECT_ATTRIBUTES);
+	attr.RootDirectory = (HANDLE*)NULL;
+	attr.ObjectName = &unicode_name;
+	attr.Attributes = OBJ_CASE_INSENSITIVE;
+	attr.SecurityDescriptor = (void*)NULL;
+	attr.SecurityQualityOfService = (void*)NULL;
+
+	io_status.Status = 0;
+	io_status.Information = 0;
+	mode = flags & O_ACCMODE;
+	share = (mode == O_RDWR ?
+			0 : FILE_SHARE_READ | FILE_SHARE_WRITE);
+	access = (mode == O_RDWR ?
+			 FILE_READ_DATA | FILE_WRITE_DATA | SYNCHRONIZE
+			: FILE_READ_DATA | SYNCHRONIZE);
+
+	st = NtOpenFile(&handle, access,
+			&attr, &io_status,
+			share,
+			FILE_SYNCHRONOUS_IO_ALERT);
+	if (st != STATUS_SUCCESS) {
+		errno = ntfs_ntstatus_to_errno(st);
+		return (-1);
+	}
+	ntfs_device_win32_setlock(handle,FSCTL_LOCK_VOLUME);
+	/* store the drive geometry */
+	ntfs_device_win32_getntgeo(handle, fd);
+	fd->ntdll = TRUE;
+	/* allow accessing the full partition */
+	st = NtFsControlFile(handle, (HANDLE)NULL,
+			(PIO_APC_ROUTINE)NULL,
+			(PVOID)NULL, &io_status,
+			FSCTL_ALLOW_EXTENDED_DASD_IO,
+			NULL, 0, NULL, 0);
+	if (st != STATUS_SUCCESS) {
+		errno = ntfs_ntstatus_to_errno(st);
+		NtClose(handle);
+		return (-1);
+	}
+	/* fill fd */
+	fd->handle = handle;
+	fd->part_start = 0;
+	fd->part_length = fd->geo_size;
+	fd->pos = 0;
+	fd->part_hidden_sectors = -1;
+	fd->vol_handle = INVALID_HANDLE_VALUE;
+	return 0;
+}
+
+/**
+ * ntfs_device_win32_open_volume_for_partition - find and open a volume
+ *
+ * Windows NT/2k/XP handles volumes instead of partitions.
+ * This function gets the partition details and return an open volume handle.
+ * That volume is the one whose only physical location on disk is the described
+ * partition.
+ *
+ * The function required Windows 2k/XP, otherwise it fails (gracefully).
+ *
+ * Return success: a valid open volume handle.
+ *        fail   : INVALID_HANDLE_VALUE
+ */
+static HANDLE ntfs_device_win32_open_volume_for_partition(unsigned int drive_id,
+		s64 part_offset, s64 part_length, int flags)
+{
+	HANDLE vol_find_handle;
+	TCHAR vol_name[MAX_PATH];
+
+	/* Make sure all the required imports exist. */
+	if (!fnFindFirstVolume || !fnFindNextVolume || !fnFindVolumeClose) {
+		ntfs_log_trace("Required dll imports not found.\n");
+		return INVALID_HANDLE_VALUE;
+	}
+	/* Start iterating through volumes. */
+	ntfs_log_trace("Entering with drive_id=%d, part_offset=%lld, "
+			"path_length=%lld, flags=%d.\n", drive_id,
+			(unsigned long long)part_offset,
+			(unsigned long long)part_length, flags);
+	vol_find_handle = fnFindFirstVolume(vol_name, MAX_PATH);
+	/* If a valid handle could not be aquired, reply with "don't know". */
+	if (vol_find_handle == INVALID_HANDLE_VALUE) {
+		ntfs_log_trace("FindFirstVolume failed.\n");
+		return INVALID_HANDLE_VALUE;
+	}
+	do {
+		int vol_name_length;
+		HANDLE handle;
+
+		/* remove trailing '/' from vol_name */
+#ifdef UNICODE
+		vol_name_length = wcslen(vol_name);
+#else
+		vol_name_length = strlen(vol_name);
+#endif
+		if (vol_name_length>0)
+			vol_name[vol_name_length-1]=0;
+
+		ntfs_log_debug("Processing %s.\n", vol_name);
+		/* open the file */
+		handle = CreateFile(vol_name,
+				ntfs_device_unix_status_flags_to_win32(flags),
+				FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+				OPEN_EXISTING, 0, NULL);
+		if (handle != INVALID_HANDLE_VALUE) {
+			DWORD bytesReturned;
+#define EXTENTS_SIZE sizeof(VOLUME_DISK_EXTENTS) + 9 * sizeof(DISK_EXTENT)
+			char extents[EXTENTS_SIZE];
+
+			/* Check physical locations. */
+			if (DeviceIoControl(handle,
+					IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
+					NULL, 0, extents, EXTENTS_SIZE,
+					&bytesReturned, NULL)) {
+				if (((VOLUME_DISK_EXTENTS *)extents)->
+						NumberOfDiskExtents == 1) {
+					DISK_EXTENT *extent = &((
+							VOLUME_DISK_EXTENTS *)
+							extents)->Extents[0];
+					if ((extent->DiskNumber==drive_id) &&
+							(extent->StartingOffset.
+							QuadPart==part_offset)
+							&& (extent->
+							ExtentLength.QuadPart
+							== part_length)) {
+						/*
+						 * Eureka! (Archimedes, 287 BC,
+						 * "I have found it!")
+						 */
+						fnFindVolumeClose(
+							vol_find_handle);
+						return handle;
+					}
+				}
+			}
+		} else
+			ntfs_log_trace("getExtents() Failed.\n");
+	} while (fnFindNextVolume(vol_find_handle, vol_name, MAX_PATH));
+	/* End of iteration through volumes. */
+	ntfs_log_trace("Closing, volume was not found.\n");
+	fnFindVolumeClose(vol_find_handle);
+	return INVALID_HANDLE_VALUE;
+}
+
+/**
+ * ntfs_device_win32_find_partition - locates partition details by id.
+ * @handle:		HANDLE to the PhysicalDrive
+ * @partition_id:	the partition number to locate
+ * @part_offset:	pointer to where to put the offset to the partition
+ * @part_length:	pointer to where to put the length of the partition
+ * @hidden_sectors:	pointer to where to put the hidden sectors
+ *
+ * This function requires an open PhysicalDrive handle and a partition_id.
+ * If a partition with the required id is found on the supplied device,
+ * the partition attributes are returned back.
+ *
+ * Returns: TRUE  if found, and sets the output parameters.
+ *          FALSE if not and errno is set to the error code.
+ */
+static BOOL ntfs_device_win32_find_partition(HANDLE handle, DWORD partition_id,
+		s64 *part_offset, s64 *part_length, int *hidden_sectors)
+{
+	DRIVE_LAYOUT_INFORMATION *drive_layout;
+	unsigned int err, buf_size, part_count;
+	DWORD i;
+
+	/*
+	 * There is no way to know the required buffer, so if the ioctl fails,
+	 * try doubling the buffer size each time until the ioctl succeeds.
+	 */
+	part_count = 8;
+	do {
+		buf_size = sizeof(DRIVE_LAYOUT_INFORMATION) +
+				part_count * sizeof(PARTITION_INFORMATION);
+		drive_layout = (DRIVE_LAYOUT_INFORMATION*)ntfs_malloc(buf_size);
+		if (!drive_layout) {
+			errno = ENOMEM;
+			return FALSE;
+		}
+		if (DeviceIoControl(handle, IOCTL_DISK_GET_DRIVE_LAYOUT, NULL,
+				0, (BYTE*)drive_layout, buf_size, &i, NULL))
+			break;
+		err = GetLastError();
+		free(drive_layout);
+		if (err != ERROR_INSUFFICIENT_BUFFER) {
+			ntfs_log_trace("GetDriveLayout failed.\n");
+			errno = ntfs_w32error_to_errno(err);
+			return FALSE;
+		}
+		ntfs_log_debug("More than %u partitions.\n", part_count);
+		part_count <<= 1;
+		if (part_count > 512) {
+			ntfs_log_trace("GetDriveLayout failed: More than 512 "
+					"partitions?\n");
+			errno = ENOBUFS;
+			return FALSE;
+		}
+	} while (1);
+	for (i = 0; i < drive_layout->PartitionCount; i++) {
+		if (drive_layout->PartitionEntry[i].PartitionNumber ==
+				partition_id) {
+			*part_offset = drive_layout->PartitionEntry[i].
+					StartingOffset.QuadPart;
+			*part_length = drive_layout->PartitionEntry[i].
+					PartitionLength.QuadPart;
+			*hidden_sectors = drive_layout->PartitionEntry[i].
+					HiddenSectors;
+			free(drive_layout);
+			return TRUE;
+		}
+	}
+	free(drive_layout);
+	errno = ENOENT;
+	return FALSE;
+}
+
+/**
+ * ntfs_device_win32_open_partition - open a partition via win32 API
+ * @drive_id:		drive to open
+ * @partition_id:	partition to open
+ * @fd:			win32 file device to return
+ * @flags:		unix open status flags
+ *
+ * Return  0 if o.k.
+ *        -1 if not, and errno set.
+ *
+ * When fails, fd contents may have not been preserved.
+ */
+static int ntfs_device_win32_open_partition(int drive_id,
+		unsigned int partition_id, win32_fd *fd, int flags)
+{
+	s64 part_start, part_length;
+	HANDLE handle;
+	int err, hidden_sectors;
+	char drive_name[MAX_PATH];
+
+	sprintf(drive_name, "\\\\.\\PhysicalDrive%d", drive_id);
+	/* Open the entire device without locking, ask questions later */
+	if ((err = ntfs_device_win32_simple_open_file(drive_name, &handle,
+			flags, FALSE))) {
+		/* error */
+		return err;
+	}
+	if (ntfs_device_win32_find_partition(handle, partition_id, &part_start,
+			&part_length, &hidden_sectors)) {
+		s64 tmp;
+		HANDLE vol_handle = ntfs_device_win32_open_volume_for_partition(
+			drive_id, part_start, part_length, flags);
+		/* Store the drive geometry. */
+		ntfs_device_win32_getgeo(handle, fd);
+		fd->handle = handle;
+		fd->pos = 0;
+		fd->part_start = part_start;
+		fd->part_length = part_length;
+		fd->part_hidden_sectors = hidden_sectors;
+		fd->geo_sector_size = 512;
+		fd->ntdll = FALSE;
+		tmp = ntfs_device_win32_getntfssize(vol_handle);
+		if (tmp > 0)
+			fd->geo_size = tmp;
+		else
+			fd->geo_size = fd->part_length;
+		if (vol_handle != INVALID_HANDLE_VALUE) {
+			if (((flags & O_RDWR) == O_RDWR) &&
+					ntfs_device_win32_lock(vol_handle)) {
+				CloseHandle(vol_handle);
+				CloseHandle(handle);
+				return -1;
+			}
+			fd->vol_handle = vol_handle;
+		} else {
+			if ((flags & O_RDWR) == O_RDWR) {
+				/* Access if read-write, no volume found. */
+				ntfs_log_trace("Partitions containing Spanned/"
+						"Mirrored volumes are not "
+						"supported in R/W status "
+						"yet.\n");
+				CloseHandle(handle);
+				errno = EOPNOTSUPP;
+				return -1;
+			}
+			fd->vol_handle = INVALID_HANDLE_VALUE;
+		}
+		return 0;
+	} else {
+		ntfs_log_debug("Partition %u not found on drive %d.\n",
+				partition_id, drive_id);
+		CloseHandle(handle);
+		errno = ENODEV;
+		return -1;
+	}
+}
+
+/**
+ * ntfs_device_win32_open - open a device
+ * @dev:	a pointer to the NTFS_DEVICE to open
+ * @flags:	unix open status flags
+ *
+ * @dev->d_name must hold the device name, the rest is ignored.
+ * Supported flags are O_RDONLY, O_WRONLY and O_RDWR.
+ *
+ * If name is in format "(hd[0-9],[0-9])" then open a partition.
+ * If name is in format "(hd[0-9])" then open a volume.
+ * Otherwise open a file.
+ */
+static int ntfs_device_win32_open(struct ntfs_device *dev, int flags)
+{
+	int drive_id = 0, numparams;
+	unsigned int part = 0;
+	char drive_char;
+	win32_fd fd;
+	int err;
+
+	if (NDevOpen(dev)) {
+		errno = EBUSY;
+		return -1;
+	}
+	ntfs_device_win32_init_imports();
+	numparams = sscanf(dev->d_name, "/dev/hd%c%u", &drive_char, &part);
+	if (!numparams
+	    && (dev->d_name[1] == ':')
+	    && (dev->d_name[2] == '\0')) {
+		drive_char = dev->d_name[0];
+		numparams = 3;
+		drive_id = toupper(drive_char) - 'A';
+	}
+	switch (numparams) {
+	case 0:
+		ntfs_log_debug("win32_open(%s) -> file.\n", dev->d_name);
+		err = ntfs_device_win32_open_file(dev->d_name, &fd, flags);
+		break;
+	case 1:
+		ntfs_log_debug("win32_open(%s) -> drive %d.\n", dev->d_name,
+				drive_id);
+		err = ntfs_device_win32_open_drive(drive_id, &fd, flags);
+		break;
+	case 2:
+		ntfs_log_debug("win32_open(%s) -> drive %d, part %u.\n",
+				dev->d_name, drive_id, part);
+		err = ntfs_device_win32_open_partition(drive_id, part, &fd,
+				flags);
+		break;
+	case 3:
+		ntfs_log_debug("win32_open(%s) -> drive %c:\n",
+				dev->d_name, drive_char);
+		err = ntfs_device_win32_open_lowlevel(drive_id, &fd,
+				flags);
+		break;
+	default:
+		ntfs_log_debug("win32_open(%s) -> unknwon file format.\n",
+				dev->d_name);
+		err = -1;
+	}
+	if (err)
+		return err;
+	ntfs_log_debug("win32_open(%s) -> %p, offset 0x%llx.\n", dev->d_name,
+			dev, fd.part_start);
+	/* Setup our read-only flag. */
+	if ((flags & O_RDWR) != O_RDWR)
+		NDevSetReadOnly(dev);
+	dev->d_private = (win32_fd*)ntfs_malloc(sizeof(win32_fd));
+	memcpy(dev->d_private, &fd, sizeof(win32_fd));
+	NDevSetOpen(dev);
+	NDevClearDirty(dev);
+	return 0;
+}
+
+/**
+ * ntfs_device_win32_seek - change current logical file position
+ * @dev:	ntfs device obtained via ->open
+ * @offset:	required offset from the whence anchor
+ * @whence:	whence anchor specifying what @offset is relative to
+ *
+ * Return the new position on the volume on success and -1 on error with errno
+ * set to the error code.
+ *
+ * @whence may be one of the following:
+ *	SEEK_SET - Offset is relative to file start.
+ *	SEEK_CUR - Offset is relative to current position.
+ *	SEEK_END - Offset is relative to end of file.
+ */
+static s64 ntfs_device_win32_seek(struct ntfs_device *dev, s64 offset,
+		int whence)
+{
+	s64 abs_ofs;
+	win32_fd *fd = (win32_fd *)dev->d_private;
+
+	ntfs_log_trace("seek offset = 0x%llx, whence = %d.\n", offset, whence);
+	switch (whence) {
+	case SEEK_SET:
+		abs_ofs = offset;
+		break;
+	case SEEK_CUR:
+		abs_ofs = fd->pos + offset;
+		break;
+	case SEEK_END:
+		/* End of partition != end of disk. */
+		if (fd->part_length == -1) {
+			ntfs_log_trace("Position relative to end of disk not "
+					"implemented.\n");
+			errno = EOPNOTSUPP;
+			return -1;
+		}
+		abs_ofs = fd->part_length + offset;
+		break;
+	default:
+		ntfs_log_trace("Wrong mode %d.\n", whence);
+		errno = EINVAL;
+		return -1;
+	}
+	if ((abs_ofs < 0)
+	    || (fd->ntdll && (abs_ofs > fd->part_length))) {
+		ntfs_log_trace("Seeking outsize seekable area.\n");
+		errno = EINVAL;
+		return -1;
+	}
+	fd->pos = abs_ofs;
+	return abs_ofs;
+}
+
+/**
+ * ntfs_device_win32_pio - positioned low level i/o
+ * @fd:		win32 device descriptor obtained via ->open
+ * @pos:	at which position to do i/o from/to
+ * @count:	how many bytes should be transfered
+ * @b:		source/destination buffer
+ * @write:	TRUE if write transfer and FALSE if read transfer
+ *
+ * On success returns the number of bytes transfered (can be < @count) and on
+ * error returns -1 and errno set.  Transfer starts from position @pos on @fd.
+ *
+ * Notes:
+ *	- @pos, @buf, and @count must be aligned to geo_sector_size
+ *	- When dealing with volumes, a single call must not span both volume
+ *	  and disk extents.
+ *	- Does not use/set @fd->pos.
+ */
+static s64 ntfs_device_win32_pio(win32_fd *fd, const s64 pos,
+		const s64 count, void *rbuf, const void *wbuf)
+{
+	LARGE_INTEGER li;
+	HANDLE handle;
+	DWORD bt;
+	BOOL res;
+	s64 bytes;
+
+	ntfs_log_trace("pos = 0x%llx, count = 0x%llx, direction = %s.\n",
+			(long long)pos, (long long)count, write ? "write" :
+			"read");
+	li.QuadPart = pos;
+	if (fd->vol_handle != INVALID_HANDLE_VALUE && pos < fd->geo_size) {
+		ntfs_log_debug("Transfering via vol_handle.\n");
+		handle = fd->vol_handle;
+	} else {
+		ntfs_log_debug("Transfering via handle.\n");
+		handle = fd->handle;
+		li.QuadPart += fd->part_start;
+	}
+
+	if (fd->ntdll) {
+		IO_STATUS_BLOCK io_status;
+		NTSTATUS res;
+		LARGE_INTEGER offset;
+
+		io_status.Status = STATUS_SUCCESS;
+		io_status.Information = 0;
+		offset.QuadPart = pos;
+		if (wbuf) {
+			res = NtWriteFile(fd->handle,(HANDLE)NULL,
+					(PIO_APC_ROUTINE)NULL,(void*)NULL,
+					&io_status, wbuf, count,
+					&offset, (PULONG)NULL);
+		} else {
+			res = NtReadFile(fd->handle,(HANDLE)NULL,
+					(PIO_APC_ROUTINE)NULL,(void*)NULL,
+					&io_status, rbuf, count,
+					&offset, (PULONG)NULL);
+		}
+		if (res == STATUS_SUCCESS) {
+			bytes = io_status.Information;
+		} else {
+			bytes = -1;
+			errno = ntfs_ntstatus_to_errno(res);
+		}
+	} else {
+		if (!fnSetFilePointerEx(handle, li, NULL, FILE_BEGIN)) {
+			errno = ntfs_w32error_to_errno(GetLastError());
+			ntfs_log_trace("SetFilePointer failed.\n");
+			return -1;
+		}
+		if (wbuf)
+			res = WriteFile(handle, wbuf, count, &bt, NULL);
+		else
+			res = ReadFile(handle, rbuf, count, &bt, NULL);
+		bytes = bt;
+		if (!res) {
+			errno = ntfs_w32error_to_errno(GetLastError());
+			ntfs_log_trace("%sFile() failed.\n", write ?
+							"Write" : "Read");
+			return -1;
+		}
+		if (rbuf && !pos) {
+			/* get the sector size from the boot sector */
+			char *boot = (char*)rbuf;
+			fd->geo_sector_size = (boot[11] & 255)
+						+ ((boot[12] & 255) << 8);
+		}
+	}
+	return bytes;
+}
+
+/**
+ * ntfs_device_win32_pread_simple - positioned simple read
+ * @fd:		win32 device descriptor obtained via ->open
+ * @pos:	at which position to read from
+ * @count:	how many bytes should be read
+ * @b:		a pointer to where to put the contents
+ *
+ * On success returns the number of bytes read (can be < @count) and on error
+ * returns -1 and errno set.  Read starts from position @pos.
+ *
+ * Notes:
+ *	- @pos, @buf, and @count must be aligned to geo_sector_size.
+ *	- When dealing with volumes, a single call must not span both volume
+ *	  and disk extents.
+ *	- Does not use/set @fd->pos.
+ */
+static inline s64 ntfs_device_win32_pread_simple(win32_fd *fd, const s64 pos,
+		const s64 count, void *b)
+{
+	return ntfs_device_win32_pio(fd, pos, count, b, (void*)NULL);
+}
+
+/**
+ * ntfs_device_win32_read - read bytes from an ntfs device
+ * @dev:	ntfs device obtained via ->open
+ * @b:		pointer to where to put the contents
+ * @count:	how many bytes should be read
+ *
+ * On success returns the number of bytes actually read (can be < @count).
+ * On error returns -1 with errno set.
+ */
+static s64 ntfs_device_win32_read(struct ntfs_device *dev, void *b, s64 count)
+{
+	s64 old_pos, to_read, i, br = 0;
+	win32_fd *fd = (win32_fd *)dev->d_private;
+	BYTE *alignedbuffer;
+	int old_ofs, ofs;
+
+	old_pos = fd->pos;
+	old_ofs = ofs = old_pos & (fd->geo_sector_size - 1);
+	to_read = (ofs + count + fd->geo_sector_size - 1) &
+			~(s64)(fd->geo_sector_size - 1);
+	/* Impose maximum of 2GB to be on the safe side. */
+	if (to_read > 0x80000000) {
+		int delta = to_read - count;
+		to_read = 0x80000000;
+		count = to_read - delta;
+	}
+	ntfs_log_trace("fd = %p, b = %p, count = 0x%llx, pos = 0x%llx, "
+			"ofs = %i, to_read = 0x%llx.\n", fd, b,
+			(long long)count, (long long)old_pos, ofs,
+			(long long)to_read);
+	if (!((unsigned long)b & (fd->geo_sector_size - 1)) && !old_ofs &&
+			!(count & (fd->geo_sector_size - 1)))
+		alignedbuffer = b;
+	else {
+		alignedbuffer = (BYTE *)VirtualAlloc(NULL, to_read, MEM_COMMIT,
+				PAGE_READWRITE);
+		if (!alignedbuffer) {
+			errno = ntfs_w32error_to_errno(GetLastError());
+			ntfs_log_trace("VirtualAlloc failed for read.\n");
+			return -1;
+		}
+	}
+	if (fd->vol_handle != INVALID_HANDLE_VALUE && old_pos < fd->geo_size) {
+		s64 vol_to_read = fd->geo_size - old_pos;
+		if (count > vol_to_read) {
+			br = ntfs_device_win32_pread_simple(fd,
+					old_pos & ~(s64)(fd->geo_sector_size - 1),
+					ofs + vol_to_read, alignedbuffer);
+			if (br == -1)
+				goto read_error;
+			to_read -= br;
+			if (br < ofs) {
+				br = 0;
+				goto read_partial;
+			}
+			br -= ofs;
+			fd->pos += br;
+			ofs = fd->pos & (fd->geo_sector_size - 1);
+			if (br != vol_to_read)
+				goto read_partial;
+		}
+	}
+	i = ntfs_device_win32_pread_simple(fd,
+			fd->pos & ~(s64)(fd->geo_sector_size - 1), to_read,
+			alignedbuffer + br);
+	if (i == -1) {
+		if (br)
+			goto read_partial;
+		goto read_error;
+	}
+	if (i < ofs)
+		goto read_partial;
+	i -= ofs;
+	br += i;
+	if (br > count)
+		br = count;
+	fd->pos = old_pos + br;
+read_partial:
+	if (alignedbuffer != b) {
+		memcpy((void*)b, alignedbuffer + old_ofs, br);
+		VirtualFree(alignedbuffer, 0, MEM_RELEASE);
+	}
+	return br;
+read_error:
+	if (alignedbuffer != b)
+		VirtualFree(alignedbuffer, 0, MEM_RELEASE);
+	return -1;
+}
+
+/**
+ * ntfs_device_win32_close - close an open ntfs deivce
+ * @dev:	ntfs device obtained via ->open
+ *
+ * Return 0 if o.k.
+ *	 -1 if not, and errno set.  Note if error fd->vol_handle is trashed.
+ */
+static int ntfs_device_win32_close(struct ntfs_device *dev)
+{
+	win32_fd *fd = (win32_fd *)dev->d_private;
+	BOOL rvl;
+
+	ntfs_log_trace("Closing device %p.\n", dev);
+	if (!NDevOpen(dev)) {
+		errno = EBADF;
+		return -1;
+	}
+	if (fd->vol_handle != INVALID_HANDLE_VALUE) {
+		if (!NDevReadOnly(dev)) {
+			ntfs_device_win32_dismount(fd->vol_handle);
+			ntfs_device_win32_unlock(fd->vol_handle);
+		}
+		if (!CloseHandle(fd->vol_handle))
+			ntfs_log_trace("CloseHandle() failed for volume.\n");
+	}
+	if (fd->ntdll) {
+		ntfs_device_win32_setlock(fd->handle,FSCTL_UNLOCK_VOLUME);
+		rvl = NtClose(fd->handle) == STATUS_SUCCESS;
+	} else
+		rvl = CloseHandle(fd->handle);
+	NDevClearOpen(dev);
+	free(fd);
+	if (!rvl) {
+		errno = ntfs_w32error_to_errno(GetLastError());
+		if (fd->ntdll)
+			ntfs_log_trace("NtClose() failed.\n");
+		else
+			ntfs_log_trace("CloseHandle() failed.\n");
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * ntfs_device_win32_sync - flush write buffers to disk
+ * @dev:	ntfs device obtained via ->open
+ *
+ * Return 0 if o.k.
+ *	 -1 if not, and errno set.
+ *
+ * Note: Volume syncing works differently in windows.
+ *	 Disk cannot be synced in windows.
+ */
+static int ntfs_device_win32_sync(struct ntfs_device *dev)
+{
+	int err = 0;
+	BOOL to_clear = TRUE;
+
+	if (!NDevReadOnly(dev) && NDevDirty(dev)) {
+		win32_fd *fd = (win32_fd *)dev->d_private;
+
+		if ((fd->vol_handle != INVALID_HANDLE_VALUE) &&
+				!FlushFileBuffers(fd->vol_handle)) {
+			to_clear = FALSE;
+			err = ntfs_w32error_to_errno(GetLastError());
+		}
+		if (!FlushFileBuffers(fd->handle)) {
+			to_clear = FALSE;
+			if (!err)
+				err = ntfs_w32error_to_errno(GetLastError());
+		}
+		if (!to_clear) {
+			ntfs_log_trace("Could not sync.\n");
+			errno = err;
+			return -1;
+		}
+		NDevClearDirty(dev);
+	}
+	return 0;
+}
+
+/**
+ * ntfs_device_win32_pwrite_simple - positioned simple write
+ * @fd:		win32 device descriptor obtained via ->open
+ * @pos:	at which position to write to
+ * @count:	how many bytes should be written
+ * @b:		a pointer to the data to write
+ *
+ * On success returns the number of bytes written and on error returns -1 and
+ * errno set.  Write starts from position @pos.
+ *
+ * Notes:
+ *	- @pos, @buf, and @count must be aligned to geo_sector_size.
+ *	- When dealing with volumes, a single call must not span both volume
+ *	  and disk extents.
+ *	- Does not use/set @fd->pos.
+ */
+static inline s64 ntfs_device_win32_pwrite_simple(win32_fd *fd, const s64 pos,
+		const s64 count, const void *b)
+{
+	return ntfs_device_win32_pio(fd, pos, count, (void*)NULL, b);
+}
+
+/**
+ * ntfs_device_win32_write - write bytes to an ntfs device
+ * @dev:	ntfs device obtained via ->open
+ * @b:		pointer to the data to write
+ * @count:	how many bytes should be written
+ *
+ * On success returns the number of bytes actually written.
+ * On error returns -1 with errno set.
+ */
+static s64 ntfs_device_win32_write(struct ntfs_device *dev, const void *b,
+		s64 count)
+{
+	s64 old_pos, to_write, i, bw = 0;
+	win32_fd *fd = (win32_fd *)dev->d_private;
+	const BYTE *alignedbuffer;
+	BYTE *readbuffer;
+	int old_ofs, ofs;
+
+	old_pos = fd->pos;
+	old_ofs = ofs = old_pos & (fd->geo_sector_size - 1);
+	to_write = (ofs + count + fd->geo_sector_size - 1) &
+			~(s64)(fd->geo_sector_size - 1);
+	/* Impose maximum of 2GB to be on the safe side. */
+	if (to_write > 0x80000000) {
+		int delta = to_write - count;
+		to_write = 0x80000000;
+		count = to_write - delta;
+	}
+	ntfs_log_trace("fd = %p, b = %p, count = 0x%llx, pos = 0x%llx, "
+			"ofs = %i, to_write = 0x%llx.\n", fd, b,
+			(long long)count, (long long)old_pos, ofs,
+			(long long)to_write);
+	if (NDevReadOnly(dev)) {
+		ntfs_log_trace("Can't write on a R/O device.\n");
+		errno = EROFS;
+		return -1;
+	}
+	if (!count)
+		return 0;
+	NDevSetDirty(dev);
+	readbuffer = (BYTE*)NULL;
+	if (!((unsigned long)b & (fd->geo_sector_size - 1)) && !old_ofs &&
+			!(count & (fd->geo_sector_size - 1)))
+		alignedbuffer = (const BYTE *)b;
+	else {
+		s64 end;
+
+		readbuffer = (BYTE *)VirtualAlloc(NULL, to_write,
+				MEM_COMMIT, PAGE_READWRITE);
+		if (!readbuffer) {
+			errno = ntfs_w32error_to_errno(GetLastError());
+			ntfs_log_trace("VirtualAlloc failed for write.\n");
+			return -1;
+		}
+		/* Read first sector if start of write not sector aligned. */
+		if (ofs) {
+			i = ntfs_device_win32_pread_simple(fd,
+					old_pos & ~(s64)(fd->geo_sector_size - 1),
+					fd->geo_sector_size, readbuffer);
+			if (i != fd->geo_sector_size) {
+				if (i >= 0)
+					errno = EIO;
+				goto write_error;
+			}
+		}
+		/*
+		 * Read last sector if end of write not sector aligned and last
+		 * sector is either not the same as the first sector or it is
+		 * the same as the first sector but this has not been read in
+		 * yet, i.e. the start of the write is sector aligned.
+		 */
+		end = old_pos + count;
+		if ((end & (fd->geo_sector_size - 1)) &&
+				((to_write > fd->geo_sector_size) || !ofs)) {
+			i = ntfs_device_win32_pread_simple(fd,
+					end & ~(s64)(fd->geo_sector_size - 1),
+					fd->geo_sector_size, readbuffer +
+					to_write - fd->geo_sector_size);
+			if (i != fd->geo_sector_size) {
+				if (i >= 0)
+					errno = EIO;
+				goto write_error;
+			}
+		}
+		/* Copy the data to be written into @readbuffer. */
+		memcpy(readbuffer + ofs, b, count);
+		alignedbuffer = readbuffer;
+	}
+	if (fd->vol_handle != INVALID_HANDLE_VALUE && old_pos < fd->geo_size) {
+		s64 vol_to_write = fd->geo_size - old_pos;
+		if (count > vol_to_write) {
+			bw = ntfs_device_win32_pwrite_simple(fd,
+					old_pos & ~(s64)(fd->geo_sector_size - 1),
+					ofs + vol_to_write, alignedbuffer);
+			if (bw == -1)
+				goto write_error;
+			to_write -= bw;
+			if (bw < ofs) {
+				bw = 0;
+				goto write_partial;
+			}
+			bw -= ofs;
+			fd->pos += bw;
+			ofs = fd->pos & (fd->geo_sector_size - 1);
+			if (bw != vol_to_write)
+				goto write_partial;
+		}
+	}
+	i = ntfs_device_win32_pwrite_simple(fd,
+			fd->pos & ~(s64)(fd->geo_sector_size - 1), to_write,
+			alignedbuffer + bw);
+	if (i == -1) {
+		if (bw)
+			goto write_partial;
+		goto write_error;
+	}
+	if (i < ofs)
+		goto write_partial;
+	i -= ofs;
+	bw += i;
+	if (bw > count)
+		bw = count;
+	fd->pos = old_pos + bw;
+write_partial:
+	if (readbuffer)
+		VirtualFree(readbuffer, 0, MEM_RELEASE);
+	return bw;
+write_error:
+	bw = -1;
+	goto write_partial;
+}
+
+/**
+ * ntfs_device_win32_stat - get a unix-like stat structure for an ntfs device
+ * @dev:	ntfs device obtained via ->open
+ * @buf:	pointer to the stat structure to fill
+ *
+ * Note: Only st_mode, st_size, and st_blocks are filled.
+ *
+ * Return 0 if o.k.
+ *	 -1 if not and errno set. in this case handle is trashed.
+ */
+static int ntfs_device_win32_stat(struct ntfs_device *dev, struct stat *buf)
+{
+	win32_fd *fd = (win32_fd *)dev->d_private;
+	mode_t st_mode;
+
+	if ((dev->d_name[1] == ':') && (dev->d_name[2] == '\0'))
+		st_mode = S_IFBLK;
+	else
+		switch (GetFileType(fd->handle)) {
+		case FILE_TYPE_CHAR:
+			st_mode = S_IFCHR;
+			break;
+		case FILE_TYPE_DISK:
+			st_mode = S_IFREG;
+			break;
+		case FILE_TYPE_PIPE:
+			st_mode = S_IFIFO;
+			break;
+		default:
+			st_mode = 0;
+		}
+	memset(buf, 0, sizeof(struct stat));
+	buf->st_mode = st_mode;
+	buf->st_size = fd->part_length;
+	if (buf->st_size != -1)
+		buf->st_blocks = buf->st_size >> 9;
+	else
+		buf->st_size = 0;
+	return 0;
+}
+
+#ifdef HDIO_GETGEO
+/**
+ * ntfs_win32_hdio_getgeo - get drive geometry
+ * @dev:	ntfs device obtained via ->open
+ * @argp:	pointer to where to put the output
+ *
+ * Note: Works on windows NT/2k/XP only.
+ *
+ * Return 0 if o.k.
+ *	 -1 if not, and errno set.  Note if error fd->handle is trashed.
+ */
+static __inline__ int ntfs_win32_hdio_getgeo(struct ntfs_device *dev,
+		struct hd_geometry *argp)
+{
+	win32_fd *fd = (win32_fd *)dev->d_private;
+
+	argp->heads = fd->geo_heads;
+	argp->sectors = fd->geo_sectors;
+	argp->cylinders = fd->geo_cylinders;
+	argp->start = fd->part_hidden_sectors;
+	return 0;
+}
+#endif
+
+/**
+ * ntfs_win32_blksszget - get block device sector size
+ * @dev:	ntfs device obtained via ->open
+ * @argp:	pointer to where to put the output
+ *
+ * Note: Works on windows NT/2k/XP only.
+ *
+ * Return 0 if o.k.
+ *	 -1 if not, and errno set.  Note if error fd->handle is trashed.
+ */
+static __inline__ int ntfs_win32_blksszget(struct ntfs_device *dev,int *argp)
+{
+	win32_fd *fd = (win32_fd *)dev->d_private;
+	DWORD bytesReturned;
+	DISK_GEOMETRY dg;
+
+	if (DeviceIoControl(fd->handle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,
+			&dg, sizeof(DISK_GEOMETRY), &bytesReturned, NULL)) {
+		/* success */
+		*argp = dg.BytesPerSector;
+		return 0;
+	}
+	errno = ntfs_w32error_to_errno(GetLastError());
+	ntfs_log_trace("GET_DRIVE_GEOMETRY failed.\n");
+	return -1;
+}
+
+static int ntfs_device_win32_ioctl(struct ntfs_device *dev, int request,
+		void *argp)
+{
+#if defined(BLKGETSIZE) | defined(BLKGETSIZE64)
+	win32_fd *fd = (win32_fd *)dev->d_private;
+#endif
+
+	ntfs_log_trace("win32_ioctl(%d) called.\n", request);
+	switch (request) {
+#if defined(BLKGETSIZE)
+	case BLKGETSIZE:
+		ntfs_log_debug("BLKGETSIZE detected.\n");
+		if (fd->part_length >= 0) {
+			*(int *)argp = (int)(fd->part_length / 512);
+			return 0;
+		}
+		errno = EOPNOTSUPP;
+		return -1;
+#endif
+#if defined(BLKGETSIZE64)
+	case BLKGETSIZE64:
+		ntfs_log_debug("BLKGETSIZE64 detected.\n");
+		if (fd->part_length >= 0) {
+			*(s64 *)argp = fd->part_length;
+			return 0;
+		}
+		errno = EOPNOTSUPP;
+		return -1;
+#endif
+#ifdef HDIO_GETGEO
+	case HDIO_GETGEO:
+		ntfs_log_debug("HDIO_GETGEO detected.\n");
+		return ntfs_win32_hdio_getgeo(dev, (struct hd_geometry *)argp);
+#endif
+#ifdef BLKSSZGET
+	case BLKSSZGET:
+		ntfs_log_debug("BLKSSZGET detected.\n");
+		return ntfs_win32_blksszget(dev, (int *)argp);
+#endif
+#ifdef BLKBSZSET
+	case BLKBSZSET:
+		ntfs_log_debug("BLKBSZSET detected.\n");
+		/* Nothing to do on Windows. */
+		return 0;
+#endif
+	default:
+		ntfs_log_debug("unimplemented ioctl %d.\n", request);
+		errno = EOPNOTSUPP;
+		return -1;
+	}
+}
+
+static s64 ntfs_device_win32_pread(struct ntfs_device *dev, void *b,
+		s64 count, s64 offset)
+{
+	s64 got;
+	win32_fd *fd;
+
+		/* read the fast way if sector aligned */
+	fd = (win32_fd*)dev->d_private;
+	if (!((count | offset) & (fd->geo_sector_size - 1))) {
+		got = ntfs_device_win32_pio(fd, offset, count, b, (void*)NULL);
+	} else {
+		if (ntfs_device_win32_seek(dev, offset, 0) == -1)
+			got = 0;
+		else
+			got = ntfs_device_win32_read(dev, b, count);
+	}
+
+	return (got);
+}
+
+static s64 ntfs_device_win32_pwrite(struct ntfs_device *dev, const void *b,
+		s64 count, s64 offset)
+{
+	s64 put;
+	win32_fd *fd;
+
+		/* write the fast way if sector aligned */
+	fd = (win32_fd*)dev->d_private;
+	if (!((count | offset) & (fd->geo_sector_size - 1))) {
+		put = ntfs_device_win32_pio(fd, offset, count, (void*)NULL, b);
+	} else {
+		if (ntfs_device_win32_seek(dev, offset, 0) == -1)
+			put = 0;
+		else
+			put = ntfs_device_win32_write(dev, b, count);
+	}
+	return (put);
+}
+
+struct ntfs_device_operations ntfs_device_win32_io_ops = {
+	.open		= ntfs_device_win32_open,
+	.close		= ntfs_device_win32_close,
+	.seek		= ntfs_device_win32_seek,
+	.read		= ntfs_device_win32_read,
+	.write		= ntfs_device_win32_write,
+	.pread		= ntfs_device_win32_pread,
+	.pwrite		= ntfs_device_win32_pwrite,
+	.sync		= ntfs_device_win32_sync,
+	.stat		= ntfs_device_win32_stat,
+	.ioctl		= ntfs_device_win32_ioctl
+};
+
+/*
+ *			Mark an open file as sparse
+ *
+ *	This is only called by ntfsclone when cloning a volume to a file.
+ *	The argument is the target file, not a volume.
+ *
+ *	Returns 0 if successful.
+ */
+
+int ntfs_win32_set_sparse(int fd)
+{
+	BOOL ok;
+	HANDLE handle;
+	DWORD bytes;   
+
+	handle = get_osfhandle(fd);
+	if (handle == INVALID_HANDLE_VALUE)
+		ok = FALSE;
+	else
+		ok = DeviceIoControl(handle, FSCTL_SET_SPARSE,
+				(void*)NULL, 0, (void*)NULL, 0,
+				&bytes, (LPOVERLAPPED)NULL);
+	return (!ok);
+}
+
+/*
+ *			Resize an open file
+ *
+ *	This is only called by ntfsclone when cloning a volume to a file.
+ *	The argument must designate a file, not a volume.
+ *
+ *	Returns 0 if successful.
+ */
+
+static int win32_ftruncate(HANDLE handle, s64 size)
+{
+	BOOL ok;
+	LONG hsize, lsize;
+	LONG ohsize, olsize;
+
+	if (handle == INVALID_HANDLE_VALUE)
+		ok = FALSE;
+	else {
+		SetLastError(NO_ERROR);
+			/* save original position */
+		ohsize = 0;
+		olsize = SetFilePointer(handle, 0, &ohsize, 1);
+		hsize = size >> 32;
+		lsize = size & 0xffffffff;
+		ok = (SetFilePointer(handle, lsize, &hsize, 0) == (DWORD)lsize)
+		    && (GetLastError() == NO_ERROR)
+		    && SetEndOfFile(handle);
+			/* restore original position, even if above failed */
+		SetFilePointer(handle, olsize, &ohsize, 0);
+		if (GetLastError() != NO_ERROR)
+			ok = FALSE;
+	}
+	if (!ok)
+		errno = EINVAL;
+	return (ok ? 0 : -1);
+}
+
+int ntfs_device_win32_ftruncate(struct ntfs_device *dev, s64 size)
+{
+	win32_fd *fd;
+	int ret;
+
+	ret = -1;
+	fd = (win32_fd*)dev->d_private;
+	if (fd && !fd->ntdll)
+		ret = win32_ftruncate(fd->handle, size);
+	return (ret);
+}
+
+int ntfs_win32_ftruncate(int fd, s64 size)
+{
+	int ret;
+	HANDLE handle;
+
+	handle = get_osfhandle(fd);
+	ret = win32_ftruncate(handle, size);
+	return (ret);
+}
diff --git a/libntfs-3g/xattrs.c b/libntfs-3g/xattrs.c
new file mode 100755
index 0000000000000000000000000000000000000000..6da814677a87fa203f8da7c2bf92ce14d73c3b20
--- /dev/null
+++ b/libntfs-3g/xattrs.c
@@ -0,0 +1,802 @@
+/**
+ * xattrs.c : common functions to deal with system extended attributes
+ *
+ * Copyright (c) 2010-2014 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_SETXATTR /* extended attributes support required */
+
+#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
+
+#include "types.h"
+#include "param.h"
+#include "layout.h"
+#include "attrib.h"
+#include "index.h"
+#include "dir.h"
+#include "security.h"
+#include "acls.h"
+#include "efs.h"
+#include "reparse.h"
+#include "object_id.h"
+#include "ea.h"
+#include "misc.h"
+#include "logging.h"
+#include "xattrs.h"
+
+#if POSIXACLS
+#if __BYTE_ORDER == __BIG_ENDIAN
+
+/*
+ *		       Posix ACL structures
+ */
+        
+struct LE_POSIX_ACE {
+	le16 tag;
+	le16 perms;
+	le32 id;    
+} __attribute__((__packed__));
+
+struct LE_POSIX_ACL {
+	u8 version;
+	u8 flags;
+	le16 filler; 
+	struct LE_POSIX_ACE ace[0];
+} __attribute__((__packed__));
+        
+#endif
+#endif
+
+static const char xattr_ntfs_3g[] = "ntfs-3g.";
+static const char nf_ns_user_prefix[] = "user.";
+static const int nf_ns_user_prefix_len = sizeof(nf_ns_user_prefix) - 1;
+
+static const char nf_ns_xattr_ntfs_acl[] = "system.ntfs_acl";
+static const char nf_ns_xattr_attrib[] = "system.ntfs_attrib";
+static const char nf_ns_xattr_attrib_be[] = "system.ntfs_attrib_be";
+static const char nf_ns_xattr_efsinfo[] = "system.ntfs_efsinfo";
+static const char nf_ns_xattr_reparse[] = "system.ntfs_reparse_data";
+static const char nf_ns_xattr_object_id[] = "system.ntfs_object_id";
+static const char nf_ns_xattr_dos_name[] = "system.ntfs_dos_name";
+static const char nf_ns_xattr_times[] = "system.ntfs_times";
+static const char nf_ns_xattr_times_be[] = "system.ntfs_times_be";
+static const char nf_ns_xattr_crtime[] = "system.ntfs_crtime";
+static const char nf_ns_xattr_crtime_be[] = "system.ntfs_crtime_be";
+static const char nf_ns_xattr_ea[] = "system.ntfs_ea";
+static const char nf_ns_xattr_posix_access[] = "system.posix_acl_access";
+static const char nf_ns_xattr_posix_default[] = "system.posix_acl_default";
+
+static const char nf_ns_alt_xattr_efsinfo[] = "user.ntfs.efsinfo";
+
+struct XATTRNAME {
+	enum SYSTEMXATTRS xattr;
+	const char *name;
+} ;
+
+static struct XATTRNAME nf_ns_xattr_names[] = {
+	{ XATTR_NTFS_ACL, nf_ns_xattr_ntfs_acl },
+	{ XATTR_NTFS_ATTRIB, nf_ns_xattr_attrib },
+	{ XATTR_NTFS_ATTRIB_BE, nf_ns_xattr_attrib_be },
+	{ XATTR_NTFS_EFSINFO, nf_ns_xattr_efsinfo },
+	{ XATTR_NTFS_REPARSE_DATA, nf_ns_xattr_reparse },
+	{ XATTR_NTFS_OBJECT_ID, nf_ns_xattr_object_id },
+	{ XATTR_NTFS_DOS_NAME, nf_ns_xattr_dos_name },
+	{ XATTR_NTFS_TIMES, nf_ns_xattr_times },
+	{ XATTR_NTFS_TIMES_BE, nf_ns_xattr_times_be },
+	{ XATTR_NTFS_CRTIME, nf_ns_xattr_crtime },
+	{ XATTR_NTFS_CRTIME_BE, nf_ns_xattr_crtime_be },
+	{ XATTR_NTFS_EA, nf_ns_xattr_ea },
+	{ XATTR_POSIX_ACC, nf_ns_xattr_posix_access },
+	{ XATTR_POSIX_DEF, nf_ns_xattr_posix_default },
+	{ XATTR_UNMAPPED, (char*)NULL } /* terminator */
+};
+
+/*
+ *		Make an integer big-endian
+ *
+ *	Swap bytes on a small-endian computer and does nothing on a
+ *	big-endian computer.
+ */
+
+static void fix_big_endian(char *p, int size)
+{
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+	int i,j;
+	int c;
+
+	i = 0;
+	j = size - 1;
+	while (i < j) {
+		c = p[i];
+		p[i++] = p[j];
+		p[j--] = c;
+	}
+#endif
+}
+
+#if POSIXACLS
+#if __BYTE_ORDER == __BIG_ENDIAN
+
+/*
+ *		Make a Posix ACL CPU endian
+ */
+
+static int le_acl_to_cpu(const struct LE_POSIX_ACL *le_acl, size_t size,
+				struct POSIX_ACL *acl)
+{
+	int i;
+	int cnt;
+
+	acl->version = le_acl->version;
+	acl->flags = le_acl->flags;
+	acl->filler = 0;
+	cnt = (size - sizeof(struct LE_POSIX_ACL)) / sizeof(struct LE_POSIX_ACE);
+	for (i=0; i<cnt; i++) {
+		acl->ace[i].tag = le16_to_cpu(le_acl->ace[i].tag);
+		acl->ace[i].perms = le16_to_cpu(le_acl->ace[i].perms);
+		acl->ace[i].id = le32_to_cpu(le_acl->ace[i].id);
+	}
+	return (0);
+}
+
+/*
+ *		Make a Posix ACL little endian
+ */
+
+int cpu_to_le_acl(const struct POSIX_ACL *acl, size_t size,
+			struct LE_POSIX_ACL *le_acl)
+{
+	int i;
+	int cnt;
+
+	le_acl->version = acl->version;
+	le_acl->flags = acl->flags;
+	le_acl->filler = const_cpu_to_le16(0);
+	cnt = (size - sizeof(struct POSIX_ACL)) / sizeof(struct POSIX_ACE);
+	for (i=0; i<cnt; i++) {
+		le_acl->ace[i].tag = cpu_to_le16(acl->ace[i].tag);
+		le_acl->ace[i].perms = cpu_to_le16(acl->ace[i].perms);
+		le_acl->ace[i].id = cpu_to_le32(acl->ace[i].id);
+	}
+	return (0);
+}
+
+#endif
+#endif
+
+/*
+ *		Determine whether an extended attribute is mapped to
+ *	internal data (original name in system namespace, or renamed)
+ */
+
+enum SYSTEMXATTRS ntfs_xattr_system_type(const char *name,
+			ntfs_volume *vol)
+{
+	struct XATTRNAME *p;
+	enum SYSTEMXATTRS ret;
+#ifdef XATTR_MAPPINGS
+	const struct XATTRMAPPING *q;
+#endif /* XATTR_MAPPINGS */
+
+	p = nf_ns_xattr_names;
+	while (p->name && strcmp(p->name,name))
+		p++;
+	ret = p->xattr;
+#ifdef XATTR_MAPPINGS
+	if (!p->name && vol && vol->xattr_mapping) {
+		q = vol->xattr_mapping;
+		while (q && strcmp(q->name,name))
+			q = q->next;
+		if (q)
+			ret = q->xattr;
+	}
+#else /* XATTR_MAPPINGS */
+	if (!p->name
+	    && vol
+	    && vol->efs_raw
+	    && !strcmp(nf_ns_alt_xattr_efsinfo,name))
+		ret = XATTR_NTFS_EFSINFO;
+#endif /* XATTR_MAPPINGS */
+	return (ret);
+}
+
+#ifdef XATTR_MAPPINGS
+
+/*
+ *		Basic read from a user mapping file on another volume
+ */
+
+static int basicread(void *fileid, char *buf, size_t size, off_t offs __attribute__((unused)))
+{
+	return (read(*(int*)fileid, buf, size));
+}
+
+
+/*
+ *		Read from a user mapping file on current NTFS partition
+ */
+
+static int localread(void *fileid, char *buf, size_t size, off_t offs)
+{
+	return (ntfs_attr_data_read((ntfs_inode*)fileid,
+			AT_UNNAMED, 0, buf, size, offs));
+}
+
+/*
+ *		Get a single mapping item from buffer
+ *
+ *	Always reads a full line, truncating long lines
+ *	Refills buffer when exhausted
+ *	Returns pointer to item, or NULL when there is no more
+ *	Note : errors are logged, but not returned
+// TODO partially share with acls.c
+ */
+
+static struct XATTRMAPPING *getmappingitem(FILEREADER reader, void *fileid,
+		off_t *poffs, char *buf, int *psrc, s64 *psize)
+{
+	int src;
+	int dst;
+	char *pe;
+	char *ps;
+	char *pu;
+	enum SYSTEMXATTRS xattr;
+	int gotend;
+	char maptext[LINESZ];
+	struct XATTRMAPPING *item;
+
+	src = *psrc;
+	dst = 0;
+	do {
+		gotend = 0;
+		while ((src < *psize)
+		       && (buf[src] != '\n')) {
+				/* ignore spaces */
+			if ((dst < LINESZ)
+			    && (buf[src] != '\r')
+			    && (buf[src] != '\t')
+			    && (buf[src] != ' '))
+				maptext[dst++] = buf[src];
+			src++;
+		}
+		if (src >= *psize) {
+			*poffs += *psize;
+			*psize = reader(fileid, buf, (size_t)BUFSZ, *poffs);
+			src = 0;
+		} else {
+			gotend = 1;
+			src++;
+			maptext[dst] = '\0';
+			dst = 0;
+		}
+	} while (*psize && ((maptext[0] == '#') || !gotend));
+	item = (struct XATTRMAPPING*)NULL;
+	if (gotend) {
+			/* decompose into system name and user name */
+		ps = maptext;
+		pu = strchr(maptext,':');
+		if (pu) {
+			*pu++ = 0;
+			pe = strchr(pu,':');
+			if (pe)
+				*pe = 0;
+				/* check name validity */
+			if ((strlen(pu) < 6) || strncmp(pu,"user.",5))
+				pu = (char*)NULL;
+			xattr = ntfs_xattr_system_type(ps,
+					(ntfs_volume*)NULL);
+			if (xattr == XATTR_UNMAPPED)
+				pu = (char*)NULL;
+		}
+		if (pu) {
+			item = (struct XATTRMAPPING*)ntfs_malloc(
+				sizeof(struct XATTRMAPPING)
+				+ strlen(pu));
+			if (item) {
+				item->xattr = xattr;
+				strcpy(item->name,pu);
+				item->next = (struct XATTRMAPPING*)NULL;
+			}
+		} else {
+			ntfs_log_early_error("Bad xattr mapping item, aborting\n");
+		}
+	}
+	*psrc = src;
+	return (item);
+}
+
+/*
+ *		Read xattr mapping file and split into their attribute.
+ *	Parameters are kept in a chained list.
+ *	Returns the head of list, if any
+ *	Errors are logged, but not returned
+ *
+ *	If an absolute path is provided, the mapping file is assumed
+ *	to be located in another mounted file system, and plain read()
+ *	are used to get its contents.
+ *	If a relative path is provided, the mapping file is assumed
+ *	to be located on the current file system, and internal IO
+ *	have to be used since we are still mounting and we have not
+ *	entered the fuse loop yet.
+ */
+
+static struct XATTRMAPPING *ntfs_read_xattr_mapping(FILEREADER reader,
+				void *fileid)
+{
+	char buf[BUFSZ];
+	struct XATTRMAPPING *item;
+	struct XATTRMAPPING *current;
+	struct XATTRMAPPING *firstitem;
+	struct XATTRMAPPING *lastitem;
+	BOOL duplicated;
+	int src;
+	off_t offs;
+	s64 size;
+
+	firstitem = (struct XATTRMAPPING*)NULL;
+	lastitem = (struct XATTRMAPPING*)NULL;
+	offs = 0;
+	size = reader(fileid, buf, (size_t)BUFSZ, (off_t)0);
+	if (size > 0) {
+		src = 0;
+		do {
+			item = getmappingitem(reader, fileid, &offs,
+				buf, &src, &size);
+			if (item) {
+				/* check no double mapping */
+				duplicated = FALSE;
+				for (current=firstitem; current; current=current->next)
+					if ((current->xattr == item->xattr)
+					    || !strcmp(current->name,item->name))
+						duplicated = TRUE;
+				if (duplicated) {
+					free(item);
+					ntfs_log_early_error("Conflicting xattr mapping ignored\n");
+				} else {
+					item->next = (struct XATTRMAPPING*)NULL;
+					if (lastitem)
+						lastitem->next = item;
+					else
+						firstitem = item;
+					lastitem = item;
+				}
+			}
+		} while (item);
+	}
+	return (firstitem);
+}
+
+/*
+ *		Build the extended attribute mappings to user namespace
+ *
+ *	Note : no error is returned. If we refused mounting when there
+ *	is an error it would be too difficult to fix the offending file
+ */
+
+struct XATTRMAPPING *ntfs_xattr_build_mapping(ntfs_volume *vol,
+			const char *xattrmap_path)
+{
+	struct XATTRMAPPING *firstmapping;
+	struct XATTRMAPPING *mapping;
+	BOOL user_efs;
+	BOOL notfound;
+	ntfs_inode *ni;
+	int fd;
+
+	firstmapping = (struct XATTRMAPPING*)NULL;
+	notfound = FALSE;
+	if (!xattrmap_path)
+		xattrmap_path = XATTRMAPPINGFILE;
+	if (xattrmap_path[0] == '/') {
+		fd = open(xattrmap_path,O_RDONLY);
+		if (fd > 0) {
+			firstmapping = ntfs_read_xattr_mapping(basicread, (void*)&fd);
+			close(fd);
+		} else
+			notfound = TRUE;
+	} else {
+		ni = ntfs_pathname_to_inode(vol, NULL, xattrmap_path);
+		if (ni) {
+			firstmapping = ntfs_read_xattr_mapping(localread, ni);
+			ntfs_inode_close(ni);
+		} else
+			notfound = TRUE;
+	}
+	if (notfound && strcmp(xattrmap_path, XATTRMAPPINGFILE)) {
+		ntfs_log_early_error("Could not open \"%s\"\n",xattrmap_path);
+	}
+	if (vol->efs_raw) {
+		user_efs = TRUE;
+		for (mapping=firstmapping; mapping; mapping=mapping->next)
+			if (mapping->xattr == XATTR_NTFS_EFSINFO)
+				user_efs = FALSE;
+	} else
+		user_efs = FALSE;
+	if (user_efs) {
+		mapping = (struct XATTRMAPPING*)ntfs_malloc(
+				sizeof(struct XATTRMAPPING)
+				+ strlen(nf_ns_alt_xattr_efsinfo));
+		if (mapping) {
+			mapping->next = firstmapping;
+			mapping->xattr = XATTR_NTFS_EFSINFO;
+			strcpy(mapping->name,nf_ns_alt_xattr_efsinfo);
+			firstmapping = mapping;
+		}
+	}
+	return (firstmapping);
+}
+
+void ntfs_xattr_free_mapping(struct XATTRMAPPING *mapping)
+{
+	struct XATTRMAPPING *p, *q;
+
+	p = mapping;
+	while (p) {
+		q = p->next;
+		free(p);
+		p = q;
+	}
+}
+
+#endif /* XATTR_MAPPINGS */
+
+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 res;
+	int i;
+#if POSIXACLS
+#if __BYTE_ORDER == __BIG_ENDIAN
+	struct POSIX_ACL *acl;
+#endif
+#endif
+
+				/*
+				 * the returned value is the needed
+				 * size. If it is too small, no copy
+				 * is done, and the caller has to
+				 * issue a new call with correct size.
+				 */
+	switch (attr) {
+	case XATTR_NTFS_ACL :
+		res = ntfs_get_ntfs_acl(scx, ni, value, size);
+		break;
+#if POSIXACLS
+#if __BYTE_ORDER == __BIG_ENDIAN
+	case XATTR_POSIX_ACC :
+		acl = (struct POSIX_ACL*)ntfs_malloc(size);
+		if (acl) {
+			res = ntfs_get_posix_acl(scx, ni,
+				nf_ns_xattr_posix_access, (char*)acl, size);
+			if (res > 0) {
+				if (cpu_to_le_acl(acl,res,
+						(struct LE_POSIX_ACL*)value))
+					res = -errno;
+			}
+			free(acl);
+		} else
+			res = -errno;
+		break;
+	case XATTR_POSIX_DEF :
+		acl = (struct POSIX_ACL*)ntfs_malloc(size);
+		if (acl) {
+			res = ntfs_get_posix_acl(scx, ni,
+				nf_ns_xattr_posix_default, (char*)acl, size);
+			if (res > 0) {
+				if (cpu_to_le_acl(acl,res,
+						(struct LE_POSIX_ACL*)value))
+					res = -errno;
+			}
+			free(acl);
+		} else
+			res = -errno;
+		break;
+#else
+	case XATTR_POSIX_ACC :
+		res = ntfs_get_posix_acl(scx, ni, nf_ns_xattr_posix_access,
+				value, size);
+		break;
+	case XATTR_POSIX_DEF :
+		res = ntfs_get_posix_acl(scx, ni, nf_ns_xattr_posix_default,
+				value, size);
+		break;
+#endif
+#endif
+	case XATTR_NTFS_ATTRIB :
+		res = ntfs_get_ntfs_attrib(ni, value, size);
+		break;
+	case XATTR_NTFS_ATTRIB_BE :
+		res = ntfs_get_ntfs_attrib(ni, value, size);
+		if ((res == 4) && value) {
+			if (size >= 4)
+				fix_big_endian(value,4);
+			else
+				res = -EINVAL;
+		}
+		break;
+	case XATTR_NTFS_EFSINFO :
+		if (ni->vol->efs_raw)
+			res = ntfs_get_efs_info(ni, value, size);
+		else
+			res = -EPERM;
+		break;
+	case XATTR_NTFS_REPARSE_DATA :
+		res = ntfs_get_ntfs_reparse_data(ni, value, size);
+		break;
+	case XATTR_NTFS_OBJECT_ID :
+		res = ntfs_get_ntfs_object_id(ni, value, size);
+		break;
+	case XATTR_NTFS_DOS_NAME:
+		if (dir_ni)
+			res = ntfs_get_ntfs_dos_name(ni, dir_ni, value, size);
+		else
+			res = -errno;
+		break;
+	case XATTR_NTFS_TIMES:
+		res = ntfs_inode_get_times(ni, value, size);
+		break;
+	case XATTR_NTFS_TIMES_BE:
+		res = ntfs_inode_get_times(ni, value, size);
+		if ((res > 0) && value) {
+			for (i=0; (i+1)*sizeof(u64)<=(unsigned int)res; i++)
+				fix_big_endian(&value[i*sizeof(u64)],
+						sizeof(u64));
+		}
+		break;
+	case XATTR_NTFS_CRTIME:
+		res = ntfs_inode_get_times(ni, value,
+				(size >= sizeof(u64) ? sizeof(u64) : size));
+		break;
+	case XATTR_NTFS_CRTIME_BE:
+		res = ntfs_inode_get_times(ni, value,
+				(size >= sizeof(u64) ? sizeof(u64) : size));
+		if ((res >= (int)sizeof(u64)) && value)
+			fix_big_endian(value,sizeof(u64));
+		break;
+	case XATTR_NTFS_EA :
+		res = ntfs_get_ntfs_ea(ni, value, size);
+		break;
+	default :
+		errno = EOPNOTSUPP;
+		res = -errno;
+		break;
+	}
+	return (res);
+}
+
+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 res;
+	int i;
+	char buf[4*sizeof(u64)];
+#if POSIXACLS
+#if __BYTE_ORDER == __BIG_ENDIAN
+	struct POSIX_ACL *acl;
+#endif
+#endif
+
+	switch (attr) {
+	case XATTR_NTFS_ACL :
+		res = ntfs_set_ntfs_acl(scx, ni, value, size, flags);
+		break;
+#if POSIXACLS
+#if __BYTE_ORDER == __BIG_ENDIAN
+	case XATTR_POSIX_ACC :
+		acl = (struct POSIX_ACL*)ntfs_malloc(size);
+		if (acl) {
+			if (!le_acl_to_cpu((const struct LE_POSIX_ACL*)value,
+					size, acl)) {
+				res = ntfs_set_posix_acl(scx ,ni ,
+					nf_ns_xattr_posix_access,
+					(char*)acl, size, flags);
+			} else
+				res = -errno;
+			free(acl);
+		} else
+			res = -errno;
+		break;
+	case XATTR_POSIX_DEF :
+		acl = (struct POSIX_ACL*)ntfs_malloc(size);
+		if (acl) {
+			if (!le_acl_to_cpu((const struct LE_POSIX_ACL*)value,
+					size, acl)) {
+				res = ntfs_set_posix_acl(scx ,ni ,
+					nf_ns_xattr_posix_default,
+					(char*)acl, size, flags);
+			} else
+				res = -errno;
+			free(acl);
+		} else
+			res = -errno;
+		break;
+#else
+	case XATTR_POSIX_ACC :
+		res = ntfs_set_posix_acl(scx ,ni , nf_ns_xattr_posix_access,
+					value, size, flags);
+		break;
+	case XATTR_POSIX_DEF :
+		res = ntfs_set_posix_acl(scx, ni, nf_ns_xattr_posix_default,
+					value, size, flags);
+		break;
+#endif
+#endif
+	case XATTR_NTFS_ATTRIB :
+		res = ntfs_set_ntfs_attrib(ni, value, size, flags);
+		break;
+	case XATTR_NTFS_ATTRIB_BE :
+		if (value && (size >= 4)) {
+			memcpy(buf,value,4);
+			fix_big_endian(buf,4);
+			res = ntfs_set_ntfs_attrib(ni, buf, 4, flags);
+		} else
+			res = ntfs_set_ntfs_attrib(ni, value, size, flags);
+		break;
+	case XATTR_NTFS_EFSINFO :
+		if (ni->vol->efs_raw)
+			res = ntfs_set_efs_info(ni, value, size, flags);
+		else
+			res = -EPERM;
+		break;
+	case XATTR_NTFS_REPARSE_DATA :
+		res = ntfs_set_ntfs_reparse_data(ni, value, size, flags);
+		break;
+	case XATTR_NTFS_OBJECT_ID :
+		res = ntfs_set_ntfs_object_id(ni, value, size, flags);
+		break;
+	case XATTR_NTFS_DOS_NAME:
+		if (dir_ni)
+		/* warning : this closes both inodes */
+			res = ntfs_set_ntfs_dos_name(ni, dir_ni, value,
+						size, flags);
+		else
+			res = -errno;
+		break;
+	case XATTR_NTFS_TIMES:
+		res = ntfs_inode_set_times(ni, value, size, flags);
+		break;
+	case XATTR_NTFS_TIMES_BE:
+		if (value && (size > 0) && (size <= 4*sizeof(u64))) {
+			memcpy(buf,value,size);
+			for (i=0; (i+1)*sizeof(u64)<=size; i++)
+				fix_big_endian(&buf[i*sizeof(u64)],
+						sizeof(u64));
+			res = ntfs_inode_set_times(ni, buf, size, flags);
+		} else
+			res = ntfs_inode_set_times(ni, value, size, flags);
+		break;
+	case XATTR_NTFS_CRTIME:
+		res = ntfs_inode_set_times(ni, value,
+			(size >= sizeof(u64) ? sizeof(u64) : size), flags);
+		break;
+	case XATTR_NTFS_CRTIME_BE:
+		if (value && (size >= sizeof(u64))) {
+			memcpy(buf,value,sizeof(u64));
+			fix_big_endian(buf,sizeof(u64));
+			res = ntfs_inode_set_times(ni, buf, sizeof(u64), flags);
+		} else
+			res = ntfs_inode_set_times(ni, value, size, flags);
+		break;
+	case XATTR_NTFS_EA :
+		res = ntfs_set_ntfs_ea(ni, value, size, flags);
+		break;
+	default :
+		errno = EOPNOTSUPP;
+		res = -errno;
+		break;
+	}
+	return (res);
+}
+
+int ntfs_xattr_system_removexattr(struct SECURITY_CONTEXT *scx,
+			enum SYSTEMXATTRS attr,
+			ntfs_inode *ni, ntfs_inode *dir_ni)
+{
+	int res;
+
+	res = 0;
+	switch (attr) {
+		/*
+		 * Removal of NTFS ACL, ATTRIB, EFSINFO or TIMES
+		 * is never allowed
+		 */
+	case XATTR_NTFS_ACL :
+	case XATTR_NTFS_ATTRIB :
+	case XATTR_NTFS_ATTRIB_BE :
+	case XATTR_NTFS_EFSINFO :
+	case XATTR_NTFS_TIMES :
+	case XATTR_NTFS_TIMES_BE :
+	case XATTR_NTFS_CRTIME :
+	case XATTR_NTFS_CRTIME_BE :
+		res = -EPERM;
+		break;
+#if POSIXACLS
+	case XATTR_POSIX_ACC :
+	case XATTR_POSIX_DEF :
+		if (ni) {
+			if (!ntfs_allowed_as_owner(scx, ni)
+			   || ntfs_remove_posix_acl(scx, ni,
+					(attr == XATTR_POSIX_ACC ?
+					nf_ns_xattr_posix_access :
+					nf_ns_xattr_posix_default)))
+				res = -errno;
+		} else
+			res = -errno;
+		break;
+#endif
+	case XATTR_NTFS_REPARSE_DATA :
+		if (ni) {
+			if (!ntfs_allowed_as_owner(scx, ni)
+			    || ntfs_remove_ntfs_reparse_data(ni))
+				res = -errno;
+		} else
+			res = -errno;
+		break;
+	case XATTR_NTFS_OBJECT_ID :
+		if (ni) {
+			if (!ntfs_allowed_as_owner(scx, ni)
+			    || ntfs_remove_ntfs_object_id(ni))
+				res = -errno;
+		} else
+			res = -errno;
+		break;
+	case XATTR_NTFS_DOS_NAME:
+		if (ni && dir_ni) {
+			if (ntfs_remove_ntfs_dos_name(ni,dir_ni))
+				res = -errno;
+			/* ni and dir_ni have been closed */
+		} else
+			res = -errno;
+		break;
+	case XATTR_NTFS_EA :
+		res = ntfs_remove_ntfs_ea(ni);
+		break;
+	default :
+		errno = EOPNOTSUPP;
+		res = -errno;
+		break;
+	}
+	return (res);
+}
+
+#endif  /* HAVE_SETXATTR */
diff --git a/libtool b/libtool
new file mode 100755
index 0000000000000000000000000000000000000000..e0621560fef8937133312e3f781fcca8903189c6
--- /dev/null
+++ b/libtool
@@ -0,0 +1,10077 @@
+#! /bin/bash
+
+# libtool - Provide generalized library-building support services.
+# Generated automatically by config.status (ntfs-3g) 2015.3.14
+# Libtool was configured on host cmc-HP-Compaq-Pro-6380-MT:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+#                 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+#                 Foundation, Inc.
+#   Written by Gordon Matzigkeit, 1996
+#
+#   This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can 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.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that 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 GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+# The names of the tagged configurations supported by this script.
+available_tags=""
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Which release of libtool.m4 was used?
+macro_version=2.4.2
+macro_revision=1.3337
+
+# Whether or not to build shared libraries.
+build_libtool_libs=yes
+
+# Whether or not to build static libraries.
+build_old_libs=yes
+
+# What type of objects to build.
+pic_mode=default
+
+# Whether or not to optimize for fast installation.
+fast_install=yes
+
+# Shell to use when invoking shell scripts.
+SHELL="/bin/bash"
+
+# An echo program that protects backslashes.
+ECHO="printf %s\\n"
+
+# The PATH separator for the build system.
+PATH_SEPARATOR=":"
+
+# The host system.
+host_alias=
+host=x86_64-unknown-linux-gnu
+host_os=linux-gnu
+
+# The build system.
+build_alias=
+build=x86_64-unknown-linux-gnu
+build_os=linux-gnu
+
+# A sed program that does not truncate output.
+SED="/bin/sed"
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="$SED -e 1s/^X//"
+
+# A grep program that handles long lines.
+GREP="/bin/grep"
+
+# An ERE matcher.
+EGREP="/bin/grep -E"
+
+# A literal string matcher.
+FGREP="/bin/grep -F"
+
+# A BSD- or MS-compatible name lister.
+NM="/usr/bin/nm -B"
+
+# Whether we need soft or hard links.
+LN_S="ln -s"
+
+# What is the maximum length of a command?
+max_cmd_len=1572864
+
+# Object file suffix (normally "o").
+objext=o
+
+# Executable file suffix (normally "").
+exeext=
+
+# whether the shell understands "unset".
+lt_unset=unset
+
+# turn spaces into newlines.
+SP2NL="tr \\040 \\012"
+
+# turn newlines into spaces.
+NL2SP="tr \\015\\012 \\040\\040"
+
+# convert $build file names to $host format.
+to_host_file_cmd=func_convert_file_noop
+
+# convert $build files to toolchain format.
+to_tool_file_cmd=func_convert_file_noop
+
+# An object symbol dumper.
+OBJDUMP="objdump"
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method="pass_all"
+
+# Command to use when deplibs_check_method = "file_magic".
+file_magic_cmd="\$MAGIC_CMD"
+
+# How to find potential files when deplibs_check_method = "file_magic".
+file_magic_glob=""
+
+# Find potential files using nocaseglob when deplibs_check_method = "file_magic".
+want_nocaseglob="no"
+
+# DLL creation program.
+DLLTOOL="false"
+
+# Command to associate shared and link libraries.
+sharedlib_from_linklib_cmd="printf %s\\n"
+
+# The archiver.
+AR="ar"
+
+# Flags to create an archive.
+AR_FLAGS="cru"
+
+# How to feed a file listing to the archiver.
+archiver_list_spec="@"
+
+# A symbol stripping program.
+STRIP="strip"
+
+# Commands used to install an old-style archive.
+RANLIB="ranlib"
+old_postinstall_cmds="chmod 644 \$oldlib~\$RANLIB \$tool_oldlib"
+old_postuninstall_cmds=""
+
+# Whether to use a lock for old archive extraction.
+lock_old_archive_extraction=no
+
+# A C compiler.
+LTCC="gcc"
+
+# LTCC compiler flags.
+LTCFLAGS="-g -O2 -Wall"
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe="sed -n -e 's/^.*[	 ]\\([ABCDGIRSTW][ABCDGIRSTW]*\\)[	 ][	 ]*\\([_A-Za-z][_A-Za-z0-9]*\\)\$/\\1 \\2 \\2/p' | sed '/ __gnu_lto/d'"
+
+# Transform the output of nm in a proper C declaration.
+global_symbol_to_cdecl="sed -n -e 's/^T .* \\(.*\\)\$/extern int \\1();/p' -e 's/^[ABCDGIRSTW]* .* \\(.*\\)\$/extern char \\1;/p'"
+
+# Transform the output of nm in a C name address pair.
+global_symbol_to_c_name_address="sed -n -e 's/^: \\([^ ]*\\)[ ]*\$/  {\\\"\\1\\\", (void *) 0},/p' -e 's/^[ABCDGIRSTW]* \\([^ ]*\\) \\([^ ]*\\)\$/  {\"\\2\", (void *) \\&\\2},/p'"
+
+# Transform the output of nm in a C name address pair when lib prefix is needed.
+global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \\([^ ]*\\)[ ]*\$/  {\\\"\\1\\\", (void *) 0},/p' -e 's/^[ABCDGIRSTW]* \\([^ ]*\\) \\(lib[^ ]*\\)\$/  {\"\\2\", (void *) \\&\\2},/p' -e 's/^[ABCDGIRSTW]* \\([^ ]*\\) \\([^ ]*\\)\$/  {\"lib\\2\", (void *) \\&\\2},/p'"
+
+# Specify filename containing input files for $NM.
+nm_file_list_spec="@"
+
+# The root where to search for dependent libraries,and in which our libraries should be installed.
+lt_sysroot=
+
+# The name of the directory that contains temporary libtool files.
+objdir=.libs
+
+# Used to examine libraries when file_magic_cmd begins with "file".
+MAGIC_CMD=file
+
+# Must we lock files when doing compilation?
+need_locks="no"
+
+# Manifest tool.
+MANIFEST_TOOL=":"
+
+# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
+DSYMUTIL=""
+
+# Tool to change global to local symbols on Mac OS X.
+NMEDIT=""
+
+# Tool to manipulate fat objects and archives on Mac OS X.
+LIPO=""
+
+# ldd/readelf like tool for Mach-O binaries on Mac OS X.
+OTOOL=""
+
+# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
+OTOOL64=""
+
+# Old archive suffix (normally "a").
+libext=a
+
+# Shared library suffix (normally ".so").
+shrext_cmds=".so"
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=""
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at link time.
+variables_saved_for_relink="PATH LD_LIBRARY_PATH LD_RUN_PATH GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+
+# Do we need the "lib" prefix for modules?
+need_lib_prefix=no
+
+# Do we need a version for libraries?
+need_version=no
+
+# Library versioning type.
+version_type=linux
+
+# Shared library runtime path variable.
+runpath_var=LD_RUN_PATH
+
+# Shared library path variable.
+shlibpath_var=LD_LIBRARY_PATH
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=no
+
+# Format of library name prefix.
+libname_spec="lib\$name"
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME
+library_names_spec="\${libname}\${release}\${shared_ext}\$versuffix \${libname}\${release}\${shared_ext}\$major \$libname\${shared_ext}"
+
+# The coded name of the library, if different from the real name.
+soname_spec="\${libname}\${release}\${shared_ext}\$major"
+
+# Permission mode override for installation of shared libraries.
+install_override_mode=""
+
+# Command to use after installation of a shared archive.
+postinstall_cmds=""
+
+# Command to use after uninstallation of a shared archive.
+postuninstall_cmds=""
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds="PATH=\\\"\\\$PATH:/sbin\\\" ldconfig -n \$libdir"
+
+# As "finish_cmds", except a single script fragment to be evaled but
+# not shown.
+finish_eval=""
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=yes
+
+# Compile-time system search path for libraries.
+sys_lib_search_path_spec="/usr/lib/gcc/x86_64-linux-gnu/4.8 /usr/lib/x86_64-linux-gnu /usr/lib /lib/x86_64-linux-gnu /lib "
+
+# Run-time system search path for libraries.
+sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib /usr/lib/x86_64-linux-gnu/libfakeroot /lib/i386-linux-gnu /usr/lib/i386-linux-gnu /lib/i686-linux-gnu /usr/lib/i686-linux-gnu /usr/local/lib /lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu/mesa-egl /usr/lib/x86_64-linux-gnu/mesa /usr/lib/x86_64-linux-gnu/mir/clientplatform/mesa /lib32 /usr/lib32 /libx32 /usr/libx32 "
+
+# Whether dlopen is supported.
+dlopen_support=unknown
+
+# Whether dlopen of programs is supported.
+dlopen_self=unknown
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=unknown
+
+# Commands to strip libraries.
+old_striplib="strip --strip-debug"
+striplib="strip --strip-unneeded"
+
+
+# The linker used to build libraries.
+LD="/usr/bin/ld -m elf_x86_64"
+
+# How to create reloadable object files.
+reload_flag=" -r"
+reload_cmds="\$LD\$reload_flag -o \$output\$reload_objs"
+
+# Commands used to build an old-style archive.
+old_archive_cmds="\$AR \$AR_FLAGS \$oldlib\$oldobjs~\$RANLIB \$tool_oldlib"
+
+# A language specific compiler.
+CC="gcc"
+
+# Is the compiler the GNU compiler?
+with_gcc=yes
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=" -fno-builtin"
+
+# Additional compiler flags for building library objects.
+pic_flag=" -fPIC -DPIC"
+
+# How to pass a linker flag through the compiler.
+wl="-Wl,"
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag="-static"
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o="yes"
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=no
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=no
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec="\${wl}--export-dynamic"
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec="\${wl}--whole-archive\$convenience \${wl}--no-whole-archive"
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object="no"
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=""
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=""
+
+# Commands used to build a shared archive.
+archive_cmds="\$CC -shared \$pic_flag \$libobjs \$deplibs \$compiler_flags \${wl}-soname \$wl\$soname -o \$lib"
+archive_expsym_cmds="echo \\\"{ global:\\\" > \$output_objdir/\$libname.ver~
+	    cat \$export_symbols | sed -e \\\"s/\\\\(.*\\\\)/\\\\1;/\\\" >> \$output_objdir/\$libname.ver~
+	    echo \\\"local: *; };\\\" >> \$output_objdir/\$libname.ver~
+	    \$CC -shared \$pic_flag \$libobjs \$deplibs \$compiler_flags \${wl}-soname \$wl\$soname \${wl}-version-script \${wl}\$output_objdir/\$libname.ver -o \$lib"
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=""
+module_expsym_cmds=""
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld="yes"
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=""
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=""
+
+# Flag to hardcode $libdir into a binary during linking.
+# This must work even if $libdir does not exist
+hardcode_libdir_flag_spec="\${wl}-rpath \${wl}\$libdir"
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=""
+
+# Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=no
+
+# Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting ${shlibpath_var} if the
+# library is relocated.
+hardcode_direct_absolute=no
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=no
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=unsupported
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=no
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=no
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=unknown
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=no
+
+# The commands to list exported symbols.
+export_symbols_cmds="\$NM \$libobjs \$convenience | \$global_symbol_pipe | \$SED 's/.* //' | sort | uniq > \$export_symbols"
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms="_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*"
+
+# Symbols that must always be exported.
+include_expsyms=""
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=""
+
+# Commands necessary for finishing linking programs.
+postlink_cmds=""
+
+# Specify filename containing input files.
+file_list_spec=""
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=immediate
+
+# ### END LIBTOOL CONFIG
+
+
+# libtool (GNU libtool) 2.4.2
+# Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006,
+# 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions.  There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# GNU Libtool is free software; you can 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.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that 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 GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html,
+# or obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# Usage: $progname [OPTION]... [MODE-ARG]...
+#
+# Provide generalized library-building support services.
+#
+#       --config             show all configuration variables
+#       --debug              enable verbose shell tracing
+#   -n, --dry-run            display commands without modifying any files
+#       --features           display basic configuration information and exit
+#       --mode=MODE          use operation mode MODE
+#       --preserve-dup-deps  don't remove duplicate dependency libraries
+#       --quiet, --silent    don't print informational messages
+#       --no-quiet, --no-silent
+#                            print informational messages (default)
+#       --no-warn            don't display warning messages
+#       --tag=TAG            use configuration variables from tag TAG
+#   -v, --verbose            print more informational messages than default
+#       --no-verbose         don't print the extra informational messages
+#       --version            print version information
+#   -h, --help, --help-all   print short, long, or detailed help message
+#
+# MODE must be one of the following:
+#
+#         clean              remove files from the build directory
+#         compile            compile a source file into a libtool object
+#         execute            automatically set library path, then run a program
+#         finish             complete the installation of libtool libraries
+#         install            install libraries or executables
+#         link               create a library or an executable
+#         uninstall          remove libraries from an installed directory
+#
+# MODE-ARGS vary depending on the MODE.  When passed as first option,
+# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that.
+# Try `$progname --help --mode=MODE' for a more detailed description of MODE.
+#
+# When reporting a bug, please describe a test case to reproduce it and
+# include the following information:
+#
+#         host-triplet:	$host
+#         shell:		$SHELL
+#         compiler:		$LTCC
+#         compiler flags:		$LTCFLAGS
+#         linker:		$LD (gnu? $with_gnu_ld)
+#         $progname:	(GNU libtool) 2.4.2
+#         automake:	$automake_version
+#         autoconf:	$autoconf_version
+#
+# Report bugs to <bug-libtool@gnu.org>.
+# GNU libtool home page: <http://www.gnu.org/software/libtool/>.
+# General help using GNU software: <http://www.gnu.org/gethelp/>.
+
+PROGRAM=libtool
+PACKAGE=libtool
+VERSION=2.4.2
+TIMESTAMP=""
+package_revision=1.3337
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+}
+
+# NLS nuisances: We save the old values to restore during execute mode.
+lt_user_locale=
+lt_safe_locale=
+for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+do
+  eval "if test \"\${$lt_var+set}\" = set; then
+          save_$lt_var=\$$lt_var
+          $lt_var=C
+	  export $lt_var
+	  lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\"
+	  lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\"
+	fi"
+done
+LC_ALL=C
+LANGUAGE=C
+export LANGUAGE LC_ALL
+
+$lt_unset CDPATH
+
+
+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
+# is ksh but when the shell is invoked as "sh" and the current value of
+# the _XPG environment variable is not equal to 1 (one), the special
+# positional parameter $0, within a function call, is the name of the
+# function.
+progpath="$0"
+
+
+
+: ${CP="cp -f"}
+test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'}
+: ${MAKE="make"}
+: ${MKDIR="mkdir"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+: ${SHELL="${CONFIG_SHELL-/bin/sh}"}
+: ${Xsed="$SED -e 1s/^X//"}
+
+# Global variables:
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+EXIT_MISMATCH=63  # $? = 63 is used to indicate version mismatch to missing.
+EXIT_SKIP=77	  # $? = 77 is used to indicate a skipped test to automake.
+
+exit_status=$EXIT_SUCCESS
+
+# Make sure IFS has a sensible default
+lt_nl='
+'
+IFS=" 	$lt_nl"
+
+dirname="s,/[^/]*$,,"
+basename="s,^.*/,,"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+    case ${1} in
+      */*) func_dirname_result="${1%/*}${2}" ;;
+      *  ) func_dirname_result="${3}" ;;
+    esac
+} # Extended-shell func_dirname implementation
+
+
+# func_basename file
+func_basename ()
+{
+    func_basename_result="${1##*/}"
+} # Extended-shell func_basename implementation
+
+
+# func_dirname_and_basename file append nondir_replacement
+# perform func_basename and func_dirname in a single function
+# call:
+#   dirname:  Compute the dirname of FILE.  If nonempty,
+#             add APPEND to the result, otherwise set result
+#             to NONDIR_REPLACEMENT.
+#             value returned in "$func_dirname_result"
+#   basename: Compute filename of FILE.
+#             value retuned in "$func_basename_result"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+    case ${1} in
+      */*) func_dirname_result="${1%/*}${2}" ;;
+      *  ) func_dirname_result="${3}" ;;
+    esac
+    func_basename_result="${1##*/}"
+} # Extended-shell func_dirname_and_basename implementation
+
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+# func_strip_suffix prefix name
+func_stripname ()
+{
+    # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+    # positional parameters, so assign one to ordinary parameter first.
+    func_stripname_result=${3}
+    func_stripname_result=${func_stripname_result#"${1}"}
+    func_stripname_result=${func_stripname_result%"${2}"}
+} # Extended-shell func_stripname implementation
+
+
+# These SED scripts presuppose an absolute path with a trailing slash.
+pathcar='s,^/\([^/]*\).*$,\1,'
+pathcdr='s,^/[^/]*,,'
+removedotparts=':dotsl
+		s@/\./@/@g
+		t dotsl
+		s,/\.$,/,'
+collapseslashes='s@/\{1,\}@/@g'
+finalslash='s,/*$,/,'
+
+# func_normal_abspath PATH
+# Remove doubled-up and trailing slashes, "." path components,
+# and cancel out any ".." path components in PATH after making
+# it an absolute path.
+#             value returned in "$func_normal_abspath_result"
+func_normal_abspath ()
+{
+  # Start from root dir and reassemble the path.
+  func_normal_abspath_result=
+  func_normal_abspath_tpath=$1
+  func_normal_abspath_altnamespace=
+  case $func_normal_abspath_tpath in
+    "")
+      # Empty path, that just means $cwd.
+      func_stripname '' '/' "`pwd`"
+      func_normal_abspath_result=$func_stripname_result
+      return
+    ;;
+    # The next three entries are used to spot a run of precisely
+    # two leading slashes without using negated character classes;
+    # we take advantage of case's first-match behaviour.
+    ///*)
+      # Unusual form of absolute path, do nothing.
+    ;;
+    //*)
+      # Not necessarily an ordinary path; POSIX reserves leading '//'
+      # and for example Cygwin uses it to access remote file shares
+      # over CIFS/SMB, so we conserve a leading double slash if found.
+      func_normal_abspath_altnamespace=/
+    ;;
+    /*)
+      # Absolute path, do nothing.
+    ;;
+    *)
+      # Relative path, prepend $cwd.
+      func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath
+    ;;
+  esac
+  # Cancel out all the simple stuff to save iterations.  We also want
+  # the path to end with a slash for ease of parsing, so make sure
+  # there is one (and only one) here.
+  func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
+        -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"`
+  while :; do
+    # Processed it all yet?
+    if test "$func_normal_abspath_tpath" = / ; then
+      # If we ascended to the root using ".." the result may be empty now.
+      if test -z "$func_normal_abspath_result" ; then
+        func_normal_abspath_result=/
+      fi
+      break
+    fi
+    func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \
+        -e "$pathcar"`
+    func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
+        -e "$pathcdr"`
+    # Figure out what to do with it
+    case $func_normal_abspath_tcomponent in
+      "")
+        # Trailing empty path component, ignore it.
+      ;;
+      ..)
+        # Parent dir; strip last assembled component from result.
+        func_dirname "$func_normal_abspath_result"
+        func_normal_abspath_result=$func_dirname_result
+      ;;
+      *)
+        # Actual path component, append it.
+        func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent
+      ;;
+    esac
+  done
+  # Restore leading double-slash if one was found on entry.
+  func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result
+}
+
+# func_relative_path SRCDIR DSTDIR
+# generates a relative path from SRCDIR to DSTDIR, with a trailing
+# slash if non-empty, suitable for immediately appending a filename
+# without needing to append a separator.
+#             value returned in "$func_relative_path_result"
+func_relative_path ()
+{
+  func_relative_path_result=
+  func_normal_abspath "$1"
+  func_relative_path_tlibdir=$func_normal_abspath_result
+  func_normal_abspath "$2"
+  func_relative_path_tbindir=$func_normal_abspath_result
+
+  # Ascend the tree starting from libdir
+  while :; do
+    # check if we have found a prefix of bindir
+    case $func_relative_path_tbindir in
+      $func_relative_path_tlibdir)
+        # found an exact match
+        func_relative_path_tcancelled=
+        break
+        ;;
+      $func_relative_path_tlibdir*)
+        # found a matching prefix
+        func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir"
+        func_relative_path_tcancelled=$func_stripname_result
+        if test -z "$func_relative_path_result"; then
+          func_relative_path_result=.
+        fi
+        break
+        ;;
+      *)
+        func_dirname $func_relative_path_tlibdir
+        func_relative_path_tlibdir=${func_dirname_result}
+        if test "x$func_relative_path_tlibdir" = x ; then
+          # Have to descend all the way to the root!
+          func_relative_path_result=../$func_relative_path_result
+          func_relative_path_tcancelled=$func_relative_path_tbindir
+          break
+        fi
+        func_relative_path_result=../$func_relative_path_result
+        ;;
+    esac
+  done
+
+  # Now calculate path; take care to avoid doubling-up slashes.
+  func_stripname '' '/' "$func_relative_path_result"
+  func_relative_path_result=$func_stripname_result
+  func_stripname '/' '/' "$func_relative_path_tcancelled"
+  if test "x$func_stripname_result" != x ; then
+    func_relative_path_result=${func_relative_path_result}/${func_stripname_result}
+  fi
+
+  # Normalisation. If bindir is libdir, return empty string,
+  # else relative path ending with a slash; either way, target
+  # file name can be directly appended.
+  if test ! -z "$func_relative_path_result"; then
+    func_stripname './' '' "$func_relative_path_result/"
+    func_relative_path_result=$func_stripname_result
+  fi
+}
+
+# The name of this program:
+func_dirname_and_basename "$progpath"
+progname=$func_basename_result
+
+# Make sure we have an absolute path for reexecution:
+case $progpath in
+  [\\/]*|[A-Za-z]:\\*) ;;
+  *[\\/]*)
+     progdir=$func_dirname_result
+     progdir=`cd "$progdir" && pwd`
+     progpath="$progdir/$progname"
+     ;;
+  *)
+     save_IFS="$IFS"
+     IFS=${PATH_SEPARATOR-:}
+     for progdir in $PATH; do
+       IFS="$save_IFS"
+       test -x "$progdir/$progname" && break
+     done
+     IFS="$save_IFS"
+     test -n "$progdir" || progdir=`pwd`
+     progpath="$progdir/$progname"
+     ;;
+esac
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed="${SED}"' -e 1s/^X//'
+sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Sed substitution that turns a string into a regex matching for the
+# string literally.
+sed_make_literal_regex='s,[].[^$\\*\/],\\&,g'
+
+# Sed substitution that converts a w32 file name or path
+# which contains forward slashes, into one that contains
+# (escaped) backslashes.  A very naive implementation.
+lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
+
+# Re-`\' parameter expansions in output of double_quote_subst that were
+# `\'-ed in input to the same.  If an odd number of `\' preceded a '$'
+# in input to double_quote_subst, that '$' was protected from expansion.
+# Since each input `\' is now two `\'s, look for any number of runs of
+# four `\'s followed by two `\'s and then a '$'.  `\' that '$'.
+bs='\\'
+bs2='\\\\'
+bs4='\\\\\\\\'
+dollar='\$'
+sed_double_backslash="\
+  s/$bs4/&\\
+/g
+  s/^$bs2$dollar/$bs&/
+  s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g
+  s/\n//g"
+
+# Standard options:
+opt_dry_run=false
+opt_help=false
+opt_quiet=false
+opt_verbose=false
+opt_warning=:
+
+# func_echo arg...
+# Echo program name prefixed message, along with the current mode
+# name if it has been set yet.
+func_echo ()
+{
+    $ECHO "$progname: ${opt_mode+$opt_mode: }$*"
+}
+
+# func_verbose arg...
+# Echo program name prefixed message in verbose mode only.
+func_verbose ()
+{
+    $opt_verbose && func_echo ${1+"$@"}
+
+    # A bug in bash halts the script if the last line of a function
+    # fails when set -e is in force, so we need another command to
+    # work around that:
+    :
+}
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+    $ECHO "$*"
+}
+
+# func_error arg...
+# Echo program name prefixed message to standard error.
+func_error ()
+{
+    $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2
+}
+
+# func_warning arg...
+# Echo program name prefixed warning message to standard error.
+func_warning ()
+{
+    $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2
+
+    # bash bug again:
+    :
+}
+
+# func_fatal_error arg...
+# Echo program name prefixed message to standard error, and exit.
+func_fatal_error ()
+{
+    func_error ${1+"$@"}
+    exit $EXIT_FAILURE
+}
+
+# func_fatal_help arg...
+# Echo program name prefixed message to standard error, followed by
+# a help hint, and exit.
+func_fatal_help ()
+{
+    func_error ${1+"$@"}
+    func_fatal_error "$help"
+}
+help="Try \`$progname --help' for more information."  ## default
+
+
+# func_grep expression filename
+# Check whether EXPRESSION matches any line of FILENAME, without output.
+func_grep ()
+{
+    $GREP "$1" "$2" >/dev/null 2>&1
+}
+
+
+# func_mkdir_p directory-path
+# Make sure the entire path to DIRECTORY-PATH is available.
+func_mkdir_p ()
+{
+    my_directory_path="$1"
+    my_dir_list=
+
+    if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then
+
+      # Protect directory names starting with `-'
+      case $my_directory_path in
+        -*) my_directory_path="./$my_directory_path" ;;
+      esac
+
+      # While some portion of DIR does not yet exist...
+      while test ! -d "$my_directory_path"; do
+        # ...make a list in topmost first order.  Use a colon delimited
+	# list incase some portion of path contains whitespace.
+        my_dir_list="$my_directory_path:$my_dir_list"
+
+        # If the last portion added has no slash in it, the list is done
+        case $my_directory_path in */*) ;; *) break ;; esac
+
+        # ...otherwise throw away the child directory and loop
+        my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"`
+      done
+      my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'`
+
+      save_mkdir_p_IFS="$IFS"; IFS=':'
+      for my_dir in $my_dir_list; do
+	IFS="$save_mkdir_p_IFS"
+        # mkdir can fail with a `File exist' error if two processes
+        # try to create one of the directories concurrently.  Don't
+        # stop in that case!
+        $MKDIR "$my_dir" 2>/dev/null || :
+      done
+      IFS="$save_mkdir_p_IFS"
+
+      # Bail out if we (or some other process) failed to create a directory.
+      test -d "$my_directory_path" || \
+        func_fatal_error "Failed to create \`$1'"
+    fi
+}
+
+
+# func_mktempdir [string]
+# Make a temporary directory that won't clash with other running
+# libtool processes, and avoids race conditions if possible.  If
+# given, STRING is the basename for that directory.
+func_mktempdir ()
+{
+    my_template="${TMPDIR-/tmp}/${1-$progname}"
+
+    if test "$opt_dry_run" = ":"; then
+      # Return a directory name, but don't create it in dry-run mode
+      my_tmpdir="${my_template}-$$"
+    else
+
+      # If mktemp works, use that first and foremost
+      my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
+
+      if test ! -d "$my_tmpdir"; then
+        # Failing that, at least try and use $RANDOM to avoid a race
+        my_tmpdir="${my_template}-${RANDOM-0}$$"
+
+        save_mktempdir_umask=`umask`
+        umask 0077
+        $MKDIR "$my_tmpdir"
+        umask $save_mktempdir_umask
+      fi
+
+      # If we're not in dry-run mode, bomb out on failure
+      test -d "$my_tmpdir" || \
+        func_fatal_error "cannot create temporary directory \`$my_tmpdir'"
+    fi
+
+    $ECHO "$my_tmpdir"
+}
+
+
+# func_quote_for_eval arg
+# Aesthetically quote ARG to be evaled later.
+# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT
+# is double-quoted, suitable for a subsequent eval, whereas
+# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters
+# which are still active within double quotes backslashified.
+func_quote_for_eval ()
+{
+    case $1 in
+      *[\\\`\"\$]*)
+	func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;;
+      *)
+        func_quote_for_eval_unquoted_result="$1" ;;
+    esac
+
+    case $func_quote_for_eval_unquoted_result in
+      # Double-quote args containing shell metacharacters to delay
+      # word splitting, command substitution and and variable
+      # expansion for a subsequent eval.
+      # Many Bourne shells cannot handle close brackets correctly
+      # in scan sets, so we specify it separately.
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+        func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\""
+        ;;
+      *)
+        func_quote_for_eval_result="$func_quote_for_eval_unquoted_result"
+    esac
+}
+
+
+# func_quote_for_expand arg
+# Aesthetically quote ARG to be evaled later; same as above,
+# but do not quote variable references.
+func_quote_for_expand ()
+{
+    case $1 in
+      *[\\\`\"]*)
+	my_arg=`$ECHO "$1" | $SED \
+	    -e "$double_quote_subst" -e "$sed_double_backslash"` ;;
+      *)
+        my_arg="$1" ;;
+    esac
+
+    case $my_arg in
+      # Double-quote args containing shell metacharacters to delay
+      # word splitting and command substitution for a subsequent eval.
+      # Many Bourne shells cannot handle close brackets correctly
+      # in scan sets, so we specify it separately.
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+        my_arg="\"$my_arg\""
+        ;;
+    esac
+
+    func_quote_for_expand_result="$my_arg"
+}
+
+
+# func_show_eval cmd [fail_exp]
+# Unless opt_silent is true, then output CMD.  Then, if opt_dryrun is
+# not true, evaluate CMD.  If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it.
+func_show_eval ()
+{
+    my_cmd="$1"
+    my_fail_exp="${2-:}"
+
+    ${opt_silent-false} || {
+      func_quote_for_expand "$my_cmd"
+      eval "func_echo $func_quote_for_expand_result"
+    }
+
+    if ${opt_dry_run-false}; then :; else
+      eval "$my_cmd"
+      my_status=$?
+      if test "$my_status" -eq 0; then :; else
+	eval "(exit $my_status); $my_fail_exp"
+      fi
+    fi
+}
+
+
+# func_show_eval_locale cmd [fail_exp]
+# Unless opt_silent is true, then output CMD.  Then, if opt_dryrun is
+# not true, evaluate CMD.  If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it.  Use the saved locale for evaluation.
+func_show_eval_locale ()
+{
+    my_cmd="$1"
+    my_fail_exp="${2-:}"
+
+    ${opt_silent-false} || {
+      func_quote_for_expand "$my_cmd"
+      eval "func_echo $func_quote_for_expand_result"
+    }
+
+    if ${opt_dry_run-false}; then :; else
+      eval "$lt_user_locale
+	    $my_cmd"
+      my_status=$?
+      eval "$lt_safe_locale"
+      if test "$my_status" -eq 0; then :; else
+	eval "(exit $my_status); $my_fail_exp"
+      fi
+    fi
+}
+
+# func_tr_sh
+# Turn $1 into a string suitable for a shell variable name.
+# Result is stored in $func_tr_sh_result.  All characters
+# not in the set a-zA-Z0-9_ are replaced with '_'. Further,
+# if $1 begins with a digit, a '_' is prepended as well.
+func_tr_sh ()
+{
+  case $1 in
+  [0-9]* | *[!a-zA-Z0-9_]*)
+    func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'`
+    ;;
+  * )
+    func_tr_sh_result=$1
+    ;;
+  esac
+}
+
+
+# func_version
+# Echo version message to standard output and exit.
+func_version ()
+{
+    $opt_debug
+
+    $SED -n '/(C)/!b go
+	:more
+	/\./!{
+	  N
+	  s/\n# / /
+	  b more
+	}
+	:go
+	/^# '$PROGRAM' (GNU /,/# warranty; / {
+        s/^# //
+	s/^# *$//
+        s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/
+        p
+     }' < "$progpath"
+     exit $?
+}
+
+# func_usage
+# Echo short help message to standard output and exit.
+func_usage ()
+{
+    $opt_debug
+
+    $SED -n '/^# Usage:/,/^#  *.*--help/ {
+        s/^# //
+	s/^# *$//
+	s/\$progname/'$progname'/
+	p
+    }' < "$progpath"
+    echo
+    $ECHO "run \`$progname --help | more' for full usage"
+    exit $?
+}
+
+# func_help [NOEXIT]
+# Echo long help message to standard output and exit,
+# unless 'noexit' is passed as argument.
+func_help ()
+{
+    $opt_debug
+
+    $SED -n '/^# Usage:/,/# Report bugs to/ {
+	:print
+        s/^# //
+	s/^# *$//
+	s*\$progname*'$progname'*
+	s*\$host*'"$host"'*
+	s*\$SHELL*'"$SHELL"'*
+	s*\$LTCC*'"$LTCC"'*
+	s*\$LTCFLAGS*'"$LTCFLAGS"'*
+	s*\$LD*'"$LD"'*
+	s/\$with_gnu_ld/'"$with_gnu_ld"'/
+	s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/
+	s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/
+	p
+	d
+     }
+     /^# .* home page:/b print
+     /^# General help using/b print
+     ' < "$progpath"
+    ret=$?
+    if test -z "$1"; then
+      exit $ret
+    fi
+}
+
+# func_missing_arg argname
+# Echo program name prefixed message to standard error and set global
+# exit_cmd.
+func_missing_arg ()
+{
+    $opt_debug
+
+    func_error "missing argument for $1."
+    exit_cmd=exit
+}
+
+
+# func_split_short_opt shortopt
+# Set func_split_short_opt_name and func_split_short_opt_arg shell
+# variables after splitting SHORTOPT after the 2nd character.
+func_split_short_opt ()
+{
+    func_split_short_opt_arg=${1#??}
+    func_split_short_opt_name=${1%"$func_split_short_opt_arg"}
+} # Extended-shell func_split_short_opt implementation
+
+
+# func_split_long_opt longopt
+# Set func_split_long_opt_name and func_split_long_opt_arg shell
+# variables after splitting LONGOPT at the `=' sign.
+func_split_long_opt ()
+{
+    func_split_long_opt_name=${1%%=*}
+    func_split_long_opt_arg=${1#*=}
+} # Extended-shell func_split_long_opt implementation
+
+exit_cmd=:
+
+
+
+
+
+magic="%%%MAGIC variable%%%"
+magic_exe="%%%MAGIC EXE variable%%%"
+
+# Global variables.
+nonopt=
+preserve_args=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+extracted_archives=
+extracted_serial=0
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end.  This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+    eval "${1}+=\${2}"
+} # Extended-shell func_append implementation
+
+# func_append_quoted var value
+# Quote VALUE and append to the end of shell variable VAR, separated
+# by a space.
+func_append_quoted ()
+{
+    func_quote_for_eval "${2}"
+    eval "${1}+=\\ \$func_quote_for_eval_result"
+} # Extended-shell func_append_quoted implementation
+
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+    func_arith_result=$(( $* ))
+} # Extended-shell func_arith implementation
+
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+    func_len_result=${#1}
+} # Extended-shell func_len implementation
+
+
+# func_lo2o object
+func_lo2o ()
+{
+    case ${1} in
+      *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
+      *)    func_lo2o_result=${1} ;;
+    esac
+} # Extended-shell func_lo2o implementation
+
+
+# func_xform libobj-or-source
+func_xform ()
+{
+    func_xform_result=${1%.*}.lo
+} # Extended-shell func_xform implementation
+
+
+# func_fatal_configuration arg...
+# Echo program name prefixed message to standard error, followed by
+# a configuration failure hint, and exit.
+func_fatal_configuration ()
+{
+    func_error ${1+"$@"}
+    func_error "See the $PACKAGE documentation for more information."
+    func_fatal_error "Fatal configuration error."
+}
+
+
+# func_config
+# Display the configuration for all the tags in this script.
+func_config ()
+{
+    re_begincf='^# ### BEGIN LIBTOOL'
+    re_endcf='^# ### END LIBTOOL'
+
+    # Default configuration.
+    $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath"
+
+    # Now print the configurations for the tags.
+    for tagname in $taglist; do
+      $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath"
+    done
+
+    exit $?
+}
+
+# func_features
+# Display the features supported by this script.
+func_features ()
+{
+    echo "host: $host"
+    if test "$build_libtool_libs" = yes; then
+      echo "enable shared libraries"
+    else
+      echo "disable shared libraries"
+    fi
+    if test "$build_old_libs" = yes; then
+      echo "enable static libraries"
+    else
+      echo "disable static libraries"
+    fi
+
+    exit $?
+}
+
+# func_enable_tag tagname
+# Verify that TAGNAME is valid, and either flag an error and exit, or
+# enable the TAGNAME tag.  We also add TAGNAME to the global $taglist
+# variable here.
+func_enable_tag ()
+{
+  # Global variable:
+  tagname="$1"
+
+  re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$"
+  re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$"
+  sed_extractcf="/$re_begincf/,/$re_endcf/p"
+
+  # Validate tagname.
+  case $tagname in
+    *[!-_A-Za-z0-9,/]*)
+      func_fatal_error "invalid tag name: $tagname"
+      ;;
+  esac
+
+  # Don't test for the "default" C tag, as we know it's
+  # there but not specially marked.
+  case $tagname in
+    CC) ;;
+    *)
+      if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then
+	taglist="$taglist $tagname"
+
+	# Evaluate the configuration.  Be careful to quote the path
+	# and the sed script, to avoid splitting on whitespace, but
+	# also don't use non-portable quotes within backquotes within
+	# quotes we have to do it in 2 steps:
+	extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"`
+	eval "$extractedcf"
+      else
+	func_error "ignoring unknown tag $tagname"
+      fi
+      ;;
+  esac
+}
+
+# func_check_version_match
+# Ensure that we are using m4 macros, and libtool script from the same
+# release of libtool.
+func_check_version_match ()
+{
+  if test "$package_revision" != "$macro_revision"; then
+    if test "$VERSION" != "$macro_version"; then
+      if test -z "$macro_version"; then
+        cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from an older release.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+      else
+        cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from $PACKAGE $macro_version.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+      fi
+    else
+      cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, revision $package_revision,
+$progname: but the definition of this LT_INIT comes from revision $macro_revision.
+$progname: You should recreate aclocal.m4 with macros from revision $package_revision
+$progname: of $PACKAGE $VERSION and run autoconf again.
+_LT_EOF
+    fi
+
+    exit $EXIT_MISMATCH
+  fi
+}
+
+
+# Shorthand for --mode=foo, only valid as the first argument
+case $1 in
+clean|clea|cle|cl)
+  shift; set dummy --mode clean ${1+"$@"}; shift
+  ;;
+compile|compil|compi|comp|com|co|c)
+  shift; set dummy --mode compile ${1+"$@"}; shift
+  ;;
+execute|execut|execu|exec|exe|ex|e)
+  shift; set dummy --mode execute ${1+"$@"}; shift
+  ;;
+finish|finis|fini|fin|fi|f)
+  shift; set dummy --mode finish ${1+"$@"}; shift
+  ;;
+install|instal|insta|inst|ins|in|i)
+  shift; set dummy --mode install ${1+"$@"}; shift
+  ;;
+link|lin|li|l)
+  shift; set dummy --mode link ${1+"$@"}; shift
+  ;;
+uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u)
+  shift; set dummy --mode uninstall ${1+"$@"}; shift
+  ;;
+esac
+
+
+
+# Option defaults:
+opt_debug=:
+opt_dry_run=false
+opt_config=false
+opt_preserve_dup_deps=false
+opt_features=false
+opt_finish=false
+opt_help=false
+opt_help_all=false
+opt_silent=:
+opt_warning=:
+opt_verbose=:
+opt_silent=false
+opt_verbose=false
+
+
+# Parse options once, thoroughly.  This comes as soon as possible in the
+# script to make things like `--version' happen as quickly as we can.
+{
+  # this just eases exit handling
+  while test $# -gt 0; do
+    opt="$1"
+    shift
+    case $opt in
+      --debug|-x)	opt_debug='set -x'
+			func_echo "enabling shell trace mode"
+			$opt_debug
+			;;
+      --dry-run|--dryrun|-n)
+			opt_dry_run=:
+			;;
+      --config)
+			opt_config=:
+func_config
+			;;
+      --dlopen|-dlopen)
+			optarg="$1"
+			opt_dlopen="${opt_dlopen+$opt_dlopen
+}$optarg"
+			shift
+			;;
+      --preserve-dup-deps)
+			opt_preserve_dup_deps=:
+			;;
+      --features)
+			opt_features=:
+func_features
+			;;
+      --finish)
+			opt_finish=:
+set dummy --mode finish ${1+"$@"}; shift
+			;;
+      --help)
+			opt_help=:
+			;;
+      --help-all)
+			opt_help_all=:
+opt_help=': help-all'
+			;;
+      --mode)
+			test $# = 0 && func_missing_arg $opt && break
+			optarg="$1"
+			opt_mode="$optarg"
+case $optarg in
+  # Valid mode arguments:
+  clean|compile|execute|finish|install|link|relink|uninstall) ;;
+
+  # Catch anything else as an error
+  *) func_error "invalid argument for $opt"
+     exit_cmd=exit
+     break
+     ;;
+esac
+			shift
+			;;
+      --no-silent|--no-quiet)
+			opt_silent=false
+preserve_args+=" $opt"
+			;;
+      --no-warning|--no-warn)
+			opt_warning=false
+preserve_args+=" $opt"
+			;;
+      --no-verbose)
+			opt_verbose=false
+preserve_args+=" $opt"
+			;;
+      --silent|--quiet)
+			opt_silent=:
+preserve_args+=" $opt"
+        opt_verbose=false
+			;;
+      --verbose|-v)
+			opt_verbose=:
+preserve_args+=" $opt"
+opt_silent=false
+			;;
+      --tag)
+			test $# = 0 && func_missing_arg $opt && break
+			optarg="$1"
+			opt_tag="$optarg"
+preserve_args+=" $opt $optarg"
+func_enable_tag "$optarg"
+			shift
+			;;
+
+      -\?|-h)		func_usage				;;
+      --help)		func_help				;;
+      --version)	func_version				;;
+
+      # Separate optargs to long options:
+      --*=*)
+			func_split_long_opt "$opt"
+			set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"}
+			shift
+			;;
+
+      # Separate non-argument short options:
+      -\?*|-h*|-n*|-v*)
+			func_split_short_opt "$opt"
+			set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"}
+			shift
+			;;
+
+      --)		break					;;
+      -*)		func_fatal_help "unrecognized option \`$opt'" ;;
+      *)		set dummy "$opt" ${1+"$@"};	shift; break  ;;
+    esac
+  done
+
+  # Validate options:
+
+  # save first non-option argument
+  if test "$#" -gt 0; then
+    nonopt="$opt"
+    shift
+  fi
+
+  # preserve --debug
+  test "$opt_debug" = : || preserve_args+=" --debug"
+
+  case $host in
+    *cygwin* | *mingw* | *pw32* | *cegcc*)
+      # don't eliminate duplications in $postdeps and $predeps
+      opt_duplicate_compiler_generated_deps=:
+      ;;
+    *)
+      opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps
+      ;;
+  esac
+
+  $opt_help || {
+    # Sanity checks first:
+    func_check_version_match
+
+    if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+      func_fatal_configuration "not configured to build any kind of library"
+    fi
+
+    # Darwin sucks
+    eval std_shrext=\"$shrext_cmds\"
+
+    # Only execute mode is allowed to have -dlopen flags.
+    if test -n "$opt_dlopen" && test "$opt_mode" != execute; then
+      func_error "unrecognized option \`-dlopen'"
+      $ECHO "$help" 1>&2
+      exit $EXIT_FAILURE
+    fi
+
+    # Change the help message to a mode-specific one.
+    generic_help="$help"
+    help="Try \`$progname --help --mode=$opt_mode' for more information."
+  }
+
+
+  # Bail if the options were screwed
+  $exit_cmd $EXIT_FAILURE
+}
+
+
+
+
+## ----------- ##
+##    Main.    ##
+## ----------- ##
+
+# func_lalib_p file
+# True iff FILE is a libtool `.la' library or `.lo' object file.
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_lalib_p ()
+{
+    test -f "$1" &&
+      $SED -e 4q "$1" 2>/dev/null \
+        | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1
+}
+
+# func_lalib_unsafe_p file
+# True iff FILE is a libtool `.la' library or `.lo' object file.
+# This function implements the same check as func_lalib_p without
+# resorting to external programs.  To this end, it redirects stdin and
+# closes it afterwards, without saving the original file descriptor.
+# As a safety measure, use it only where a negative result would be
+# fatal anyway.  Works if `file' does not exist.
+func_lalib_unsafe_p ()
+{
+    lalib_p=no
+    if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then
+	for lalib_p_l in 1 2 3 4
+	do
+	    read lalib_p_line
+	    case "$lalib_p_line" in
+		\#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;;
+	    esac
+	done
+	exec 0<&5 5<&-
+    fi
+    test "$lalib_p" = yes
+}
+
+# func_ltwrapper_script_p file
+# True iff FILE is a libtool wrapper script
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_script_p ()
+{
+    func_lalib_p "$1"
+}
+
+# func_ltwrapper_executable_p file
+# True iff FILE is a libtool wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_executable_p ()
+{
+    func_ltwrapper_exec_suffix=
+    case $1 in
+    *.exe) ;;
+    *) func_ltwrapper_exec_suffix=.exe ;;
+    esac
+    $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1
+}
+
+# func_ltwrapper_scriptname file
+# Assumes file is an ltwrapper_executable
+# uses $file to determine the appropriate filename for a
+# temporary ltwrapper_script.
+func_ltwrapper_scriptname ()
+{
+    func_dirname_and_basename "$1" "" "."
+    func_stripname '' '.exe' "$func_basename_result"
+    func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper"
+}
+
+# func_ltwrapper_p file
+# True iff FILE is a libtool wrapper script or wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_p ()
+{
+    func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1"
+}
+
+
+# func_execute_cmds commands fail_cmd
+# Execute tilde-delimited COMMANDS.
+# If FAIL_CMD is given, eval that upon failure.
+# FAIL_CMD may read-access the current command in variable CMD!
+func_execute_cmds ()
+{
+    $opt_debug
+    save_ifs=$IFS; IFS='~'
+    for cmd in $1; do
+      IFS=$save_ifs
+      eval cmd=\"$cmd\"
+      func_show_eval "$cmd" "${2-:}"
+    done
+    IFS=$save_ifs
+}
+
+
+# func_source file
+# Source FILE, adding directory component if necessary.
+# Note that it is not necessary on cygwin/mingw to append a dot to
+# FILE even if both FILE and FILE.exe exist: automatic-append-.exe
+# behavior happens only for exec(3), not for open(2)!  Also, sourcing
+# `FILE.' does not work on cygwin managed mounts.
+func_source ()
+{
+    $opt_debug
+    case $1 in
+    */* | *\\*)	. "$1" ;;
+    *)		. "./$1" ;;
+    esac
+}
+
+
+# func_resolve_sysroot PATH
+# Replace a leading = in PATH with a sysroot.  Store the result into
+# func_resolve_sysroot_result
+func_resolve_sysroot ()
+{
+  func_resolve_sysroot_result=$1
+  case $func_resolve_sysroot_result in
+  =*)
+    func_stripname '=' '' "$func_resolve_sysroot_result"
+    func_resolve_sysroot_result=$lt_sysroot$func_stripname_result
+    ;;
+  esac
+}
+
+# func_replace_sysroot PATH
+# If PATH begins with the sysroot, replace it with = and
+# store the result into func_replace_sysroot_result.
+func_replace_sysroot ()
+{
+  case "$lt_sysroot:$1" in
+  ?*:"$lt_sysroot"*)
+    func_stripname "$lt_sysroot" '' "$1"
+    func_replace_sysroot_result="=$func_stripname_result"
+    ;;
+  *)
+    # Including no sysroot.
+    func_replace_sysroot_result=$1
+    ;;
+  esac
+}
+
+# func_infer_tag arg
+# Infer tagged configuration to use if any are available and
+# if one wasn't chosen via the "--tag" command line option.
+# Only attempt this if the compiler in the base compile
+# command doesn't match the default compiler.
+# arg is usually of the form 'gcc ...'
+func_infer_tag ()
+{
+    $opt_debug
+    if test -n "$available_tags" && test -z "$tagname"; then
+      CC_quoted=
+      for arg in $CC; do
+	func_append_quoted CC_quoted "$arg"
+      done
+      CC_expanded=`func_echo_all $CC`
+      CC_quoted_expanded=`func_echo_all $CC_quoted`
+      case $@ in
+      # Blanks in the command may have been stripped by the calling shell,
+      # but not from the CC environment variable when configure was run.
+      " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
+      " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;;
+      # Blanks at the start of $base_compile will cause this to fail
+      # if we don't check for them as well.
+      *)
+	for z in $available_tags; do
+	  if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
+	    # Evaluate the configuration.
+	    eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
+	    CC_quoted=
+	    for arg in $CC; do
+	      # Double-quote args containing other shell metacharacters.
+	      func_append_quoted CC_quoted "$arg"
+	    done
+	    CC_expanded=`func_echo_all $CC`
+	    CC_quoted_expanded=`func_echo_all $CC_quoted`
+	    case "$@ " in
+	    " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
+	    " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*)
+	      # The compiler in the base compile command matches
+	      # the one in the tagged configuration.
+	      # Assume this is the tagged configuration we want.
+	      tagname=$z
+	      break
+	      ;;
+	    esac
+	  fi
+	done
+	# If $tagname still isn't set, then no tagged configuration
+	# was found and let the user know that the "--tag" command
+	# line option must be used.
+	if test -z "$tagname"; then
+	  func_echo "unable to infer tagged configuration"
+	  func_fatal_error "specify a tag with \`--tag'"
+#	else
+#	  func_verbose "using $tagname tagged configuration"
+	fi
+	;;
+      esac
+    fi
+}
+
+
+
+# func_write_libtool_object output_name pic_name nonpic_name
+# Create a libtool object file (analogous to a ".la" file),
+# but don't create it if we're doing a dry run.
+func_write_libtool_object ()
+{
+    write_libobj=${1}
+    if test "$build_libtool_libs" = yes; then
+      write_lobj=\'${2}\'
+    else
+      write_lobj=none
+    fi
+
+    if test "$build_old_libs" = yes; then
+      write_oldobj=\'${3}\'
+    else
+      write_oldobj=none
+    fi
+
+    $opt_dry_run || {
+      cat >${write_libobj}T <<EOF
+# $write_libobj - a libtool object file
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+pic_object=$write_lobj
+
+# Name of the non-PIC object
+non_pic_object=$write_oldobj
+
+EOF
+      $MV "${write_libobj}T" "${write_libobj}"
+    }
+}
+
+
+##################################################
+# FILE NAME AND PATH CONVERSION HELPER FUNCTIONS #
+##################################################
+
+# func_convert_core_file_wine_to_w32 ARG
+# Helper function used by file name conversion functions when $build is *nix,
+# and $host is mingw, cygwin, or some other w32 environment. Relies on a
+# correctly configured wine environment available, with the winepath program
+# in $build's $PATH.
+#
+# ARG is the $build file name to be converted to w32 format.
+# Result is available in $func_convert_core_file_wine_to_w32_result, and will
+# be empty on error (or when ARG is empty)
+func_convert_core_file_wine_to_w32 ()
+{
+  $opt_debug
+  func_convert_core_file_wine_to_w32_result="$1"
+  if test -n "$1"; then
+    # Unfortunately, winepath does not exit with a non-zero error code, so we
+    # are forced to check the contents of stdout. On the other hand, if the
+    # command is not found, the shell will set an exit code of 127 and print
+    # *an error message* to stdout. So we must check for both error code of
+    # zero AND non-empty stdout, which explains the odd construction:
+    func_convert_core_file_wine_to_w32_tmp=`winepath -w "$1" 2>/dev/null`
+    if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then
+      func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" |
+        $SED -e "$lt_sed_naive_backslashify"`
+    else
+      func_convert_core_file_wine_to_w32_result=
+    fi
+  fi
+}
+# end: func_convert_core_file_wine_to_w32
+
+
+# func_convert_core_path_wine_to_w32 ARG
+# Helper function used by path conversion functions when $build is *nix, and
+# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly
+# configured wine environment available, with the winepath program in $build's
+# $PATH. Assumes ARG has no leading or trailing path separator characters.
+#
+# ARG is path to be converted from $build format to win32.
+# Result is available in $func_convert_core_path_wine_to_w32_result.
+# Unconvertible file (directory) names in ARG are skipped; if no directory names
+# are convertible, then the result may be empty.
+func_convert_core_path_wine_to_w32 ()
+{
+  $opt_debug
+  # unfortunately, winepath doesn't convert paths, only file names
+  func_convert_core_path_wine_to_w32_result=""
+  if test -n "$1"; then
+    oldIFS=$IFS
+    IFS=:
+    for func_convert_core_path_wine_to_w32_f in $1; do
+      IFS=$oldIFS
+      func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f"
+      if test -n "$func_convert_core_file_wine_to_w32_result" ; then
+        if test -z "$func_convert_core_path_wine_to_w32_result"; then
+          func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result"
+        else
+          func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result"
+        fi
+      fi
+    done
+    IFS=$oldIFS
+  fi
+}
+# end: func_convert_core_path_wine_to_w32
+
+
+# func_cygpath ARGS...
+# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when
+# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2)
+# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or
+# (2), returns the Cygwin file name or path in func_cygpath_result (input
+# file name or path is assumed to be in w32 format, as previously converted
+# from $build's *nix or MSYS format). In case (3), returns the w32 file name
+# or path in func_cygpath_result (input file name or path is assumed to be in
+# Cygwin format). Returns an empty string on error.
+#
+# ARGS are passed to cygpath, with the last one being the file name or path to
+# be converted.
+#
+# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH
+# environment variable; do not put it in $PATH.
+func_cygpath ()
+{
+  $opt_debug
+  if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then
+    func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null`
+    if test "$?" -ne 0; then
+      # on failure, ensure result is empty
+      func_cygpath_result=
+    fi
+  else
+    func_cygpath_result=
+    func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'"
+  fi
+}
+#end: func_cygpath
+
+
+# func_convert_core_msys_to_w32 ARG
+# Convert file name or path ARG from MSYS format to w32 format.  Return
+# result in func_convert_core_msys_to_w32_result.
+func_convert_core_msys_to_w32 ()
+{
+  $opt_debug
+  # awkward: cmd appends spaces to result
+  func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null |
+    $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"`
+}
+#end: func_convert_core_msys_to_w32
+
+
+# func_convert_file_check ARG1 ARG2
+# Verify that ARG1 (a file name in $build format) was converted to $host
+# format in ARG2. Otherwise, emit an error message, but continue (resetting
+# func_to_host_file_result to ARG1).
+func_convert_file_check ()
+{
+  $opt_debug
+  if test -z "$2" && test -n "$1" ; then
+    func_error "Could not determine host file name corresponding to"
+    func_error "  \`$1'"
+    func_error "Continuing, but uninstalled executables may not work."
+    # Fallback:
+    func_to_host_file_result="$1"
+  fi
+}
+# end func_convert_file_check
+
+
+# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH
+# Verify that FROM_PATH (a path in $build format) was converted to $host
+# format in TO_PATH. Otherwise, emit an error message, but continue, resetting
+# func_to_host_file_result to a simplistic fallback value (see below).
+func_convert_path_check ()
+{
+  $opt_debug
+  if test -z "$4" && test -n "$3"; then
+    func_error "Could not determine the host path corresponding to"
+    func_error "  \`$3'"
+    func_error "Continuing, but uninstalled executables may not work."
+    # Fallback.  This is a deliberately simplistic "conversion" and
+    # should not be "improved".  See libtool.info.
+    if test "x$1" != "x$2"; then
+      lt_replace_pathsep_chars="s|$1|$2|g"
+      func_to_host_path_result=`echo "$3" |
+        $SED -e "$lt_replace_pathsep_chars"`
+    else
+      func_to_host_path_result="$3"
+    fi
+  fi
+}
+# end func_convert_path_check
+
+
+# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG
+# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT
+# and appending REPL if ORIG matches BACKPAT.
+func_convert_path_front_back_pathsep ()
+{
+  $opt_debug
+  case $4 in
+  $1 ) func_to_host_path_result="$3$func_to_host_path_result"
+    ;;
+  esac
+  case $4 in
+  $2 ) func_to_host_path_result+="$3"
+    ;;
+  esac
+}
+# end func_convert_path_front_back_pathsep
+
+
+##################################################
+# $build to $host FILE NAME CONVERSION FUNCTIONS #
+##################################################
+# invoked via `$to_host_file_cmd ARG'
+#
+# In each case, ARG is the path to be converted from $build to $host format.
+# Result will be available in $func_to_host_file_result.
+
+
+# func_to_host_file ARG
+# Converts the file name ARG from $build format to $host format. Return result
+# in func_to_host_file_result.
+func_to_host_file ()
+{
+  $opt_debug
+  $to_host_file_cmd "$1"
+}
+# end func_to_host_file
+
+
+# func_to_tool_file ARG LAZY
+# converts the file name ARG from $build format to toolchain format. Return
+# result in func_to_tool_file_result.  If the conversion in use is listed
+# in (the comma separated) LAZY, no conversion takes place.
+func_to_tool_file ()
+{
+  $opt_debug
+  case ,$2, in
+    *,"$to_tool_file_cmd",*)
+      func_to_tool_file_result=$1
+      ;;
+    *)
+      $to_tool_file_cmd "$1"
+      func_to_tool_file_result=$func_to_host_file_result
+      ;;
+  esac
+}
+# end func_to_tool_file
+
+
+# func_convert_file_noop ARG
+# Copy ARG to func_to_host_file_result.
+func_convert_file_noop ()
+{
+  func_to_host_file_result="$1"
+}
+# end func_convert_file_noop
+
+
+# func_convert_file_msys_to_w32 ARG
+# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic
+# conversion to w32 is not available inside the cwrapper.  Returns result in
+# func_to_host_file_result.
+func_convert_file_msys_to_w32 ()
+{
+  $opt_debug
+  func_to_host_file_result="$1"
+  if test -n "$1"; then
+    func_convert_core_msys_to_w32 "$1"
+    func_to_host_file_result="$func_convert_core_msys_to_w32_result"
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_msys_to_w32
+
+
+# func_convert_file_cygwin_to_w32 ARG
+# Convert file name ARG from Cygwin to w32 format.  Returns result in
+# func_to_host_file_result.
+func_convert_file_cygwin_to_w32 ()
+{
+  $opt_debug
+  func_to_host_file_result="$1"
+  if test -n "$1"; then
+    # because $build is cygwin, we call "the" cygpath in $PATH; no need to use
+    # LT_CYGPATH in this case.
+    func_to_host_file_result=`cygpath -m "$1"`
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_cygwin_to_w32
+
+
+# func_convert_file_nix_to_w32 ARG
+# Convert file name ARG from *nix to w32 format.  Requires a wine environment
+# and a working winepath. Returns result in func_to_host_file_result.
+func_convert_file_nix_to_w32 ()
+{
+  $opt_debug
+  func_to_host_file_result="$1"
+  if test -n "$1"; then
+    func_convert_core_file_wine_to_w32 "$1"
+    func_to_host_file_result="$func_convert_core_file_wine_to_w32_result"
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_nix_to_w32
+
+
+# func_convert_file_msys_to_cygwin ARG
+# Convert file name ARG from MSYS to Cygwin format.  Requires LT_CYGPATH set.
+# Returns result in func_to_host_file_result.
+func_convert_file_msys_to_cygwin ()
+{
+  $opt_debug
+  func_to_host_file_result="$1"
+  if test -n "$1"; then
+    func_convert_core_msys_to_w32 "$1"
+    func_cygpath -u "$func_convert_core_msys_to_w32_result"
+    func_to_host_file_result="$func_cygpath_result"
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_msys_to_cygwin
+
+
+# func_convert_file_nix_to_cygwin ARG
+# Convert file name ARG from *nix to Cygwin format.  Requires Cygwin installed
+# in a wine environment, working winepath, and LT_CYGPATH set.  Returns result
+# in func_to_host_file_result.
+func_convert_file_nix_to_cygwin ()
+{
+  $opt_debug
+  func_to_host_file_result="$1"
+  if test -n "$1"; then
+    # convert from *nix to w32, then use cygpath to convert from w32 to cygwin.
+    func_convert_core_file_wine_to_w32 "$1"
+    func_cygpath -u "$func_convert_core_file_wine_to_w32_result"
+    func_to_host_file_result="$func_cygpath_result"
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_nix_to_cygwin
+
+
+#############################################
+# $build to $host PATH CONVERSION FUNCTIONS #
+#############################################
+# invoked via `$to_host_path_cmd ARG'
+#
+# In each case, ARG is the path to be converted from $build to $host format.
+# The result will be available in $func_to_host_path_result.
+#
+# Path separators are also converted from $build format to $host format.  If
+# ARG begins or ends with a path separator character, it is preserved (but
+# converted to $host format) on output.
+#
+# All path conversion functions are named using the following convention:
+#   file name conversion function    : func_convert_file_X_to_Y ()
+#   path conversion function         : func_convert_path_X_to_Y ()
+# where, for any given $build/$host combination the 'X_to_Y' value is the
+# same.  If conversion functions are added for new $build/$host combinations,
+# the two new functions must follow this pattern, or func_init_to_host_path_cmd
+# will break.
+
+
+# func_init_to_host_path_cmd
+# Ensures that function "pointer" variable $to_host_path_cmd is set to the
+# appropriate value, based on the value of $to_host_file_cmd.
+to_host_path_cmd=
+func_init_to_host_path_cmd ()
+{
+  $opt_debug
+  if test -z "$to_host_path_cmd"; then
+    func_stripname 'func_convert_file_' '' "$to_host_file_cmd"
+    to_host_path_cmd="func_convert_path_${func_stripname_result}"
+  fi
+}
+
+
+# func_to_host_path ARG
+# Converts the path ARG from $build format to $host format. Return result
+# in func_to_host_path_result.
+func_to_host_path ()
+{
+  $opt_debug
+  func_init_to_host_path_cmd
+  $to_host_path_cmd "$1"
+}
+# end func_to_host_path
+
+
+# func_convert_path_noop ARG
+# Copy ARG to func_to_host_path_result.
+func_convert_path_noop ()
+{
+  func_to_host_path_result="$1"
+}
+# end func_convert_path_noop
+
+
+# func_convert_path_msys_to_w32 ARG
+# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic
+# conversion to w32 is not available inside the cwrapper.  Returns result in
+# func_to_host_path_result.
+func_convert_path_msys_to_w32 ()
+{
+  $opt_debug
+  func_to_host_path_result="$1"
+  if test -n "$1"; then
+    # Remove leading and trailing path separator characters from ARG.  MSYS
+    # behavior is inconsistent here; cygpath turns them into '.;' and ';.';
+    # and winepath ignores them completely.
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_convert_core_msys_to_w32 "$func_to_host_path_tmp1"
+    func_to_host_path_result="$func_convert_core_msys_to_w32_result"
+    func_convert_path_check : ";" \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
+  fi
+}
+# end func_convert_path_msys_to_w32
+
+
+# func_convert_path_cygwin_to_w32 ARG
+# Convert path ARG from Cygwin to w32 format.  Returns result in
+# func_to_host_file_result.
+func_convert_path_cygwin_to_w32 ()
+{
+  $opt_debug
+  func_to_host_path_result="$1"
+  if test -n "$1"; then
+    # See func_convert_path_msys_to_w32:
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"`
+    func_convert_path_check : ";" \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
+  fi
+}
+# end func_convert_path_cygwin_to_w32
+
+
+# func_convert_path_nix_to_w32 ARG
+# Convert path ARG from *nix to w32 format.  Requires a wine environment and
+# a working winepath.  Returns result in func_to_host_file_result.
+func_convert_path_nix_to_w32 ()
+{
+  $opt_debug
+  func_to_host_path_result="$1"
+  if test -n "$1"; then
+    # See func_convert_path_msys_to_w32:
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1"
+    func_to_host_path_result="$func_convert_core_path_wine_to_w32_result"
+    func_convert_path_check : ";" \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
+  fi
+}
+# end func_convert_path_nix_to_w32
+
+
+# func_convert_path_msys_to_cygwin ARG
+# Convert path ARG from MSYS to Cygwin format.  Requires LT_CYGPATH set.
+# Returns result in func_to_host_file_result.
+func_convert_path_msys_to_cygwin ()
+{
+  $opt_debug
+  func_to_host_path_result="$1"
+  if test -n "$1"; then
+    # See func_convert_path_msys_to_w32:
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_convert_core_msys_to_w32 "$func_to_host_path_tmp1"
+    func_cygpath -u -p "$func_convert_core_msys_to_w32_result"
+    func_to_host_path_result="$func_cygpath_result"
+    func_convert_path_check : : \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" : "$1"
+  fi
+}
+# end func_convert_path_msys_to_cygwin
+
+
+# func_convert_path_nix_to_cygwin ARG
+# Convert path ARG from *nix to Cygwin format.  Requires Cygwin installed in a
+# a wine environment, working winepath, and LT_CYGPATH set.  Returns result in
+# func_to_host_file_result.
+func_convert_path_nix_to_cygwin ()
+{
+  $opt_debug
+  func_to_host_path_result="$1"
+  if test -n "$1"; then
+    # Remove leading and trailing path separator characters from
+    # ARG. msys behavior is inconsistent here, cygpath turns them
+    # into '.;' and ';.', and winepath ignores them completely.
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1"
+    func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result"
+    func_to_host_path_result="$func_cygpath_result"
+    func_convert_path_check : : \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" : "$1"
+  fi
+}
+# end func_convert_path_nix_to_cygwin
+
+
+# func_mode_compile arg...
+func_mode_compile ()
+{
+    $opt_debug
+    # Get the compilation command and the source file.
+    base_compile=
+    srcfile="$nonopt"  #  always keep a non-empty value in "srcfile"
+    suppress_opt=yes
+    suppress_output=
+    arg_mode=normal
+    libobj=
+    later=
+    pie_flag=
+
+    for arg
+    do
+      case $arg_mode in
+      arg  )
+	# do not "continue".  Instead, add this to base_compile
+	lastarg="$arg"
+	arg_mode=normal
+	;;
+
+      target )
+	libobj="$arg"
+	arg_mode=normal
+	continue
+	;;
+
+      normal )
+	# Accept any command-line options.
+	case $arg in
+	-o)
+	  test -n "$libobj" && \
+	    func_fatal_error "you cannot specify \`-o' more than once"
+	  arg_mode=target
+	  continue
+	  ;;
+
+	-pie | -fpie | -fPIE)
+          pie_flag+=" $arg"
+	  continue
+	  ;;
+
+	-shared | -static | -prefer-pic | -prefer-non-pic)
+	  later+=" $arg"
+	  continue
+	  ;;
+
+	-no-suppress)
+	  suppress_opt=no
+	  continue
+	  ;;
+
+	-Xcompiler)
+	  arg_mode=arg  #  the next one goes into the "base_compile" arg list
+	  continue      #  The current "srcfile" will either be retained or
+	  ;;            #  replaced later.  I would guess that would be a bug.
+
+	-Wc,*)
+	  func_stripname '-Wc,' '' "$arg"
+	  args=$func_stripname_result
+	  lastarg=
+	  save_ifs="$IFS"; IFS=','
+	  for arg in $args; do
+	    IFS="$save_ifs"
+	    func_append_quoted lastarg "$arg"
+	  done
+	  IFS="$save_ifs"
+	  func_stripname ' ' '' "$lastarg"
+	  lastarg=$func_stripname_result
+
+	  # Add the arguments to base_compile.
+	  base_compile+=" $lastarg"
+	  continue
+	  ;;
+
+	*)
+	  # Accept the current argument as the source file.
+	  # The previous "srcfile" becomes the current argument.
+	  #
+	  lastarg="$srcfile"
+	  srcfile="$arg"
+	  ;;
+	esac  #  case $arg
+	;;
+      esac    #  case $arg_mode
+
+      # Aesthetically quote the previous argument.
+      func_append_quoted base_compile "$lastarg"
+    done # for arg
+
+    case $arg_mode in
+    arg)
+      func_fatal_error "you must specify an argument for -Xcompile"
+      ;;
+    target)
+      func_fatal_error "you must specify a target with \`-o'"
+      ;;
+    *)
+      # Get the name of the library object.
+      test -z "$libobj" && {
+	func_basename "$srcfile"
+	libobj="$func_basename_result"
+      }
+      ;;
+    esac
+
+    # Recognize several different file suffixes.
+    # If the user specifies -o file.o, it is replaced with file.lo
+    case $libobj in
+    *.[cCFSifmso] | \
+    *.ada | *.adb | *.ads | *.asm | \
+    *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \
+    *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup)
+      func_xform "$libobj"
+      libobj=$func_xform_result
+      ;;
+    esac
+
+    case $libobj in
+    *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;;
+    *)
+      func_fatal_error "cannot determine name of library object from \`$libobj'"
+      ;;
+    esac
+
+    func_infer_tag $base_compile
+
+    for arg in $later; do
+      case $arg in
+      -shared)
+	test "$build_libtool_libs" != yes && \
+	  func_fatal_configuration "can not build a shared library"
+	build_old_libs=no
+	continue
+	;;
+
+      -static)
+	build_libtool_libs=no
+	build_old_libs=yes
+	continue
+	;;
+
+      -prefer-pic)
+	pic_mode=yes
+	continue
+	;;
+
+      -prefer-non-pic)
+	pic_mode=no
+	continue
+	;;
+      esac
+    done
+
+    func_quote_for_eval "$libobj"
+    test "X$libobj" != "X$func_quote_for_eval_result" \
+      && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"'	 &()|`$[]' \
+      && func_warning "libobj name \`$libobj' may not contain shell special characters."
+    func_dirname_and_basename "$obj" "/" ""
+    objname="$func_basename_result"
+    xdir="$func_dirname_result"
+    lobj=${xdir}$objdir/$objname
+
+    test -z "$base_compile" && \
+      func_fatal_help "you must specify a compilation command"
+
+    # Delete any leftover library objects.
+    if test "$build_old_libs" = yes; then
+      removelist="$obj $lobj $libobj ${libobj}T"
+    else
+      removelist="$lobj $libobj ${libobj}T"
+    fi
+
+    # On Cygwin there's no "real" PIC flag so we must build both object types
+    case $host_os in
+    cygwin* | mingw* | pw32* | os2* | cegcc*)
+      pic_mode=default
+      ;;
+    esac
+    if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
+      # non-PIC code in shared libraries is not supported
+      pic_mode=default
+    fi
+
+    # Calculate the filename of the output object if compiler does
+    # not support -o with -c
+    if test "$compiler_c_o" = no; then
+      output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext}
+      lockfile="$output_obj.lock"
+    else
+      output_obj=
+      need_locks=no
+      lockfile=
+    fi
+
+    # Lock this critical section if it is needed
+    # We use this script file to make the link, it avoids creating a new file
+    if test "$need_locks" = yes; then
+      until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
+	func_echo "Waiting for $lockfile to be removed"
+	sleep 2
+      done
+    elif test "$need_locks" = warn; then
+      if test -f "$lockfile"; then
+	$ECHO "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$opt_dry_run || $RM $removelist
+	exit $EXIT_FAILURE
+      fi
+      removelist+=" $output_obj"
+      $ECHO "$srcfile" > "$lockfile"
+    fi
+
+    $opt_dry_run || $RM $removelist
+    removelist+=" $lockfile"
+    trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15
+
+    func_to_tool_file "$srcfile" func_convert_file_msys_to_w32
+    srcfile=$func_to_tool_file_result
+    func_quote_for_eval "$srcfile"
+    qsrcfile=$func_quote_for_eval_result
+
+    # Only build a PIC object if we are building libtool libraries.
+    if test "$build_libtool_libs" = yes; then
+      # Without this assignment, base_compile gets emptied.
+      fbsd_hideous_sh_bug=$base_compile
+
+      if test "$pic_mode" != no; then
+	command="$base_compile $qsrcfile $pic_flag"
+      else
+	# Don't build PIC code
+	command="$base_compile $qsrcfile"
+      fi
+
+      func_mkdir_p "$xdir$objdir"
+
+      if test -z "$output_obj"; then
+	# Place PIC objects in $objdir
+	command+=" -o $lobj"
+      fi
+
+      func_show_eval_locale "$command"	\
+          'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE'
+
+      if test "$need_locks" = warn &&
+	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+	$ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$opt_dry_run || $RM $removelist
+	exit $EXIT_FAILURE
+      fi
+
+      # Just move the object if needed, then go on to compile the next one
+      if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
+	func_show_eval '$MV "$output_obj" "$lobj"' \
+	  'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+      fi
+
+      # Allow error messages only from the first compilation.
+      if test "$suppress_opt" = yes; then
+	suppress_output=' >/dev/null 2>&1'
+      fi
+    fi
+
+    # Only build a position-dependent object if we build old libraries.
+    if test "$build_old_libs" = yes; then
+      if test "$pic_mode" != yes; then
+	# Don't build PIC code
+	command="$base_compile $qsrcfile$pie_flag"
+      else
+	command="$base_compile $qsrcfile $pic_flag"
+      fi
+      if test "$compiler_c_o" = yes; then
+	command+=" -o $obj"
+      fi
+
+      # Suppress compiler output if we already did a PIC compilation.
+      command+="$suppress_output"
+      func_show_eval_locale "$command" \
+        '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE'
+
+      if test "$need_locks" = warn &&
+	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+	$ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$opt_dry_run || $RM $removelist
+	exit $EXIT_FAILURE
+      fi
+
+      # Just move the object if needed
+      if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
+	func_show_eval '$MV "$output_obj" "$obj"' \
+	  'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+      fi
+    fi
+
+    $opt_dry_run || {
+      func_write_libtool_object "$libobj" "$objdir/$objname" "$objname"
+
+      # Unlock the critical section if it was locked
+      if test "$need_locks" != no; then
+	removelist=$lockfile
+        $RM "$lockfile"
+      fi
+    }
+
+    exit $EXIT_SUCCESS
+}
+
+$opt_help || {
+  test "$opt_mode" = compile && func_mode_compile ${1+"$@"}
+}
+
+func_mode_help ()
+{
+    # We need to display help for each of the modes.
+    case $opt_mode in
+      "")
+        # Generic help is extracted from the usage comments
+        # at the start of this file.
+        func_help
+        ;;
+
+      clean)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+        ;;
+
+      compile)
+      $ECHO \
+"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+  -o OUTPUT-FILE    set the output file name to OUTPUT-FILE
+  -no-suppress      do not suppress compiler output for multiple passes
+  -prefer-pic       try to build PIC objects only
+  -prefer-non-pic   try to build non-PIC objects only
+  -shared           do not build a \`.o' file suitable for static linking
+  -static           only build a \`.o' file suitable for static linking
+  -Wc,FLAG          pass FLAG directly to the compiler
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+        ;;
+
+      execute)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+  -dlopen FILE      add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+        ;;
+
+      finish)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges.  Use
+the \`--dry-run' option if you just want to see what would be executed."
+        ;;
+
+      install)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command.  The first component should be
+either the \`install' or \`cp' program.
+
+The following components of INSTALL-COMMAND are treated specially:
+
+  -inst-prefix-dir PREFIX-DIR  Use PREFIX-DIR as a staging area for installation
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+        ;;
+
+      link)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+  -all-static       do not do any dynamic linking at all
+  -avoid-version    do not add a version suffix if possible
+  -bindir BINDIR    specify path to binaries directory (for systems where
+                    libraries must be found in the PATH setting at runtime)
+  -dlopen FILE      \`-dlpreopen' FILE if it cannot be dlopened at runtime
+  -dlpreopen FILE   link in FILE and add its symbols to lt_preloaded_symbols
+  -export-dynamic   allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+  -export-symbols SYMFILE
+                    try to export only the symbols listed in SYMFILE
+  -export-symbols-regex REGEX
+                    try to export only the symbols matching REGEX
+  -LLIBDIR          search LIBDIR for required installed libraries
+  -lNAME            OUTPUT-FILE requires the installed library libNAME
+  -module           build a library that can dlopened
+  -no-fast-install  disable the fast-install mode
+  -no-install       link a not-installable executable
+  -no-undefined     declare that a library does not refer to external symbols
+  -o OUTPUT-FILE    create OUTPUT-FILE from the specified objects
+  -objectlist FILE  Use a list of object files found in FILE to specify objects
+  -precious-files-regex REGEX
+                    don't remove output files matching REGEX
+  -release RELEASE  specify package release information
+  -rpath LIBDIR     the created library will eventually be installed in LIBDIR
+  -R[ ]LIBDIR       add LIBDIR to the runtime path of programs and libraries
+  -shared           only do dynamic linking of libtool libraries
+  -shrext SUFFIX    override the standard shared library file extension
+  -static           do not do any dynamic linking of uninstalled libtool libraries
+  -static-libtool-libs
+                    do not do any dynamic linking of libtool libraries
+  -version-info CURRENT[:REVISION[:AGE]]
+                    specify library version info [each variable defaults to 0]
+  -weak LIBNAME     declare that the target provides the LIBNAME interface
+  -Wc,FLAG
+  -Xcompiler FLAG   pass linker-specific FLAG directly to the compiler
+  -Wl,FLAG
+  -Xlinker FLAG     pass linker-specific FLAG directly to the linker
+  -XCClinker FLAG   pass link-specific FLAG to the compiler driver (CC)
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename.  Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+        ;;
+
+      uninstall)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+        ;;
+
+      *)
+        func_fatal_help "invalid operation mode \`$opt_mode'"
+        ;;
+    esac
+
+    echo
+    $ECHO "Try \`$progname --help' for more information about other modes."
+}
+
+# Now that we've collected a possible --mode arg, show help if necessary
+if $opt_help; then
+  if test "$opt_help" = :; then
+    func_mode_help
+  else
+    {
+      func_help noexit
+      for opt_mode in compile link execute install finish uninstall clean; do
+	func_mode_help
+      done
+    } | sed -n '1p; 2,$s/^Usage:/  or: /p'
+    {
+      func_help noexit
+      for opt_mode in compile link execute install finish uninstall clean; do
+	echo
+	func_mode_help
+      done
+    } |
+    sed '1d
+      /^When reporting/,/^Report/{
+	H
+	d
+      }
+      $x
+      /information about other modes/d
+      /more detailed .*MODE/d
+      s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/'
+  fi
+  exit $?
+fi
+
+
+# func_mode_execute arg...
+func_mode_execute ()
+{
+    $opt_debug
+    # The first argument is the command name.
+    cmd="$nonopt"
+    test -z "$cmd" && \
+      func_fatal_help "you must specify a COMMAND"
+
+    # Handle -dlopen flags immediately.
+    for file in $opt_dlopen; do
+      test -f "$file" \
+	|| func_fatal_help "\`$file' is not a file"
+
+      dir=
+      case $file in
+      *.la)
+	func_resolve_sysroot "$file"
+	file=$func_resolve_sysroot_result
+
+	# Check to see that this really is a libtool archive.
+	func_lalib_unsafe_p "$file" \
+	  || func_fatal_help "\`$lib' is not a valid libtool archive"
+
+	# Read the libtool library.
+	dlname=
+	library_names=
+	func_source "$file"
+
+	# Skip this library if it cannot be dlopened.
+	if test -z "$dlname"; then
+	  # Warn if it was a shared library.
+	  test -n "$library_names" && \
+	    func_warning "\`$file' was not linked with \`-export-dynamic'"
+	  continue
+	fi
+
+	func_dirname "$file" "" "."
+	dir="$func_dirname_result"
+
+	if test -f "$dir/$objdir/$dlname"; then
+	  dir+="/$objdir"
+	else
+	  if test ! -f "$dir/$dlname"; then
+	    func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'"
+	  fi
+	fi
+	;;
+
+      *.lo)
+	# Just add the directory containing the .lo file.
+	func_dirname "$file" "" "."
+	dir="$func_dirname_result"
+	;;
+
+      *)
+	func_warning "\`-dlopen' is ignored for non-libtool libraries and objects"
+	continue
+	;;
+      esac
+
+      # Get the absolute pathname.
+      absdir=`cd "$dir" && pwd`
+      test -n "$absdir" && dir="$absdir"
+
+      # Now add the directory to shlibpath_var.
+      if eval "test -z \"\$$shlibpath_var\""; then
+	eval "$shlibpath_var=\"\$dir\""
+      else
+	eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+      fi
+    done
+
+    # This variable tells wrapper scripts just to set shlibpath_var
+    # rather than running their programs.
+    libtool_execute_magic="$magic"
+
+    # Check if any of the arguments is a wrapper script.
+    args=
+    for file
+    do
+      case $file in
+      -* | *.la | *.lo ) ;;
+      *)
+	# Do a test to see if this is really a libtool program.
+	if func_ltwrapper_script_p "$file"; then
+	  func_source "$file"
+	  # Transform arg to wrapped name.
+	  file="$progdir/$program"
+	elif func_ltwrapper_executable_p "$file"; then
+	  func_ltwrapper_scriptname "$file"
+	  func_source "$func_ltwrapper_scriptname_result"
+	  # Transform arg to wrapped name.
+	  file="$progdir/$program"
+	fi
+	;;
+      esac
+      # Quote arguments (to preserve shell metacharacters).
+      func_append_quoted args "$file"
+    done
+
+    if test "X$opt_dry_run" = Xfalse; then
+      if test -n "$shlibpath_var"; then
+	# Export the shlibpath_var.
+	eval "export $shlibpath_var"
+      fi
+
+      # Restore saved environment variables
+      for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+      do
+	eval "if test \"\${save_$lt_var+set}\" = set; then
+                $lt_var=\$save_$lt_var; export $lt_var
+	      else
+		$lt_unset $lt_var
+	      fi"
+      done
+
+      # Now prepare to actually exec the command.
+      exec_cmd="\$cmd$args"
+    else
+      # Display what would be done.
+      if test -n "$shlibpath_var"; then
+	eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\""
+	echo "export $shlibpath_var"
+      fi
+      $ECHO "$cmd$args"
+      exit $EXIT_SUCCESS
+    fi
+}
+
+test "$opt_mode" = execute && func_mode_execute ${1+"$@"}
+
+
+# func_mode_finish arg...
+func_mode_finish ()
+{
+    $opt_debug
+    libs=
+    libdirs=
+    admincmds=
+
+    for opt in "$nonopt" ${1+"$@"}
+    do
+      if test -d "$opt"; then
+	libdirs+=" $opt"
+
+      elif test -f "$opt"; then
+	if func_lalib_unsafe_p "$opt"; then
+	  libs+=" $opt"
+	else
+	  func_warning "\`$opt' is not a valid libtool archive"
+	fi
+
+      else
+	func_fatal_error "invalid argument \`$opt'"
+      fi
+    done
+
+    if test -n "$libs"; then
+      if test -n "$lt_sysroot"; then
+        sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"`
+        sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;"
+      else
+        sysroot_cmd=
+      fi
+
+      # Remove sysroot references
+      if $opt_dry_run; then
+        for lib in $libs; do
+          echo "removing references to $lt_sysroot and \`=' prefixes from $lib"
+        done
+      else
+        tmpdir=`func_mktempdir`
+        for lib in $libs; do
+	  sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \
+	    > $tmpdir/tmp-la
+	  mv -f $tmpdir/tmp-la $lib
+	done
+        ${RM}r "$tmpdir"
+      fi
+    fi
+
+    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+      for libdir in $libdirs; do
+	if test -n "$finish_cmds"; then
+	  # Do each command in the finish commands.
+	  func_execute_cmds "$finish_cmds" 'admincmds="$admincmds
+'"$cmd"'"'
+	fi
+	if test -n "$finish_eval"; then
+	  # Do the single finish_eval.
+	  eval cmds=\"$finish_eval\"
+	  $opt_dry_run || eval "$cmds" || admincmds+="
+       $cmds"
+	fi
+      done
+    fi
+
+    # Exit here if they wanted silent mode.
+    $opt_silent && exit $EXIT_SUCCESS
+
+    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+      echo "----------------------------------------------------------------------"
+      echo "Libraries have been installed in:"
+      for libdir in $libdirs; do
+	$ECHO "   $libdir"
+      done
+      echo
+      echo "If you ever happen to want to link against installed libraries"
+      echo "in a given directory, LIBDIR, you must either use libtool, and"
+      echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
+      echo "flag during linking and do at least one of the following:"
+      if test -n "$shlibpath_var"; then
+	echo "   - add LIBDIR to the \`$shlibpath_var' environment variable"
+	echo "     during execution"
+      fi
+      if test -n "$runpath_var"; then
+	echo "   - add LIBDIR to the \`$runpath_var' environment variable"
+	echo "     during linking"
+      fi
+      if test -n "$hardcode_libdir_flag_spec"; then
+	libdir=LIBDIR
+	eval flag=\"$hardcode_libdir_flag_spec\"
+
+	$ECHO "   - use the \`$flag' linker flag"
+      fi
+      if test -n "$admincmds"; then
+	$ECHO "   - have your system administrator run these commands:$admincmds"
+      fi
+      if test -f /etc/ld.so.conf; then
+	echo "   - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+      fi
+      echo
+
+      echo "See any operating system documentation about shared libraries for"
+      case $host in
+	solaris2.[6789]|solaris2.1[0-9])
+	  echo "more information, such as the ld(1), crle(1) and ld.so(8) manual"
+	  echo "pages."
+	  ;;
+	*)
+	  echo "more information, such as the ld(1) and ld.so(8) manual pages."
+	  ;;
+      esac
+      echo "----------------------------------------------------------------------"
+    fi
+    exit $EXIT_SUCCESS
+}
+
+test "$opt_mode" = finish && func_mode_finish ${1+"$@"}
+
+
+# func_mode_install arg...
+func_mode_install ()
+{
+    $opt_debug
+    # There may be an optional sh(1) argument at the beginning of
+    # install_prog (especially on Windows NT).
+    if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
+       # Allow the use of GNU shtool's install command.
+       case $nonopt in *shtool*) :;; *) false;; esac; then
+      # Aesthetically quote it.
+      func_quote_for_eval "$nonopt"
+      install_prog="$func_quote_for_eval_result "
+      arg=$1
+      shift
+    else
+      install_prog=
+      arg=$nonopt
+    fi
+
+    # The real first argument should be the name of the installation program.
+    # Aesthetically quote it.
+    func_quote_for_eval "$arg"
+    install_prog+="$func_quote_for_eval_result"
+    install_shared_prog=$install_prog
+    case " $install_prog " in
+      *[\\\ /]cp\ *) install_cp=: ;;
+      *) install_cp=false ;;
+    esac
+
+    # We need to accept at least all the BSD install flags.
+    dest=
+    files=
+    opts=
+    prev=
+    install_type=
+    isdir=no
+    stripme=
+    no_mode=:
+    for arg
+    do
+      arg2=
+      if test -n "$dest"; then
+	files+=" $dest"
+	dest=$arg
+	continue
+      fi
+
+      case $arg in
+      -d) isdir=yes ;;
+      -f)
+	if $install_cp; then :; else
+	  prev=$arg
+	fi
+	;;
+      -g | -m | -o)
+	prev=$arg
+	;;
+      -s)
+	stripme=" -s"
+	continue
+	;;
+      -*)
+	;;
+      *)
+	# If the previous option needed an argument, then skip it.
+	if test -n "$prev"; then
+	  if test "x$prev" = x-m && test -n "$install_override_mode"; then
+	    arg2=$install_override_mode
+	    no_mode=false
+	  fi
+	  prev=
+	else
+	  dest=$arg
+	  continue
+	fi
+	;;
+      esac
+
+      # Aesthetically quote the argument.
+      func_quote_for_eval "$arg"
+      install_prog+=" $func_quote_for_eval_result"
+      if test -n "$arg2"; then
+	func_quote_for_eval "$arg2"
+      fi
+      install_shared_prog+=" $func_quote_for_eval_result"
+    done
+
+    test -z "$install_prog" && \
+      func_fatal_help "you must specify an install program"
+
+    test -n "$prev" && \
+      func_fatal_help "the \`$prev' option requires an argument"
+
+    if test -n "$install_override_mode" && $no_mode; then
+      if $install_cp; then :; else
+	func_quote_for_eval "$install_override_mode"
+	install_shared_prog+=" -m $func_quote_for_eval_result"
+      fi
+    fi
+
+    if test -z "$files"; then
+      if test -z "$dest"; then
+	func_fatal_help "no file or destination specified"
+      else
+	func_fatal_help "you must specify a destination"
+      fi
+    fi
+
+    # Strip any trailing slash from the destination.
+    func_stripname '' '/' "$dest"
+    dest=$func_stripname_result
+
+    # Check to see that the destination is a directory.
+    test -d "$dest" && isdir=yes
+    if test "$isdir" = yes; then
+      destdir="$dest"
+      destname=
+    else
+      func_dirname_and_basename "$dest" "" "."
+      destdir="$func_dirname_result"
+      destname="$func_basename_result"
+
+      # Not a directory, so check to see that there is only one file specified.
+      set dummy $files; shift
+      test "$#" -gt 1 && \
+	func_fatal_help "\`$dest' is not a directory"
+    fi
+    case $destdir in
+    [\\/]* | [A-Za-z]:[\\/]*) ;;
+    *)
+      for file in $files; do
+	case $file in
+	*.lo) ;;
+	*)
+	  func_fatal_help "\`$destdir' must be an absolute directory name"
+	  ;;
+	esac
+      done
+      ;;
+    esac
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    staticlibs=
+    future_libdirs=
+    current_libdirs=
+    for file in $files; do
+
+      # Do each installation.
+      case $file in
+      *.$libext)
+	# Do the static libraries later.
+	staticlibs+=" $file"
+	;;
+
+      *.la)
+	func_resolve_sysroot "$file"
+	file=$func_resolve_sysroot_result
+
+	# Check to see that this really is a libtool archive.
+	func_lalib_unsafe_p "$file" \
+	  || func_fatal_help "\`$file' is not a valid libtool archive"
+
+	library_names=
+	old_library=
+	relink_command=
+	func_source "$file"
+
+	# Add the libdir to current_libdirs if it is the destination.
+	if test "X$destdir" = "X$libdir"; then
+	  case "$current_libdirs " in
+	  *" $libdir "*) ;;
+	  *) current_libdirs+=" $libdir" ;;
+	  esac
+	else
+	  # Note the libdir as a future libdir.
+	  case "$future_libdirs " in
+	  *" $libdir "*) ;;
+	  *) future_libdirs+=" $libdir" ;;
+	  esac
+	fi
+
+	func_dirname "$file" "/" ""
+	dir="$func_dirname_result"
+	dir+="$objdir"
+
+	if test -n "$relink_command"; then
+	  # Determine the prefix the user has applied to our future dir.
+	  inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"`
+
+	  # Don't allow the user to place us outside of our expected
+	  # location b/c this prevents finding dependent libraries that
+	  # are installed to the same prefix.
+	  # At present, this check doesn't affect windows .dll's that
+	  # are installed into $libdir/../bin (currently, that works fine)
+	  # but it's something to keep an eye on.
+	  test "$inst_prefix_dir" = "$destdir" && \
+	    func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir"
+
+	  if test -n "$inst_prefix_dir"; then
+	    # Stick the inst_prefix_dir data into the link command.
+	    relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+	  else
+	    relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
+	  fi
+
+	  func_warning "relinking \`$file'"
+	  func_show_eval "$relink_command" \
+	    'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"'
+	fi
+
+	# See the names of the shared library.
+	set dummy $library_names; shift
+	if test -n "$1"; then
+	  realname="$1"
+	  shift
+
+	  srcname="$realname"
+	  test -n "$relink_command" && srcname="$realname"T
+
+	  # Install the shared library and build the symlinks.
+	  func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \
+	      'exit $?'
+	  tstripme="$stripme"
+	  case $host_os in
+	  cygwin* | mingw* | pw32* | cegcc*)
+	    case $realname in
+	    *.dll.a)
+	      tstripme=""
+	      ;;
+	    esac
+	    ;;
+	  esac
+	  if test -n "$tstripme" && test -n "$striplib"; then
+	    func_show_eval "$striplib $destdir/$realname" 'exit $?'
+	  fi
+
+	  if test "$#" -gt 0; then
+	    # Delete the old symlinks, and create new ones.
+	    # Try `ln -sf' first, because the `ln' binary might depend on
+	    # the symlink we replace!  Solaris /bin/ln does not understand -f,
+	    # so we also need to try rm && ln -s.
+	    for linkname
+	    do
+	      test "$linkname" != "$realname" \
+		&& func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })"
+	    done
+	  fi
+
+	  # Do each command in the postinstall commands.
+	  lib="$destdir/$realname"
+	  func_execute_cmds "$postinstall_cmds" 'exit $?'
+	fi
+
+	# Install the pseudo-library for information purposes.
+	func_basename "$file"
+	name="$func_basename_result"
+	instname="$dir/$name"i
+	func_show_eval "$install_prog $instname $destdir/$name" 'exit $?'
+
+	# Maybe install the static library, too.
+	test -n "$old_library" && staticlibs+=" $dir/$old_library"
+	;;
+
+      *.lo)
+	# Install (i.e. copy) a libtool object.
+
+	# Figure out destination file name, if it wasn't already specified.
+	if test -n "$destname"; then
+	  destfile="$destdir/$destname"
+	else
+	  func_basename "$file"
+	  destfile="$func_basename_result"
+	  destfile="$destdir/$destfile"
+	fi
+
+	# Deduce the name of the destination old-style object file.
+	case $destfile in
+	*.lo)
+	  func_lo2o "$destfile"
+	  staticdest=$func_lo2o_result
+	  ;;
+	*.$objext)
+	  staticdest="$destfile"
+	  destfile=
+	  ;;
+	*)
+	  func_fatal_help "cannot copy a libtool object to \`$destfile'"
+	  ;;
+	esac
+
+	# Install the libtool object if requested.
+	test -n "$destfile" && \
+	  func_show_eval "$install_prog $file $destfile" 'exit $?'
+
+	# Install the old object if enabled.
+	if test "$build_old_libs" = yes; then
+	  # Deduce the name of the old-style object file.
+	  func_lo2o "$file"
+	  staticobj=$func_lo2o_result
+	  func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?'
+	fi
+	exit $EXIT_SUCCESS
+	;;
+
+      *)
+	# Figure out destination file name, if it wasn't already specified.
+	if test -n "$destname"; then
+	  destfile="$destdir/$destname"
+	else
+	  func_basename "$file"
+	  destfile="$func_basename_result"
+	  destfile="$destdir/$destfile"
+	fi
+
+	# If the file is missing, and there is a .exe on the end, strip it
+	# because it is most likely a libtool script we actually want to
+	# install
+	stripped_ext=""
+	case $file in
+	  *.exe)
+	    if test ! -f "$file"; then
+	      func_stripname '' '.exe' "$file"
+	      file=$func_stripname_result
+	      stripped_ext=".exe"
+	    fi
+	    ;;
+	esac
+
+	# Do a test to see if this is really a libtool program.
+	case $host in
+	*cygwin* | *mingw*)
+	    if func_ltwrapper_executable_p "$file"; then
+	      func_ltwrapper_scriptname "$file"
+	      wrapper=$func_ltwrapper_scriptname_result
+	    else
+	      func_stripname '' '.exe' "$file"
+	      wrapper=$func_stripname_result
+	    fi
+	    ;;
+	*)
+	    wrapper=$file
+	    ;;
+	esac
+	if func_ltwrapper_script_p "$wrapper"; then
+	  notinst_deplibs=
+	  relink_command=
+
+	  func_source "$wrapper"
+
+	  # Check the variables that should have been set.
+	  test -z "$generated_by_libtool_version" && \
+	    func_fatal_error "invalid libtool wrapper script \`$wrapper'"
+
+	  finalize=yes
+	  for lib in $notinst_deplibs; do
+	    # Check to see that each library is installed.
+	    libdir=
+	    if test -f "$lib"; then
+	      func_source "$lib"
+	    fi
+	    libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test
+	    if test -n "$libdir" && test ! -f "$libfile"; then
+	      func_warning "\`$lib' has not been installed in \`$libdir'"
+	      finalize=no
+	    fi
+	  done
+
+	  relink_command=
+	  func_source "$wrapper"
+
+	  outputname=
+	  if test "$fast_install" = no && test -n "$relink_command"; then
+	    $opt_dry_run || {
+	      if test "$finalize" = yes; then
+	        tmpdir=`func_mktempdir`
+		func_basename "$file$stripped_ext"
+		file="$func_basename_result"
+	        outputname="$tmpdir/$file"
+	        # Replace the output file specification.
+	        relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'`
+
+	        $opt_silent || {
+	          func_quote_for_expand "$relink_command"
+		  eval "func_echo $func_quote_for_expand_result"
+	        }
+	        if eval "$relink_command"; then :
+	          else
+		  func_error "error: relink \`$file' with the above command before installing it"
+		  $opt_dry_run || ${RM}r "$tmpdir"
+		  continue
+	        fi
+	        file="$outputname"
+	      else
+	        func_warning "cannot relink \`$file'"
+	      fi
+	    }
+	  else
+	    # Install the binary that we compiled earlier.
+	    file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"`
+	  fi
+	fi
+
+	# remove .exe since cygwin /usr/bin/install will append another
+	# one anyway
+	case $install_prog,$host in
+	*/usr/bin/install*,*cygwin*)
+	  case $file:$destfile in
+	  *.exe:*.exe)
+	    # this is ok
+	    ;;
+	  *.exe:*)
+	    destfile=$destfile.exe
+	    ;;
+	  *:*.exe)
+	    func_stripname '' '.exe' "$destfile"
+	    destfile=$func_stripname_result
+	    ;;
+	  esac
+	  ;;
+	esac
+	func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?'
+	$opt_dry_run || if test -n "$outputname"; then
+	  ${RM}r "$tmpdir"
+	fi
+	;;
+      esac
+    done
+
+    for file in $staticlibs; do
+      func_basename "$file"
+      name="$func_basename_result"
+
+      # Set up the ranlib parameters.
+      oldlib="$destdir/$name"
+      func_to_tool_file "$oldlib" func_convert_file_msys_to_w32
+      tool_oldlib=$func_to_tool_file_result
+
+      func_show_eval "$install_prog \$file \$oldlib" 'exit $?'
+
+      if test -n "$stripme" && test -n "$old_striplib"; then
+	func_show_eval "$old_striplib $tool_oldlib" 'exit $?'
+      fi
+
+      # Do each command in the postinstall commands.
+      func_execute_cmds "$old_postinstall_cmds" 'exit $?'
+    done
+
+    test -n "$future_libdirs" && \
+      func_warning "remember to run \`$progname --finish$future_libdirs'"
+
+    if test -n "$current_libdirs"; then
+      # Maybe just do a dry run.
+      $opt_dry_run && current_libdirs=" -n$current_libdirs"
+      exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
+    else
+      exit $EXIT_SUCCESS
+    fi
+}
+
+test "$opt_mode" = install && func_mode_install ${1+"$@"}
+
+
+# func_generate_dlsyms outputname originator pic_p
+# Extract symbols from dlprefiles and create ${outputname}S.o with
+# a dlpreopen symbol table.
+func_generate_dlsyms ()
+{
+    $opt_debug
+    my_outputname="$1"
+    my_originator="$2"
+    my_pic_p="${3-no}"
+    my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'`
+    my_dlsyms=
+
+    if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+      if test -n "$NM" && test -n "$global_symbol_pipe"; then
+	my_dlsyms="${my_outputname}S.c"
+      else
+	func_error "not configured to extract global symbols from dlpreopened files"
+      fi
+    fi
+
+    if test -n "$my_dlsyms"; then
+      case $my_dlsyms in
+      "") ;;
+      *.c)
+	# Discover the nlist of each of the dlfiles.
+	nlist="$output_objdir/${my_outputname}.nm"
+
+	func_show_eval "$RM $nlist ${nlist}S ${nlist}T"
+
+	# Parse the name list into a source file.
+	func_verbose "creating $output_objdir/$my_dlsyms"
+
+	$opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\
+/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */
+/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4))
+#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
+#endif
+
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE)
+/* DATA imports from DLLs on WIN32 con't be const, because runtime
+   relocations are performed -- see ld's documentation on pseudo-relocs.  */
+# define LT_DLSYM_CONST
+#elif defined(__osf__)
+/* This system does not cope well with relocations in const data.  */
+# define LT_DLSYM_CONST
+#else
+# define LT_DLSYM_CONST const
+#endif
+
+/* External symbol declarations for the compiler. */\
+"
+
+	if test "$dlself" = yes; then
+	  func_verbose "generating symbol list for \`$output'"
+
+	  $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist"
+
+	  # Add our own program objects to the symbol list.
+	  progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP`
+	  for progfile in $progfiles; do
+	    func_to_tool_file "$progfile" func_convert_file_msys_to_w32
+	    func_verbose "extracting global C symbols from \`$func_to_tool_file_result'"
+	    $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'"
+	  done
+
+	  if test -n "$exclude_expsyms"; then
+	    $opt_dry_run || {
+	      eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+	      eval '$MV "$nlist"T "$nlist"'
+	    }
+	  fi
+
+	  if test -n "$export_symbols_regex"; then
+	    $opt_dry_run || {
+	      eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+	      eval '$MV "$nlist"T "$nlist"'
+	    }
+	  fi
+
+	  # Prepare the list of exported symbols
+	  if test -z "$export_symbols"; then
+	    export_symbols="$output_objdir/$outputname.exp"
+	    $opt_dry_run || {
+	      $RM $export_symbols
+	      eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+	      case $host in
+	      *cygwin* | *mingw* | *cegcc* )
+                eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+                eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
+	        ;;
+	      esac
+	    }
+	  else
+	    $opt_dry_run || {
+	      eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
+	      eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
+	      eval '$MV "$nlist"T "$nlist"'
+	      case $host in
+	        *cygwin* | *mingw* | *cegcc* )
+	          eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+	          eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
+	          ;;
+	      esac
+	    }
+	  fi
+	fi
+
+	for dlprefile in $dlprefiles; do
+	  func_verbose "extracting global C symbols from \`$dlprefile'"
+	  func_basename "$dlprefile"
+	  name="$func_basename_result"
+          case $host in
+	    *cygwin* | *mingw* | *cegcc* )
+	      # if an import library, we need to obtain dlname
+	      if func_win32_import_lib_p "$dlprefile"; then
+	        func_tr_sh "$dlprefile"
+	        eval "curr_lafile=\$libfile_$func_tr_sh_result"
+	        dlprefile_dlbasename=""
+	        if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then
+	          # Use subshell, to avoid clobbering current variable values
+	          dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"`
+	          if test -n "$dlprefile_dlname" ; then
+	            func_basename "$dlprefile_dlname"
+	            dlprefile_dlbasename="$func_basename_result"
+	          else
+	            # no lafile. user explicitly requested -dlpreopen <import library>.
+	            $sharedlib_from_linklib_cmd "$dlprefile"
+	            dlprefile_dlbasename=$sharedlib_from_linklib_result
+	          fi
+	        fi
+	        $opt_dry_run || {
+	          if test -n "$dlprefile_dlbasename" ; then
+	            eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"'
+	          else
+	            func_warning "Could not compute DLL name from $name"
+	            eval '$ECHO ": $name " >> "$nlist"'
+	          fi
+	          func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
+	          eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe |
+	            $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'"
+	        }
+	      else # not an import lib
+	        $opt_dry_run || {
+	          eval '$ECHO ": $name " >> "$nlist"'
+	          func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
+	          eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'"
+	        }
+	      fi
+	    ;;
+	    *)
+	      $opt_dry_run || {
+	        eval '$ECHO ": $name " >> "$nlist"'
+	        func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
+	        eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'"
+	      }
+	    ;;
+          esac
+	done
+
+	$opt_dry_run || {
+	  # Make sure we have at least an empty file.
+	  test -f "$nlist" || : > "$nlist"
+
+	  if test -n "$exclude_expsyms"; then
+	    $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+	    $MV "$nlist"T "$nlist"
+	  fi
+
+	  # Try sorting and uniquifying the output.
+	  if $GREP -v "^: " < "$nlist" |
+	      if sort -k 3 </dev/null >/dev/null 2>&1; then
+		sort -k 3
+	      else
+		sort +2
+	      fi |
+	      uniq > "$nlist"S; then
+	    :
+	  else
+	    $GREP -v "^: " < "$nlist" > "$nlist"S
+	  fi
+
+	  if test -f "$nlist"S; then
+	    eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"'
+	  else
+	    echo '/* NONE */' >> "$output_objdir/$my_dlsyms"
+	  fi
+
+	  echo >> "$output_objdir/$my_dlsyms" "\
+
+/* The mapping between symbol names and symbols.  */
+typedef struct {
+  const char *name;
+  void *address;
+} lt_dlsymlist;
+extern LT_DLSYM_CONST lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[];
+LT_DLSYM_CONST lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[] =
+{\
+  { \"$my_originator\", (void *) 0 },"
+
+	  case $need_lib_prefix in
+	  no)
+	    eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms"
+	    ;;
+	  *)
+	    eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms"
+	    ;;
+	  esac
+	  echo >> "$output_objdir/$my_dlsyms" "\
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt_${my_prefix}_LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+	} # !$opt_dry_run
+
+	pic_flag_for_symtable=
+	case "$compile_command " in
+	*" -static "*) ;;
+	*)
+	  case $host in
+	  # compiling the symbol table file with pic_flag works around
+	  # a FreeBSD bug that causes programs to crash when -lm is
+	  # linked before any other PIC object.  But we must not use
+	  # pic_flag when linking with -static.  The problem exists in
+	  # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+	  *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+	    pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;;
+	  *-*-hpux*)
+	    pic_flag_for_symtable=" $pic_flag"  ;;
+	  *)
+	    if test "X$my_pic_p" != Xno; then
+	      pic_flag_for_symtable=" $pic_flag"
+	    fi
+	    ;;
+	  esac
+	  ;;
+	esac
+	symtab_cflags=
+	for arg in $LTCFLAGS; do
+	  case $arg in
+	  -pie | -fpie | -fPIE) ;;
+	  *) symtab_cflags+=" $arg" ;;
+	  esac
+	done
+
+	# Now compile the dynamic symbol file.
+	func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?'
+
+	# Clean up the generated files.
+	func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"'
+
+	# Transform the symbol file into the correct name.
+	symfileobj="$output_objdir/${my_outputname}S.$objext"
+	case $host in
+	*cygwin* | *mingw* | *cegcc* )
+	  if test -f "$output_objdir/$my_outputname.def"; then
+	    compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+	    finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+	  else
+	    compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+	    finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+	  fi
+	  ;;
+	*)
+	  compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+	  finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+	  ;;
+	esac
+	;;
+      *)
+	func_fatal_error "unknown suffix for \`$my_dlsyms'"
+	;;
+      esac
+    else
+      # We keep going just in case the user didn't refer to
+      # lt_preloaded_symbols.  The linker will fail if global_symbol_pipe
+      # really was required.
+
+      # Nullify the symbol file.
+      compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"`
+      finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"`
+    fi
+}
+
+# func_win32_libid arg
+# return the library type of file 'arg'
+#
+# Need a lot of goo to handle *both* DLLs and import libs
+# Has to be a shell function in order to 'eat' the argument
+# that is supplied when $file_magic_command is called.
+# Despite the name, also deal with 64 bit binaries.
+func_win32_libid ()
+{
+  $opt_debug
+  win32_libid_type="unknown"
+  win32_fileres=`file -L $1 2>/dev/null`
+  case $win32_fileres in
+  *ar\ archive\ import\ library*) # definitely import
+    win32_libid_type="x86 archive import"
+    ;;
+  *ar\ archive*) # could be an import, or static
+    # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD.
+    if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null |
+       $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then
+      func_to_tool_file "$1" func_convert_file_msys_to_w32
+      win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" |
+	$SED -n -e '
+	    1,100{
+		/ I /{
+		    s,.*,import,
+		    p
+		    q
+		}
+	    }'`
+      case $win32_nmres in
+      import*)  win32_libid_type="x86 archive import";;
+      *)        win32_libid_type="x86 archive static";;
+      esac
+    fi
+    ;;
+  *DLL*)
+    win32_libid_type="x86 DLL"
+    ;;
+  *executable*) # but shell scripts are "executable" too...
+    case $win32_fileres in
+    *MS\ Windows\ PE\ Intel*)
+      win32_libid_type="x86 DLL"
+      ;;
+    esac
+    ;;
+  esac
+  $ECHO "$win32_libid_type"
+}
+
+# func_cygming_dll_for_implib ARG
+#
+# Platform-specific function to extract the
+# name of the DLL associated with the specified
+# import library ARG.
+# Invoked by eval'ing the libtool variable
+#    $sharedlib_from_linklib_cmd
+# Result is available in the variable
+#    $sharedlib_from_linklib_result
+func_cygming_dll_for_implib ()
+{
+  $opt_debug
+  sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"`
+}
+
+# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs
+#
+# The is the core of a fallback implementation of a
+# platform-specific function to extract the name of the
+# DLL associated with the specified import library LIBNAME.
+#
+# SECTION_NAME is either .idata$6 or .idata$7, depending
+# on the platform and compiler that created the implib.
+#
+# Echos the name of the DLL associated with the
+# specified import library.
+func_cygming_dll_for_implib_fallback_core ()
+{
+  $opt_debug
+  match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"`
+  $OBJDUMP -s --section "$1" "$2" 2>/dev/null |
+    $SED '/^Contents of section '"$match_literal"':/{
+      # Place marker at beginning of archive member dllname section
+      s/.*/====MARK====/
+      p
+      d
+    }
+    # These lines can sometimes be longer than 43 characters, but
+    # are always uninteresting
+    /:[	 ]*file format pe[i]\{,1\}-/d
+    /^In archive [^:]*:/d
+    # Ensure marker is printed
+    /^====MARK====/p
+    # Remove all lines with less than 43 characters
+    /^.\{43\}/!d
+    # From remaining lines, remove first 43 characters
+    s/^.\{43\}//' |
+    $SED -n '
+      # Join marker and all lines until next marker into a single line
+      /^====MARK====/ b para
+      H
+      $ b para
+      b
+      :para
+      x
+      s/\n//g
+      # Remove the marker
+      s/^====MARK====//
+      # Remove trailing dots and whitespace
+      s/[\. \t]*$//
+      # Print
+      /./p' |
+    # we now have a list, one entry per line, of the stringified
+    # contents of the appropriate section of all members of the
+    # archive which possess that section. Heuristic: eliminate
+    # all those which have a first or second character that is
+    # a '.' (that is, objdump's representation of an unprintable
+    # character.) This should work for all archives with less than
+    # 0x302f exports -- but will fail for DLLs whose name actually
+    # begins with a literal '.' or a single character followed by
+    # a '.'.
+    #
+    # Of those that remain, print the first one.
+    $SED -e '/^\./d;/^.\./d;q'
+}
+
+# func_cygming_gnu_implib_p ARG
+# This predicate returns with zero status (TRUE) if
+# ARG is a GNU/binutils-style import library. Returns
+# with nonzero status (FALSE) otherwise.
+func_cygming_gnu_implib_p ()
+{
+  $opt_debug
+  func_to_tool_file "$1" func_convert_file_msys_to_w32
+  func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'`
+  test -n "$func_cygming_gnu_implib_tmp"
+}
+
+# func_cygming_ms_implib_p ARG
+# This predicate returns with zero status (TRUE) if
+# ARG is an MS-style import library. Returns
+# with nonzero status (FALSE) otherwise.
+func_cygming_ms_implib_p ()
+{
+  $opt_debug
+  func_to_tool_file "$1" func_convert_file_msys_to_w32
+  func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'`
+  test -n "$func_cygming_ms_implib_tmp"
+}
+
+# func_cygming_dll_for_implib_fallback ARG
+# Platform-specific function to extract the
+# name of the DLL associated with the specified
+# import library ARG.
+#
+# This fallback implementation is for use when $DLLTOOL
+# does not support the --identify-strict option.
+# Invoked by eval'ing the libtool variable
+#    $sharedlib_from_linklib_cmd
+# Result is available in the variable
+#    $sharedlib_from_linklib_result
+func_cygming_dll_for_implib_fallback ()
+{
+  $opt_debug
+  if func_cygming_gnu_implib_p "$1" ; then
+    # binutils import library
+    sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"`
+  elif func_cygming_ms_implib_p "$1" ; then
+    # ms-generated import library
+    sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"`
+  else
+    # unknown
+    sharedlib_from_linklib_result=""
+  fi
+}
+
+
+# func_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+    $opt_debug
+    f_ex_an_ar_dir="$1"; shift
+    f_ex_an_ar_oldlib="$1"
+    if test "$lock_old_archive_extraction" = yes; then
+      lockfile=$f_ex_an_ar_oldlib.lock
+      until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
+	func_echo "Waiting for $lockfile to be removed"
+	sleep 2
+      done
+    fi
+    func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \
+		   'stat=$?; rm -f "$lockfile"; exit $stat'
+    if test "$lock_old_archive_extraction" = yes; then
+      $opt_dry_run || rm -f "$lockfile"
+    fi
+    if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
+     :
+    else
+      func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib"
+    fi
+}
+
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives ()
+{
+    $opt_debug
+    my_gentop="$1"; shift
+    my_oldlibs=${1+"$@"}
+    my_oldobjs=""
+    my_xlib=""
+    my_xabs=""
+    my_xdir=""
+
+    for my_xlib in $my_oldlibs; do
+      # Extract the objects.
+      case $my_xlib in
+	[\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
+	*) my_xabs=`pwd`"/$my_xlib" ;;
+      esac
+      func_basename "$my_xlib"
+      my_xlib="$func_basename_result"
+      my_xlib_u=$my_xlib
+      while :; do
+        case " $extracted_archives " in
+	*" $my_xlib_u "*)
+	  func_arith $extracted_serial + 1
+	  extracted_serial=$func_arith_result
+	  my_xlib_u=lt$extracted_serial-$my_xlib ;;
+	*) break ;;
+	esac
+      done
+      extracted_archives="$extracted_archives $my_xlib_u"
+      my_xdir="$my_gentop/$my_xlib_u"
+
+      func_mkdir_p "$my_xdir"
+
+      case $host in
+      *-darwin*)
+	func_verbose "Extracting $my_xabs"
+	# Do not bother doing anything if just a dry run
+	$opt_dry_run || {
+	  darwin_orig_dir=`pwd`
+	  cd $my_xdir || exit $?
+	  darwin_archive=$my_xabs
+	  darwin_curdir=`pwd`
+	  darwin_base_archive=`basename "$darwin_archive"`
+	  darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true`
+	  if test -n "$darwin_arches"; then
+	    darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'`
+	    darwin_arch=
+	    func_verbose "$darwin_base_archive has multiple architectures $darwin_arches"
+	    for darwin_arch in  $darwin_arches ; do
+	      func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+	      $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
+	      cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+	      func_extract_an_archive "`pwd`" "${darwin_base_archive}"
+	      cd "$darwin_curdir"
+	      $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
+	    done # $darwin_arches
+            ## Okay now we've a bunch of thin objects, gotta fatten them up :)
+	    darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u`
+	    darwin_file=
+	    darwin_files=
+	    for darwin_file in $darwin_filelist; do
+	      darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP`
+	      $LIPO -create -output "$darwin_file" $darwin_files
+	    done # $darwin_filelist
+	    $RM -rf unfat-$$
+	    cd "$darwin_orig_dir"
+	  else
+	    cd $darwin_orig_dir
+	    func_extract_an_archive "$my_xdir" "$my_xabs"
+	  fi # $darwin_arches
+	} # !$opt_dry_run
+	;;
+      *)
+        func_extract_an_archive "$my_xdir" "$my_xabs"
+	;;
+      esac
+      my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP`
+    done
+
+    func_extract_archives_result="$my_oldobjs"
+}
+
+
+# func_emit_wrapper [arg=no]
+#
+# Emit a libtool wrapper script on stdout.
+# Don't directly open a file because we may want to
+# incorporate the script contents within a cygwin/mingw
+# wrapper executable.  Must ONLY be called from within
+# func_mode_link because it depends on a number of variables
+# set therein.
+#
+# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR
+# variable will take.  If 'yes', then the emitted script
+# will assume that the directory in which it is stored is
+# the $objdir directory.  This is a cygwin/mingw-specific
+# behavior.
+func_emit_wrapper ()
+{
+	func_emit_wrapper_arg1=${1-no}
+
+	$ECHO "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='$sed_quote_subst'
+
+# Be Bourne compatible
+if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+  # install mode needs the following variables:
+  generated_by_libtool_version='$macro_version'
+  notinst_deplibs='$notinst_deplibs'
+else
+  # When we are sourced in execute mode, \$file and \$ECHO are already set.
+  if test \"\$libtool_execute_magic\" != \"$magic\"; then
+    file=\"\$0\""
+
+    qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"`
+    $ECHO "\
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+\$1
+_LTECHO_EOF'
+}
+    ECHO=\"$qECHO\"
+  fi
+
+# Very basic option parsing. These options are (a) specific to
+# the libtool wrapper, (b) are identical between the wrapper
+# /script/ and the wrapper /executable/ which is used only on
+# windows platforms, and (c) all begin with the string "--lt-"
+# (application programs are unlikely to have options which match
+# this pattern).
+#
+# There are only two supported options: --lt-debug and
+# --lt-dump-script. There is, deliberately, no --lt-help.
+#
+# The first argument to this parsing function should be the
+# script's $0 value, followed by "$@".
+lt_option_debug=
+func_parse_lt_options ()
+{
+  lt_script_arg0=\$0
+  shift
+  for lt_opt
+  do
+    case \"\$lt_opt\" in
+    --lt-debug) lt_option_debug=1 ;;
+    --lt-dump-script)
+        lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\`
+        test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=.
+        lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\`
+        cat \"\$lt_dump_D/\$lt_dump_F\"
+        exit 0
+      ;;
+    --lt-*)
+        \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2
+        exit 1
+      ;;
+    esac
+  done
+
+  # Print the debug banner immediately:
+  if test -n \"\$lt_option_debug\"; then
+    echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2
+  fi
+}
+
+# Used when --lt-debug. Prints its arguments to stdout
+# (redirection is the responsibility of the caller)
+func_lt_dump_args ()
+{
+  lt_dump_args_N=1;
+  for lt_arg
+  do
+    \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\"
+    lt_dump_args_N=\`expr \$lt_dump_args_N + 1\`
+  done
+}
+
+# Core function for launching the target application
+func_exec_program_core ()
+{
+"
+  case $host in
+  # Backslashes separate directories on plain windows
+  *-*-mingw | *-*-os2* | *-cegcc*)
+    $ECHO "\
+      if test -n \"\$lt_option_debug\"; then
+        \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2
+        func_lt_dump_args \${1+\"\$@\"} 1>&2
+      fi
+      exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
+"
+    ;;
+
+  *)
+    $ECHO "\
+      if test -n \"\$lt_option_debug\"; then
+        \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2
+        func_lt_dump_args \${1+\"\$@\"} 1>&2
+      fi
+      exec \"\$progdir/\$program\" \${1+\"\$@\"}
+"
+    ;;
+  esac
+  $ECHO "\
+      \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2
+      exit 1
+}
+
+# A function to encapsulate launching the target application
+# Strips options in the --lt-* namespace from \$@ and
+# launches target application with the remaining arguments.
+func_exec_program ()
+{
+  case \" \$* \" in
+  *\\ --lt-*)
+    for lt_wr_arg
+    do
+      case \$lt_wr_arg in
+      --lt-*) ;;
+      *) set x \"\$@\" \"\$lt_wr_arg\"; shift;;
+      esac
+      shift
+    done ;;
+  esac
+  func_exec_program_core \${1+\"\$@\"}
+}
+
+  # Parse options
+  func_parse_lt_options \"\$0\" \${1+\"\$@\"}
+
+  # Find the directory that this script lives in.
+  thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\`
+  test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+  # Follow symbolic links until we get to the real thisdir.
+  file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\`
+  while test -n \"\$file\"; do
+    destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\`
+
+    # If there was a directory component, then change thisdir.
+    if test \"x\$destdir\" != \"x\$file\"; then
+      case \"\$destdir\" in
+      [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+      *) thisdir=\"\$thisdir/\$destdir\" ;;
+      esac
+    fi
+
+    file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\`
+    file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\`
+  done
+
+  # Usually 'no', except on cygwin/mingw when embedded into
+  # the cwrapper.
+  WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1
+  if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then
+    # special case for '.'
+    if test \"\$thisdir\" = \".\"; then
+      thisdir=\`pwd\`
+    fi
+    # remove .libs from thisdir
+    case \"\$thisdir\" in
+    *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;;
+    $objdir )   thisdir=. ;;
+    esac
+  fi
+
+  # Try to get the absolute directory name.
+  absdir=\`cd \"\$thisdir\" && pwd\`
+  test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+	if test "$fast_install" = yes; then
+	  $ECHO "\
+  program=lt-'$outputname'$exeext
+  progdir=\"\$thisdir/$objdir\"
+
+  if test ! -f \"\$progdir/\$program\" ||
+     { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
+       test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+    file=\"\$\$-\$program\"
+
+    if test ! -d \"\$progdir\"; then
+      $MKDIR \"\$progdir\"
+    else
+      $RM \"\$progdir/\$file\"
+    fi"
+
+	  $ECHO "\
+
+    # relink executable if necessary
+    if test -n \"\$relink_command\"; then
+      if relink_command_output=\`eval \$relink_command 2>&1\`; then :
+      else
+	$ECHO \"\$relink_command_output\" >&2
+	$RM \"\$progdir/\$file\"
+	exit 1
+      fi
+    fi
+
+    $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+    { $RM \"\$progdir/\$program\";
+      $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+    $RM \"\$progdir/\$file\"
+  fi"
+	else
+	  $ECHO "\
+  program='$outputname'
+  progdir=\"\$thisdir/$objdir\"
+"
+	fi
+
+	$ECHO "\
+
+  if test -f \"\$progdir/\$program\"; then"
+
+	# fixup the dll searchpath if we need to.
+	#
+	# Fix the DLL searchpath if we need to.  Do this before prepending
+	# to shlibpath, because on Windows, both are PATH and uninstalled
+	# libraries must come first.
+	if test -n "$dllsearchpath"; then
+	  $ECHO "\
+    # Add the dll search path components to the executable PATH
+    PATH=$dllsearchpath:\$PATH
+"
+	fi
+
+	# Export our shlibpath_var if we have one.
+	if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+	  $ECHO "\
+    # Add our own library path to $shlibpath_var
+    $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+    # Some systems cannot cope with colon-terminated $shlibpath_var
+    # The second colon is a workaround for a bug in BeOS R4 sed
+    $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\`
+
+    export $shlibpath_var
+"
+	fi
+
+	$ECHO "\
+    if test \"\$libtool_execute_magic\" != \"$magic\"; then
+      # Run the actual program with our arguments.
+      func_exec_program \${1+\"\$@\"}
+    fi
+  else
+    # The program doesn't exist.
+    \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
+    \$ECHO \"This script is just a wrapper for \$program.\" 1>&2
+    \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2
+    exit 1
+  fi
+fi\
+"
+}
+
+
+# func_emit_cwrapperexe_src
+# emit the source code for a wrapper executable on stdout
+# Must ONLY be called from within func_mode_link because
+# it depends on a number of variable set therein.
+func_emit_cwrapperexe_src ()
+{
+	cat <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+   Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+
+   The $output program cannot be directly executed until all the libtool
+   libraries that it depends on are installed.
+
+   This wrapper executable should never be moved out of the build directory.
+   If it is, it will not operate correctly.
+*/
+EOF
+	    cat <<"EOF"
+#ifdef _MSC_VER
+# define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef _MSC_VER
+# include <direct.h>
+# include <process.h>
+# include <io.h>
+#else
+# include <unistd.h>
+# include <stdint.h>
+# ifdef __CYGWIN__
+#  include <io.h>
+# endif
+#endif
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+/* declarations of non-ANSI functions */
+#if defined(__MINGW32__)
+# ifdef __STRICT_ANSI__
+int _putenv (const char *);
+# endif
+#elif defined(__CYGWIN__)
+# ifdef __STRICT_ANSI__
+char *realpath (const char *, char *);
+int putenv (char *);
+int setenv (const char *, const char *, int);
+# endif
+/* #elif defined (other platforms) ... */
+#endif
+
+/* portability defines, excluding path handling macros */
+#if defined(_MSC_VER)
+# define setmode _setmode
+# define stat    _stat
+# define chmod   _chmod
+# define getcwd  _getcwd
+# define putenv  _putenv
+# define S_IXUSR _S_IEXEC
+# ifndef _INTPTR_T_DEFINED
+#  define _INTPTR_T_DEFINED
+#  define intptr_t int
+# endif
+#elif defined(__MINGW32__)
+# define setmode _setmode
+# define stat    _stat
+# define chmod   _chmod
+# define getcwd  _getcwd
+# define putenv  _putenv
+#elif defined(__CYGWIN__)
+# define HAVE_SETENV
+# define FOPEN_WB "wb"
+/* #elif defined (other platforms) ... */
+#endif
+
+#if defined(PATH_MAX)
+# define LT_PATHMAX PATH_MAX
+#elif defined(MAXPATHLEN)
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef S_IXOTH
+# define S_IXOTH 0
+#endif
+#ifndef S_IXGRP
+# define S_IXGRP 0
+#endif
+
+/* path handling portability macros */
+#ifndef DIR_SEPARATOR
+# define DIR_SEPARATOR '/'
+# define PATH_SEPARATOR ':'
+#endif
+
+#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
+  defined (__OS2__)
+# define HAVE_DOS_BASED_FILE_SYSTEM
+# define FOPEN_WB "wb"
+# ifndef DIR_SEPARATOR_2
+#  define DIR_SEPARATOR_2 '\\'
+# endif
+# ifndef PATH_SEPARATOR_2
+#  define PATH_SEPARATOR_2 ';'
+# endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+	(((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#ifndef PATH_SEPARATOR_2
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
+#else /* PATH_SEPARATOR_2 */
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
+#endif /* PATH_SEPARATOR_2 */
+
+#ifndef FOPEN_WB
+# define FOPEN_WB "w"
+#endif
+#ifndef _O_BINARY
+# define _O_BINARY 0
+#endif
+
+#define XMALLOC(type, num)      ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+  if (stale) { free ((void *) stale); stale = 0; } \
+} while (0)
+
+#if defined(LT_DEBUGWRAPPER)
+static int lt_debug = 1;
+#else
+static int lt_debug = 0;
+#endif
+
+const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */
+
+void *xmalloc (size_t num);
+char *xstrdup (const char *string);
+const char *base_name (const char *name);
+char *find_executable (const char *wrapper);
+char *chase_symlinks (const char *pathspec);
+int make_executable (const char *path);
+int check_executable (const char *path);
+char *strendzap (char *str, const char *pat);
+void lt_debugprintf (const char *file, int line, const char *fmt, ...);
+void lt_fatal (const char *file, int line, const char *message, ...);
+static const char *nonnull (const char *s);
+static const char *nonempty (const char *s);
+void lt_setenv (const char *name, const char *value);
+char *lt_extend_str (const char *orig_value, const char *add, int to_end);
+void lt_update_exe_path (const char *name, const char *value);
+void lt_update_lib_path (const char *name, const char *value);
+char **prepare_spawn (char **argv);
+void lt_dump_script (FILE *f);
+EOF
+
+	    cat <<EOF
+volatile const char * MAGIC_EXE = "$magic_exe";
+const char * LIB_PATH_VARNAME = "$shlibpath_var";
+EOF
+
+	    if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+              func_to_host_path "$temp_rpath"
+	      cat <<EOF
+const char * LIB_PATH_VALUE   = "$func_to_host_path_result";
+EOF
+	    else
+	      cat <<"EOF"
+const char * LIB_PATH_VALUE   = "";
+EOF
+	    fi
+
+	    if test -n "$dllsearchpath"; then
+              func_to_host_path "$dllsearchpath:"
+	      cat <<EOF
+const char * EXE_PATH_VARNAME = "PATH";
+const char * EXE_PATH_VALUE   = "$func_to_host_path_result";
+EOF
+	    else
+	      cat <<"EOF"
+const char * EXE_PATH_VARNAME = "";
+const char * EXE_PATH_VALUE   = "";
+EOF
+	    fi
+
+	    if test "$fast_install" = yes; then
+	      cat <<EOF
+const char * TARGET_PROGRAM_NAME = "lt-$outputname"; /* hopefully, no .exe */
+EOF
+	    else
+	      cat <<EOF
+const char * TARGET_PROGRAM_NAME = "$outputname"; /* hopefully, no .exe */
+EOF
+	    fi
+
+
+	    cat <<"EOF"
+
+#define LTWRAPPER_OPTION_PREFIX         "--lt-"
+
+static const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX;
+static const char *dumpscript_opt       = LTWRAPPER_OPTION_PREFIX "dump-script";
+static const char *debug_opt            = LTWRAPPER_OPTION_PREFIX "debug";
+
+int
+main (int argc, char *argv[])
+{
+  char **newargz;
+  int  newargc;
+  char *tmp_pathspec;
+  char *actual_cwrapper_path;
+  char *actual_cwrapper_name;
+  char *target_name;
+  char *lt_argv_zero;
+  intptr_t rval = 127;
+
+  int i;
+
+  program_name = (char *) xstrdup (base_name (argv[0]));
+  newargz = XMALLOC (char *, argc + 1);
+
+  /* very simple arg parsing; don't want to rely on getopt
+   * also, copy all non cwrapper options to newargz, except
+   * argz[0], which is handled differently
+   */
+  newargc=0;
+  for (i = 1; i < argc; i++)
+    {
+      if (strcmp (argv[i], dumpscript_opt) == 0)
+	{
+EOF
+	    case "$host" in
+	      *mingw* | *cygwin* )
+		# make stdout use "unix" line endings
+		echo "          setmode(1,_O_BINARY);"
+		;;
+	      esac
+
+	    cat <<"EOF"
+	  lt_dump_script (stdout);
+	  return 0;
+	}
+      if (strcmp (argv[i], debug_opt) == 0)
+	{
+          lt_debug = 1;
+          continue;
+	}
+      if (strcmp (argv[i], ltwrapper_option_prefix) == 0)
+        {
+          /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX
+             namespace, but it is not one of the ones we know about and
+             have already dealt with, above (inluding dump-script), then
+             report an error. Otherwise, targets might begin to believe
+             they are allowed to use options in the LTWRAPPER_OPTION_PREFIX
+             namespace. The first time any user complains about this, we'll
+             need to make LTWRAPPER_OPTION_PREFIX a configure-time option
+             or a configure.ac-settable value.
+           */
+          lt_fatal (__FILE__, __LINE__,
+		    "unrecognized %s option: '%s'",
+                    ltwrapper_option_prefix, argv[i]);
+        }
+      /* otherwise ... */
+      newargz[++newargc] = xstrdup (argv[i]);
+    }
+  newargz[++newargc] = NULL;
+
+EOF
+	    cat <<EOF
+  /* The GNU banner must be the first non-error debug message */
+  lt_debugprintf (__FILE__, __LINE__, "libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\n");
+EOF
+	    cat <<"EOF"
+  lt_debugprintf (__FILE__, __LINE__, "(main) argv[0]: %s\n", argv[0]);
+  lt_debugprintf (__FILE__, __LINE__, "(main) program_name: %s\n", program_name);
+
+  tmp_pathspec = find_executable (argv[0]);
+  if (tmp_pathspec == NULL)
+    lt_fatal (__FILE__, __LINE__, "couldn't find %s", argv[0]);
+  lt_debugprintf (__FILE__, __LINE__,
+                  "(main) found exe (before symlink chase) at: %s\n",
+		  tmp_pathspec);
+
+  actual_cwrapper_path = chase_symlinks (tmp_pathspec);
+  lt_debugprintf (__FILE__, __LINE__,
+                  "(main) found exe (after symlink chase) at: %s\n",
+		  actual_cwrapper_path);
+  XFREE (tmp_pathspec);
+
+  actual_cwrapper_name = xstrdup (base_name (actual_cwrapper_path));
+  strendzap (actual_cwrapper_path, actual_cwrapper_name);
+
+  /* wrapper name transforms */
+  strendzap (actual_cwrapper_name, ".exe");
+  tmp_pathspec = lt_extend_str (actual_cwrapper_name, ".exe", 1);
+  XFREE (actual_cwrapper_name);
+  actual_cwrapper_name = tmp_pathspec;
+  tmp_pathspec = 0;
+
+  /* target_name transforms -- use actual target program name; might have lt- prefix */
+  target_name = xstrdup (base_name (TARGET_PROGRAM_NAME));
+  strendzap (target_name, ".exe");
+  tmp_pathspec = lt_extend_str (target_name, ".exe", 1);
+  XFREE (target_name);
+  target_name = tmp_pathspec;
+  tmp_pathspec = 0;
+
+  lt_debugprintf (__FILE__, __LINE__,
+		  "(main) libtool target name: %s\n",
+		  target_name);
+EOF
+
+	    cat <<EOF
+  newargz[0] =
+    XMALLOC (char, (strlen (actual_cwrapper_path) +
+		    strlen ("$objdir") + 1 + strlen (actual_cwrapper_name) + 1));
+  strcpy (newargz[0], actual_cwrapper_path);
+  strcat (newargz[0], "$objdir");
+  strcat (newargz[0], "/");
+EOF
+
+	    cat <<"EOF"
+  /* stop here, and copy so we don't have to do this twice */
+  tmp_pathspec = xstrdup (newargz[0]);
+
+  /* do NOT want the lt- prefix here, so use actual_cwrapper_name */
+  strcat (newargz[0], actual_cwrapper_name);
+
+  /* DO want the lt- prefix here if it exists, so use target_name */
+  lt_argv_zero = lt_extend_str (tmp_pathspec, target_name, 1);
+  XFREE (tmp_pathspec);
+  tmp_pathspec = NULL;
+EOF
+
+	    case $host_os in
+	      mingw*)
+	    cat <<"EOF"
+  {
+    char* p;
+    while ((p = strchr (newargz[0], '\\')) != NULL)
+      {
+	*p = '/';
+      }
+    while ((p = strchr (lt_argv_zero, '\\')) != NULL)
+      {
+	*p = '/';
+      }
+  }
+EOF
+	    ;;
+	    esac
+
+	    cat <<"EOF"
+  XFREE (target_name);
+  XFREE (actual_cwrapper_path);
+  XFREE (actual_cwrapper_name);
+
+  lt_setenv ("BIN_SH", "xpg4"); /* for Tru64 */
+  lt_setenv ("DUALCASE", "1");  /* for MSK sh */
+  /* Update the DLL searchpath.  EXE_PATH_VALUE ($dllsearchpath) must
+     be prepended before (that is, appear after) LIB_PATH_VALUE ($temp_rpath)
+     because on Windows, both *_VARNAMEs are PATH but uninstalled
+     libraries must come first. */
+  lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE);
+  lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE);
+
+  lt_debugprintf (__FILE__, __LINE__, "(main) lt_argv_zero: %s\n",
+		  nonnull (lt_argv_zero));
+  for (i = 0; i < newargc; i++)
+    {
+      lt_debugprintf (__FILE__, __LINE__, "(main) newargz[%d]: %s\n",
+		      i, nonnull (newargz[i]));
+    }
+
+EOF
+
+	    case $host_os in
+	      mingw*)
+		cat <<"EOF"
+  /* execv doesn't actually work on mingw as expected on unix */
+  newargz = prepare_spawn (newargz);
+  rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz);
+  if (rval == -1)
+    {
+      /* failed to start process */
+      lt_debugprintf (__FILE__, __LINE__,
+		      "(main) failed to launch target \"%s\": %s\n",
+		      lt_argv_zero, nonnull (strerror (errno)));
+      return 127;
+    }
+  return rval;
+EOF
+		;;
+	      *)
+		cat <<"EOF"
+  execv (lt_argv_zero, newargz);
+  return rval; /* =127, but avoids unused variable warning */
+EOF
+		;;
+	    esac
+
+	    cat <<"EOF"
+}
+
+void *
+xmalloc (size_t num)
+{
+  void *p = (void *) malloc (num);
+  if (!p)
+    lt_fatal (__FILE__, __LINE__, "memory exhausted");
+
+  return p;
+}
+
+char *
+xstrdup (const char *string)
+{
+  return string ? strcpy ((char *) xmalloc (strlen (string) + 1),
+			  string) : NULL;
+}
+
+const char *
+base_name (const char *name)
+{
+  const char *base;
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  /* Skip over the disk name in MSDOS pathnames. */
+  if (isalpha ((unsigned char) name[0]) && name[1] == ':')
+    name += 2;
+#endif
+
+  for (base = name; *name; name++)
+    if (IS_DIR_SEPARATOR (*name))
+      base = name + 1;
+  return base;
+}
+
+int
+check_executable (const char *path)
+{
+  struct stat st;
+
+  lt_debugprintf (__FILE__, __LINE__, "(check_executable): %s\n",
+                  nonempty (path));
+  if ((!path) || (!*path))
+    return 0;
+
+  if ((stat (path, &st) >= 0)
+      && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+    return 1;
+  else
+    return 0;
+}
+
+int
+make_executable (const char *path)
+{
+  int rval = 0;
+  struct stat st;
+
+  lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n",
+                  nonempty (path));
+  if ((!path) || (!*path))
+    return 0;
+
+  if (stat (path, &st) >= 0)
+    {
+      rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR);
+    }
+  return rval;
+}
+
+/* Searches for the full path of the wrapper.  Returns
+   newly allocated full path name if found, NULL otherwise
+   Does not chase symlinks, even on platforms that support them.
+*/
+char *
+find_executable (const char *wrapper)
+{
+  int has_slash = 0;
+  const char *p;
+  const char *p_next;
+  /* static buffer for getcwd */
+  char tmp[LT_PATHMAX + 1];
+  int tmp_len;
+  char *concat_name;
+
+  lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n",
+                  nonempty (wrapper));
+
+  if ((wrapper == NULL) || (*wrapper == '\0'))
+    return NULL;
+
+  /* Absolute path? */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':')
+    {
+      concat_name = xstrdup (wrapper);
+      if (check_executable (concat_name))
+	return concat_name;
+      XFREE (concat_name);
+    }
+  else
+    {
+#endif
+      if (IS_DIR_SEPARATOR (wrapper[0]))
+	{
+	  concat_name = xstrdup (wrapper);
+	  if (check_executable (concat_name))
+	    return concat_name;
+	  XFREE (concat_name);
+	}
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+    }
+#endif
+
+  for (p = wrapper; *p; p++)
+    if (*p == '/')
+      {
+	has_slash = 1;
+	break;
+      }
+  if (!has_slash)
+    {
+      /* no slashes; search PATH */
+      const char *path = getenv ("PATH");
+      if (path != NULL)
+	{
+	  for (p = path; *p; p = p_next)
+	    {
+	      const char *q;
+	      size_t p_len;
+	      for (q = p; *q; q++)
+		if (IS_PATH_SEPARATOR (*q))
+		  break;
+	      p_len = q - p;
+	      p_next = (*q == '\0' ? q : q + 1);
+	      if (p_len == 0)
+		{
+		  /* empty path: current directory */
+		  if (getcwd (tmp, LT_PATHMAX) == NULL)
+		    lt_fatal (__FILE__, __LINE__, "getcwd failed: %s",
+                              nonnull (strerror (errno)));
+		  tmp_len = strlen (tmp);
+		  concat_name =
+		    XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+		  memcpy (concat_name, tmp, tmp_len);
+		  concat_name[tmp_len] = '/';
+		  strcpy (concat_name + tmp_len + 1, wrapper);
+		}
+	      else
+		{
+		  concat_name =
+		    XMALLOC (char, p_len + 1 + strlen (wrapper) + 1);
+		  memcpy (concat_name, p, p_len);
+		  concat_name[p_len] = '/';
+		  strcpy (concat_name + p_len + 1, wrapper);
+		}
+	      if (check_executable (concat_name))
+		return concat_name;
+	      XFREE (concat_name);
+	    }
+	}
+      /* not found in PATH; assume curdir */
+    }
+  /* Relative path | not found in path: prepend cwd */
+  if (getcwd (tmp, LT_PATHMAX) == NULL)
+    lt_fatal (__FILE__, __LINE__, "getcwd failed: %s",
+              nonnull (strerror (errno)));
+  tmp_len = strlen (tmp);
+  concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+  memcpy (concat_name, tmp, tmp_len);
+  concat_name[tmp_len] = '/';
+  strcpy (concat_name + tmp_len + 1, wrapper);
+
+  if (check_executable (concat_name))
+    return concat_name;
+  XFREE (concat_name);
+  return NULL;
+}
+
+char *
+chase_symlinks (const char *pathspec)
+{
+#ifndef S_ISLNK
+  return xstrdup (pathspec);
+#else
+  char buf[LT_PATHMAX];
+  struct stat s;
+  char *tmp_pathspec = xstrdup (pathspec);
+  char *p;
+  int has_symlinks = 0;
+  while (strlen (tmp_pathspec) && !has_symlinks)
+    {
+      lt_debugprintf (__FILE__, __LINE__,
+		      "checking path component for symlinks: %s\n",
+		      tmp_pathspec);
+      if (lstat (tmp_pathspec, &s) == 0)
+	{
+	  if (S_ISLNK (s.st_mode) != 0)
+	    {
+	      has_symlinks = 1;
+	      break;
+	    }
+
+	  /* search backwards for last DIR_SEPARATOR */
+	  p = tmp_pathspec + strlen (tmp_pathspec) - 1;
+	  while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+	    p--;
+	  if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+	    {
+	      /* no more DIR_SEPARATORS left */
+	      break;
+	    }
+	  *p = '\0';
+	}
+      else
+	{
+	  lt_fatal (__FILE__, __LINE__,
+		    "error accessing file \"%s\": %s",
+		    tmp_pathspec, nonnull (strerror (errno)));
+	}
+    }
+  XFREE (tmp_pathspec);
+
+  if (!has_symlinks)
+    {
+      return xstrdup (pathspec);
+    }
+
+  tmp_pathspec = realpath (pathspec, buf);
+  if (tmp_pathspec == 0)
+    {
+      lt_fatal (__FILE__, __LINE__,
+		"could not follow symlinks for %s", pathspec);
+    }
+  return xstrdup (tmp_pathspec);
+#endif
+}
+
+char *
+strendzap (char *str, const char *pat)
+{
+  size_t len, patlen;
+
+  assert (str != NULL);
+  assert (pat != NULL);
+
+  len = strlen (str);
+  patlen = strlen (pat);
+
+  if (patlen <= len)
+    {
+      str += len - patlen;
+      if (strcmp (str, pat) == 0)
+	*str = '\0';
+    }
+  return str;
+}
+
+void
+lt_debugprintf (const char *file, int line, const char *fmt, ...)
+{
+  va_list args;
+  if (lt_debug)
+    {
+      (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line);
+      va_start (args, fmt);
+      (void) vfprintf (stderr, fmt, args);
+      va_end (args);
+    }
+}
+
+static void
+lt_error_core (int exit_status, const char *file,
+	       int line, const char *mode,
+	       const char *message, va_list ap)
+{
+  fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode);
+  vfprintf (stderr, message, ap);
+  fprintf (stderr, ".\n");
+
+  if (exit_status >= 0)
+    exit (exit_status);
+}
+
+void
+lt_fatal (const char *file, int line, const char *message, ...)
+{
+  va_list ap;
+  va_start (ap, message);
+  lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap);
+  va_end (ap);
+}
+
+static const char *
+nonnull (const char *s)
+{
+  return s ? s : "(null)";
+}
+
+static const char *
+nonempty (const char *s)
+{
+  return (s && !*s) ? "(empty)" : nonnull (s);
+}
+
+void
+lt_setenv (const char *name, const char *value)
+{
+  lt_debugprintf (__FILE__, __LINE__,
+		  "(lt_setenv) setting '%s' to '%s'\n",
+                  nonnull (name), nonnull (value));
+  {
+#ifdef HAVE_SETENV
+    /* always make a copy, for consistency with !HAVE_SETENV */
+    char *str = xstrdup (value);
+    setenv (name, str, 1);
+#else
+    int len = strlen (name) + 1 + strlen (value) + 1;
+    char *str = XMALLOC (char, len);
+    sprintf (str, "%s=%s", name, value);
+    if (putenv (str) != EXIT_SUCCESS)
+      {
+        XFREE (str);
+      }
+#endif
+  }
+}
+
+char *
+lt_extend_str (const char *orig_value, const char *add, int to_end)
+{
+  char *new_value;
+  if (orig_value && *orig_value)
+    {
+      int orig_value_len = strlen (orig_value);
+      int add_len = strlen (add);
+      new_value = XMALLOC (char, add_len + orig_value_len + 1);
+      if (to_end)
+        {
+          strcpy (new_value, orig_value);
+          strcpy (new_value + orig_value_len, add);
+        }
+      else
+        {
+          strcpy (new_value, add);
+          strcpy (new_value + add_len, orig_value);
+        }
+    }
+  else
+    {
+      new_value = xstrdup (add);
+    }
+  return new_value;
+}
+
+void
+lt_update_exe_path (const char *name, const char *value)
+{
+  lt_debugprintf (__FILE__, __LINE__,
+		  "(lt_update_exe_path) modifying '%s' by prepending '%s'\n",
+                  nonnull (name), nonnull (value));
+
+  if (name && *name && value && *value)
+    {
+      char *new_value = lt_extend_str (getenv (name), value, 0);
+      /* some systems can't cope with a ':'-terminated path #' */
+      int len = strlen (new_value);
+      while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1]))
+        {
+          new_value[len-1] = '\0';
+        }
+      lt_setenv (name, new_value);
+      XFREE (new_value);
+    }
+}
+
+void
+lt_update_lib_path (const char *name, const char *value)
+{
+  lt_debugprintf (__FILE__, __LINE__,
+		  "(lt_update_lib_path) modifying '%s' by prepending '%s'\n",
+                  nonnull (name), nonnull (value));
+
+  if (name && *name && value && *value)
+    {
+      char *new_value = lt_extend_str (getenv (name), value, 0);
+      lt_setenv (name, new_value);
+      XFREE (new_value);
+    }
+}
+
+EOF
+	    case $host_os in
+	      mingw*)
+		cat <<"EOF"
+
+/* Prepares an argument vector before calling spawn().
+   Note that spawn() does not by itself call the command interpreter
+     (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
+      ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+         GetVersionEx(&v);
+         v.dwPlatformId == VER_PLATFORM_WIN32_NT;
+      }) ? "cmd.exe" : "command.com").
+   Instead it simply concatenates the arguments, separated by ' ', and calls
+   CreateProcess().  We must quote the arguments since Win32 CreateProcess()
+   interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
+   special way:
+   - Space and tab are interpreted as delimiters. They are not treated as
+     delimiters if they are surrounded by double quotes: "...".
+   - Unescaped double quotes are removed from the input. Their only effect is
+     that within double quotes, space and tab are treated like normal
+     characters.
+   - Backslashes not followed by double quotes are not special.
+   - But 2*n+1 backslashes followed by a double quote become
+     n backslashes followed by a double quote (n >= 0):
+       \" -> "
+       \\\" -> \"
+       \\\\\" -> \\"
+ */
+#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
+#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
+char **
+prepare_spawn (char **argv)
+{
+  size_t argc;
+  char **new_argv;
+  size_t i;
+
+  /* Count number of arguments.  */
+  for (argc = 0; argv[argc] != NULL; argc++)
+    ;
+
+  /* Allocate new argument vector.  */
+  new_argv = XMALLOC (char *, argc + 1);
+
+  /* Put quoted arguments into the new argument vector.  */
+  for (i = 0; i < argc; i++)
+    {
+      const char *string = argv[i];
+
+      if (string[0] == '\0')
+	new_argv[i] = xstrdup ("\"\"");
+      else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
+	{
+	  int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
+	  size_t length;
+	  unsigned int backslashes;
+	  const char *s;
+	  char *quoted_string;
+	  char *p;
+
+	  length = 0;
+	  backslashes = 0;
+	  if (quote_around)
+	    length++;
+	  for (s = string; *s != '\0'; s++)
+	    {
+	      char c = *s;
+	      if (c == '"')
+		length += backslashes + 1;
+	      length++;
+	      if (c == '\\')
+		backslashes++;
+	      else
+		backslashes = 0;
+	    }
+	  if (quote_around)
+	    length += backslashes + 1;
+
+	  quoted_string = XMALLOC (char, length + 1);
+
+	  p = quoted_string;
+	  backslashes = 0;
+	  if (quote_around)
+	    *p++ = '"';
+	  for (s = string; *s != '\0'; s++)
+	    {
+	      char c = *s;
+	      if (c == '"')
+		{
+		  unsigned int j;
+		  for (j = backslashes + 1; j > 0; j--)
+		    *p++ = '\\';
+		}
+	      *p++ = c;
+	      if (c == '\\')
+		backslashes++;
+	      else
+		backslashes = 0;
+	    }
+	  if (quote_around)
+	    {
+	      unsigned int j;
+	      for (j = backslashes; j > 0; j--)
+		*p++ = '\\';
+	      *p++ = '"';
+	    }
+	  *p = '\0';
+
+	  new_argv[i] = quoted_string;
+	}
+      else
+	new_argv[i] = (char *) string;
+    }
+  new_argv[argc] = NULL;
+
+  return new_argv;
+}
+EOF
+		;;
+	    esac
+
+            cat <<"EOF"
+void lt_dump_script (FILE* f)
+{
+EOF
+	    func_emit_wrapper yes |
+	      $SED -n -e '
+s/^\(.\{79\}\)\(..*\)/\1\
+\2/
+h
+s/\([\\"]\)/\\\1/g
+s/$/\\n/
+s/\([^\n]*\).*/  fputs ("\1", f);/p
+g
+D'
+            cat <<"EOF"
+}
+EOF
+}
+# end: func_emit_cwrapperexe_src
+
+# func_win32_import_lib_p ARG
+# True if ARG is an import lib, as indicated by $file_magic_cmd
+func_win32_import_lib_p ()
+{
+    $opt_debug
+    case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in
+    *import*) : ;;
+    *) false ;;
+    esac
+}
+
+# func_mode_link arg...
+func_mode_link ()
+{
+    $opt_debug
+    case $host in
+    *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+      # It is impossible to link a dll without this setting, and
+      # we shouldn't force the makefile maintainer to figure out
+      # which system we are compiling for in order to pass an extra
+      # flag for every libtool invocation.
+      # allow_undefined=no
+
+      # FIXME: Unfortunately, there are problems with the above when trying
+      # to make a dll which has undefined symbols, in which case not
+      # even a static library is built.  For now, we need to specify
+      # -no-undefined on the libtool link line when we can be certain
+      # that all symbols are satisfied, otherwise we get a static library.
+      allow_undefined=yes
+      ;;
+    *)
+      allow_undefined=yes
+      ;;
+    esac
+    libtool_args=$nonopt
+    base_compile="$nonopt $@"
+    compile_command=$nonopt
+    finalize_command=$nonopt
+
+    compile_rpath=
+    finalize_rpath=
+    compile_shlibpath=
+    finalize_shlibpath=
+    convenience=
+    old_convenience=
+    deplibs=
+    old_deplibs=
+    compiler_flags=
+    linker_flags=
+    dllsearchpath=
+    lib_search_path=`pwd`
+    inst_prefix_dir=
+    new_inherited_linker_flags=
+
+    avoid_version=no
+    bindir=
+    dlfiles=
+    dlprefiles=
+    dlself=no
+    export_dynamic=no
+    export_symbols=
+    export_symbols_regex=
+    generated=
+    libobjs=
+    ltlibs=
+    module=no
+    no_install=no
+    objs=
+    non_pic_objects=
+    precious_files_regex=
+    prefer_static_libs=no
+    preload=no
+    prev=
+    prevarg=
+    release=
+    rpath=
+    xrpath=
+    perm_rpath=
+    temp_rpath=
+    thread_safe=no
+    vinfo=
+    vinfo_number=no
+    weak_libs=
+    single_module="${wl}-single_module"
+    func_infer_tag $base_compile
+
+    # We need to know -static, to get the right output filenames.
+    for arg
+    do
+      case $arg in
+      -shared)
+	test "$build_libtool_libs" != yes && \
+	  func_fatal_configuration "can not build a shared library"
+	build_old_libs=no
+	break
+	;;
+      -all-static | -static | -static-libtool-libs)
+	case $arg in
+	-all-static)
+	  if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+	    func_warning "complete static linking is impossible in this configuration"
+	  fi
+	  if test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	  prefer_static_libs=yes
+	  ;;
+	-static)
+	  if test -z "$pic_flag" && test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	  prefer_static_libs=built
+	  ;;
+	-static-libtool-libs)
+	  if test -z "$pic_flag" && test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	  prefer_static_libs=yes
+	  ;;
+	esac
+	build_libtool_libs=no
+	build_old_libs=yes
+	break
+	;;
+      esac
+    done
+
+    # See if our shared archives depend on static archives.
+    test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+    # Go through the arguments, transforming them on the way.
+    while test "$#" -gt 0; do
+      arg="$1"
+      shift
+      func_quote_for_eval "$arg"
+      qarg=$func_quote_for_eval_unquoted_result
+      libtool_args+=" $func_quote_for_eval_result"
+
+      # If the previous option needs an argument, assign it.
+      if test -n "$prev"; then
+	case $prev in
+	output)
+	  compile_command+=" @OUTPUT@"
+	  finalize_command+=" @OUTPUT@"
+	  ;;
+	esac
+
+	case $prev in
+	bindir)
+	  bindir="$arg"
+	  prev=
+	  continue
+	  ;;
+	dlfiles|dlprefiles)
+	  if test "$preload" = no; then
+	    # Add the symbol object into the linking commands.
+	    compile_command+=" @SYMFILE@"
+	    finalize_command+=" @SYMFILE@"
+	    preload=yes
+	  fi
+	  case $arg in
+	  *.la | *.lo) ;;  # We handle these cases below.
+	  force)
+	    if test "$dlself" = no; then
+	      dlself=needless
+	      export_dynamic=yes
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  self)
+	    if test "$prev" = dlprefiles; then
+	      dlself=yes
+	    elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+	      dlself=yes
+	    else
+	      dlself=needless
+	      export_dynamic=yes
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  *)
+	    if test "$prev" = dlfiles; then
+	      dlfiles+=" $arg"
+	    else
+	      dlprefiles+=" $arg"
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  esac
+	  ;;
+	expsyms)
+	  export_symbols="$arg"
+	  test -f "$arg" \
+	    || func_fatal_error "symbol file \`$arg' does not exist"
+	  prev=
+	  continue
+	  ;;
+	expsyms_regex)
+	  export_symbols_regex="$arg"
+	  prev=
+	  continue
+	  ;;
+	framework)
+	  case $host in
+	    *-*-darwin*)
+	      case "$deplibs " in
+		*" $qarg.ltframework "*) ;;
+		*) deplibs+=" $qarg.ltframework" # this is fixed later
+		   ;;
+	      esac
+	      ;;
+	  esac
+	  prev=
+	  continue
+	  ;;
+	inst_prefix)
+	  inst_prefix_dir="$arg"
+	  prev=
+	  continue
+	  ;;
+	objectlist)
+	  if test -f "$arg"; then
+	    save_arg=$arg
+	    moreargs=
+	    for fil in `cat "$save_arg"`
+	    do
+#	      moreargs+=" $fil"
+	      arg=$fil
+	      # A libtool-controlled object.
+
+	      # Check to see that this really is a libtool object.
+	      if func_lalib_unsafe_p "$arg"; then
+		pic_object=
+		non_pic_object=
+
+		# Read the .lo file
+		func_source "$arg"
+
+		if test -z "$pic_object" ||
+		   test -z "$non_pic_object" ||
+		   test "$pic_object" = none &&
+		   test "$non_pic_object" = none; then
+		  func_fatal_error "cannot find name of object for \`$arg'"
+		fi
+
+		# Extract subdirectory from the argument.
+		func_dirname "$arg" "/" ""
+		xdir="$func_dirname_result"
+
+		if test "$pic_object" != none; then
+		  # Prepend the subdirectory the object is found in.
+		  pic_object="$xdir$pic_object"
+
+		  if test "$prev" = dlfiles; then
+		    if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+		      dlfiles+=" $pic_object"
+		      prev=
+		      continue
+		    else
+		      # If libtool objects are unsupported, then we need to preload.
+		      prev=dlprefiles
+		    fi
+		  fi
+
+		  # CHECK ME:  I think I busted this.  -Ossama
+		  if test "$prev" = dlprefiles; then
+		    # Preload the old-style object.
+		    dlprefiles+=" $pic_object"
+		    prev=
+		  fi
+
+		  # A PIC object.
+		  libobjs+=" $pic_object"
+		  arg="$pic_object"
+		fi
+
+		# Non-PIC object.
+		if test "$non_pic_object" != none; then
+		  # Prepend the subdirectory the object is found in.
+		  non_pic_object="$xdir$non_pic_object"
+
+		  # A standard non-PIC object
+		  non_pic_objects+=" $non_pic_object"
+		  if test -z "$pic_object" || test "$pic_object" = none ; then
+		    arg="$non_pic_object"
+		  fi
+		else
+		  # If the PIC object exists, use it instead.
+		  # $xdir was prepended to $pic_object above.
+		  non_pic_object="$pic_object"
+		  non_pic_objects+=" $non_pic_object"
+		fi
+	      else
+		# Only an error if not doing a dry-run.
+		if $opt_dry_run; then
+		  # Extract subdirectory from the argument.
+		  func_dirname "$arg" "/" ""
+		  xdir="$func_dirname_result"
+
+		  func_lo2o "$arg"
+		  pic_object=$xdir$objdir/$func_lo2o_result
+		  non_pic_object=$xdir$func_lo2o_result
+		  libobjs+=" $pic_object"
+		  non_pic_objects+=" $non_pic_object"
+	        else
+		  func_fatal_error "\`$arg' is not a valid libtool object"
+		fi
+	      fi
+	    done
+	  else
+	    func_fatal_error "link input file \`$arg' does not exist"
+	  fi
+	  arg=$save_arg
+	  prev=
+	  continue
+	  ;;
+	precious_regex)
+	  precious_files_regex="$arg"
+	  prev=
+	  continue
+	  ;;
+	release)
+	  release="-$arg"
+	  prev=
+	  continue
+	  ;;
+	rpath | xrpath)
+	  # We need an absolute path.
+	  case $arg in
+	  [\\/]* | [A-Za-z]:[\\/]*) ;;
+	  *)
+	    func_fatal_error "only absolute run-paths are allowed"
+	    ;;
+	  esac
+	  if test "$prev" = rpath; then
+	    case "$rpath " in
+	    *" $arg "*) ;;
+	    *) rpath+=" $arg" ;;
+	    esac
+	  else
+	    case "$xrpath " in
+	    *" $arg "*) ;;
+	    *) xrpath+=" $arg" ;;
+	    esac
+	  fi
+	  prev=
+	  continue
+	  ;;
+	shrext)
+	  shrext_cmds="$arg"
+	  prev=
+	  continue
+	  ;;
+	weak)
+	  weak_libs+=" $arg"
+	  prev=
+	  continue
+	  ;;
+	xcclinker)
+	  linker_flags+=" $qarg"
+	  compiler_flags+=" $qarg"
+	  prev=
+	  compile_command+=" $qarg"
+	  finalize_command+=" $qarg"
+	  continue
+	  ;;
+	xcompiler)
+	  compiler_flags+=" $qarg"
+	  prev=
+	  compile_command+=" $qarg"
+	  finalize_command+=" $qarg"
+	  continue
+	  ;;
+	xlinker)
+	  linker_flags+=" $qarg"
+	  compiler_flags+=" $wl$qarg"
+	  prev=
+	  compile_command+=" $wl$qarg"
+	  finalize_command+=" $wl$qarg"
+	  continue
+	  ;;
+	*)
+	  eval "$prev=\"\$arg\""
+	  prev=
+	  continue
+	  ;;
+	esac
+      fi # test -n "$prev"
+
+      prevarg="$arg"
+
+      case $arg in
+      -all-static)
+	if test -n "$link_static_flag"; then
+	  # See comment for -static flag below, for more details.
+	  compile_command+=" $link_static_flag"
+	  finalize_command+=" $link_static_flag"
+	fi
+	continue
+	;;
+
+      -allow-undefined)
+	# FIXME: remove this flag sometime in the future.
+	func_fatal_error "\`-allow-undefined' must not be used because it is the default"
+	;;
+
+      -avoid-version)
+	avoid_version=yes
+	continue
+	;;
+
+      -bindir)
+	prev=bindir
+	continue
+	;;
+
+      -dlopen)
+	prev=dlfiles
+	continue
+	;;
+
+      -dlpreopen)
+	prev=dlprefiles
+	continue
+	;;
+
+      -export-dynamic)
+	export_dynamic=yes
+	continue
+	;;
+
+      -export-symbols | -export-symbols-regex)
+	if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+	  func_fatal_error "more than one -exported-symbols argument is not allowed"
+	fi
+	if test "X$arg" = "X-export-symbols"; then
+	  prev=expsyms
+	else
+	  prev=expsyms_regex
+	fi
+	continue
+	;;
+
+      -framework)
+	prev=framework
+	continue
+	;;
+
+      -inst-prefix-dir)
+	prev=inst_prefix
+	continue
+	;;
+
+      # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+      # so, if we see these flags be careful not to treat them like -L
+      -L[A-Z][A-Z]*:*)
+	case $with_gcc/$host in
+	no/*-*-irix* | /*-*-irix*)
+	  compile_command+=" $arg"
+	  finalize_command+=" $arg"
+	  ;;
+	esac
+	continue
+	;;
+
+      -L*)
+	func_stripname "-L" '' "$arg"
+	if test -z "$func_stripname_result"; then
+	  if test "$#" -gt 0; then
+	    func_fatal_error "require no space between \`-L' and \`$1'"
+	  else
+	    func_fatal_error "need path for \`-L' option"
+	  fi
+	fi
+	func_resolve_sysroot "$func_stripname_result"
+	dir=$func_resolve_sysroot_result
+	# We need an absolute path.
+	case $dir in
+	[\\/]* | [A-Za-z]:[\\/]*) ;;
+	*)
+	  absdir=`cd "$dir" && pwd`
+	  test -z "$absdir" && \
+	    func_fatal_error "cannot determine absolute directory name of \`$dir'"
+	  dir="$absdir"
+	  ;;
+	esac
+	case "$deplibs " in
+	*" -L$dir "* | *" $arg "*)
+	  # Will only happen for absolute or sysroot arguments
+	  ;;
+	*)
+	  # Preserve sysroot, but never include relative directories
+	  case $dir in
+	    [\\/]* | [A-Za-z]:[\\/]* | =*) deplibs+=" $arg" ;;
+	    *) deplibs+=" -L$dir" ;;
+	  esac
+	  lib_search_path+=" $dir"
+	  ;;
+	esac
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+	  testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'`
+	  case :$dllsearchpath: in
+	  *":$dir:"*) ;;
+	  ::) dllsearchpath=$dir;;
+	  *) dllsearchpath+=":$dir";;
+	  esac
+	  case :$dllsearchpath: in
+	  *":$testbindir:"*) ;;
+	  ::) dllsearchpath=$testbindir;;
+	  *) dllsearchpath+=":$testbindir";;
+	  esac
+	  ;;
+	esac
+	continue
+	;;
+
+      -l*)
+	if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
+	  case $host in
+	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*)
+	    # These systems don't actually have a C or math library (as such)
+	    continue
+	    ;;
+	  *-*-os2*)
+	    # These systems don't actually have a C library (as such)
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+	    # Do not include libc due to us having libc/libc_r.
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-rhapsody* | *-*-darwin1.[012])
+	    # Rhapsody C and math libraries are in the System framework
+	    deplibs+=" System.ltframework"
+	    continue
+	    ;;
+	  *-*-sco3.2v5* | *-*-sco5v6*)
+	    # Causes problems with __ctype
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+	    # Compiler inserts libc in the correct place for threads to work
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  esac
+	elif test "X$arg" = "X-lc_r"; then
+	 case $host in
+	 *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+	   # Do not include libc_r directly, use -pthread flag.
+	   continue
+	   ;;
+	 esac
+	fi
+	deplibs+=" $arg"
+	continue
+	;;
+
+      -module)
+	module=yes
+	continue
+	;;
+
+      # Tru64 UNIX uses -model [arg] to determine the layout of C++
+      # classes, name mangling, and exception handling.
+      # Darwin uses the -arch flag to determine output architecture.
+      -model|-arch|-isysroot|--sysroot)
+	compiler_flags+=" $arg"
+	compile_command+=" $arg"
+	finalize_command+=" $arg"
+	prev=xcompiler
+	continue
+	;;
+
+      -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \
+      |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
+	compiler_flags+=" $arg"
+	compile_command+=" $arg"
+	finalize_command+=" $arg"
+	case "$new_inherited_linker_flags " in
+	    *" $arg "*) ;;
+	    * ) new_inherited_linker_flags+=" $arg" ;;
+	esac
+	continue
+	;;
+
+      -multi_module)
+	single_module="${wl}-multi_module"
+	continue
+	;;
+
+      -no-fast-install)
+	fast_install=no
+	continue
+	;;
+
+      -no-install)
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*)
+	  # The PATH hackery in wrapper scripts is required on Windows
+	  # and Darwin in order for the loader to find any dlls it needs.
+	  func_warning "\`-no-install' is ignored for $host"
+	  func_warning "assuming \`-no-fast-install' instead"
+	  fast_install=no
+	  ;;
+	*) no_install=yes ;;
+	esac
+	continue
+	;;
+
+      -no-undefined)
+	allow_undefined=no
+	continue
+	;;
+
+      -objectlist)
+	prev=objectlist
+	continue
+	;;
+
+      -o) prev=output ;;
+
+      -precious-files-regex)
+	prev=precious_regex
+	continue
+	;;
+
+      -release)
+	prev=release
+	continue
+	;;
+
+      -rpath)
+	prev=rpath
+	continue
+	;;
+
+      -R)
+	prev=xrpath
+	continue
+	;;
+
+      -R*)
+	func_stripname '-R' '' "$arg"
+	dir=$func_stripname_result
+	# We need an absolute path.
+	case $dir in
+	[\\/]* | [A-Za-z]:[\\/]*) ;;
+	=*)
+	  func_stripname '=' '' "$dir"
+	  dir=$lt_sysroot$func_stripname_result
+	  ;;
+	*)
+	  func_fatal_error "only absolute run-paths are allowed"
+	  ;;
+	esac
+	case "$xrpath " in
+	*" $dir "*) ;;
+	*) xrpath+=" $dir" ;;
+	esac
+	continue
+	;;
+
+      -shared)
+	# The effects of -shared are defined in a previous loop.
+	continue
+	;;
+
+      -shrext)
+	prev=shrext
+	continue
+	;;
+
+      -static | -static-libtool-libs)
+	# The effects of -static are defined in a previous loop.
+	# We used to do the same as -all-static on platforms that
+	# didn't have a PIC flag, but the assumption that the effects
+	# would be equivalent was wrong.  It would break on at least
+	# Digital Unix and AIX.
+	continue
+	;;
+
+      -thread-safe)
+	thread_safe=yes
+	continue
+	;;
+
+      -version-info)
+	prev=vinfo
+	continue
+	;;
+
+      -version-number)
+	prev=vinfo
+	vinfo_number=yes
+	continue
+	;;
+
+      -weak)
+        prev=weak
+	continue
+	;;
+
+      -Wc,*)
+	func_stripname '-Wc,' '' "$arg"
+	args=$func_stripname_result
+	arg=
+	save_ifs="$IFS"; IFS=','
+	for flag in $args; do
+	  IFS="$save_ifs"
+          func_quote_for_eval "$flag"
+	  arg+=" $func_quote_for_eval_result"
+	  compiler_flags+=" $func_quote_for_eval_result"
+	done
+	IFS="$save_ifs"
+	func_stripname ' ' '' "$arg"
+	arg=$func_stripname_result
+	;;
+
+      -Wl,*)
+	func_stripname '-Wl,' '' "$arg"
+	args=$func_stripname_result
+	arg=
+	save_ifs="$IFS"; IFS=','
+	for flag in $args; do
+	  IFS="$save_ifs"
+          func_quote_for_eval "$flag"
+	  arg+=" $wl$func_quote_for_eval_result"
+	  compiler_flags+=" $wl$func_quote_for_eval_result"
+	  linker_flags+=" $func_quote_for_eval_result"
+	done
+	IFS="$save_ifs"
+	func_stripname ' ' '' "$arg"
+	arg=$func_stripname_result
+	;;
+
+      -Xcompiler)
+	prev=xcompiler
+	continue
+	;;
+
+      -Xlinker)
+	prev=xlinker
+	continue
+	;;
+
+      -XCClinker)
+	prev=xcclinker
+	continue
+	;;
+
+      # -msg_* for osf cc
+      -msg_*)
+	func_quote_for_eval "$arg"
+	arg="$func_quote_for_eval_result"
+	;;
+
+      # Flags to be passed through unchanged, with rationale:
+      # -64, -mips[0-9]      enable 64-bit mode for the SGI compiler
+      # -r[0-9][0-9]*        specify processor for the SGI compiler
+      # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler
+      # +DA*, +DD*           enable 64-bit mode for the HP compiler
+      # -q*                  compiler args for the IBM compiler
+      # -m*, -t[45]*, -txscale* architecture-specific flags for GCC
+      # -F/path              path to uninstalled frameworks, gcc on darwin
+      # -p, -pg, --coverage, -fprofile-*  profiling flags for GCC
+      # @file                GCC response files
+      # -tp=*                Portland pgcc target processor selection
+      # --sysroot=*          for sysroot support
+      # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization
+      -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
+      -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \
+      -O*|-flto*|-fwhopr*|-fuse-linker-plugin)
+        func_quote_for_eval "$arg"
+	arg="$func_quote_for_eval_result"
+        compile_command+=" $arg"
+        finalize_command+=" $arg"
+        compiler_flags+=" $arg"
+        continue
+        ;;
+
+      # Some other compiler flag.
+      -* | +*)
+        func_quote_for_eval "$arg"
+	arg="$func_quote_for_eval_result"
+	;;
+
+      *.$objext)
+	# A standard object.
+	objs+=" $arg"
+	;;
+
+      *.lo)
+	# A libtool-controlled object.
+
+	# Check to see that this really is a libtool object.
+	if func_lalib_unsafe_p "$arg"; then
+	  pic_object=
+	  non_pic_object=
+
+	  # Read the .lo file
+	  func_source "$arg"
+
+	  if test -z "$pic_object" ||
+	     test -z "$non_pic_object" ||
+	     test "$pic_object" = none &&
+	     test "$non_pic_object" = none; then
+	    func_fatal_error "cannot find name of object for \`$arg'"
+	  fi
+
+	  # Extract subdirectory from the argument.
+	  func_dirname "$arg" "/" ""
+	  xdir="$func_dirname_result"
+
+	  if test "$pic_object" != none; then
+	    # Prepend the subdirectory the object is found in.
+	    pic_object="$xdir$pic_object"
+
+	    if test "$prev" = dlfiles; then
+	      if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+		dlfiles+=" $pic_object"
+		prev=
+		continue
+	      else
+		# If libtool objects are unsupported, then we need to preload.
+		prev=dlprefiles
+	      fi
+	    fi
+
+	    # CHECK ME:  I think I busted this.  -Ossama
+	    if test "$prev" = dlprefiles; then
+	      # Preload the old-style object.
+	      dlprefiles+=" $pic_object"
+	      prev=
+	    fi
+
+	    # A PIC object.
+	    libobjs+=" $pic_object"
+	    arg="$pic_object"
+	  fi
+
+	  # Non-PIC object.
+	  if test "$non_pic_object" != none; then
+	    # Prepend the subdirectory the object is found in.
+	    non_pic_object="$xdir$non_pic_object"
+
+	    # A standard non-PIC object
+	    non_pic_objects+=" $non_pic_object"
+	    if test -z "$pic_object" || test "$pic_object" = none ; then
+	      arg="$non_pic_object"
+	    fi
+	  else
+	    # If the PIC object exists, use it instead.
+	    # $xdir was prepended to $pic_object above.
+	    non_pic_object="$pic_object"
+	    non_pic_objects+=" $non_pic_object"
+	  fi
+	else
+	  # Only an error if not doing a dry-run.
+	  if $opt_dry_run; then
+	    # Extract subdirectory from the argument.
+	    func_dirname "$arg" "/" ""
+	    xdir="$func_dirname_result"
+
+	    func_lo2o "$arg"
+	    pic_object=$xdir$objdir/$func_lo2o_result
+	    non_pic_object=$xdir$func_lo2o_result
+	    libobjs+=" $pic_object"
+	    non_pic_objects+=" $non_pic_object"
+	  else
+	    func_fatal_error "\`$arg' is not a valid libtool object"
+	  fi
+	fi
+	;;
+
+      *.$libext)
+	# An archive.
+	deplibs+=" $arg"
+	old_deplibs+=" $arg"
+	continue
+	;;
+
+      *.la)
+	# A libtool-controlled library.
+
+	func_resolve_sysroot "$arg"
+	if test "$prev" = dlfiles; then
+	  # This library was specified with -dlopen.
+	  dlfiles+=" $func_resolve_sysroot_result"
+	  prev=
+	elif test "$prev" = dlprefiles; then
+	  # The library was specified with -dlpreopen.
+	  dlprefiles+=" $func_resolve_sysroot_result"
+	  prev=
+	else
+	  deplibs+=" $func_resolve_sysroot_result"
+	fi
+	continue
+	;;
+
+      # Some other compiler argument.
+      *)
+	# Unknown arguments in both finalize_command and compile_command need
+	# to be aesthetically quoted because they are evaled later.
+	func_quote_for_eval "$arg"
+	arg="$func_quote_for_eval_result"
+	;;
+      esac # arg
+
+      # Now actually substitute the argument into the commands.
+      if test -n "$arg"; then
+	compile_command+=" $arg"
+	finalize_command+=" $arg"
+      fi
+    done # argument parsing loop
+
+    test -n "$prev" && \
+      func_fatal_help "the \`$prevarg' option requires an argument"
+
+    if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+      eval arg=\"$export_dynamic_flag_spec\"
+      compile_command+=" $arg"
+      finalize_command+=" $arg"
+    fi
+
+    oldlibs=
+    # calculate the name of the file, without its directory
+    func_basename "$output"
+    outputname="$func_basename_result"
+    libobjs_save="$libobjs"
+
+    if test -n "$shlibpath_var"; then
+      # get the directories listed in $shlibpath_var
+      eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\`
+    else
+      shlib_search_path=
+    fi
+    eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
+    eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+    func_dirname "$output" "/" ""
+    output_objdir="$func_dirname_result$objdir"
+    func_to_tool_file "$output_objdir/"
+    tool_output_objdir=$func_to_tool_file_result
+    # Create the object directory.
+    func_mkdir_p "$output_objdir"
+
+    # Determine the type of output
+    case $output in
+    "")
+      func_fatal_help "you must specify an output file"
+      ;;
+    *.$libext) linkmode=oldlib ;;
+    *.lo | *.$objext) linkmode=obj ;;
+    *.la) linkmode=lib ;;
+    *) linkmode=prog ;; # Anything else should be a program.
+    esac
+
+    specialdeplibs=
+
+    libs=
+    # Find all interdependent deplibs by searching for libraries
+    # that are linked more than once (e.g. -la -lb -la)
+    for deplib in $deplibs; do
+      if $opt_preserve_dup_deps ; then
+	case "$libs " in
+	*" $deplib "*) specialdeplibs+=" $deplib" ;;
+	esac
+      fi
+      libs+=" $deplib"
+    done
+
+    if test "$linkmode" = lib; then
+      libs="$predeps $libs $compiler_lib_search_path $postdeps"
+
+      # Compute libraries that are listed more than once in $predeps
+      # $postdeps and mark them as special (i.e., whose duplicates are
+      # not to be eliminated).
+      pre_post_deps=
+      if $opt_duplicate_compiler_generated_deps; then
+	for pre_post_dep in $predeps $postdeps; do
+	  case "$pre_post_deps " in
+	  *" $pre_post_dep "*) specialdeplibs+=" $pre_post_deps" ;;
+	  esac
+	  pre_post_deps+=" $pre_post_dep"
+	done
+      fi
+      pre_post_deps=
+    fi
+
+    deplibs=
+    newdependency_libs=
+    newlib_search_path=
+    need_relink=no # whether we're linking any uninstalled libtool libraries
+    notinst_deplibs= # not-installed libtool libraries
+    notinst_path= # paths that contain not-installed libtool libraries
+
+    case $linkmode in
+    lib)
+	passes="conv dlpreopen link"
+	for file in $dlfiles $dlprefiles; do
+	  case $file in
+	  *.la) ;;
+	  *)
+	    func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file"
+	    ;;
+	  esac
+	done
+	;;
+    prog)
+	compile_deplibs=
+	finalize_deplibs=
+	alldeplibs=no
+	newdlfiles=
+	newdlprefiles=
+	passes="conv scan dlopen dlpreopen link"
+	;;
+    *)  passes="conv"
+	;;
+    esac
+
+    for pass in $passes; do
+      # The preopen pass in lib mode reverses $deplibs; put it back here
+      # so that -L comes before libs that need it for instance...
+      if test "$linkmode,$pass" = "lib,link"; then
+	## FIXME: Find the place where the list is rebuilt in the wrong
+	##        order, and fix it there properly
+        tmp_deplibs=
+	for deplib in $deplibs; do
+	  tmp_deplibs="$deplib $tmp_deplibs"
+	done
+	deplibs="$tmp_deplibs"
+      fi
+
+      if test "$linkmode,$pass" = "lib,link" ||
+	 test "$linkmode,$pass" = "prog,scan"; then
+	libs="$deplibs"
+	deplibs=
+      fi
+      if test "$linkmode" = prog; then
+	case $pass in
+	dlopen) libs="$dlfiles" ;;
+	dlpreopen) libs="$dlprefiles" ;;
+	link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
+	esac
+      fi
+      if test "$linkmode,$pass" = "lib,dlpreopen"; then
+	# Collect and forward deplibs of preopened libtool libs
+	for lib in $dlprefiles; do
+	  # Ignore non-libtool-libs
+	  dependency_libs=
+	  func_resolve_sysroot "$lib"
+	  case $lib in
+	  *.la)	func_source "$func_resolve_sysroot_result" ;;
+	  esac
+
+	  # Collect preopened libtool deplibs, except any this library
+	  # has declared as weak libs
+	  for deplib in $dependency_libs; do
+	    func_basename "$deplib"
+            deplib_base=$func_basename_result
+	    case " $weak_libs " in
+	    *" $deplib_base "*) ;;
+	    *) deplibs+=" $deplib" ;;
+	    esac
+	  done
+	done
+	libs="$dlprefiles"
+      fi
+      if test "$pass" = dlopen; then
+	# Collect dlpreopened libraries
+	save_deplibs="$deplibs"
+	deplibs=
+      fi
+
+      for deplib in $libs; do
+	lib=
+	found=no
+	case $deplib in
+	-mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \
+        |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
+	  if test "$linkmode,$pass" = "prog,link"; then
+	    compile_deplibs="$deplib $compile_deplibs"
+	    finalize_deplibs="$deplib $finalize_deplibs"
+	  else
+	    compiler_flags+=" $deplib"
+	    if test "$linkmode" = lib ; then
+		case "$new_inherited_linker_flags " in
+		    *" $deplib "*) ;;
+		    * ) new_inherited_linker_flags+=" $deplib" ;;
+		esac
+	    fi
+	  fi
+	  continue
+	  ;;
+	-l*)
+	  if test "$linkmode" != lib && test "$linkmode" != prog; then
+	    func_warning "\`-l' is ignored for archives/objects"
+	    continue
+	  fi
+	  func_stripname '-l' '' "$deplib"
+	  name=$func_stripname_result
+	  if test "$linkmode" = lib; then
+	    searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path"
+	  else
+	    searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path"
+	  fi
+	  for searchdir in $searchdirs; do
+	    for search_ext in .la $std_shrext .so .a; do
+	      # Search the libtool library
+	      lib="$searchdir/lib${name}${search_ext}"
+	      if test -f "$lib"; then
+		if test "$search_ext" = ".la"; then
+		  found=yes
+		else
+		  found=no
+		fi
+		break 2
+	      fi
+	    done
+	  done
+	  if test "$found" != yes; then
+	    # deplib doesn't seem to be a libtool library
+	    if test "$linkmode,$pass" = "prog,link"; then
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    else
+	      deplibs="$deplib $deplibs"
+	      test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+	    fi
+	    continue
+	  else # deplib is a libtool library
+	    # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
+	    # We need to do some special things here, and not later.
+	    if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+	      case " $predeps $postdeps " in
+	      *" $deplib "*)
+		if func_lalib_p "$lib"; then
+		  library_names=
+		  old_library=
+		  func_source "$lib"
+		  for l in $old_library $library_names; do
+		    ll="$l"
+		  done
+		  if test "X$ll" = "X$old_library" ; then # only static version available
+		    found=no
+		    func_dirname "$lib" "" "."
+		    ladir="$func_dirname_result"
+		    lib=$ladir/$old_library
+		    if test "$linkmode,$pass" = "prog,link"; then
+		      compile_deplibs="$deplib $compile_deplibs"
+		      finalize_deplibs="$deplib $finalize_deplibs"
+		    else
+		      deplibs="$deplib $deplibs"
+		      test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+		    fi
+		    continue
+		  fi
+		fi
+		;;
+	      *) ;;
+	      esac
+	    fi
+	  fi
+	  ;; # -l
+	*.ltframework)
+	  if test "$linkmode,$pass" = "prog,link"; then
+	    compile_deplibs="$deplib $compile_deplibs"
+	    finalize_deplibs="$deplib $finalize_deplibs"
+	  else
+	    deplibs="$deplib $deplibs"
+	    if test "$linkmode" = lib ; then
+		case "$new_inherited_linker_flags " in
+		    *" $deplib "*) ;;
+		    * ) new_inherited_linker_flags+=" $deplib" ;;
+		esac
+	    fi
+	  fi
+	  continue
+	  ;;
+	-L*)
+	  case $linkmode in
+	  lib)
+	    deplibs="$deplib $deplibs"
+	    test "$pass" = conv && continue
+	    newdependency_libs="$deplib $newdependency_libs"
+	    func_stripname '-L' '' "$deplib"
+	    func_resolve_sysroot "$func_stripname_result"
+	    newlib_search_path+=" $func_resolve_sysroot_result"
+	    ;;
+	  prog)
+	    if test "$pass" = conv; then
+	      deplibs="$deplib $deplibs"
+	      continue
+	    fi
+	    if test "$pass" = scan; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    fi
+	    func_stripname '-L' '' "$deplib"
+	    func_resolve_sysroot "$func_stripname_result"
+	    newlib_search_path+=" $func_resolve_sysroot_result"
+	    ;;
+	  *)
+	    func_warning "\`-L' is ignored for archives/objects"
+	    ;;
+	  esac # linkmode
+	  continue
+	  ;; # -L
+	-R*)
+	  if test "$pass" = link; then
+	    func_stripname '-R' '' "$deplib"
+	    func_resolve_sysroot "$func_stripname_result"
+	    dir=$func_resolve_sysroot_result
+	    # Make sure the xrpath contains only unique directories.
+	    case "$xrpath " in
+	    *" $dir "*) ;;
+	    *) xrpath+=" $dir" ;;
+	    esac
+	  fi
+	  deplibs="$deplib $deplibs"
+	  continue
+	  ;;
+	*.la)
+	  func_resolve_sysroot "$deplib"
+	  lib=$func_resolve_sysroot_result
+	  ;;
+	*.$libext)
+	  if test "$pass" = conv; then
+	    deplibs="$deplib $deplibs"
+	    continue
+	  fi
+	  case $linkmode in
+	  lib)
+	    # Linking convenience modules into shared libraries is allowed,
+	    # but linking other static libraries is non-portable.
+	    case " $dlpreconveniencelibs " in
+	    *" $deplib "*) ;;
+	    *)
+	      valid_a_lib=no
+	      case $deplibs_check_method in
+		match_pattern*)
+		  set dummy $deplibs_check_method; shift
+		  match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+		  if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \
+		    | $EGREP "$match_pattern_regex" > /dev/null; then
+		    valid_a_lib=yes
+		  fi
+		;;
+		pass_all)
+		  valid_a_lib=yes
+		;;
+	      esac
+	      if test "$valid_a_lib" != yes; then
+		echo
+		$ECHO "*** Warning: Trying to link with static lib archive $deplib."
+		echo "*** I have the capability to make that library automatically link in when"
+		echo "*** you link to this library.  But I can only do this if you have a"
+		echo "*** shared version of the library, which you do not appear to have"
+		echo "*** because the file extensions .$libext of this argument makes me believe"
+		echo "*** that it is just a static archive that I should not use here."
+	      else
+		echo
+		$ECHO "*** Warning: Linking the shared library $output against the"
+		$ECHO "*** static library $deplib is not portable!"
+		deplibs="$deplib $deplibs"
+	      fi
+	      ;;
+	    esac
+	    continue
+	    ;;
+	  prog)
+	    if test "$pass" != link; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    fi
+	    continue
+	    ;;
+	  esac # linkmode
+	  ;; # *.$libext
+	*.lo | *.$objext)
+	  if test "$pass" = conv; then
+	    deplibs="$deplib $deplibs"
+	  elif test "$linkmode" = prog; then
+	    if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+	      # If there is no dlopen support or we're linking statically,
+	      # we need to preload.
+	      newdlprefiles+=" $deplib"
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    else
+	      newdlfiles+=" $deplib"
+	    fi
+	  fi
+	  continue
+	  ;;
+	%DEPLIBS%)
+	  alldeplibs=yes
+	  continue
+	  ;;
+	esac # case $deplib
+
+	if test "$found" = yes || test -f "$lib"; then :
+	else
+	  func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'"
+	fi
+
+	# Check to see that this really is a libtool archive.
+	func_lalib_unsafe_p "$lib" \
+	  || func_fatal_error "\`$lib' is not a valid libtool archive"
+
+	func_dirname "$lib" "" "."
+	ladir="$func_dirname_result"
+
+	dlname=
+	dlopen=
+	dlpreopen=
+	libdir=
+	library_names=
+	old_library=
+	inherited_linker_flags=
+	# If the library was installed with an old release of libtool,
+	# it will not redefine variables installed, or shouldnotlink
+	installed=yes
+	shouldnotlink=no
+	avoidtemprpath=
+
+
+	# Read the .la file
+	func_source "$lib"
+
+	# Convert "-framework foo" to "foo.ltframework"
+	if test -n "$inherited_linker_flags"; then
+	  tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'`
+	  for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do
+	    case " $new_inherited_linker_flags " in
+	      *" $tmp_inherited_linker_flag "*) ;;
+	      *) new_inherited_linker_flags+=" $tmp_inherited_linker_flag";;
+	    esac
+	  done
+	fi
+	dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	if test "$linkmode,$pass" = "lib,link" ||
+	   test "$linkmode,$pass" = "prog,scan" ||
+	   { test "$linkmode" != prog && test "$linkmode" != lib; }; then
+	  test -n "$dlopen" && dlfiles+=" $dlopen"
+	  test -n "$dlpreopen" && dlprefiles+=" $dlpreopen"
+	fi
+
+	if test "$pass" = conv; then
+	  # Only check for convenience libraries
+	  deplibs="$lib $deplibs"
+	  if test -z "$libdir"; then
+	    if test -z "$old_library"; then
+	      func_fatal_error "cannot find name of link library for \`$lib'"
+	    fi
+	    # It is a libtool convenience library, so add in its objects.
+	    convenience+=" $ladir/$objdir/$old_library"
+	    old_convenience+=" $ladir/$objdir/$old_library"
+	  elif test "$linkmode" != prog && test "$linkmode" != lib; then
+	    func_fatal_error "\`$lib' is not a convenience library"
+	  fi
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    deplibs="$deplib $deplibs"
+	    if $opt_preserve_dup_deps ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) specialdeplibs+=" $deplib" ;;
+	      esac
+	    fi
+	    tmp_libs+=" $deplib"
+	  done
+	  continue
+	fi # $pass = conv
+
+
+	# Get the name of the library we link against.
+	linklib=
+	if test -n "$old_library" &&
+	   { test "$prefer_static_libs" = yes ||
+	     test "$prefer_static_libs,$installed" = "built,no"; }; then
+	  linklib=$old_library
+	else
+	  for l in $old_library $library_names; do
+	    linklib="$l"
+	  done
+	fi
+	if test -z "$linklib"; then
+	  func_fatal_error "cannot find name of link library for \`$lib'"
+	fi
+
+	# This library was specified with -dlopen.
+	if test "$pass" = dlopen; then
+	  if test -z "$libdir"; then
+	    func_fatal_error "cannot -dlopen a convenience library: \`$lib'"
+	  fi
+	  if test -z "$dlname" ||
+	     test "$dlopen_support" != yes ||
+	     test "$build_libtool_libs" = no; then
+	    # If there is no dlname, no dlopen support or we're linking
+	    # statically, we need to preload.  We also need to preload any
+	    # dependent libraries so libltdl's deplib preloader doesn't
+	    # bomb out in the load deplibs phase.
+	    dlprefiles+=" $lib $dependency_libs"
+	  else
+	    newdlfiles+=" $lib"
+	  fi
+	  continue
+	fi # $pass = dlopen
+
+	# We need an absolute path.
+	case $ladir in
+	[\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
+	*)
+	  abs_ladir=`cd "$ladir" && pwd`
+	  if test -z "$abs_ladir"; then
+	    func_warning "cannot determine absolute directory name of \`$ladir'"
+	    func_warning "passing it literally to the linker, although it might fail"
+	    abs_ladir="$ladir"
+	  fi
+	  ;;
+	esac
+	func_basename "$lib"
+	laname="$func_basename_result"
+
+	# Find the relevant object directory and library name.
+	if test "X$installed" = Xyes; then
+	  if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+	    func_warning "library \`$lib' was moved."
+	    dir="$ladir"
+	    absdir="$abs_ladir"
+	    libdir="$abs_ladir"
+	  else
+	    dir="$lt_sysroot$libdir"
+	    absdir="$lt_sysroot$libdir"
+	  fi
+	  test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
+	else
+	  if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+	    dir="$ladir"
+	    absdir="$abs_ladir"
+	    # Remove this search path later
+	    notinst_path+=" $abs_ladir"
+	  else
+	    dir="$ladir/$objdir"
+	    absdir="$abs_ladir/$objdir"
+	    # Remove this search path later
+	    notinst_path+=" $abs_ladir"
+	  fi
+	fi # $installed = yes
+	func_stripname 'lib' '.la' "$laname"
+	name=$func_stripname_result
+
+	# This library was specified with -dlpreopen.
+	if test "$pass" = dlpreopen; then
+	  if test -z "$libdir" && test "$linkmode" = prog; then
+	    func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'"
+	  fi
+	  case "$host" in
+	    # special handling for platforms with PE-DLLs.
+	    *cygwin* | *mingw* | *cegcc* )
+	      # Linker will automatically link against shared library if both
+	      # static and shared are present.  Therefore, ensure we extract
+	      # symbols from the import library if a shared library is present
+	      # (otherwise, the dlopen module name will be incorrect).  We do
+	      # this by putting the import library name into $newdlprefiles.
+	      # We recover the dlopen module name by 'saving' the la file
+	      # name in a special purpose variable, and (later) extracting the
+	      # dlname from the la file.
+	      if test -n "$dlname"; then
+	        func_tr_sh "$dir/$linklib"
+	        eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname"
+	        newdlprefiles+=" $dir/$linklib"
+	      else
+	        newdlprefiles+=" $dir/$old_library"
+	        # Keep a list of preopened convenience libraries to check
+	        # that they are being used correctly in the link pass.
+	        test -z "$libdir" && \
+	          dlpreconveniencelibs+=" $dir/$old_library"
+	      fi
+	    ;;
+	    * )
+	      # Prefer using a static library (so that no silly _DYNAMIC symbols
+	      # are required to link).
+	      if test -n "$old_library"; then
+	        newdlprefiles+=" $dir/$old_library"
+	        # Keep a list of preopened convenience libraries to check
+	        # that they are being used correctly in the link pass.
+	        test -z "$libdir" && \
+	          dlpreconveniencelibs+=" $dir/$old_library"
+	      # Otherwise, use the dlname, so that lt_dlopen finds it.
+	      elif test -n "$dlname"; then
+	        newdlprefiles+=" $dir/$dlname"
+	      else
+	        newdlprefiles+=" $dir/$linklib"
+	      fi
+	    ;;
+	  esac
+	fi # $pass = dlpreopen
+
+	if test -z "$libdir"; then
+	  # Link the convenience library
+	  if test "$linkmode" = lib; then
+	    deplibs="$dir/$old_library $deplibs"
+	  elif test "$linkmode,$pass" = "prog,link"; then
+	    compile_deplibs="$dir/$old_library $compile_deplibs"
+	    finalize_deplibs="$dir/$old_library $finalize_deplibs"
+	  else
+	    deplibs="$lib $deplibs" # used for prog,scan pass
+	  fi
+	  continue
+	fi
+
+
+	if test "$linkmode" = prog && test "$pass" != link; then
+	  newlib_search_path+=" $ladir"
+	  deplibs="$lib $deplibs"
+
+	  linkalldeplibs=no
+	  if test "$link_all_deplibs" != no || test -z "$library_names" ||
+	     test "$build_libtool_libs" = no; then
+	    linkalldeplibs=yes
+	  fi
+
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    case $deplib in
+	    -L*) func_stripname '-L' '' "$deplib"
+	         func_resolve_sysroot "$func_stripname_result"
+	         newlib_search_path+=" $func_resolve_sysroot_result"
+		 ;;
+	    esac
+	    # Need to link against all dependency_libs?
+	    if test "$linkalldeplibs" = yes; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      # Need to hardcode shared library paths
+	      # or/and link against static libraries
+	      newdependency_libs="$deplib $newdependency_libs"
+	    fi
+	    if $opt_preserve_dup_deps ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) specialdeplibs+=" $deplib" ;;
+	      esac
+	    fi
+	    tmp_libs+=" $deplib"
+	  done # for deplib
+	  continue
+	fi # $linkmode = prog...
+
+	if test "$linkmode,$pass" = "prog,link"; then
+	  if test -n "$library_names" &&
+	     { { test "$prefer_static_libs" = no ||
+	         test "$prefer_static_libs,$installed" = "built,yes"; } ||
+	       test -z "$old_library"; }; then
+	    # We need to hardcode the library path
+	    if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
+	      # Make sure the rpath contains only unique directories.
+	      case "$temp_rpath:" in
+	      *"$absdir:"*) ;;
+	      *) temp_rpath+="$absdir:" ;;
+	      esac
+	    fi
+
+	    # Hardcode the library path.
+	    # Skip directories that are in the system default run-time
+	    # search path.
+	    case " $sys_lib_dlsearch_path " in
+	    *" $absdir "*) ;;
+	    *)
+	      case "$compile_rpath " in
+	      *" $absdir "*) ;;
+	      *) compile_rpath+=" $absdir" ;;
+	      esac
+	      ;;
+	    esac
+	    case " $sys_lib_dlsearch_path " in
+	    *" $libdir "*) ;;
+	    *)
+	      case "$finalize_rpath " in
+	      *" $libdir "*) ;;
+	      *) finalize_rpath+=" $libdir" ;;
+	      esac
+	      ;;
+	    esac
+	  fi # $linkmode,$pass = prog,link...
+
+	  if test "$alldeplibs" = yes &&
+	     { test "$deplibs_check_method" = pass_all ||
+	       { test "$build_libtool_libs" = yes &&
+		 test -n "$library_names"; }; }; then
+	    # We only need to search for static libraries
+	    continue
+	  fi
+	fi
+
+	link_static=no # Whether the deplib will be linked statically
+	use_static_libs=$prefer_static_libs
+	if test "$use_static_libs" = built && test "$installed" = yes; then
+	  use_static_libs=no
+	fi
+	if test -n "$library_names" &&
+	   { test "$use_static_libs" = no || test -z "$old_library"; }; then
+	  case $host in
+	  *cygwin* | *mingw* | *cegcc*)
+	      # No point in relinking DLLs because paths are not encoded
+	      notinst_deplibs+=" $lib"
+	      need_relink=no
+	    ;;
+	  *)
+	    if test "$installed" = no; then
+	      notinst_deplibs+=" $lib"
+	      need_relink=yes
+	    fi
+	    ;;
+	  esac
+	  # This is a shared library
+
+	  # Warn about portability, can't link against -module's on some
+	  # systems (darwin).  Don't bleat about dlopened modules though!
+	  dlopenmodule=""
+	  for dlpremoduletest in $dlprefiles; do
+	    if test "X$dlpremoduletest" = "X$lib"; then
+	      dlopenmodule="$dlpremoduletest"
+	      break
+	    fi
+	  done
+	  if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then
+	    echo
+	    if test "$linkmode" = prog; then
+	      $ECHO "*** Warning: Linking the executable $output against the loadable module"
+	    else
+	      $ECHO "*** Warning: Linking the shared library $output against the loadable module"
+	    fi
+	    $ECHO "*** $linklib is not portable!"
+	  fi
+	  if test "$linkmode" = lib &&
+	     test "$hardcode_into_libs" = yes; then
+	    # Hardcode the library path.
+	    # Skip directories that are in the system default run-time
+	    # search path.
+	    case " $sys_lib_dlsearch_path " in
+	    *" $absdir "*) ;;
+	    *)
+	      case "$compile_rpath " in
+	      *" $absdir "*) ;;
+	      *) compile_rpath+=" $absdir" ;;
+	      esac
+	      ;;
+	    esac
+	    case " $sys_lib_dlsearch_path " in
+	    *" $libdir "*) ;;
+	    *)
+	      case "$finalize_rpath " in
+	      *" $libdir "*) ;;
+	      *) finalize_rpath+=" $libdir" ;;
+	      esac
+	      ;;
+	    esac
+	  fi
+
+	  if test -n "$old_archive_from_expsyms_cmds"; then
+	    # figure out the soname
+	    set dummy $library_names
+	    shift
+	    realname="$1"
+	    shift
+	    libname=`eval "\\$ECHO \"$libname_spec\""`
+	    # use dlname if we got it. it's perfectly good, no?
+	    if test -n "$dlname"; then
+	      soname="$dlname"
+	    elif test -n "$soname_spec"; then
+	      # bleh windows
+	      case $host in
+	      *cygwin* | mingw* | *cegcc*)
+	        func_arith $current - $age
+		major=$func_arith_result
+		versuffix="-$major"
+		;;
+	      esac
+	      eval soname=\"$soname_spec\"
+	    else
+	      soname="$realname"
+	    fi
+
+	    # Make a new name for the extract_expsyms_cmds to use
+	    soroot="$soname"
+	    func_basename "$soroot"
+	    soname="$func_basename_result"
+	    func_stripname 'lib' '.dll' "$soname"
+	    newlib=libimp-$func_stripname_result.a
+
+	    # If the library has no export list, then create one now
+	    if test -f "$output_objdir/$soname-def"; then :
+	    else
+	      func_verbose "extracting exported symbol list from \`$soname'"
+	      func_execute_cmds "$extract_expsyms_cmds" 'exit $?'
+	    fi
+
+	    # Create $newlib
+	    if test -f "$output_objdir/$newlib"; then :; else
+	      func_verbose "generating import library for \`$soname'"
+	      func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?'
+	    fi
+	    # make sure the library variables are pointing to the new library
+	    dir=$output_objdir
+	    linklib=$newlib
+	  fi # test -n "$old_archive_from_expsyms_cmds"
+
+	  if test "$linkmode" = prog || test "$opt_mode" != relink; then
+	    add_shlibpath=
+	    add_dir=
+	    add=
+	    lib_linked=yes
+	    case $hardcode_action in
+	    immediate | unsupported)
+	      if test "$hardcode_direct" = no; then
+		add="$dir/$linklib"
+		case $host in
+		  *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;;
+		  *-*-sysv4*uw2*) add_dir="-L$dir" ;;
+		  *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
+		    *-*-unixware7*) add_dir="-L$dir" ;;
+		  *-*-darwin* )
+		    # if the lib is a (non-dlopened) module then we can not
+		    # link against it, someone is ignoring the earlier warnings
+		    if /usr/bin/file -L $add 2> /dev/null |
+			 $GREP ": [^:]* bundle" >/dev/null ; then
+		      if test "X$dlopenmodule" != "X$lib"; then
+			$ECHO "*** Warning: lib $linklib is a module, not a shared library"
+			if test -z "$old_library" ; then
+			  echo
+			  echo "*** And there doesn't seem to be a static archive available"
+			  echo "*** The link will probably fail, sorry"
+			else
+			  add="$dir/$old_library"
+			fi
+		      elif test -n "$old_library"; then
+			add="$dir/$old_library"
+		      fi
+		    fi
+		esac
+	      elif test "$hardcode_minus_L" = no; then
+		case $host in
+		*-*-sunos*) add_shlibpath="$dir" ;;
+		esac
+		add_dir="-L$dir"
+		add="-l$name"
+	      elif test "$hardcode_shlibpath_var" = no; then
+		add_shlibpath="$dir"
+		add="-l$name"
+	      else
+		lib_linked=no
+	      fi
+	      ;;
+	    relink)
+	      if test "$hardcode_direct" = yes &&
+	         test "$hardcode_direct_absolute" = no; then
+		add="$dir/$linklib"
+	      elif test "$hardcode_minus_L" = yes; then
+		add_dir="-L$absdir"
+		# Try looking first in the location we're being installed to.
+		if test -n "$inst_prefix_dir"; then
+		  case $libdir in
+		    [\\/]*)
+		      add_dir+=" -L$inst_prefix_dir$libdir"
+		      ;;
+		  esac
+		fi
+		add="-l$name"
+	      elif test "$hardcode_shlibpath_var" = yes; then
+		add_shlibpath="$dir"
+		add="-l$name"
+	      else
+		lib_linked=no
+	      fi
+	      ;;
+	    *) lib_linked=no ;;
+	    esac
+
+	    if test "$lib_linked" != yes; then
+	      func_fatal_configuration "unsupported hardcode properties"
+	    fi
+
+	    if test -n "$add_shlibpath"; then
+	      case :$compile_shlibpath: in
+	      *":$add_shlibpath:"*) ;;
+	      *) compile_shlibpath+="$add_shlibpath:" ;;
+	      esac
+	    fi
+	    if test "$linkmode" = prog; then
+	      test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+	      test -n "$add" && compile_deplibs="$add $compile_deplibs"
+	    else
+	      test -n "$add_dir" && deplibs="$add_dir $deplibs"
+	      test -n "$add" && deplibs="$add $deplibs"
+	      if test "$hardcode_direct" != yes &&
+		 test "$hardcode_minus_L" != yes &&
+		 test "$hardcode_shlibpath_var" = yes; then
+		case :$finalize_shlibpath: in
+		*":$libdir:"*) ;;
+		*) finalize_shlibpath+="$libdir:" ;;
+		esac
+	      fi
+	    fi
+	  fi
+
+	  if test "$linkmode" = prog || test "$opt_mode" = relink; then
+	    add_shlibpath=
+	    add_dir=
+	    add=
+	    # Finalize command for both is simple: just hardcode it.
+	    if test "$hardcode_direct" = yes &&
+	       test "$hardcode_direct_absolute" = no; then
+	      add="$libdir/$linklib"
+	    elif test "$hardcode_minus_L" = yes; then
+	      add_dir="-L$libdir"
+	      add="-l$name"
+	    elif test "$hardcode_shlibpath_var" = yes; then
+	      case :$finalize_shlibpath: in
+	      *":$libdir:"*) ;;
+	      *) finalize_shlibpath+="$libdir:" ;;
+	      esac
+	      add="-l$name"
+	    elif test "$hardcode_automatic" = yes; then
+	      if test -n "$inst_prefix_dir" &&
+		 test -f "$inst_prefix_dir$libdir/$linklib" ; then
+		add="$inst_prefix_dir$libdir/$linklib"
+	      else
+		add="$libdir/$linklib"
+	      fi
+	    else
+	      # We cannot seem to hardcode it, guess we'll fake it.
+	      add_dir="-L$libdir"
+	      # Try looking first in the location we're being installed to.
+	      if test -n "$inst_prefix_dir"; then
+		case $libdir in
+		  [\\/]*)
+		    add_dir+=" -L$inst_prefix_dir$libdir"
+		    ;;
+		esac
+	      fi
+	      add="-l$name"
+	    fi
+
+	    if test "$linkmode" = prog; then
+	      test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+	      test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+	    else
+	      test -n "$add_dir" && deplibs="$add_dir $deplibs"
+	      test -n "$add" && deplibs="$add $deplibs"
+	    fi
+	  fi
+	elif test "$linkmode" = prog; then
+	  # Here we assume that one of hardcode_direct or hardcode_minus_L
+	  # is not unsupported.  This is valid on all known static and
+	  # shared platforms.
+	  if test "$hardcode_direct" != unsupported; then
+	    test -n "$old_library" && linklib="$old_library"
+	    compile_deplibs="$dir/$linklib $compile_deplibs"
+	    finalize_deplibs="$dir/$linklib $finalize_deplibs"
+	  else
+	    compile_deplibs="-l$name -L$dir $compile_deplibs"
+	    finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+	  fi
+	elif test "$build_libtool_libs" = yes; then
+	  # Not a shared library
+	  if test "$deplibs_check_method" != pass_all; then
+	    # We're trying link a shared library against a static one
+	    # but the system doesn't support it.
+
+	    # Just print a warning and add the library to dependency_libs so
+	    # that the program can be linked against the static library.
+	    echo
+	    $ECHO "*** Warning: This system can not link to static lib archive $lib."
+	    echo "*** I have the capability to make that library automatically link in when"
+	    echo "*** you link to this library.  But I can only do this if you have a"
+	    echo "*** shared version of the library, which you do not appear to have."
+	    if test "$module" = yes; then
+	      echo "*** But as you try to build a module library, libtool will still create "
+	      echo "*** a static module, that should work as long as the dlopening application"
+	      echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
+	      if test -z "$global_symbol_pipe"; then
+		echo
+		echo "*** However, this would only work if libtool was able to extract symbol"
+		echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+		echo "*** not find such a program.  So, this module is probably useless."
+		echo "*** \`nm' from GNU binutils and a full rebuild may help."
+	      fi
+	      if test "$build_old_libs" = no; then
+		build_libtool_libs=module
+		build_old_libs=yes
+	      else
+		build_libtool_libs=no
+	      fi
+	    fi
+	  else
+	    deplibs="$dir/$old_library $deplibs"
+	    link_static=yes
+	  fi
+	fi # link shared/static library?
+
+	if test "$linkmode" = lib; then
+	  if test -n "$dependency_libs" &&
+	     { test "$hardcode_into_libs" != yes ||
+	       test "$build_old_libs" = yes ||
+	       test "$link_static" = yes; }; then
+	    # Extract -R from dependency_libs
+	    temp_deplibs=
+	    for libdir in $dependency_libs; do
+	      case $libdir in
+	      -R*) func_stripname '-R' '' "$libdir"
+	           temp_xrpath=$func_stripname_result
+		   case " $xrpath " in
+		   *" $temp_xrpath "*) ;;
+		   *) xrpath+=" $temp_xrpath";;
+		   esac;;
+	      *) temp_deplibs+=" $libdir";;
+	      esac
+	    done
+	    dependency_libs="$temp_deplibs"
+	  fi
+
+	  newlib_search_path+=" $absdir"
+	  # Link against this library
+	  test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+	  # ... and its dependency_libs
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    newdependency_libs="$deplib $newdependency_libs"
+	    case $deplib in
+              -L*) func_stripname '-L' '' "$deplib"
+                   func_resolve_sysroot "$func_stripname_result";;
+              *) func_resolve_sysroot "$deplib" ;;
+            esac
+	    if $opt_preserve_dup_deps ; then
+	      case "$tmp_libs " in
+	      *" $func_resolve_sysroot_result "*)
+                specialdeplibs+=" $func_resolve_sysroot_result" ;;
+	      esac
+	    fi
+	    tmp_libs+=" $func_resolve_sysroot_result"
+	  done
+
+	  if test "$link_all_deplibs" != no; then
+	    # Add the search paths of all dependency libraries
+	    for deplib in $dependency_libs; do
+	      path=
+	      case $deplib in
+	      -L*) path="$deplib" ;;
+	      *.la)
+	        func_resolve_sysroot "$deplib"
+	        deplib=$func_resolve_sysroot_result
+	        func_dirname "$deplib" "" "."
+		dir=$func_dirname_result
+		# We need an absolute path.
+		case $dir in
+		[\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+		*)
+		  absdir=`cd "$dir" && pwd`
+		  if test -z "$absdir"; then
+		    func_warning "cannot determine absolute directory name of \`$dir'"
+		    absdir="$dir"
+		  fi
+		  ;;
+		esac
+		if $GREP "^installed=no" $deplib > /dev/null; then
+		case $host in
+		*-*-darwin*)
+		  depdepl=
+		  eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
+		  if test -n "$deplibrary_names" ; then
+		    for tmp in $deplibrary_names ; do
+		      depdepl=$tmp
+		    done
+		    if test -f "$absdir/$objdir/$depdepl" ; then
+		      depdepl="$absdir/$objdir/$depdepl"
+		      darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
+                      if test -z "$darwin_install_name"; then
+                          darwin_install_name=`${OTOOL64} -L $depdepl  | awk '{if (NR == 2) {print $1;exit}}'`
+                      fi
+		      compiler_flags+=" ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}"
+		      linker_flags+=" -dylib_file ${darwin_install_name}:${depdepl}"
+		      path=
+		    fi
+		  fi
+		  ;;
+		*)
+		  path="-L$absdir/$objdir"
+		  ;;
+		esac
+		else
+		  eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+		  test -z "$libdir" && \
+		    func_fatal_error "\`$deplib' is not a valid libtool archive"
+		  test "$absdir" != "$libdir" && \
+		    func_warning "\`$deplib' seems to be moved"
+
+		  path="-L$absdir"
+		fi
+		;;
+	      esac
+	      case " $deplibs " in
+	      *" $path "*) ;;
+	      *) deplibs="$path $deplibs" ;;
+	      esac
+	    done
+	  fi # link_all_deplibs != no
+	fi # linkmode = lib
+      done # for deplib in $libs
+      if test "$pass" = link; then
+	if test "$linkmode" = "prog"; then
+	  compile_deplibs="$new_inherited_linker_flags $compile_deplibs"
+	  finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs"
+	else
+	  compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	fi
+      fi
+      dependency_libs="$newdependency_libs"
+      if test "$pass" = dlpreopen; then
+	# Link the dlpreopened libraries before other libraries
+	for deplib in $save_deplibs; do
+	  deplibs="$deplib $deplibs"
+	done
+      fi
+      if test "$pass" != dlopen; then
+	if test "$pass" != conv; then
+	  # Make sure lib_search_path contains only unique directories.
+	  lib_search_path=
+	  for dir in $newlib_search_path; do
+	    case "$lib_search_path " in
+	    *" $dir "*) ;;
+	    *) lib_search_path+=" $dir" ;;
+	    esac
+	  done
+	  newlib_search_path=
+	fi
+
+	if test "$linkmode,$pass" != "prog,link"; then
+	  vars="deplibs"
+	else
+	  vars="compile_deplibs finalize_deplibs"
+	fi
+	for var in $vars dependency_libs; do
+	  # Add libraries to $var in reverse order
+	  eval tmp_libs=\"\$$var\"
+	  new_libs=
+	  for deplib in $tmp_libs; do
+	    # FIXME: Pedantically, this is the right thing to do, so
+	    #        that some nasty dependency loop isn't accidentally
+	    #        broken:
+	    #new_libs="$deplib $new_libs"
+	    # Pragmatically, this seems to cause very few problems in
+	    # practice:
+	    case $deplib in
+	    -L*) new_libs="$deplib $new_libs" ;;
+	    -R*) ;;
+	    *)
+	      # And here is the reason: when a library appears more
+	      # than once as an explicit dependence of a library, or
+	      # is implicitly linked in more than once by the
+	      # compiler, it is considered special, and multiple
+	      # occurrences thereof are not removed.  Compare this
+	      # with having the same library being listed as a
+	      # dependency of multiple other libraries: in this case,
+	      # we know (pedantically, we assume) the library does not
+	      # need to be listed more than once, so we keep only the
+	      # last copy.  This is not always right, but it is rare
+	      # enough that we require users that really mean to play
+	      # such unportable linking tricks to link the library
+	      # using -Wl,-lname, so that libtool does not consider it
+	      # for duplicate removal.
+	      case " $specialdeplibs " in
+	      *" $deplib "*) new_libs="$deplib $new_libs" ;;
+	      *)
+		case " $new_libs " in
+		*" $deplib "*) ;;
+		*) new_libs="$deplib $new_libs" ;;
+		esac
+		;;
+	      esac
+	      ;;
+	    esac
+	  done
+	  tmp_libs=
+	  for deplib in $new_libs; do
+	    case $deplib in
+	    -L*)
+	      case " $tmp_libs " in
+	      *" $deplib "*) ;;
+	      *) tmp_libs+=" $deplib" ;;
+	      esac
+	      ;;
+	    *) tmp_libs+=" $deplib" ;;
+	    esac
+	  done
+	  eval $var=\"$tmp_libs\"
+	done # for var
+      fi
+      # Last step: remove runtime libs from dependency_libs
+      # (they stay in deplibs)
+      tmp_libs=
+      for i in $dependency_libs ; do
+	case " $predeps $postdeps $compiler_lib_search_path " in
+	*" $i "*)
+	  i=""
+	  ;;
+	esac
+	if test -n "$i" ; then
+	  tmp_libs+=" $i"
+	fi
+      done
+      dependency_libs=$tmp_libs
+    done # for pass
+    if test "$linkmode" = prog; then
+      dlfiles="$newdlfiles"
+    fi
+    if test "$linkmode" = prog || test "$linkmode" = lib; then
+      dlprefiles="$newdlprefiles"
+    fi
+
+    case $linkmode in
+    oldlib)
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+	func_warning "\`-dlopen' is ignored for archives"
+      fi
+
+      case " $deplibs" in
+      *\ -l* | *\ -L*)
+	func_warning "\`-l' and \`-L' are ignored for archives" ;;
+      esac
+
+      test -n "$rpath" && \
+	func_warning "\`-rpath' is ignored for archives"
+
+      test -n "$xrpath" && \
+	func_warning "\`-R' is ignored for archives"
+
+      test -n "$vinfo" && \
+	func_warning "\`-version-info/-version-number' is ignored for archives"
+
+      test -n "$release" && \
+	func_warning "\`-release' is ignored for archives"
+
+      test -n "$export_symbols$export_symbols_regex" && \
+	func_warning "\`-export-symbols' is ignored for archives"
+
+      # Now set the variables for building old libraries.
+      build_libtool_libs=no
+      oldlibs="$output"
+      objs+="$old_deplibs"
+      ;;
+
+    lib)
+      # Make sure we only generate libraries of the form `libNAME.la'.
+      case $outputname in
+      lib*)
+	func_stripname 'lib' '.la' "$outputname"
+	name=$func_stripname_result
+	eval shared_ext=\"$shrext_cmds\"
+	eval libname=\"$libname_spec\"
+	;;
+      *)
+	test "$module" = no && \
+	  func_fatal_help "libtool library \`$output' must begin with \`lib'"
+
+	if test "$need_lib_prefix" != no; then
+	  # Add the "lib" prefix for modules if required
+	  func_stripname '' '.la' "$outputname"
+	  name=$func_stripname_result
+	  eval shared_ext=\"$shrext_cmds\"
+	  eval libname=\"$libname_spec\"
+	else
+	  func_stripname '' '.la' "$outputname"
+	  libname=$func_stripname_result
+	fi
+	;;
+      esac
+
+      if test -n "$objs"; then
+	if test "$deplibs_check_method" != pass_all; then
+	  func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs"
+	else
+	  echo
+	  $ECHO "*** Warning: Linking the shared library $output against the non-libtool"
+	  $ECHO "*** objects $objs is not portable!"
+	  libobjs+=" $objs"
+	fi
+      fi
+
+      test "$dlself" != no && \
+	func_warning "\`-dlopen self' is ignored for libtool libraries"
+
+      set dummy $rpath
+      shift
+      test "$#" -gt 1 && \
+	func_warning "ignoring multiple \`-rpath's for a libtool library"
+
+      install_libdir="$1"
+
+      oldlibs=
+      if test -z "$rpath"; then
+	if test "$build_libtool_libs" = yes; then
+	  # Building a libtool convenience library.
+	  # Some compilers have problems with a `.al' extension so
+	  # convenience libraries should have the same extension an
+	  # archive normally would.
+	  oldlibs="$output_objdir/$libname.$libext $oldlibs"
+	  build_libtool_libs=convenience
+	  build_old_libs=yes
+	fi
+
+	test -n "$vinfo" && \
+	  func_warning "\`-version-info/-version-number' is ignored for convenience libraries"
+
+	test -n "$release" && \
+	  func_warning "\`-release' is ignored for convenience libraries"
+      else
+
+	# Parse the version information argument.
+	save_ifs="$IFS"; IFS=':'
+	set dummy $vinfo 0 0 0
+	shift
+	IFS="$save_ifs"
+
+	test -n "$7" && \
+	  func_fatal_help "too many parameters to \`-version-info'"
+
+	# convert absolute version numbers to libtool ages
+	# this retains compatibility with .la files and attempts
+	# to make the code below a bit more comprehensible
+
+	case $vinfo_number in
+	yes)
+	  number_major="$1"
+	  number_minor="$2"
+	  number_revision="$3"
+	  #
+	  # There are really only two kinds -- those that
+	  # use the current revision as the major version
+	  # and those that subtract age and use age as
+	  # a minor version.  But, then there is irix
+	  # which has an extra 1 added just for fun
+	  #
+	  case $version_type in
+	  # correct linux to gnu/linux during the next big refactor
+	  darwin|linux|osf|windows|none)
+	    func_arith $number_major + $number_minor
+	    current=$func_arith_result
+	    age="$number_minor"
+	    revision="$number_revision"
+	    ;;
+	  freebsd-aout|freebsd-elf|qnx|sunos)
+	    current="$number_major"
+	    revision="$number_minor"
+	    age="0"
+	    ;;
+	  irix|nonstopux)
+	    func_arith $number_major + $number_minor
+	    current=$func_arith_result
+	    age="$number_minor"
+	    revision="$number_minor"
+	    lt_irix_increment=no
+	    ;;
+	  esac
+	  ;;
+	no)
+	  current="$1"
+	  revision="$2"
+	  age="$3"
+	  ;;
+	esac
+
+	# Check that each of the things are valid numbers.
+	case $current in
+	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+	*)
+	  func_error "CURRENT \`$current' must be a nonnegative integer"
+	  func_fatal_error "\`$vinfo' is not valid version information"
+	  ;;
+	esac
+
+	case $revision in
+	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+	*)
+	  func_error "REVISION \`$revision' must be a nonnegative integer"
+	  func_fatal_error "\`$vinfo' is not valid version information"
+	  ;;
+	esac
+
+	case $age in
+	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+	*)
+	  func_error "AGE \`$age' must be a nonnegative integer"
+	  func_fatal_error "\`$vinfo' is not valid version information"
+	  ;;
+	esac
+
+	if test "$age" -gt "$current"; then
+	  func_error "AGE \`$age' is greater than the current interface number \`$current'"
+	  func_fatal_error "\`$vinfo' is not valid version information"
+	fi
+
+	# Calculate the version variables.
+	major=
+	versuffix=
+	verstring=
+	case $version_type in
+	none) ;;
+
+	darwin)
+	  # Like Linux, but with the current version available in
+	  # verstring for coding it into the library header
+	  func_arith $current - $age
+	  major=.$func_arith_result
+	  versuffix="$major.$age.$revision"
+	  # Darwin ld doesn't like 0 for these options...
+	  func_arith $current + 1
+	  minor_current=$func_arith_result
+	  xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
+	  verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+	  ;;
+
+	freebsd-aout)
+	  major=".$current"
+	  versuffix=".$current.$revision";
+	  ;;
+
+	freebsd-elf)
+	  major=".$current"
+	  versuffix=".$current"
+	  ;;
+
+	irix | nonstopux)
+	  if test "X$lt_irix_increment" = "Xno"; then
+	    func_arith $current - $age
+	  else
+	    func_arith $current - $age + 1
+	  fi
+	  major=$func_arith_result
+
+	  case $version_type in
+	    nonstopux) verstring_prefix=nonstopux ;;
+	    *)         verstring_prefix=sgi ;;
+	  esac
+	  verstring="$verstring_prefix$major.$revision"
+
+	  # Add in all the interfaces that we are compatible with.
+	  loop=$revision
+	  while test "$loop" -ne 0; do
+	    func_arith $revision - $loop
+	    iface=$func_arith_result
+	    func_arith $loop - 1
+	    loop=$func_arith_result
+	    verstring="$verstring_prefix$major.$iface:$verstring"
+	  done
+
+	  # Before this point, $major must not contain `.'.
+	  major=.$major
+	  versuffix="$major.$revision"
+	  ;;
+
+	linux) # correct to gnu/linux during the next big refactor
+	  func_arith $current - $age
+	  major=.$func_arith_result
+	  versuffix="$major.$age.$revision"
+	  ;;
+
+	osf)
+	  func_arith $current - $age
+	  major=.$func_arith_result
+	  versuffix=".$current.$age.$revision"
+	  verstring="$current.$age.$revision"
+
+	  # Add in all the interfaces that we are compatible with.
+	  loop=$age
+	  while test "$loop" -ne 0; do
+	    func_arith $current - $loop
+	    iface=$func_arith_result
+	    func_arith $loop - 1
+	    loop=$func_arith_result
+	    verstring="$verstring:${iface}.0"
+	  done
+
+	  # Make executables depend on our current version.
+	  verstring+=":${current}.0"
+	  ;;
+
+	qnx)
+	  major=".$current"
+	  versuffix=".$current"
+	  ;;
+
+	sunos)
+	  major=".$current"
+	  versuffix=".$current.$revision"
+	  ;;
+
+	windows)
+	  # Use '-' rather than '.', since we only want one
+	  # extension on DOS 8.3 filesystems.
+	  func_arith $current - $age
+	  major=$func_arith_result
+	  versuffix="-$major"
+	  ;;
+
+	*)
+	  func_fatal_configuration "unknown library version type \`$version_type'"
+	  ;;
+	esac
+
+	# Clear the version info if we defaulted, and they specified a release.
+	if test -z "$vinfo" && test -n "$release"; then
+	  major=
+	  case $version_type in
+	  darwin)
+	    # we can't check for "0.0" in archive_cmds due to quoting
+	    # problems, so we reset it completely
+	    verstring=
+	    ;;
+	  *)
+	    verstring="0.0"
+	    ;;
+	  esac
+	  if test "$need_version" = no; then
+	    versuffix=
+	  else
+	    versuffix=".0.0"
+	  fi
+	fi
+
+	# Remove version info from name if versioning should be avoided
+	if test "$avoid_version" = yes && test "$need_version" = no; then
+	  major=
+	  versuffix=
+	  verstring=""
+	fi
+
+	# Check to see if the archive will have undefined symbols.
+	if test "$allow_undefined" = yes; then
+	  if test "$allow_undefined_flag" = unsupported; then
+	    func_warning "undefined symbols not allowed in $host shared libraries"
+	    build_libtool_libs=no
+	    build_old_libs=yes
+	  fi
+	else
+	  # Don't allow undefined symbols.
+	  allow_undefined_flag="$no_undefined_flag"
+	fi
+
+      fi
+
+      func_generate_dlsyms "$libname" "$libname" "yes"
+      libobjs+=" $symfileobj"
+      test "X$libobjs" = "X " && libobjs=
+
+      if test "$opt_mode" != relink; then
+	# Remove our outputs, but don't remove object files since they
+	# may have been created when compiling PIC objects.
+	removelist=
+	tempremovelist=`$ECHO "$output_objdir/*"`
+	for p in $tempremovelist; do
+	  case $p in
+	    *.$objext | *.gcno)
+	       ;;
+	    $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
+	       if test "X$precious_files_regex" != "X"; then
+		 if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
+		 then
+		   continue
+		 fi
+	       fi
+	       removelist+=" $p"
+	       ;;
+	    *) ;;
+	  esac
+	done
+	test -n "$removelist" && \
+	  func_show_eval "${RM}r \$removelist"
+      fi
+
+      # Now set the variables for building old libraries.
+      if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+	oldlibs+=" $output_objdir/$libname.$libext"
+
+	# Transform .lo files to .o files.
+	oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP`
+      fi
+
+      # Eliminate all temporary directories.
+      #for path in $notinst_path; do
+      #	lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"`
+      #	deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"`
+      #	dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"`
+      #done
+
+      if test -n "$xrpath"; then
+	# If the user specified any rpath flags, then add them.
+	temp_xrpath=
+	for libdir in $xrpath; do
+	  func_replace_sysroot "$libdir"
+	  temp_xrpath+=" -R$func_replace_sysroot_result"
+	  case "$finalize_rpath " in
+	  *" $libdir "*) ;;
+	  *) finalize_rpath+=" $libdir" ;;
+	  esac
+	done
+	if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
+	  dependency_libs="$temp_xrpath $dependency_libs"
+	fi
+      fi
+
+      # Make sure dlfiles contains only unique files that won't be dlpreopened
+      old_dlfiles="$dlfiles"
+      dlfiles=
+      for lib in $old_dlfiles; do
+	case " $dlprefiles $dlfiles " in
+	*" $lib "*) ;;
+	*) dlfiles+=" $lib" ;;
+	esac
+      done
+
+      # Make sure dlprefiles contains only unique files
+      old_dlprefiles="$dlprefiles"
+      dlprefiles=
+      for lib in $old_dlprefiles; do
+	case "$dlprefiles " in
+	*" $lib "*) ;;
+	*) dlprefiles+=" $lib" ;;
+	esac
+      done
+
+      if test "$build_libtool_libs" = yes; then
+	if test -n "$rpath"; then
+	  case $host in
+	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*)
+	    # these systems don't actually have a c library (as such)!
+	    ;;
+	  *-*-rhapsody* | *-*-darwin1.[012])
+	    # Rhapsody C library is in the System framework
+	    deplibs+=" System.ltframework"
+	    ;;
+	  *-*-netbsd*)
+	    # Don't link with libc until the a.out ld.so is fixed.
+	    ;;
+	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+	    # Do not include libc due to us having libc/libc_r.
+	    ;;
+	  *-*-sco3.2v5* | *-*-sco5v6*)
+	    # Causes problems with __ctype
+	    ;;
+	  *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+	    # Compiler inserts libc in the correct place for threads to work
+	    ;;
+	  *)
+	    # Add libc to deplibs on all other systems if necessary.
+	    if test "$build_libtool_need_lc" = "yes"; then
+	      deplibs+=" -lc"
+	    fi
+	    ;;
+	  esac
+	fi
+
+	# Transform deplibs into only deplibs that can be linked in shared.
+	name_save=$name
+	libname_save=$libname
+	release_save=$release
+	versuffix_save=$versuffix
+	major_save=$major
+	# I'm not sure if I'm treating the release correctly.  I think
+	# release should show up in the -l (ie -lgmp5) so we don't want to
+	# add it in twice.  Is that correct?
+	release=""
+	versuffix=""
+	major=""
+	newdeplibs=
+	droppeddeps=no
+	case $deplibs_check_method in
+	pass_all)
+	  # Don't check for shared/static.  Everything works.
+	  # This might be a little naive.  We might want to check
+	  # whether the library exists or not.  But this is on
+	  # osf3 & osf4 and I'm not really sure... Just
+	  # implementing what was already the behavior.
+	  newdeplibs=$deplibs
+	  ;;
+	test_compile)
+	  # This code stresses the "libraries are programs" paradigm to its
+	  # limits. Maybe even breaks it.  We compile a program, linking it
+	  # against the deplibs as a proxy for the library.  Then we can check
+	  # whether they linked in statically or dynamically with ldd.
+	  $opt_dry_run || $RM conftest.c
+	  cat > conftest.c <<EOF
+	  int main() { return 0; }
+EOF
+	  $opt_dry_run || $RM conftest
+	  if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
+	    ldd_output=`ldd conftest`
+	    for i in $deplibs; do
+	      case $i in
+	      -l*)
+		func_stripname -l '' "$i"
+		name=$func_stripname_result
+		if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		  case " $predeps $postdeps " in
+		  *" $i "*)
+		    newdeplibs+=" $i"
+		    i=""
+		    ;;
+		  esac
+		fi
+		if test -n "$i" ; then
+		  libname=`eval "\\$ECHO \"$libname_spec\""`
+		  deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+		  set dummy $deplib_matches; shift
+		  deplib_match=$1
+		  if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+		    newdeplibs+=" $i"
+		  else
+		    droppeddeps=yes
+		    echo
+		    $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+		    echo "*** I have the capability to make that library automatically link in when"
+		    echo "*** you link to this library.  But I can only do this if you have a"
+		    echo "*** shared version of the library, which I believe you do not have"
+		    echo "*** because a test_compile did reveal that the linker did not use it for"
+		    echo "*** its dynamic dependency list that programs get resolved with at runtime."
+		  fi
+		fi
+		;;
+	      *)
+		newdeplibs+=" $i"
+		;;
+	      esac
+	    done
+	  else
+	    # Error occurred in the first compile.  Let's try to salvage
+	    # the situation: Compile a separate program for each library.
+	    for i in $deplibs; do
+	      case $i in
+	      -l*)
+		func_stripname -l '' "$i"
+		name=$func_stripname_result
+		$opt_dry_run || $RM conftest
+		if $LTCC $LTCFLAGS -o conftest conftest.c $i; then
+		  ldd_output=`ldd conftest`
+		  if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		    case " $predeps $postdeps " in
+		    *" $i "*)
+		      newdeplibs+=" $i"
+		      i=""
+		      ;;
+		    esac
+		  fi
+		  if test -n "$i" ; then
+		    libname=`eval "\\$ECHO \"$libname_spec\""`
+		    deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+		    set dummy $deplib_matches; shift
+		    deplib_match=$1
+		    if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+		      newdeplibs+=" $i"
+		    else
+		      droppeddeps=yes
+		      echo
+		      $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+		      echo "*** I have the capability to make that library automatically link in when"
+		      echo "*** you link to this library.  But I can only do this if you have a"
+		      echo "*** shared version of the library, which you do not appear to have"
+		      echo "*** because a test_compile did reveal that the linker did not use this one"
+		      echo "*** as a dynamic dependency that programs can get resolved with at runtime."
+		    fi
+		  fi
+		else
+		  droppeddeps=yes
+		  echo
+		  $ECHO "*** Warning!  Library $i is needed by this library but I was not able to"
+		  echo "*** make it link in!  You will probably need to install it or some"
+		  echo "*** library that it depends on before this library will be fully"
+		  echo "*** functional.  Installing it before continuing would be even better."
+		fi
+		;;
+	      *)
+		newdeplibs+=" $i"
+		;;
+	      esac
+	    done
+	  fi
+	  ;;
+	file_magic*)
+	  set dummy $deplibs_check_method; shift
+	  file_magic_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+	  for a_deplib in $deplibs; do
+	    case $a_deplib in
+	    -l*)
+	      func_stripname -l '' "$a_deplib"
+	      name=$func_stripname_result
+	      if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		case " $predeps $postdeps " in
+		*" $a_deplib "*)
+		  newdeplibs+=" $a_deplib"
+		  a_deplib=""
+		  ;;
+		esac
+	      fi
+	      if test -n "$a_deplib" ; then
+		libname=`eval "\\$ECHO \"$libname_spec\""`
+		if test -n "$file_magic_glob"; then
+		  libnameglob=`func_echo_all "$libname" | $SED -e $file_magic_glob`
+		else
+		  libnameglob=$libname
+		fi
+		test "$want_nocaseglob" = yes && nocaseglob=`shopt -p nocaseglob`
+		for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+		  if test "$want_nocaseglob" = yes; then
+		    shopt -s nocaseglob
+		    potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null`
+		    $nocaseglob
+		  else
+		    potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null`
+		  fi
+		  for potent_lib in $potential_libs; do
+		      # Follow soft links.
+		      if ls -lLd "$potent_lib" 2>/dev/null |
+			 $GREP " -> " >/dev/null; then
+			continue
+		      fi
+		      # The statement above tries to avoid entering an
+		      # endless loop below, in case of cyclic links.
+		      # We might still enter an endless loop, since a link
+		      # loop can be closed while we follow links,
+		      # but so what?
+		      potlib="$potent_lib"
+		      while test -h "$potlib" 2>/dev/null; do
+			potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
+			case $potliblink in
+			[\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+			*) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";;
+			esac
+		      done
+		      if eval $file_magic_cmd \"\$potlib\" 2>/dev/null |
+			 $SED -e 10q |
+			 $EGREP "$file_magic_regex" > /dev/null; then
+			newdeplibs+=" $a_deplib"
+			a_deplib=""
+			break 2
+		      fi
+		  done
+		done
+	      fi
+	      if test -n "$a_deplib" ; then
+		droppeddeps=yes
+		echo
+		$ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+		echo "*** I have the capability to make that library automatically link in when"
+		echo "*** you link to this library.  But I can only do this if you have a"
+		echo "*** shared version of the library, which you do not appear to have"
+		echo "*** because I did check the linker path looking for a file starting"
+		if test -z "$potlib" ; then
+		  $ECHO "*** with $libname but no candidates were found. (...for file magic test)"
+		else
+		  $ECHO "*** with $libname and none of the candidates passed a file format test"
+		  $ECHO "*** using a file magic. Last file checked: $potlib"
+		fi
+	      fi
+	      ;;
+	    *)
+	      # Add a -L argument.
+	      newdeplibs+=" $a_deplib"
+	      ;;
+	    esac
+	  done # Gone through all deplibs.
+	  ;;
+	match_pattern*)
+	  set dummy $deplibs_check_method; shift
+	  match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+	  for a_deplib in $deplibs; do
+	    case $a_deplib in
+	    -l*)
+	      func_stripname -l '' "$a_deplib"
+	      name=$func_stripname_result
+	      if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		case " $predeps $postdeps " in
+		*" $a_deplib "*)
+		  newdeplibs+=" $a_deplib"
+		  a_deplib=""
+		  ;;
+		esac
+	      fi
+	      if test -n "$a_deplib" ; then
+		libname=`eval "\\$ECHO \"$libname_spec\""`
+		for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+		  potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+		  for potent_lib in $potential_libs; do
+		    potlib="$potent_lib" # see symlink-check above in file_magic test
+		    if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \
+		       $EGREP "$match_pattern_regex" > /dev/null; then
+		      newdeplibs+=" $a_deplib"
+		      a_deplib=""
+		      break 2
+		    fi
+		  done
+		done
+	      fi
+	      if test -n "$a_deplib" ; then
+		droppeddeps=yes
+		echo
+		$ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+		echo "*** I have the capability to make that library automatically link in when"
+		echo "*** you link to this library.  But I can only do this if you have a"
+		echo "*** shared version of the library, which you do not appear to have"
+		echo "*** because I did check the linker path looking for a file starting"
+		if test -z "$potlib" ; then
+		  $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)"
+		else
+		  $ECHO "*** with $libname and none of the candidates passed a file format test"
+		  $ECHO "*** using a regex pattern. Last file checked: $potlib"
+		fi
+	      fi
+	      ;;
+	    *)
+	      # Add a -L argument.
+	      newdeplibs+=" $a_deplib"
+	      ;;
+	    esac
+	  done # Gone through all deplibs.
+	  ;;
+	none | unknown | *)
+	  newdeplibs=""
+	  tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'`
+	  if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+	    for i in $predeps $postdeps ; do
+	      # can't use Xsed below, because $i might contain '/'
+	      tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"`
+	    done
+	  fi
+	  case $tmp_deplibs in
+	  *[!\	\ ]*)
+	    echo
+	    if test "X$deplibs_check_method" = "Xnone"; then
+	      echo "*** Warning: inter-library dependencies are not supported in this platform."
+	    else
+	      echo "*** Warning: inter-library dependencies are not known to be supported."
+	    fi
+	    echo "*** All declared inter-library dependencies are being dropped."
+	    droppeddeps=yes
+	    ;;
+	  esac
+	  ;;
+	esac
+	versuffix=$versuffix_save
+	major=$major_save
+	release=$release_save
+	libname=$libname_save
+	name=$name_save
+
+	case $host in
+	*-*-rhapsody* | *-*-darwin1.[012])
+	  # On Rhapsody replace the C library with the System framework
+	  newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'`
+	  ;;
+	esac
+
+	if test "$droppeddeps" = yes; then
+	  if test "$module" = yes; then
+	    echo
+	    echo "*** Warning: libtool could not satisfy all declared inter-library"
+	    $ECHO "*** dependencies of module $libname.  Therefore, libtool will create"
+	    echo "*** a static module, that should work as long as the dlopening"
+	    echo "*** application is linked with the -dlopen flag."
+	    if test -z "$global_symbol_pipe"; then
+	      echo
+	      echo "*** However, this would only work if libtool was able to extract symbol"
+	      echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+	      echo "*** not find such a program.  So, this module is probably useless."
+	      echo "*** \`nm' from GNU binutils and a full rebuild may help."
+	    fi
+	    if test "$build_old_libs" = no; then
+	      oldlibs="$output_objdir/$libname.$libext"
+	      build_libtool_libs=module
+	      build_old_libs=yes
+	    else
+	      build_libtool_libs=no
+	    fi
+	  else
+	    echo "*** The inter-library dependencies that have been dropped here will be"
+	    echo "*** automatically added whenever a program is linked with this library"
+	    echo "*** or is declared to -dlopen it."
+
+	    if test "$allow_undefined" = no; then
+	      echo
+	      echo "*** Since this library must not contain undefined symbols,"
+	      echo "*** because either the platform does not support them or"
+	      echo "*** it was explicitly requested with -no-undefined,"
+	      echo "*** libtool will only create a static version of it."
+	      if test "$build_old_libs" = no; then
+		oldlibs="$output_objdir/$libname.$libext"
+		build_libtool_libs=module
+		build_old_libs=yes
+	      else
+		build_libtool_libs=no
+	      fi
+	    fi
+	  fi
+	fi
+	# Done checking deplibs!
+	deplibs=$newdeplibs
+      fi
+      # Time to change all our "foo.ltframework" stuff back to "-framework foo"
+      case $host in
+	*-*-darwin*)
+	  newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  ;;
+      esac
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+	case " $new_libs " in
+	*" -L$path/$objdir "*) ;;
+	*)
+	  case " $deplibs " in
+	  *" -L$path/$objdir "*)
+	    new_libs+=" -L$path/$objdir" ;;
+	  esac
+	  ;;
+	esac
+      done
+      for deplib in $deplibs; do
+	case $deplib in
+	-L*)
+	  case " $new_libs " in
+	  *" $deplib "*) ;;
+	  *) new_libs+=" $deplib" ;;
+	  esac
+	  ;;
+	*) new_libs+=" $deplib" ;;
+	esac
+      done
+      deplibs="$new_libs"
+
+      # All the library-specific variables (install_libdir is set above).
+      library_names=
+      old_library=
+      dlname=
+
+      # Test again, we may have decided not to build it any more
+      if test "$build_libtool_libs" = yes; then
+	# Remove ${wl} instances when linking with ld.
+	# FIXME: should test the right _cmds variable.
+	case $archive_cmds in
+	  *\$LD\ *) wl= ;;
+        esac
+	if test "$hardcode_into_libs" = yes; then
+	  # Hardcode the library paths
+	  hardcode_libdirs=
+	  dep_rpath=
+	  rpath="$finalize_rpath"
+	  test "$opt_mode" != relink && rpath="$compile_rpath$rpath"
+	  for libdir in $rpath; do
+	    if test -n "$hardcode_libdir_flag_spec"; then
+	      if test -n "$hardcode_libdir_separator"; then
+		func_replace_sysroot "$libdir"
+		libdir=$func_replace_sysroot_result
+		if test -z "$hardcode_libdirs"; then
+		  hardcode_libdirs="$libdir"
+		else
+		  # Just accumulate the unique libdirs.
+		  case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+		  *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		    ;;
+		  *)
+		    hardcode_libdirs+="$hardcode_libdir_separator$libdir"
+		    ;;
+		  esac
+		fi
+	      else
+		eval flag=\"$hardcode_libdir_flag_spec\"
+		dep_rpath+=" $flag"
+	      fi
+	    elif test -n "$runpath_var"; then
+	      case "$perm_rpath " in
+	      *" $libdir "*) ;;
+	      *) perm_rpath+=" $libdir" ;;
+	      esac
+	    fi
+	  done
+	  # Substitute the hardcoded libdirs into the rpath.
+	  if test -n "$hardcode_libdir_separator" &&
+	     test -n "$hardcode_libdirs"; then
+	    libdir="$hardcode_libdirs"
+	    eval "dep_rpath=\"$hardcode_libdir_flag_spec\""
+	  fi
+	  if test -n "$runpath_var" && test -n "$perm_rpath"; then
+	    # We should set the runpath_var.
+	    rpath=
+	    for dir in $perm_rpath; do
+	      rpath+="$dir:"
+	    done
+	    eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
+	  fi
+	  test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+	fi
+
+	shlibpath="$finalize_shlibpath"
+	test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
+	if test -n "$shlibpath"; then
+	  eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
+	fi
+
+	# Get the real and link names of the library.
+	eval shared_ext=\"$shrext_cmds\"
+	eval library_names=\"$library_names_spec\"
+	set dummy $library_names
+	shift
+	realname="$1"
+	shift
+
+	if test -n "$soname_spec"; then
+	  eval soname=\"$soname_spec\"
+	else
+	  soname="$realname"
+	fi
+	if test -z "$dlname"; then
+	  dlname=$soname
+	fi
+
+	lib="$output_objdir/$realname"
+	linknames=
+	for link
+	do
+	  linknames+=" $link"
+	done
+
+	# Use standard objects if they are pic
+	test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP`
+	test "X$libobjs" = "X " && libobjs=
+
+	delfiles=
+	if test -n "$export_symbols" && test -n "$include_expsyms"; then
+	  $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp"
+	  export_symbols="$output_objdir/$libname.uexp"
+	  delfiles+=" $export_symbols"
+	fi
+
+	orig_export_symbols=
+	case $host_os in
+	cygwin* | mingw* | cegcc*)
+	  if test -n "$export_symbols" && test -z "$export_symbols_regex"; then
+	    # exporting using user supplied symfile
+	    if test "x`$SED 1q $export_symbols`" != xEXPORTS; then
+	      # and it's NOT already a .def file. Must figure out
+	      # which of the given symbols are data symbols and tag
+	      # them as such. So, trigger use of export_symbols_cmds.
+	      # export_symbols gets reassigned inside the "prepare
+	      # the list of exported symbols" if statement, so the
+	      # include_expsyms logic still works.
+	      orig_export_symbols="$export_symbols"
+	      export_symbols=
+	      always_export_symbols=yes
+	    fi
+	  fi
+	  ;;
+	esac
+
+	# Prepare the list of exported symbols
+	if test -z "$export_symbols"; then
+	  if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+	    func_verbose "generating symbol list for \`$libname.la'"
+	    export_symbols="$output_objdir/$libname.exp"
+	    $opt_dry_run || $RM $export_symbols
+	    cmds=$export_symbols_cmds
+	    save_ifs="$IFS"; IFS='~'
+	    for cmd1 in $cmds; do
+	      IFS="$save_ifs"
+	      # Take the normal branch if the nm_file_list_spec branch
+	      # doesn't work or if tool conversion is not needed.
+	      case $nm_file_list_spec~$to_tool_file_cmd in
+		*~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*)
+		  try_normal_branch=yes
+		  eval cmd=\"$cmd1\"
+		  func_len " $cmd"
+		  len=$func_len_result
+		  ;;
+		*)
+		  try_normal_branch=no
+		  ;;
+	      esac
+	      if test "$try_normal_branch" = yes \
+		 && { test "$len" -lt "$max_cmd_len" \
+		      || test "$max_cmd_len" -le -1; }
+	      then
+		func_show_eval "$cmd" 'exit $?'
+		skipped_export=false
+	      elif test -n "$nm_file_list_spec"; then
+		func_basename "$output"
+		output_la=$func_basename_result
+		save_libobjs=$libobjs
+		save_output=$output
+		output=${output_objdir}/${output_la}.nm
+		func_to_tool_file "$output"
+		libobjs=$nm_file_list_spec$func_to_tool_file_result
+		delfiles+=" $output"
+		func_verbose "creating $NM input file list: $output"
+		for obj in $save_libobjs; do
+		  func_to_tool_file "$obj"
+		  $ECHO "$func_to_tool_file_result"
+		done > "$output"
+		eval cmd=\"$cmd1\"
+		func_show_eval "$cmd" 'exit $?'
+		output=$save_output
+		libobjs=$save_libobjs
+		skipped_export=false
+	      else
+		# The command line is too long to execute in one step.
+		func_verbose "using reloadable object file for export list..."
+		skipped_export=:
+		# Break out early, otherwise skipped_export may be
+		# set to false by a later but shorter cmd.
+		break
+	      fi
+	    done
+	    IFS="$save_ifs"
+	    if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then
+	      func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+	      func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+	    fi
+	  fi
+	fi
+
+	if test -n "$export_symbols" && test -n "$include_expsyms"; then
+	  tmp_export_symbols="$export_symbols"
+	  test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
+	  $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"'
+	fi
+
+	if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then
+	  # The given exports_symbols file has to be filtered, so filter it.
+	  func_verbose "filter symbol list for \`$libname.la' to tag DATA exports"
+	  # FIXME: $output_objdir/$libname.filter potentially contains lots of
+	  # 's' commands which not all seds can handle. GNU sed should be fine
+	  # though. Also, the filter scales superlinearly with the number of
+	  # global variables. join(1) would be nice here, but unfortunately
+	  # isn't a blessed tool.
+	  $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+	  delfiles+=" $export_symbols $output_objdir/$libname.filter"
+	  export_symbols=$output_objdir/$libname.def
+	  $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+	fi
+
+	tmp_deplibs=
+	for test_deplib in $deplibs; do
+	  case " $convenience " in
+	  *" $test_deplib "*) ;;
+	  *)
+	    tmp_deplibs+=" $test_deplib"
+	    ;;
+	  esac
+	done
+	deplibs="$tmp_deplibs"
+
+	if test -n "$convenience"; then
+	  if test -n "$whole_archive_flag_spec" &&
+	    test "$compiler_needs_object" = yes &&
+	    test -z "$libobjs"; then
+	    # extract the archives, so we have objects to list.
+	    # TODO: could optimize this to just extract one archive.
+	    whole_archive_flag_spec=
+	  fi
+	  if test -n "$whole_archive_flag_spec"; then
+	    save_libobjs=$libobjs
+	    eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+	    test "X$libobjs" = "X " && libobjs=
+	  else
+	    gentop="$output_objdir/${outputname}x"
+	    generated+=" $gentop"
+
+	    func_extract_archives $gentop $convenience
+	    libobjs+=" $func_extract_archives_result"
+	    test "X$libobjs" = "X " && libobjs=
+	  fi
+	fi
+
+	if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+	  eval flag=\"$thread_safe_flag_spec\"
+	  linker_flags+=" $flag"
+	fi
+
+	# Make a backup of the uninstalled library when relinking
+	if test "$opt_mode" = relink; then
+	  $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $?
+	fi
+
+	# Do each of the archive commands.
+	if test "$module" = yes && test -n "$module_cmds" ; then
+	  if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+	    eval test_cmds=\"$module_expsym_cmds\"
+	    cmds=$module_expsym_cmds
+	  else
+	    eval test_cmds=\"$module_cmds\"
+	    cmds=$module_cmds
+	  fi
+	else
+	  if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+	    eval test_cmds=\"$archive_expsym_cmds\"
+	    cmds=$archive_expsym_cmds
+	  else
+	    eval test_cmds=\"$archive_cmds\"
+	    cmds=$archive_cmds
+	  fi
+	fi
+
+	if test "X$skipped_export" != "X:" &&
+	   func_len " $test_cmds" &&
+	   len=$func_len_result &&
+	   test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+	  :
+	else
+	  # The command line is too long to link in one step, link piecewise
+	  # or, if using GNU ld and skipped_export is not :, use a linker
+	  # script.
+
+	  # Save the value of $output and $libobjs because we want to
+	  # use them later.  If we have whole_archive_flag_spec, we
+	  # want to use save_libobjs as it was before
+	  # whole_archive_flag_spec was expanded, because we can't
+	  # assume the linker understands whole_archive_flag_spec.
+	  # This may have to be revisited, in case too many
+	  # convenience libraries get linked in and end up exceeding
+	  # the spec.
+	  if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
+	    save_libobjs=$libobjs
+	  fi
+	  save_output=$output
+	  func_basename "$output"
+	  output_la=$func_basename_result
+
+	  # Clear the reloadable object creation command queue and
+	  # initialize k to one.
+	  test_cmds=
+	  concat_cmds=
+	  objlist=
+	  last_robj=
+	  k=1
+
+	  if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then
+	    output=${output_objdir}/${output_la}.lnkscript
+	    func_verbose "creating GNU ld script: $output"
+	    echo 'INPUT (' > $output
+	    for obj in $save_libobjs
+	    do
+	      func_to_tool_file "$obj"
+	      $ECHO "$func_to_tool_file_result" >> $output
+	    done
+	    echo ')' >> $output
+	    delfiles+=" $output"
+	    func_to_tool_file "$output"
+	    output=$func_to_tool_file_result
+	  elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then
+	    output=${output_objdir}/${output_la}.lnk
+	    func_verbose "creating linker input file list: $output"
+	    : > $output
+	    set x $save_libobjs
+	    shift
+	    firstobj=
+	    if test "$compiler_needs_object" = yes; then
+	      firstobj="$1 "
+	      shift
+	    fi
+	    for obj
+	    do
+	      func_to_tool_file "$obj"
+	      $ECHO "$func_to_tool_file_result" >> $output
+	    done
+	    delfiles+=" $output"
+	    func_to_tool_file "$output"
+	    output=$firstobj\"$file_list_spec$func_to_tool_file_result\"
+	  else
+	    if test -n "$save_libobjs"; then
+	      func_verbose "creating reloadable object files..."
+	      output=$output_objdir/$output_la-${k}.$objext
+	      eval test_cmds=\"$reload_cmds\"
+	      func_len " $test_cmds"
+	      len0=$func_len_result
+	      len=$len0
+
+	      # Loop over the list of objects to be linked.
+	      for obj in $save_libobjs
+	      do
+		func_len " $obj"
+		func_arith $len + $func_len_result
+		len=$func_arith_result
+		if test "X$objlist" = X ||
+		   test "$len" -lt "$max_cmd_len"; then
+		  objlist+=" $obj"
+		else
+		  # The command $test_cmds is almost too long, add a
+		  # command to the queue.
+		  if test "$k" -eq 1 ; then
+		    # The first file doesn't have a previous command to add.
+		    reload_objs=$objlist
+		    eval concat_cmds=\"$reload_cmds\"
+		  else
+		    # All subsequent reloadable object files will link in
+		    # the last one created.
+		    reload_objs="$objlist $last_robj"
+		    eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\"
+		  fi
+		  last_robj=$output_objdir/$output_la-${k}.$objext
+		  func_arith $k + 1
+		  k=$func_arith_result
+		  output=$output_objdir/$output_la-${k}.$objext
+		  objlist=" $obj"
+		  func_len " $last_robj"
+		  func_arith $len0 + $func_len_result
+		  len=$func_arith_result
+		fi
+	      done
+	      # Handle the remaining objects by creating one last
+	      # reloadable object file.  All subsequent reloadable object
+	      # files will link in the last one created.
+	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	      reload_objs="$objlist $last_robj"
+	      eval concat_cmds=\"\${concat_cmds}$reload_cmds\"
+	      if test -n "$last_robj"; then
+	        eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\"
+	      fi
+	      delfiles+=" $output"
+
+	    else
+	      output=
+	    fi
+
+	    if ${skipped_export-false}; then
+	      func_verbose "generating symbol list for \`$libname.la'"
+	      export_symbols="$output_objdir/$libname.exp"
+	      $opt_dry_run || $RM $export_symbols
+	      libobjs=$output
+	      # Append the command to create the export file.
+	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	      eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\"
+	      if test -n "$last_robj"; then
+		eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\"
+	      fi
+	    fi
+
+	    test -n "$save_libobjs" &&
+	      func_verbose "creating a temporary reloadable object file: $output"
+
+	    # Loop through the commands generated above and execute them.
+	    save_ifs="$IFS"; IFS='~'
+	    for cmd in $concat_cmds; do
+	      IFS="$save_ifs"
+	      $opt_silent || {
+		  func_quote_for_expand "$cmd"
+		  eval "func_echo $func_quote_for_expand_result"
+	      }
+	      $opt_dry_run || eval "$cmd" || {
+		lt_exit=$?
+
+		# Restore the uninstalled library and exit
+		if test "$opt_mode" = relink; then
+		  ( cd "$output_objdir" && \
+		    $RM "${realname}T" && \
+		    $MV "${realname}U" "$realname" )
+		fi
+
+		exit $lt_exit
+	      }
+	    done
+	    IFS="$save_ifs"
+
+	    if test -n "$export_symbols_regex" && ${skipped_export-false}; then
+	      func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+	      func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+	    fi
+	  fi
+
+          if ${skipped_export-false}; then
+	    if test -n "$export_symbols" && test -n "$include_expsyms"; then
+	      tmp_export_symbols="$export_symbols"
+	      test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
+	      $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"'
+	    fi
+
+	    if test -n "$orig_export_symbols"; then
+	      # The given exports_symbols file has to be filtered, so filter it.
+	      func_verbose "filter symbol list for \`$libname.la' to tag DATA exports"
+	      # FIXME: $output_objdir/$libname.filter potentially contains lots of
+	      # 's' commands which not all seds can handle. GNU sed should be fine
+	      # though. Also, the filter scales superlinearly with the number of
+	      # global variables. join(1) would be nice here, but unfortunately
+	      # isn't a blessed tool.
+	      $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+	      delfiles+=" $export_symbols $output_objdir/$libname.filter"
+	      export_symbols=$output_objdir/$libname.def
+	      $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+	    fi
+	  fi
+
+	  libobjs=$output
+	  # Restore the value of output.
+	  output=$save_output
+
+	  if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
+	    eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+	    test "X$libobjs" = "X " && libobjs=
+	  fi
+	  # Expand the library linking commands again to reset the
+	  # value of $libobjs for piecewise linking.
+
+	  # Do each of the archive commands.
+	  if test "$module" = yes && test -n "$module_cmds" ; then
+	    if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+	      cmds=$module_expsym_cmds
+	    else
+	      cmds=$module_cmds
+	    fi
+	  else
+	    if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+	      cmds=$archive_expsym_cmds
+	    else
+	      cmds=$archive_cmds
+	    fi
+	  fi
+	fi
+
+	if test -n "$delfiles"; then
+	  # Append the command to remove temporary files to $cmds.
+	  eval cmds=\"\$cmds~\$RM $delfiles\"
+	fi
+
+	# Add any objects from preloaded convenience libraries
+	if test -n "$dlprefiles"; then
+	  gentop="$output_objdir/${outputname}x"
+	  generated+=" $gentop"
+
+	  func_extract_archives $gentop $dlprefiles
+	  libobjs+=" $func_extract_archives_result"
+	  test "X$libobjs" = "X " && libobjs=
+	fi
+
+	save_ifs="$IFS"; IFS='~'
+	for cmd in $cmds; do
+	  IFS="$save_ifs"
+	  eval cmd=\"$cmd\"
+	  $opt_silent || {
+	    func_quote_for_expand "$cmd"
+	    eval "func_echo $func_quote_for_expand_result"
+	  }
+	  $opt_dry_run || eval "$cmd" || {
+	    lt_exit=$?
+
+	    # Restore the uninstalled library and exit
+	    if test "$opt_mode" = relink; then
+	      ( cd "$output_objdir" && \
+	        $RM "${realname}T" && \
+		$MV "${realname}U" "$realname" )
+	    fi
+
+	    exit $lt_exit
+	  }
+	done
+	IFS="$save_ifs"
+
+	# Restore the uninstalled library and exit
+	if test "$opt_mode" = relink; then
+	  $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $?
+
+	  if test -n "$convenience"; then
+	    if test -z "$whole_archive_flag_spec"; then
+	      func_show_eval '${RM}r "$gentop"'
+	    fi
+	  fi
+
+	  exit $EXIT_SUCCESS
+	fi
+
+	# Create links to the real library.
+	for linkname in $linknames; do
+	  if test "$realname" != "$linkname"; then
+	    func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?'
+	  fi
+	done
+
+	# If -module or -export-dynamic was specified, set the dlname.
+	if test "$module" = yes || test "$export_dynamic" = yes; then
+	  # On all known operating systems, these are identical.
+	  dlname="$soname"
+	fi
+      fi
+      ;;
+
+    obj)
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+	func_warning "\`-dlopen' is ignored for objects"
+      fi
+
+      case " $deplibs" in
+      *\ -l* | *\ -L*)
+	func_warning "\`-l' and \`-L' are ignored for objects" ;;
+      esac
+
+      test -n "$rpath" && \
+	func_warning "\`-rpath' is ignored for objects"
+
+      test -n "$xrpath" && \
+	func_warning "\`-R' is ignored for objects"
+
+      test -n "$vinfo" && \
+	func_warning "\`-version-info' is ignored for objects"
+
+      test -n "$release" && \
+	func_warning "\`-release' is ignored for objects"
+
+      case $output in
+      *.lo)
+	test -n "$objs$old_deplibs" && \
+	  func_fatal_error "cannot build library object \`$output' from non-libtool objects"
+
+	libobj=$output
+	func_lo2o "$libobj"
+	obj=$func_lo2o_result
+	;;
+      *)
+	libobj=
+	obj="$output"
+	;;
+      esac
+
+      # Delete the old objects.
+      $opt_dry_run || $RM $obj $libobj
+
+      # Objects from convenience libraries.  This assumes
+      # single-version convenience libraries.  Whenever we create
+      # different ones for PIC/non-PIC, this we'll have to duplicate
+      # the extraction.
+      reload_conv_objs=
+      gentop=
+      # reload_cmds runs $LD directly, so let us get rid of
+      # -Wl from whole_archive_flag_spec and hope we can get by with
+      # turning comma into space..
+      wl=
+
+      if test -n "$convenience"; then
+	if test -n "$whole_archive_flag_spec"; then
+	  eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
+	  reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'`
+	else
+	  gentop="$output_objdir/${obj}x"
+	  generated+=" $gentop"
+
+	  func_extract_archives $gentop $convenience
+	  reload_conv_objs="$reload_objs $func_extract_archives_result"
+	fi
+      fi
+
+      # If we're not building shared, we need to use non_pic_objs
+      test "$build_libtool_libs" != yes && libobjs="$non_pic_objects"
+
+      # Create the old-style object.
+      reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
+
+      output="$obj"
+      func_execute_cmds "$reload_cmds" 'exit $?'
+
+      # Exit if we aren't doing a library object file.
+      if test -z "$libobj"; then
+	if test -n "$gentop"; then
+	  func_show_eval '${RM}r "$gentop"'
+	fi
+
+	exit $EXIT_SUCCESS
+      fi
+
+      if test "$build_libtool_libs" != yes; then
+	if test -n "$gentop"; then
+	  func_show_eval '${RM}r "$gentop"'
+	fi
+
+	# Create an invalid libtool object if no PIC, so that we don't
+	# accidentally link it into a program.
+	# $show "echo timestamp > $libobj"
+	# $opt_dry_run || eval "echo timestamp > $libobj" || exit $?
+	exit $EXIT_SUCCESS
+      fi
+
+      if test -n "$pic_flag" || test "$pic_mode" != default; then
+	# Only do commands if we really have different PIC objects.
+	reload_objs="$libobjs $reload_conv_objs"
+	output="$libobj"
+	func_execute_cmds "$reload_cmds" 'exit $?'
+      fi
+
+      if test -n "$gentop"; then
+	func_show_eval '${RM}r "$gentop"'
+      fi
+
+      exit $EXIT_SUCCESS
+      ;;
+
+    prog)
+      case $host in
+	*cygwin*) func_stripname '' '.exe' "$output"
+	          output=$func_stripname_result.exe;;
+      esac
+      test -n "$vinfo" && \
+	func_warning "\`-version-info' is ignored for programs"
+
+      test -n "$release" && \
+	func_warning "\`-release' is ignored for programs"
+
+      test "$preload" = yes \
+        && test "$dlopen_support" = unknown \
+	&& test "$dlopen_self" = unknown \
+	&& test "$dlopen_self_static" = unknown && \
+	  func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support."
+
+      case $host in
+      *-*-rhapsody* | *-*-darwin1.[012])
+	# On Rhapsody replace the C library is the System framework
+	compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'`
+	finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'`
+	;;
+      esac
+
+      case $host in
+      *-*-darwin*)
+	# Don't allow lazy linking, it breaks C++ global constructors
+	# But is supposedly fixed on 10.4 or later (yay!).
+	if test "$tagname" = CXX ; then
+	  case ${MACOSX_DEPLOYMENT_TARGET-10.0} in
+	    10.[0123])
+	      compile_command+=" ${wl}-bind_at_load"
+	      finalize_command+=" ${wl}-bind_at_load"
+	    ;;
+	  esac
+	fi
+	# Time to change all our "foo.ltframework" stuff back to "-framework foo"
+	compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	;;
+      esac
+
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+	case " $new_libs " in
+	*" -L$path/$objdir "*) ;;
+	*)
+	  case " $compile_deplibs " in
+	  *" -L$path/$objdir "*)
+	    new_libs+=" -L$path/$objdir" ;;
+	  esac
+	  ;;
+	esac
+      done
+      for deplib in $compile_deplibs; do
+	case $deplib in
+	-L*)
+	  case " $new_libs " in
+	  *" $deplib "*) ;;
+	  *) new_libs+=" $deplib" ;;
+	  esac
+	  ;;
+	*) new_libs+=" $deplib" ;;
+	esac
+      done
+      compile_deplibs="$new_libs"
+
+
+      compile_command+=" $compile_deplibs"
+      finalize_command+=" $finalize_deplibs"
+
+      if test -n "$rpath$xrpath"; then
+	# If the user specified any rpath flags, then add them.
+	for libdir in $rpath $xrpath; do
+	  # This is the magic to use -rpath.
+	  case "$finalize_rpath " in
+	  *" $libdir "*) ;;
+	  *) finalize_rpath+=" $libdir" ;;
+	  esac
+	done
+      fi
+
+      # Now hardcode the library paths
+      rpath=
+      hardcode_libdirs=
+      for libdir in $compile_rpath $finalize_rpath; do
+	if test -n "$hardcode_libdir_flag_spec"; then
+	  if test -n "$hardcode_libdir_separator"; then
+	    if test -z "$hardcode_libdirs"; then
+	      hardcode_libdirs="$libdir"
+	    else
+	      # Just accumulate the unique libdirs.
+	      case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		;;
+	      *)
+		hardcode_libdirs+="$hardcode_libdir_separator$libdir"
+		;;
+	      esac
+	    fi
+	  else
+	    eval flag=\"$hardcode_libdir_flag_spec\"
+	    rpath+=" $flag"
+	  fi
+	elif test -n "$runpath_var"; then
+	  case "$perm_rpath " in
+	  *" $libdir "*) ;;
+	  *) perm_rpath+=" $libdir" ;;
+	  esac
+	fi
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+	  testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'`
+	  case :$dllsearchpath: in
+	  *":$libdir:"*) ;;
+	  ::) dllsearchpath=$libdir;;
+	  *) dllsearchpath+=":$libdir";;
+	  esac
+	  case :$dllsearchpath: in
+	  *":$testbindir:"*) ;;
+	  ::) dllsearchpath=$testbindir;;
+	  *) dllsearchpath+=":$testbindir";;
+	  esac
+	  ;;
+	esac
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+	 test -n "$hardcode_libdirs"; then
+	libdir="$hardcode_libdirs"
+	eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      compile_rpath="$rpath"
+
+      rpath=
+      hardcode_libdirs=
+      for libdir in $finalize_rpath; do
+	if test -n "$hardcode_libdir_flag_spec"; then
+	  if test -n "$hardcode_libdir_separator"; then
+	    if test -z "$hardcode_libdirs"; then
+	      hardcode_libdirs="$libdir"
+	    else
+	      # Just accumulate the unique libdirs.
+	      case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		;;
+	      *)
+		hardcode_libdirs+="$hardcode_libdir_separator$libdir"
+		;;
+	      esac
+	    fi
+	  else
+	    eval flag=\"$hardcode_libdir_flag_spec\"
+	    rpath+=" $flag"
+	  fi
+	elif test -n "$runpath_var"; then
+	  case "$finalize_perm_rpath " in
+	  *" $libdir "*) ;;
+	  *) finalize_perm_rpath+=" $libdir" ;;
+	  esac
+	fi
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+	 test -n "$hardcode_libdirs"; then
+	libdir="$hardcode_libdirs"
+	eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      finalize_rpath="$rpath"
+
+      if test -n "$libobjs" && test "$build_old_libs" = yes; then
+	# Transform all the library objects into standard objects.
+	compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
+	finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
+      fi
+
+      func_generate_dlsyms "$outputname" "@PROGRAM@" "no"
+
+      # template prelinking step
+      if test -n "$prelink_cmds"; then
+	func_execute_cmds "$prelink_cmds" 'exit $?'
+      fi
+
+      wrappers_required=yes
+      case $host in
+      *cegcc* | *mingw32ce*)
+        # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway.
+        wrappers_required=no
+        ;;
+      *cygwin* | *mingw* )
+        if test "$build_libtool_libs" != yes; then
+          wrappers_required=no
+        fi
+        ;;
+      *)
+        if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
+          wrappers_required=no
+        fi
+        ;;
+      esac
+      if test "$wrappers_required" = no; then
+	# Replace the output file specification.
+	compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
+	link_command="$compile_command$compile_rpath"
+
+	# We have no uninstalled library dependencies, so finalize right now.
+	exit_status=0
+	func_show_eval "$link_command" 'exit_status=$?'
+
+	if test -n "$postlink_cmds"; then
+	  func_to_tool_file "$output"
+	  postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
+	  func_execute_cmds "$postlink_cmds" 'exit $?'
+	fi
+
+	# Delete the generated files.
+	if test -f "$output_objdir/${outputname}S.${objext}"; then
+	  func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"'
+	fi
+
+	exit $exit_status
+      fi
+
+      if test -n "$compile_shlibpath$finalize_shlibpath"; then
+	compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+      fi
+      if test -n "$finalize_shlibpath"; then
+	finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+      fi
+
+      compile_var=
+      finalize_var=
+      if test -n "$runpath_var"; then
+	if test -n "$perm_rpath"; then
+	  # We should set the runpath_var.
+	  rpath=
+	  for dir in $perm_rpath; do
+	    rpath+="$dir:"
+	  done
+	  compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+	fi
+	if test -n "$finalize_perm_rpath"; then
+	  # We should set the runpath_var.
+	  rpath=
+	  for dir in $finalize_perm_rpath; do
+	    rpath+="$dir:"
+	  done
+	  finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+	fi
+      fi
+
+      if test "$no_install" = yes; then
+	# We don't need to create a wrapper script.
+	link_command="$compile_var$compile_command$compile_rpath"
+	# Replace the output file specification.
+	link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
+	# Delete the old output file.
+	$opt_dry_run || $RM $output
+	# Link the executable and exit
+	func_show_eval "$link_command" 'exit $?'
+
+	if test -n "$postlink_cmds"; then
+	  func_to_tool_file "$output"
+	  postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
+	  func_execute_cmds "$postlink_cmds" 'exit $?'
+	fi
+
+	exit $EXIT_SUCCESS
+      fi
+
+      if test "$hardcode_action" = relink; then
+	# Fast installation is not supported
+	link_command="$compile_var$compile_command$compile_rpath"
+	relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+	func_warning "this platform does not like uninstalled shared libraries"
+	func_warning "\`$output' will be relinked during installation"
+      else
+	if test "$fast_install" != no; then
+	  link_command="$finalize_var$compile_command$finalize_rpath"
+	  if test "$fast_install" = yes; then
+	    relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'`
+	  else
+	    # fast_install is set to needless
+	    relink_command=
+	  fi
+	else
+	  link_command="$compile_var$compile_command$compile_rpath"
+	  relink_command="$finalize_var$finalize_command$finalize_rpath"
+	fi
+      fi
+
+      # Replace the output file specification.
+      link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+      # Delete the old output files.
+      $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+      func_show_eval "$link_command" 'exit $?'
+
+      if test -n "$postlink_cmds"; then
+	func_to_tool_file "$output_objdir/$outputname"
+	postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
+	func_execute_cmds "$postlink_cmds" 'exit $?'
+      fi
+
+      # Now create the wrapper script.
+      func_verbose "creating $output"
+
+      # Quote the relink command for shipping.
+      if test -n "$relink_command"; then
+	# Preserve any variables that may affect compiler behavior
+	for var in $variables_saved_for_relink; do
+	  if eval test -z \"\${$var+set}\"; then
+	    relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+	  elif eval var_value=\$$var; test -z "$var_value"; then
+	    relink_command="$var=; export $var; $relink_command"
+	  else
+	    func_quote_for_eval "$var_value"
+	    relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
+	  fi
+	done
+	relink_command="(cd `pwd`; $relink_command)"
+	relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"`
+      fi
+
+      # Only actually do things if not in dry run mode.
+      $opt_dry_run || {
+	# win32 will think the script is a binary if it has
+	# a .exe suffix, so we strip it off here.
+	case $output in
+	  *.exe) func_stripname '' '.exe' "$output"
+	         output=$func_stripname_result ;;
+	esac
+	# test for cygwin because mv fails w/o .exe extensions
+	case $host in
+	  *cygwin*)
+	    exeext=.exe
+	    func_stripname '' '.exe' "$outputname"
+	    outputname=$func_stripname_result ;;
+	  *) exeext= ;;
+	esac
+	case $host in
+	  *cygwin* | *mingw* )
+	    func_dirname_and_basename "$output" "" "."
+	    output_name=$func_basename_result
+	    output_path=$func_dirname_result
+	    cwrappersource="$output_path/$objdir/lt-$output_name.c"
+	    cwrapper="$output_path/$output_name.exe"
+	    $RM $cwrappersource $cwrapper
+	    trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+
+	    func_emit_cwrapperexe_src > $cwrappersource
+
+	    # The wrapper executable is built using the $host compiler,
+	    # because it contains $host paths and files. If cross-
+	    # compiling, it, like the target executable, must be
+	    # executed on the $host or under an emulation environment.
+	    $opt_dry_run || {
+	      $LTCC $LTCFLAGS -o $cwrapper $cwrappersource
+	      $STRIP $cwrapper
+	    }
+
+	    # Now, create the wrapper script for func_source use:
+	    func_ltwrapper_scriptname $cwrapper
+	    $RM $func_ltwrapper_scriptname_result
+	    trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15
+	    $opt_dry_run || {
+	      # note: this script will not be executed, so do not chmod.
+	      if test "x$build" = "x$host" ; then
+		$cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result
+	      else
+		func_emit_wrapper no > $func_ltwrapper_scriptname_result
+	      fi
+	    }
+	  ;;
+	  * )
+	    $RM $output
+	    trap "$RM $output; exit $EXIT_FAILURE" 1 2 15
+
+	    func_emit_wrapper no > $output
+	    chmod +x $output
+	  ;;
+	esac
+      }
+      exit $EXIT_SUCCESS
+      ;;
+    esac
+
+    # See if we need to build an old-fashioned archive.
+    for oldlib in $oldlibs; do
+
+      if test "$build_libtool_libs" = convenience; then
+	oldobjs="$libobjs_save $symfileobj"
+	addlibs="$convenience"
+	build_libtool_libs=no
+      else
+	if test "$build_libtool_libs" = module; then
+	  oldobjs="$libobjs_save"
+	  build_libtool_libs=no
+	else
+	  oldobjs="$old_deplibs $non_pic_objects"
+	  if test "$preload" = yes && test -f "$symfileobj"; then
+	    oldobjs+=" $symfileobj"
+	  fi
+	fi
+	addlibs="$old_convenience"
+      fi
+
+      if test -n "$addlibs"; then
+	gentop="$output_objdir/${outputname}x"
+	generated+=" $gentop"
+
+	func_extract_archives $gentop $addlibs
+	oldobjs+=" $func_extract_archives_result"
+      fi
+
+      # Do each command in the archive commands.
+      if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+	cmds=$old_archive_from_new_cmds
+      else
+
+	# Add any objects from preloaded convenience libraries
+	if test -n "$dlprefiles"; then
+	  gentop="$output_objdir/${outputname}x"
+	  generated+=" $gentop"
+
+	  func_extract_archives $gentop $dlprefiles
+	  oldobjs+=" $func_extract_archives_result"
+	fi
+
+	# POSIX demands no paths to be encoded in archives.  We have
+	# to avoid creating archives with duplicate basenames if we
+	# might have to extract them afterwards, e.g., when creating a
+	# static archive out of a convenience library, or when linking
+	# the entirety of a libtool archive into another (currently
+	# not supported by libtool).
+	if (for obj in $oldobjs
+	    do
+	      func_basename "$obj"
+	      $ECHO "$func_basename_result"
+	    done | sort | sort -uc >/dev/null 2>&1); then
+	  :
+	else
+	  echo "copying selected object files to avoid basename conflicts..."
+	  gentop="$output_objdir/${outputname}x"
+	  generated+=" $gentop"
+	  func_mkdir_p "$gentop"
+	  save_oldobjs=$oldobjs
+	  oldobjs=
+	  counter=1
+	  for obj in $save_oldobjs
+	  do
+	    func_basename "$obj"
+	    objbase="$func_basename_result"
+	    case " $oldobjs " in
+	    " ") oldobjs=$obj ;;
+	    *[\ /]"$objbase "*)
+	      while :; do
+		# Make sure we don't pick an alternate name that also
+		# overlaps.
+		newobj=lt$counter-$objbase
+		func_arith $counter + 1
+		counter=$func_arith_result
+		case " $oldobjs " in
+		*[\ /]"$newobj "*) ;;
+		*) if test ! -f "$gentop/$newobj"; then break; fi ;;
+		esac
+	      done
+	      func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+	      oldobjs+=" $gentop/$newobj"
+	      ;;
+	    *) oldobjs+=" $obj" ;;
+	    esac
+	  done
+	fi
+	func_to_tool_file "$oldlib" func_convert_file_msys_to_w32
+	tool_oldlib=$func_to_tool_file_result
+	eval cmds=\"$old_archive_cmds\"
+
+	func_len " $cmds"
+	len=$func_len_result
+	if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+	  cmds=$old_archive_cmds
+	elif test -n "$archiver_list_spec"; then
+	  func_verbose "using command file archive linking..."
+	  for obj in $oldobjs
+	  do
+	    func_to_tool_file "$obj"
+	    $ECHO "$func_to_tool_file_result"
+	  done > $output_objdir/$libname.libcmd
+	  func_to_tool_file "$output_objdir/$libname.libcmd"
+	  oldobjs=" $archiver_list_spec$func_to_tool_file_result"
+	  cmds=$old_archive_cmds
+	else
+	  # the command line is too long to link in one step, link in parts
+	  func_verbose "using piecewise archive linking..."
+	  save_RANLIB=$RANLIB
+	  RANLIB=:
+	  objlist=
+	  concat_cmds=
+	  save_oldobjs=$oldobjs
+	  oldobjs=
+	  # Is there a better way of finding the last object in the list?
+	  for obj in $save_oldobjs
+	  do
+	    last_oldobj=$obj
+	  done
+	  eval test_cmds=\"$old_archive_cmds\"
+	  func_len " $test_cmds"
+	  len0=$func_len_result
+	  len=$len0
+	  for obj in $save_oldobjs
+	  do
+	    func_len " $obj"
+	    func_arith $len + $func_len_result
+	    len=$func_arith_result
+	    objlist+=" $obj"
+	    if test "$len" -lt "$max_cmd_len"; then
+	      :
+	    else
+	      # the above command should be used before it gets too long
+	      oldobjs=$objlist
+	      if test "$obj" = "$last_oldobj" ; then
+		RANLIB=$save_RANLIB
+	      fi
+	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	      eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
+	      objlist=
+	      len=$len0
+	    fi
+	  done
+	  RANLIB=$save_RANLIB
+	  oldobjs=$objlist
+	  if test "X$oldobjs" = "X" ; then
+	    eval cmds=\"\$concat_cmds\"
+	  else
+	    eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
+	  fi
+	fi
+      fi
+      func_execute_cmds "$cmds" 'exit $?'
+    done
+
+    test -n "$generated" && \
+      func_show_eval "${RM}r$generated"
+
+    # Now create the libtool archive.
+    case $output in
+    *.la)
+      old_library=
+      test "$build_old_libs" = yes && old_library="$libname.$libext"
+      func_verbose "creating $output"
+
+      # Preserve any variables that may affect compiler behavior
+      for var in $variables_saved_for_relink; do
+	if eval test -z \"\${$var+set}\"; then
+	  relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+	elif eval var_value=\$$var; test -z "$var_value"; then
+	  relink_command="$var=; export $var; $relink_command"
+	else
+	  func_quote_for_eval "$var_value"
+	  relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
+	fi
+      done
+      # Quote the link command for shipping.
+      relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
+      relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"`
+      if test "$hardcode_automatic" = yes ; then
+	relink_command=
+      fi
+
+      # Only create the output if not a dry run.
+      $opt_dry_run || {
+	for installed in no yes; do
+	  if test "$installed" = yes; then
+	    if test -z "$install_libdir"; then
+	      break
+	    fi
+	    output="$output_objdir/$outputname"i
+	    # Replace all uninstalled libtool libraries with the installed ones
+	    newdependency_libs=
+	    for deplib in $dependency_libs; do
+	      case $deplib in
+	      *.la)
+		func_basename "$deplib"
+		name="$func_basename_result"
+		func_resolve_sysroot "$deplib"
+		eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result`
+		test -z "$libdir" && \
+		  func_fatal_error "\`$deplib' is not a valid libtool archive"
+		newdependency_libs+=" ${lt_sysroot:+=}$libdir/$name"
+		;;
+	      -L*)
+		func_stripname -L '' "$deplib"
+		func_replace_sysroot "$func_stripname_result"
+		newdependency_libs+=" -L$func_replace_sysroot_result"
+		;;
+	      -R*)
+		func_stripname -R '' "$deplib"
+		func_replace_sysroot "$func_stripname_result"
+		newdependency_libs+=" -R$func_replace_sysroot_result"
+		;;
+	      *) newdependency_libs+=" $deplib" ;;
+	      esac
+	    done
+	    dependency_libs="$newdependency_libs"
+	    newdlfiles=
+
+	    for lib in $dlfiles; do
+	      case $lib in
+	      *.la)
+	        func_basename "$lib"
+		name="$func_basename_result"
+		eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+		test -z "$libdir" && \
+		  func_fatal_error "\`$lib' is not a valid libtool archive"
+		newdlfiles+=" ${lt_sysroot:+=}$libdir/$name"
+		;;
+	      *) newdlfiles+=" $lib" ;;
+	      esac
+	    done
+	    dlfiles="$newdlfiles"
+	    newdlprefiles=
+	    for lib in $dlprefiles; do
+	      case $lib in
+	      *.la)
+		# Only pass preopened files to the pseudo-archive (for
+		# eventual linking with the app. that links it) if we
+		# didn't already link the preopened objects directly into
+		# the library:
+		func_basename "$lib"
+		name="$func_basename_result"
+		eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+		test -z "$libdir" && \
+		  func_fatal_error "\`$lib' is not a valid libtool archive"
+		newdlprefiles+=" ${lt_sysroot:+=}$libdir/$name"
+		;;
+	      esac
+	    done
+	    dlprefiles="$newdlprefiles"
+	  else
+	    newdlfiles=
+	    for lib in $dlfiles; do
+	      case $lib in
+		[\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+		*) abs=`pwd`"/$lib" ;;
+	      esac
+	      newdlfiles+=" $abs"
+	    done
+	    dlfiles="$newdlfiles"
+	    newdlprefiles=
+	    for lib in $dlprefiles; do
+	      case $lib in
+		[\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+		*) abs=`pwd`"/$lib" ;;
+	      esac
+	      newdlprefiles+=" $abs"
+	    done
+	    dlprefiles="$newdlprefiles"
+	  fi
+	  $RM $output
+	  # place dlname in correct position for cygwin
+	  # In fact, it would be nice if we could use this code for all target
+	  # systems that can't hard-code library paths into their executables
+	  # and that have no shared library path variable independent of PATH,
+	  # but it turns out we can't easily determine that from inspecting
+	  # libtool variables, so we have to hard-code the OSs to which it
+	  # applies here; at the moment, that means platforms that use the PE
+	  # object format with DLL files.  See the long comment at the top of
+	  # tests/bindir.at for full details.
+	  tdlname=$dlname
+	  case $host,$output,$installed,$module,$dlname in
+	    *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll)
+	      # If a -bindir argument was supplied, place the dll there.
+	      if test "x$bindir" != x ;
+	      then
+		func_relative_path "$install_libdir" "$bindir"
+		tdlname=$func_relative_path_result$dlname
+	      else
+		# Otherwise fall back on heuristic.
+		tdlname=../bin/$dlname
+	      fi
+	      ;;
+	  esac
+	  $ECHO > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Linker flags that can not go in dependency_libs.
+inherited_linker_flags='$new_inherited_linker_flags'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Names of additional weak libraries provided by this library
+weak_library_names='$weak_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=$module
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+	  if test "$installed" = no && test "$need_relink" = yes; then
+	    $ECHO >> $output "\
+relink_command=\"$relink_command\""
+	  fi
+	done
+      }
+
+      # Do a symbolic link so that the libtool archive can be found in
+      # LD_LIBRARY_PATH before the program is installed.
+      func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?'
+      ;;
+    esac
+    exit $EXIT_SUCCESS
+}
+
+{ test "$opt_mode" = link || test "$opt_mode" = relink; } &&
+    func_mode_link ${1+"$@"}
+
+
+# func_mode_uninstall arg...
+func_mode_uninstall ()
+{
+    $opt_debug
+    RM="$nonopt"
+    files=
+    rmforce=
+    exit_status=0
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    for arg
+    do
+      case $arg in
+      -f) RM+=" $arg"; rmforce=yes ;;
+      -*) RM+=" $arg" ;;
+      *) files+=" $arg" ;;
+      esac
+    done
+
+    test -z "$RM" && \
+      func_fatal_help "you must specify an RM program"
+
+    rmdirs=
+
+    for file in $files; do
+      func_dirname "$file" "" "."
+      dir="$func_dirname_result"
+      if test "X$dir" = X.; then
+	odir="$objdir"
+      else
+	odir="$dir/$objdir"
+      fi
+      func_basename "$file"
+      name="$func_basename_result"
+      test "$opt_mode" = uninstall && odir="$dir"
+
+      # Remember odir for removal later, being careful to avoid duplicates
+      if test "$opt_mode" = clean; then
+	case " $rmdirs " in
+	  *" $odir "*) ;;
+	  *) rmdirs+=" $odir" ;;
+	esac
+      fi
+
+      # Don't error if the file doesn't exist and rm -f was used.
+      if { test -L "$file"; } >/dev/null 2>&1 ||
+	 { test -h "$file"; } >/dev/null 2>&1 ||
+	 test -f "$file"; then
+	:
+      elif test -d "$file"; then
+	exit_status=1
+	continue
+      elif test "$rmforce" = yes; then
+	continue
+      fi
+
+      rmfiles="$file"
+
+      case $name in
+      *.la)
+	# Possibly a libtool archive, so verify it.
+	if func_lalib_p "$file"; then
+	  func_source $dir/$name
+
+	  # Delete the libtool libraries and symlinks.
+	  for n in $library_names; do
+	    rmfiles+=" $odir/$n"
+	  done
+	  test -n "$old_library" && rmfiles+=" $odir/$old_library"
+
+	  case "$opt_mode" in
+	  clean)
+	    case " $library_names " in
+	    *" $dlname "*) ;;
+	    *) test -n "$dlname" && rmfiles+=" $odir/$dlname" ;;
+	    esac
+	    test -n "$libdir" && rmfiles+=" $odir/$name $odir/${name}i"
+	    ;;
+	  uninstall)
+	    if test -n "$library_names"; then
+	      # Do each command in the postuninstall commands.
+	      func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
+	    fi
+
+	    if test -n "$old_library"; then
+	      # Do each command in the old_postuninstall commands.
+	      func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
+	    fi
+	    # FIXME: should reinstall the best remaining shared library.
+	    ;;
+	  esac
+	fi
+	;;
+
+      *.lo)
+	# Possibly a libtool object, so verify it.
+	if func_lalib_p "$file"; then
+
+	  # Read the .lo file
+	  func_source $dir/$name
+
+	  # Add PIC object to the list of files to remove.
+	  if test -n "$pic_object" &&
+	     test "$pic_object" != none; then
+	    rmfiles+=" $dir/$pic_object"
+	  fi
+
+	  # Add non-PIC object to the list of files to remove.
+	  if test -n "$non_pic_object" &&
+	     test "$non_pic_object" != none; then
+	    rmfiles+=" $dir/$non_pic_object"
+	  fi
+	fi
+	;;
+
+      *)
+	if test "$opt_mode" = clean ; then
+	  noexename=$name
+	  case $file in
+	  *.exe)
+	    func_stripname '' '.exe' "$file"
+	    file=$func_stripname_result
+	    func_stripname '' '.exe' "$name"
+	    noexename=$func_stripname_result
+	    # $file with .exe has already been added to rmfiles,
+	    # add $file without .exe
+	    rmfiles+=" $file"
+	    ;;
+	  esac
+	  # Do a test to see if this is a libtool program.
+	  if func_ltwrapper_p "$file"; then
+	    if func_ltwrapper_executable_p "$file"; then
+	      func_ltwrapper_scriptname "$file"
+	      relink_command=
+	      func_source $func_ltwrapper_scriptname_result
+	      rmfiles+=" $func_ltwrapper_scriptname_result"
+	    else
+	      relink_command=
+	      func_source $dir/$noexename
+	    fi
+
+	    # note $name still contains .exe if it was in $file originally
+	    # as does the version of $file that was added into $rmfiles
+	    rmfiles+=" $odir/$name $odir/${name}S.${objext}"
+	    if test "$fast_install" = yes && test -n "$relink_command"; then
+	      rmfiles+=" $odir/lt-$name"
+	    fi
+	    if test "X$noexename" != "X$name" ; then
+	      rmfiles+=" $odir/lt-${noexename}.c"
+	    fi
+	  fi
+	fi
+	;;
+      esac
+      func_show_eval "$RM $rmfiles" 'exit_status=1'
+    done
+
+    # Try to remove the ${objdir}s in the directories where we deleted files
+    for dir in $rmdirs; do
+      if test -d "$dir"; then
+	func_show_eval "rmdir $dir >/dev/null 2>&1"
+      fi
+    done
+
+    exit $exit_status
+}
+
+{ test "$opt_mode" = uninstall || test "$opt_mode" = clean; } &&
+    func_mode_uninstall ${1+"$@"}
+
+test -z "$opt_mode" && {
+  help="$generic_help"
+  func_fatal_help "you must specify a MODE"
+}
+
+test -z "$exec_cmd" && \
+  func_fatal_help "invalid operation mode \`$opt_mode'"
+
+if test -n "$exec_cmd"; then
+  eval exec "$exec_cmd"
+  exit $EXIT_FAILURE
+fi
+
+exit $exit_status
+
+
+# The TAGs below are defined such that we never get into a situation
+# in which we disable both kinds of libraries.  Given conflicting
+# choices, we go for a static library, that is the most portable,
+# since we can't tell whether shared libraries were disabled because
+# the user asked for that or because the platform doesn't support
+# them.  This is particularly important on AIX, because we don't
+# support having both static and shared libraries enabled at the same
+# time on that platform, so we default to a shared-only configuration.
+# If a disable-shared tag is given, we'll fallback to a static-only
+# configuration.  But we'll never go from static-only to shared-only.
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
+build_libtool_libs=no
+build_old_libs=yes
+# ### END LIBTOOL TAG CONFIG: disable-shared
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
+build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
+# ### END LIBTOOL TAG CONFIG: disable-static
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
+# vi:sw=2
+
diff --git a/ltmain.sh b/ltmain.sh
new file mode 100755
index 0000000000000000000000000000000000000000..63ae69dc6fecaf83c52fba2ad334f4b1369fb1cd
--- /dev/null
+++ b/ltmain.sh
@@ -0,0 +1,9655 @@
+
+# libtool (GNU libtool) 2.4.2
+# Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006,
+# 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions.  There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# GNU Libtool is free software; you can 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.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that 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 GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html,
+# or obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# Usage: $progname [OPTION]... [MODE-ARG]...
+#
+# Provide generalized library-building support services.
+#
+#       --config             show all configuration variables
+#       --debug              enable verbose shell tracing
+#   -n, --dry-run            display commands without modifying any files
+#       --features           display basic configuration information and exit
+#       --mode=MODE          use operation mode MODE
+#       --preserve-dup-deps  don't remove duplicate dependency libraries
+#       --quiet, --silent    don't print informational messages
+#       --no-quiet, --no-silent
+#                            print informational messages (default)
+#       --no-warn            don't display warning messages
+#       --tag=TAG            use configuration variables from tag TAG
+#   -v, --verbose            print more informational messages than default
+#       --no-verbose         don't print the extra informational messages
+#       --version            print version information
+#   -h, --help, --help-all   print short, long, or detailed help message
+#
+# MODE must be one of the following:
+#
+#         clean              remove files from the build directory
+#         compile            compile a source file into a libtool object
+#         execute            automatically set library path, then run a program
+#         finish             complete the installation of libtool libraries
+#         install            install libraries or executables
+#         link               create a library or an executable
+#         uninstall          remove libraries from an installed directory
+#
+# MODE-ARGS vary depending on the MODE.  When passed as first option,
+# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that.
+# Try `$progname --help --mode=MODE' for a more detailed description of MODE.
+#
+# When reporting a bug, please describe a test case to reproduce it and
+# include the following information:
+#
+#         host-triplet:	$host
+#         shell:		$SHELL
+#         compiler:		$LTCC
+#         compiler flags:		$LTCFLAGS
+#         linker:		$LD (gnu? $with_gnu_ld)
+#         $progname:	(GNU libtool) 2.4.2
+#         automake:	$automake_version
+#         autoconf:	$autoconf_version
+#
+# Report bugs to <bug-libtool@gnu.org>.
+# GNU libtool home page: <http://www.gnu.org/software/libtool/>.
+# General help using GNU software: <http://www.gnu.org/gethelp/>.
+
+PROGRAM=libtool
+PACKAGE=libtool
+VERSION=2.4.2
+TIMESTAMP=""
+package_revision=1.3337
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+}
+
+# NLS nuisances: We save the old values to restore during execute mode.
+lt_user_locale=
+lt_safe_locale=
+for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+do
+  eval "if test \"\${$lt_var+set}\" = set; then
+          save_$lt_var=\$$lt_var
+          $lt_var=C
+	  export $lt_var
+	  lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\"
+	  lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\"
+	fi"
+done
+LC_ALL=C
+LANGUAGE=C
+export LANGUAGE LC_ALL
+
+$lt_unset CDPATH
+
+
+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
+# is ksh but when the shell is invoked as "sh" and the current value of
+# the _XPG environment variable is not equal to 1 (one), the special
+# positional parameter $0, within a function call, is the name of the
+# function.
+progpath="$0"
+
+
+
+: ${CP="cp -f"}
+test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'}
+: ${MAKE="make"}
+: ${MKDIR="mkdir"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+: ${SHELL="${CONFIG_SHELL-/bin/sh}"}
+: ${Xsed="$SED -e 1s/^X//"}
+
+# Global variables:
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+EXIT_MISMATCH=63  # $? = 63 is used to indicate version mismatch to missing.
+EXIT_SKIP=77	  # $? = 77 is used to indicate a skipped test to automake.
+
+exit_status=$EXIT_SUCCESS
+
+# Make sure IFS has a sensible default
+lt_nl='
+'
+IFS=" 	$lt_nl"
+
+dirname="s,/[^/]*$,,"
+basename="s,^.*/,,"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+    func_dirname_result=`$ECHO "${1}" | $SED "$dirname"`
+    if test "X$func_dirname_result" = "X${1}"; then
+      func_dirname_result="${3}"
+    else
+      func_dirname_result="$func_dirname_result${2}"
+    fi
+} # func_dirname may be replaced by extended shell implementation
+
+
+# func_basename file
+func_basename ()
+{
+    func_basename_result=`$ECHO "${1}" | $SED "$basename"`
+} # func_basename may be replaced by extended shell implementation
+
+
+# func_dirname_and_basename file append nondir_replacement
+# perform func_basename and func_dirname in a single function
+# call:
+#   dirname:  Compute the dirname of FILE.  If nonempty,
+#             add APPEND to the result, otherwise set result
+#             to NONDIR_REPLACEMENT.
+#             value returned in "$func_dirname_result"
+#   basename: Compute filename of FILE.
+#             value retuned in "$func_basename_result"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+    # Extract subdirectory from the argument.
+    func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"`
+    if test "X$func_dirname_result" = "X${1}"; then
+      func_dirname_result="${3}"
+    else
+      func_dirname_result="$func_dirname_result${2}"
+    fi
+    func_basename_result=`$ECHO "${1}" | $SED -e "$basename"`
+} # func_dirname_and_basename may be replaced by extended shell implementation
+
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+# func_strip_suffix prefix name
+func_stripname ()
+{
+    case ${2} in
+      .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;;
+      *)  func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;;
+    esac
+} # func_stripname may be replaced by extended shell implementation
+
+
+# These SED scripts presuppose an absolute path with a trailing slash.
+pathcar='s,^/\([^/]*\).*$,\1,'
+pathcdr='s,^/[^/]*,,'
+removedotparts=':dotsl
+		s@/\./@/@g
+		t dotsl
+		s,/\.$,/,'
+collapseslashes='s@/\{1,\}@/@g'
+finalslash='s,/*$,/,'
+
+# func_normal_abspath PATH
+# Remove doubled-up and trailing slashes, "." path components,
+# and cancel out any ".." path components in PATH after making
+# it an absolute path.
+#             value returned in "$func_normal_abspath_result"
+func_normal_abspath ()
+{
+  # Start from root dir and reassemble the path.
+  func_normal_abspath_result=
+  func_normal_abspath_tpath=$1
+  func_normal_abspath_altnamespace=
+  case $func_normal_abspath_tpath in
+    "")
+      # Empty path, that just means $cwd.
+      func_stripname '' '/' "`pwd`"
+      func_normal_abspath_result=$func_stripname_result
+      return
+    ;;
+    # The next three entries are used to spot a run of precisely
+    # two leading slashes without using negated character classes;
+    # we take advantage of case's first-match behaviour.
+    ///*)
+      # Unusual form of absolute path, do nothing.
+    ;;
+    //*)
+      # Not necessarily an ordinary path; POSIX reserves leading '//'
+      # and for example Cygwin uses it to access remote file shares
+      # over CIFS/SMB, so we conserve a leading double slash if found.
+      func_normal_abspath_altnamespace=/
+    ;;
+    /*)
+      # Absolute path, do nothing.
+    ;;
+    *)
+      # Relative path, prepend $cwd.
+      func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath
+    ;;
+  esac
+  # Cancel out all the simple stuff to save iterations.  We also want
+  # the path to end with a slash for ease of parsing, so make sure
+  # there is one (and only one) here.
+  func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
+        -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"`
+  while :; do
+    # Processed it all yet?
+    if test "$func_normal_abspath_tpath" = / ; then
+      # If we ascended to the root using ".." the result may be empty now.
+      if test -z "$func_normal_abspath_result" ; then
+        func_normal_abspath_result=/
+      fi
+      break
+    fi
+    func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \
+        -e "$pathcar"`
+    func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
+        -e "$pathcdr"`
+    # Figure out what to do with it
+    case $func_normal_abspath_tcomponent in
+      "")
+        # Trailing empty path component, ignore it.
+      ;;
+      ..)
+        # Parent dir; strip last assembled component from result.
+        func_dirname "$func_normal_abspath_result"
+        func_normal_abspath_result=$func_dirname_result
+      ;;
+      *)
+        # Actual path component, append it.
+        func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent
+      ;;
+    esac
+  done
+  # Restore leading double-slash if one was found on entry.
+  func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result
+}
+
+# func_relative_path SRCDIR DSTDIR
+# generates a relative path from SRCDIR to DSTDIR, with a trailing
+# slash if non-empty, suitable for immediately appending a filename
+# without needing to append a separator.
+#             value returned in "$func_relative_path_result"
+func_relative_path ()
+{
+  func_relative_path_result=
+  func_normal_abspath "$1"
+  func_relative_path_tlibdir=$func_normal_abspath_result
+  func_normal_abspath "$2"
+  func_relative_path_tbindir=$func_normal_abspath_result
+
+  # Ascend the tree starting from libdir
+  while :; do
+    # check if we have found a prefix of bindir
+    case $func_relative_path_tbindir in
+      $func_relative_path_tlibdir)
+        # found an exact match
+        func_relative_path_tcancelled=
+        break
+        ;;
+      $func_relative_path_tlibdir*)
+        # found a matching prefix
+        func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir"
+        func_relative_path_tcancelled=$func_stripname_result
+        if test -z "$func_relative_path_result"; then
+          func_relative_path_result=.
+        fi
+        break
+        ;;
+      *)
+        func_dirname $func_relative_path_tlibdir
+        func_relative_path_tlibdir=${func_dirname_result}
+        if test "x$func_relative_path_tlibdir" = x ; then
+          # Have to descend all the way to the root!
+          func_relative_path_result=../$func_relative_path_result
+          func_relative_path_tcancelled=$func_relative_path_tbindir
+          break
+        fi
+        func_relative_path_result=../$func_relative_path_result
+        ;;
+    esac
+  done
+
+  # Now calculate path; take care to avoid doubling-up slashes.
+  func_stripname '' '/' "$func_relative_path_result"
+  func_relative_path_result=$func_stripname_result
+  func_stripname '/' '/' "$func_relative_path_tcancelled"
+  if test "x$func_stripname_result" != x ; then
+    func_relative_path_result=${func_relative_path_result}/${func_stripname_result}
+  fi
+
+  # Normalisation. If bindir is libdir, return empty string,
+  # else relative path ending with a slash; either way, target
+  # file name can be directly appended.
+  if test ! -z "$func_relative_path_result"; then
+    func_stripname './' '' "$func_relative_path_result/"
+    func_relative_path_result=$func_stripname_result
+  fi
+}
+
+# The name of this program:
+func_dirname_and_basename "$progpath"
+progname=$func_basename_result
+
+# Make sure we have an absolute path for reexecution:
+case $progpath in
+  [\\/]*|[A-Za-z]:\\*) ;;
+  *[\\/]*)
+     progdir=$func_dirname_result
+     progdir=`cd "$progdir" && pwd`
+     progpath="$progdir/$progname"
+     ;;
+  *)
+     save_IFS="$IFS"
+     IFS=${PATH_SEPARATOR-:}
+     for progdir in $PATH; do
+       IFS="$save_IFS"
+       test -x "$progdir/$progname" && break
+     done
+     IFS="$save_IFS"
+     test -n "$progdir" || progdir=`pwd`
+     progpath="$progdir/$progname"
+     ;;
+esac
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed="${SED}"' -e 1s/^X//'
+sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Sed substitution that turns a string into a regex matching for the
+# string literally.
+sed_make_literal_regex='s,[].[^$\\*\/],\\&,g'
+
+# Sed substitution that converts a w32 file name or path
+# which contains forward slashes, into one that contains
+# (escaped) backslashes.  A very naive implementation.
+lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
+
+# Re-`\' parameter expansions in output of double_quote_subst that were
+# `\'-ed in input to the same.  If an odd number of `\' preceded a '$'
+# in input to double_quote_subst, that '$' was protected from expansion.
+# Since each input `\' is now two `\'s, look for any number of runs of
+# four `\'s followed by two `\'s and then a '$'.  `\' that '$'.
+bs='\\'
+bs2='\\\\'
+bs4='\\\\\\\\'
+dollar='\$'
+sed_double_backslash="\
+  s/$bs4/&\\
+/g
+  s/^$bs2$dollar/$bs&/
+  s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g
+  s/\n//g"
+
+# Standard options:
+opt_dry_run=false
+opt_help=false
+opt_quiet=false
+opt_verbose=false
+opt_warning=:
+
+# func_echo arg...
+# Echo program name prefixed message, along with the current mode
+# name if it has been set yet.
+func_echo ()
+{
+    $ECHO "$progname: ${opt_mode+$opt_mode: }$*"
+}
+
+# func_verbose arg...
+# Echo program name prefixed message in verbose mode only.
+func_verbose ()
+{
+    $opt_verbose && func_echo ${1+"$@"}
+
+    # A bug in bash halts the script if the last line of a function
+    # fails when set -e is in force, so we need another command to
+    # work around that:
+    :
+}
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+    $ECHO "$*"
+}
+
+# func_error arg...
+# Echo program name prefixed message to standard error.
+func_error ()
+{
+    $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2
+}
+
+# func_warning arg...
+# Echo program name prefixed warning message to standard error.
+func_warning ()
+{
+    $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2
+
+    # bash bug again:
+    :
+}
+
+# func_fatal_error arg...
+# Echo program name prefixed message to standard error, and exit.
+func_fatal_error ()
+{
+    func_error ${1+"$@"}
+    exit $EXIT_FAILURE
+}
+
+# func_fatal_help arg...
+# Echo program name prefixed message to standard error, followed by
+# a help hint, and exit.
+func_fatal_help ()
+{
+    func_error ${1+"$@"}
+    func_fatal_error "$help"
+}
+help="Try \`$progname --help' for more information."  ## default
+
+
+# func_grep expression filename
+# Check whether EXPRESSION matches any line of FILENAME, without output.
+func_grep ()
+{
+    $GREP "$1" "$2" >/dev/null 2>&1
+}
+
+
+# func_mkdir_p directory-path
+# Make sure the entire path to DIRECTORY-PATH is available.
+func_mkdir_p ()
+{
+    my_directory_path="$1"
+    my_dir_list=
+
+    if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then
+
+      # Protect directory names starting with `-'
+      case $my_directory_path in
+        -*) my_directory_path="./$my_directory_path" ;;
+      esac
+
+      # While some portion of DIR does not yet exist...
+      while test ! -d "$my_directory_path"; do
+        # ...make a list in topmost first order.  Use a colon delimited
+	# list incase some portion of path contains whitespace.
+        my_dir_list="$my_directory_path:$my_dir_list"
+
+        # If the last portion added has no slash in it, the list is done
+        case $my_directory_path in */*) ;; *) break ;; esac
+
+        # ...otherwise throw away the child directory and loop
+        my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"`
+      done
+      my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'`
+
+      save_mkdir_p_IFS="$IFS"; IFS=':'
+      for my_dir in $my_dir_list; do
+	IFS="$save_mkdir_p_IFS"
+        # mkdir can fail with a `File exist' error if two processes
+        # try to create one of the directories concurrently.  Don't
+        # stop in that case!
+        $MKDIR "$my_dir" 2>/dev/null || :
+      done
+      IFS="$save_mkdir_p_IFS"
+
+      # Bail out if we (or some other process) failed to create a directory.
+      test -d "$my_directory_path" || \
+        func_fatal_error "Failed to create \`$1'"
+    fi
+}
+
+
+# func_mktempdir [string]
+# Make a temporary directory that won't clash with other running
+# libtool processes, and avoids race conditions if possible.  If
+# given, STRING is the basename for that directory.
+func_mktempdir ()
+{
+    my_template="${TMPDIR-/tmp}/${1-$progname}"
+
+    if test "$opt_dry_run" = ":"; then
+      # Return a directory name, but don't create it in dry-run mode
+      my_tmpdir="${my_template}-$$"
+    else
+
+      # If mktemp works, use that first and foremost
+      my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
+
+      if test ! -d "$my_tmpdir"; then
+        # Failing that, at least try and use $RANDOM to avoid a race
+        my_tmpdir="${my_template}-${RANDOM-0}$$"
+
+        save_mktempdir_umask=`umask`
+        umask 0077
+        $MKDIR "$my_tmpdir"
+        umask $save_mktempdir_umask
+      fi
+
+      # If we're not in dry-run mode, bomb out on failure
+      test -d "$my_tmpdir" || \
+        func_fatal_error "cannot create temporary directory \`$my_tmpdir'"
+    fi
+
+    $ECHO "$my_tmpdir"
+}
+
+
+# func_quote_for_eval arg
+# Aesthetically quote ARG to be evaled later.
+# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT
+# is double-quoted, suitable for a subsequent eval, whereas
+# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters
+# which are still active within double quotes backslashified.
+func_quote_for_eval ()
+{
+    case $1 in
+      *[\\\`\"\$]*)
+	func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;;
+      *)
+        func_quote_for_eval_unquoted_result="$1" ;;
+    esac
+
+    case $func_quote_for_eval_unquoted_result in
+      # Double-quote args containing shell metacharacters to delay
+      # word splitting, command substitution and and variable
+      # expansion for a subsequent eval.
+      # Many Bourne shells cannot handle close brackets correctly
+      # in scan sets, so we specify it separately.
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+        func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\""
+        ;;
+      *)
+        func_quote_for_eval_result="$func_quote_for_eval_unquoted_result"
+    esac
+}
+
+
+# func_quote_for_expand arg
+# Aesthetically quote ARG to be evaled later; same as above,
+# but do not quote variable references.
+func_quote_for_expand ()
+{
+    case $1 in
+      *[\\\`\"]*)
+	my_arg=`$ECHO "$1" | $SED \
+	    -e "$double_quote_subst" -e "$sed_double_backslash"` ;;
+      *)
+        my_arg="$1" ;;
+    esac
+
+    case $my_arg in
+      # Double-quote args containing shell metacharacters to delay
+      # word splitting and command substitution for a subsequent eval.
+      # Many Bourne shells cannot handle close brackets correctly
+      # in scan sets, so we specify it separately.
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+        my_arg="\"$my_arg\""
+        ;;
+    esac
+
+    func_quote_for_expand_result="$my_arg"
+}
+
+
+# func_show_eval cmd [fail_exp]
+# Unless opt_silent is true, then output CMD.  Then, if opt_dryrun is
+# not true, evaluate CMD.  If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it.
+func_show_eval ()
+{
+    my_cmd="$1"
+    my_fail_exp="${2-:}"
+
+    ${opt_silent-false} || {
+      func_quote_for_expand "$my_cmd"
+      eval "func_echo $func_quote_for_expand_result"
+    }
+
+    if ${opt_dry_run-false}; then :; else
+      eval "$my_cmd"
+      my_status=$?
+      if test "$my_status" -eq 0; then :; else
+	eval "(exit $my_status); $my_fail_exp"
+      fi
+    fi
+}
+
+
+# func_show_eval_locale cmd [fail_exp]
+# Unless opt_silent is true, then output CMD.  Then, if opt_dryrun is
+# not true, evaluate CMD.  If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it.  Use the saved locale for evaluation.
+func_show_eval_locale ()
+{
+    my_cmd="$1"
+    my_fail_exp="${2-:}"
+
+    ${opt_silent-false} || {
+      func_quote_for_expand "$my_cmd"
+      eval "func_echo $func_quote_for_expand_result"
+    }
+
+    if ${opt_dry_run-false}; then :; else
+      eval "$lt_user_locale
+	    $my_cmd"
+      my_status=$?
+      eval "$lt_safe_locale"
+      if test "$my_status" -eq 0; then :; else
+	eval "(exit $my_status); $my_fail_exp"
+      fi
+    fi
+}
+
+# func_tr_sh
+# Turn $1 into a string suitable for a shell variable name.
+# Result is stored in $func_tr_sh_result.  All characters
+# not in the set a-zA-Z0-9_ are replaced with '_'. Further,
+# if $1 begins with a digit, a '_' is prepended as well.
+func_tr_sh ()
+{
+  case $1 in
+  [0-9]* | *[!a-zA-Z0-9_]*)
+    func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'`
+    ;;
+  * )
+    func_tr_sh_result=$1
+    ;;
+  esac
+}
+
+
+# func_version
+# Echo version message to standard output and exit.
+func_version ()
+{
+    $opt_debug
+
+    $SED -n '/(C)/!b go
+	:more
+	/\./!{
+	  N
+	  s/\n# / /
+	  b more
+	}
+	:go
+	/^# '$PROGRAM' (GNU /,/# warranty; / {
+        s/^# //
+	s/^# *$//
+        s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/
+        p
+     }' < "$progpath"
+     exit $?
+}
+
+# func_usage
+# Echo short help message to standard output and exit.
+func_usage ()
+{
+    $opt_debug
+
+    $SED -n '/^# Usage:/,/^#  *.*--help/ {
+        s/^# //
+	s/^# *$//
+	s/\$progname/'$progname'/
+	p
+    }' < "$progpath"
+    echo
+    $ECHO "run \`$progname --help | more' for full usage"
+    exit $?
+}
+
+# func_help [NOEXIT]
+# Echo long help message to standard output and exit,
+# unless 'noexit' is passed as argument.
+func_help ()
+{
+    $opt_debug
+
+    $SED -n '/^# Usage:/,/# Report bugs to/ {
+	:print
+        s/^# //
+	s/^# *$//
+	s*\$progname*'$progname'*
+	s*\$host*'"$host"'*
+	s*\$SHELL*'"$SHELL"'*
+	s*\$LTCC*'"$LTCC"'*
+	s*\$LTCFLAGS*'"$LTCFLAGS"'*
+	s*\$LD*'"$LD"'*
+	s/\$with_gnu_ld/'"$with_gnu_ld"'/
+	s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/
+	s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/
+	p
+	d
+     }
+     /^# .* home page:/b print
+     /^# General help using/b print
+     ' < "$progpath"
+    ret=$?
+    if test -z "$1"; then
+      exit $ret
+    fi
+}
+
+# func_missing_arg argname
+# Echo program name prefixed message to standard error and set global
+# exit_cmd.
+func_missing_arg ()
+{
+    $opt_debug
+
+    func_error "missing argument for $1."
+    exit_cmd=exit
+}
+
+
+# func_split_short_opt shortopt
+# Set func_split_short_opt_name and func_split_short_opt_arg shell
+# variables after splitting SHORTOPT after the 2nd character.
+func_split_short_opt ()
+{
+    my_sed_short_opt='1s/^\(..\).*$/\1/;q'
+    my_sed_short_rest='1s/^..\(.*\)$/\1/;q'
+
+    func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"`
+    func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"`
+} # func_split_short_opt may be replaced by extended shell implementation
+
+
+# func_split_long_opt longopt
+# Set func_split_long_opt_name and func_split_long_opt_arg shell
+# variables after splitting LONGOPT at the `=' sign.
+func_split_long_opt ()
+{
+    my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q'
+    my_sed_long_arg='1s/^--[^=]*=//'
+
+    func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"`
+    func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"`
+} # func_split_long_opt may be replaced by extended shell implementation
+
+exit_cmd=:
+
+
+
+
+
+magic="%%%MAGIC variable%%%"
+magic_exe="%%%MAGIC EXE variable%%%"
+
+# Global variables.
+nonopt=
+preserve_args=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+extracted_archives=
+extracted_serial=0
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end.  This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+    eval "${1}=\$${1}\${2}"
+} # func_append may be replaced by extended shell implementation
+
+# func_append_quoted var value
+# Quote VALUE and append to the end of shell variable VAR, separated
+# by a space.
+func_append_quoted ()
+{
+    func_quote_for_eval "${2}"
+    eval "${1}=\$${1}\\ \$func_quote_for_eval_result"
+} # func_append_quoted may be replaced by extended shell implementation
+
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+    func_arith_result=`expr "${@}"`
+} # func_arith may be replaced by extended shell implementation
+
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+    func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len`
+} # func_len may be replaced by extended shell implementation
+
+
+# func_lo2o object
+func_lo2o ()
+{
+    func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"`
+} # func_lo2o may be replaced by extended shell implementation
+
+
+# func_xform libobj-or-source
+func_xform ()
+{
+    func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'`
+} # func_xform may be replaced by extended shell implementation
+
+
+# func_fatal_configuration arg...
+# Echo program name prefixed message to standard error, followed by
+# a configuration failure hint, and exit.
+func_fatal_configuration ()
+{
+    func_error ${1+"$@"}
+    func_error "See the $PACKAGE documentation for more information."
+    func_fatal_error "Fatal configuration error."
+}
+
+
+# func_config
+# Display the configuration for all the tags in this script.
+func_config ()
+{
+    re_begincf='^# ### BEGIN LIBTOOL'
+    re_endcf='^# ### END LIBTOOL'
+
+    # Default configuration.
+    $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath"
+
+    # Now print the configurations for the tags.
+    for tagname in $taglist; do
+      $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath"
+    done
+
+    exit $?
+}
+
+# func_features
+# Display the features supported by this script.
+func_features ()
+{
+    echo "host: $host"
+    if test "$build_libtool_libs" = yes; then
+      echo "enable shared libraries"
+    else
+      echo "disable shared libraries"
+    fi
+    if test "$build_old_libs" = yes; then
+      echo "enable static libraries"
+    else
+      echo "disable static libraries"
+    fi
+
+    exit $?
+}
+
+# func_enable_tag tagname
+# Verify that TAGNAME is valid, and either flag an error and exit, or
+# enable the TAGNAME tag.  We also add TAGNAME to the global $taglist
+# variable here.
+func_enable_tag ()
+{
+  # Global variable:
+  tagname="$1"
+
+  re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$"
+  re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$"
+  sed_extractcf="/$re_begincf/,/$re_endcf/p"
+
+  # Validate tagname.
+  case $tagname in
+    *[!-_A-Za-z0-9,/]*)
+      func_fatal_error "invalid tag name: $tagname"
+      ;;
+  esac
+
+  # Don't test for the "default" C tag, as we know it's
+  # there but not specially marked.
+  case $tagname in
+    CC) ;;
+    *)
+      if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then
+	taglist="$taglist $tagname"
+
+	# Evaluate the configuration.  Be careful to quote the path
+	# and the sed script, to avoid splitting on whitespace, but
+	# also don't use non-portable quotes within backquotes within
+	# quotes we have to do it in 2 steps:
+	extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"`
+	eval "$extractedcf"
+      else
+	func_error "ignoring unknown tag $tagname"
+      fi
+      ;;
+  esac
+}
+
+# func_check_version_match
+# Ensure that we are using m4 macros, and libtool script from the same
+# release of libtool.
+func_check_version_match ()
+{
+  if test "$package_revision" != "$macro_revision"; then
+    if test "$VERSION" != "$macro_version"; then
+      if test -z "$macro_version"; then
+        cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from an older release.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+      else
+        cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from $PACKAGE $macro_version.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+      fi
+    else
+      cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, revision $package_revision,
+$progname: but the definition of this LT_INIT comes from revision $macro_revision.
+$progname: You should recreate aclocal.m4 with macros from revision $package_revision
+$progname: of $PACKAGE $VERSION and run autoconf again.
+_LT_EOF
+    fi
+
+    exit $EXIT_MISMATCH
+  fi
+}
+
+
+# Shorthand for --mode=foo, only valid as the first argument
+case $1 in
+clean|clea|cle|cl)
+  shift; set dummy --mode clean ${1+"$@"}; shift
+  ;;
+compile|compil|compi|comp|com|co|c)
+  shift; set dummy --mode compile ${1+"$@"}; shift
+  ;;
+execute|execut|execu|exec|exe|ex|e)
+  shift; set dummy --mode execute ${1+"$@"}; shift
+  ;;
+finish|finis|fini|fin|fi|f)
+  shift; set dummy --mode finish ${1+"$@"}; shift
+  ;;
+install|instal|insta|inst|ins|in|i)
+  shift; set dummy --mode install ${1+"$@"}; shift
+  ;;
+link|lin|li|l)
+  shift; set dummy --mode link ${1+"$@"}; shift
+  ;;
+uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u)
+  shift; set dummy --mode uninstall ${1+"$@"}; shift
+  ;;
+esac
+
+
+
+# Option defaults:
+opt_debug=:
+opt_dry_run=false
+opt_config=false
+opt_preserve_dup_deps=false
+opt_features=false
+opt_finish=false
+opt_help=false
+opt_help_all=false
+opt_silent=:
+opt_warning=:
+opt_verbose=:
+opt_silent=false
+opt_verbose=false
+
+
+# Parse options once, thoroughly.  This comes as soon as possible in the
+# script to make things like `--version' happen as quickly as we can.
+{
+  # this just eases exit handling
+  while test $# -gt 0; do
+    opt="$1"
+    shift
+    case $opt in
+      --debug|-x)	opt_debug='set -x'
+			func_echo "enabling shell trace mode"
+			$opt_debug
+			;;
+      --dry-run|--dryrun|-n)
+			opt_dry_run=:
+			;;
+      --config)
+			opt_config=:
+func_config
+			;;
+      --dlopen|-dlopen)
+			optarg="$1"
+			opt_dlopen="${opt_dlopen+$opt_dlopen
+}$optarg"
+			shift
+			;;
+      --preserve-dup-deps)
+			opt_preserve_dup_deps=:
+			;;
+      --features)
+			opt_features=:
+func_features
+			;;
+      --finish)
+			opt_finish=:
+set dummy --mode finish ${1+"$@"}; shift
+			;;
+      --help)
+			opt_help=:
+			;;
+      --help-all)
+			opt_help_all=:
+opt_help=': help-all'
+			;;
+      --mode)
+			test $# = 0 && func_missing_arg $opt && break
+			optarg="$1"
+			opt_mode="$optarg"
+case $optarg in
+  # Valid mode arguments:
+  clean|compile|execute|finish|install|link|relink|uninstall) ;;
+
+  # Catch anything else as an error
+  *) func_error "invalid argument for $opt"
+     exit_cmd=exit
+     break
+     ;;
+esac
+			shift
+			;;
+      --no-silent|--no-quiet)
+			opt_silent=false
+func_append preserve_args " $opt"
+			;;
+      --no-warning|--no-warn)
+			opt_warning=false
+func_append preserve_args " $opt"
+			;;
+      --no-verbose)
+			opt_verbose=false
+func_append preserve_args " $opt"
+			;;
+      --silent|--quiet)
+			opt_silent=:
+func_append preserve_args " $opt"
+        opt_verbose=false
+			;;
+      --verbose|-v)
+			opt_verbose=:
+func_append preserve_args " $opt"
+opt_silent=false
+			;;
+      --tag)
+			test $# = 0 && func_missing_arg $opt && break
+			optarg="$1"
+			opt_tag="$optarg"
+func_append preserve_args " $opt $optarg"
+func_enable_tag "$optarg"
+			shift
+			;;
+
+      -\?|-h)		func_usage				;;
+      --help)		func_help				;;
+      --version)	func_version				;;
+
+      # Separate optargs to long options:
+      --*=*)
+			func_split_long_opt "$opt"
+			set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"}
+			shift
+			;;
+
+      # Separate non-argument short options:
+      -\?*|-h*|-n*|-v*)
+			func_split_short_opt "$opt"
+			set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"}
+			shift
+			;;
+
+      --)		break					;;
+      -*)		func_fatal_help "unrecognized option \`$opt'" ;;
+      *)		set dummy "$opt" ${1+"$@"};	shift; break  ;;
+    esac
+  done
+
+  # Validate options:
+
+  # save first non-option argument
+  if test "$#" -gt 0; then
+    nonopt="$opt"
+    shift
+  fi
+
+  # preserve --debug
+  test "$opt_debug" = : || func_append preserve_args " --debug"
+
+  case $host in
+    *cygwin* | *mingw* | *pw32* | *cegcc*)
+      # don't eliminate duplications in $postdeps and $predeps
+      opt_duplicate_compiler_generated_deps=:
+      ;;
+    *)
+      opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps
+      ;;
+  esac
+
+  $opt_help || {
+    # Sanity checks first:
+    func_check_version_match
+
+    if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+      func_fatal_configuration "not configured to build any kind of library"
+    fi
+
+    # Darwin sucks
+    eval std_shrext=\"$shrext_cmds\"
+
+    # Only execute mode is allowed to have -dlopen flags.
+    if test -n "$opt_dlopen" && test "$opt_mode" != execute; then
+      func_error "unrecognized option \`-dlopen'"
+      $ECHO "$help" 1>&2
+      exit $EXIT_FAILURE
+    fi
+
+    # Change the help message to a mode-specific one.
+    generic_help="$help"
+    help="Try \`$progname --help --mode=$opt_mode' for more information."
+  }
+
+
+  # Bail if the options were screwed
+  $exit_cmd $EXIT_FAILURE
+}
+
+
+
+
+## ----------- ##
+##    Main.    ##
+## ----------- ##
+
+# func_lalib_p file
+# True iff FILE is a libtool `.la' library or `.lo' object file.
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_lalib_p ()
+{
+    test -f "$1" &&
+      $SED -e 4q "$1" 2>/dev/null \
+        | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1
+}
+
+# func_lalib_unsafe_p file
+# True iff FILE is a libtool `.la' library or `.lo' object file.
+# This function implements the same check as func_lalib_p without
+# resorting to external programs.  To this end, it redirects stdin and
+# closes it afterwards, without saving the original file descriptor.
+# As a safety measure, use it only where a negative result would be
+# fatal anyway.  Works if `file' does not exist.
+func_lalib_unsafe_p ()
+{
+    lalib_p=no
+    if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then
+	for lalib_p_l in 1 2 3 4
+	do
+	    read lalib_p_line
+	    case "$lalib_p_line" in
+		\#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;;
+	    esac
+	done
+	exec 0<&5 5<&-
+    fi
+    test "$lalib_p" = yes
+}
+
+# func_ltwrapper_script_p file
+# True iff FILE is a libtool wrapper script
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_script_p ()
+{
+    func_lalib_p "$1"
+}
+
+# func_ltwrapper_executable_p file
+# True iff FILE is a libtool wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_executable_p ()
+{
+    func_ltwrapper_exec_suffix=
+    case $1 in
+    *.exe) ;;
+    *) func_ltwrapper_exec_suffix=.exe ;;
+    esac
+    $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1
+}
+
+# func_ltwrapper_scriptname file
+# Assumes file is an ltwrapper_executable
+# uses $file to determine the appropriate filename for a
+# temporary ltwrapper_script.
+func_ltwrapper_scriptname ()
+{
+    func_dirname_and_basename "$1" "" "."
+    func_stripname '' '.exe' "$func_basename_result"
+    func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper"
+}
+
+# func_ltwrapper_p file
+# True iff FILE is a libtool wrapper script or wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_p ()
+{
+    func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1"
+}
+
+
+# func_execute_cmds commands fail_cmd
+# Execute tilde-delimited COMMANDS.
+# If FAIL_CMD is given, eval that upon failure.
+# FAIL_CMD may read-access the current command in variable CMD!
+func_execute_cmds ()
+{
+    $opt_debug
+    save_ifs=$IFS; IFS='~'
+    for cmd in $1; do
+      IFS=$save_ifs
+      eval cmd=\"$cmd\"
+      func_show_eval "$cmd" "${2-:}"
+    done
+    IFS=$save_ifs
+}
+
+
+# func_source file
+# Source FILE, adding directory component if necessary.
+# Note that it is not necessary on cygwin/mingw to append a dot to
+# FILE even if both FILE and FILE.exe exist: automatic-append-.exe
+# behavior happens only for exec(3), not for open(2)!  Also, sourcing
+# `FILE.' does not work on cygwin managed mounts.
+func_source ()
+{
+    $opt_debug
+    case $1 in
+    */* | *\\*)	. "$1" ;;
+    *)		. "./$1" ;;
+    esac
+}
+
+
+# func_resolve_sysroot PATH
+# Replace a leading = in PATH with a sysroot.  Store the result into
+# func_resolve_sysroot_result
+func_resolve_sysroot ()
+{
+  func_resolve_sysroot_result=$1
+  case $func_resolve_sysroot_result in
+  =*)
+    func_stripname '=' '' "$func_resolve_sysroot_result"
+    func_resolve_sysroot_result=$lt_sysroot$func_stripname_result
+    ;;
+  esac
+}
+
+# func_replace_sysroot PATH
+# If PATH begins with the sysroot, replace it with = and
+# store the result into func_replace_sysroot_result.
+func_replace_sysroot ()
+{
+  case "$lt_sysroot:$1" in
+  ?*:"$lt_sysroot"*)
+    func_stripname "$lt_sysroot" '' "$1"
+    func_replace_sysroot_result="=$func_stripname_result"
+    ;;
+  *)
+    # Including no sysroot.
+    func_replace_sysroot_result=$1
+    ;;
+  esac
+}
+
+# func_infer_tag arg
+# Infer tagged configuration to use if any are available and
+# if one wasn't chosen via the "--tag" command line option.
+# Only attempt this if the compiler in the base compile
+# command doesn't match the default compiler.
+# arg is usually of the form 'gcc ...'
+func_infer_tag ()
+{
+    $opt_debug
+    if test -n "$available_tags" && test -z "$tagname"; then
+      CC_quoted=
+      for arg in $CC; do
+	func_append_quoted CC_quoted "$arg"
+      done
+      CC_expanded=`func_echo_all $CC`
+      CC_quoted_expanded=`func_echo_all $CC_quoted`
+      case $@ in
+      # Blanks in the command may have been stripped by the calling shell,
+      # but not from the CC environment variable when configure was run.
+      " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
+      " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;;
+      # Blanks at the start of $base_compile will cause this to fail
+      # if we don't check for them as well.
+      *)
+	for z in $available_tags; do
+	  if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
+	    # Evaluate the configuration.
+	    eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
+	    CC_quoted=
+	    for arg in $CC; do
+	      # Double-quote args containing other shell metacharacters.
+	      func_append_quoted CC_quoted "$arg"
+	    done
+	    CC_expanded=`func_echo_all $CC`
+	    CC_quoted_expanded=`func_echo_all $CC_quoted`
+	    case "$@ " in
+	    " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
+	    " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*)
+	      # The compiler in the base compile command matches
+	      # the one in the tagged configuration.
+	      # Assume this is the tagged configuration we want.
+	      tagname=$z
+	      break
+	      ;;
+	    esac
+	  fi
+	done
+	# If $tagname still isn't set, then no tagged configuration
+	# was found and let the user know that the "--tag" command
+	# line option must be used.
+	if test -z "$tagname"; then
+	  func_echo "unable to infer tagged configuration"
+	  func_fatal_error "specify a tag with \`--tag'"
+#	else
+#	  func_verbose "using $tagname tagged configuration"
+	fi
+	;;
+      esac
+    fi
+}
+
+
+
+# func_write_libtool_object output_name pic_name nonpic_name
+# Create a libtool object file (analogous to a ".la" file),
+# but don't create it if we're doing a dry run.
+func_write_libtool_object ()
+{
+    write_libobj=${1}
+    if test "$build_libtool_libs" = yes; then
+      write_lobj=\'${2}\'
+    else
+      write_lobj=none
+    fi
+
+    if test "$build_old_libs" = yes; then
+      write_oldobj=\'${3}\'
+    else
+      write_oldobj=none
+    fi
+
+    $opt_dry_run || {
+      cat >${write_libobj}T <<EOF
+# $write_libobj - a libtool object file
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+pic_object=$write_lobj
+
+# Name of the non-PIC object
+non_pic_object=$write_oldobj
+
+EOF
+      $MV "${write_libobj}T" "${write_libobj}"
+    }
+}
+
+
+##################################################
+# FILE NAME AND PATH CONVERSION HELPER FUNCTIONS #
+##################################################
+
+# func_convert_core_file_wine_to_w32 ARG
+# Helper function used by file name conversion functions when $build is *nix,
+# and $host is mingw, cygwin, or some other w32 environment. Relies on a
+# correctly configured wine environment available, with the winepath program
+# in $build's $PATH.
+#
+# ARG is the $build file name to be converted to w32 format.
+# Result is available in $func_convert_core_file_wine_to_w32_result, and will
+# be empty on error (or when ARG is empty)
+func_convert_core_file_wine_to_w32 ()
+{
+  $opt_debug
+  func_convert_core_file_wine_to_w32_result="$1"
+  if test -n "$1"; then
+    # Unfortunately, winepath does not exit with a non-zero error code, so we
+    # are forced to check the contents of stdout. On the other hand, if the
+    # command is not found, the shell will set an exit code of 127 and print
+    # *an error message* to stdout. So we must check for both error code of
+    # zero AND non-empty stdout, which explains the odd construction:
+    func_convert_core_file_wine_to_w32_tmp=`winepath -w "$1" 2>/dev/null`
+    if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then
+      func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" |
+        $SED -e "$lt_sed_naive_backslashify"`
+    else
+      func_convert_core_file_wine_to_w32_result=
+    fi
+  fi
+}
+# end: func_convert_core_file_wine_to_w32
+
+
+# func_convert_core_path_wine_to_w32 ARG
+# Helper function used by path conversion functions when $build is *nix, and
+# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly
+# configured wine environment available, with the winepath program in $build's
+# $PATH. Assumes ARG has no leading or trailing path separator characters.
+#
+# ARG is path to be converted from $build format to win32.
+# Result is available in $func_convert_core_path_wine_to_w32_result.
+# Unconvertible file (directory) names in ARG are skipped; if no directory names
+# are convertible, then the result may be empty.
+func_convert_core_path_wine_to_w32 ()
+{
+  $opt_debug
+  # unfortunately, winepath doesn't convert paths, only file names
+  func_convert_core_path_wine_to_w32_result=""
+  if test -n "$1"; then
+    oldIFS=$IFS
+    IFS=:
+    for func_convert_core_path_wine_to_w32_f in $1; do
+      IFS=$oldIFS
+      func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f"
+      if test -n "$func_convert_core_file_wine_to_w32_result" ; then
+        if test -z "$func_convert_core_path_wine_to_w32_result"; then
+          func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result"
+        else
+          func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result"
+        fi
+      fi
+    done
+    IFS=$oldIFS
+  fi
+}
+# end: func_convert_core_path_wine_to_w32
+
+
+# func_cygpath ARGS...
+# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when
+# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2)
+# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or
+# (2), returns the Cygwin file name or path in func_cygpath_result (input
+# file name or path is assumed to be in w32 format, as previously converted
+# from $build's *nix or MSYS format). In case (3), returns the w32 file name
+# or path in func_cygpath_result (input file name or path is assumed to be in
+# Cygwin format). Returns an empty string on error.
+#
+# ARGS are passed to cygpath, with the last one being the file name or path to
+# be converted.
+#
+# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH
+# environment variable; do not put it in $PATH.
+func_cygpath ()
+{
+  $opt_debug
+  if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then
+    func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null`
+    if test "$?" -ne 0; then
+      # on failure, ensure result is empty
+      func_cygpath_result=
+    fi
+  else
+    func_cygpath_result=
+    func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'"
+  fi
+}
+#end: func_cygpath
+
+
+# func_convert_core_msys_to_w32 ARG
+# Convert file name or path ARG from MSYS format to w32 format.  Return
+# result in func_convert_core_msys_to_w32_result.
+func_convert_core_msys_to_w32 ()
+{
+  $opt_debug
+  # awkward: cmd appends spaces to result
+  func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null |
+    $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"`
+}
+#end: func_convert_core_msys_to_w32
+
+
+# func_convert_file_check ARG1 ARG2
+# Verify that ARG1 (a file name in $build format) was converted to $host
+# format in ARG2. Otherwise, emit an error message, but continue (resetting
+# func_to_host_file_result to ARG1).
+func_convert_file_check ()
+{
+  $opt_debug
+  if test -z "$2" && test -n "$1" ; then
+    func_error "Could not determine host file name corresponding to"
+    func_error "  \`$1'"
+    func_error "Continuing, but uninstalled executables may not work."
+    # Fallback:
+    func_to_host_file_result="$1"
+  fi
+}
+# end func_convert_file_check
+
+
+# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH
+# Verify that FROM_PATH (a path in $build format) was converted to $host
+# format in TO_PATH. Otherwise, emit an error message, but continue, resetting
+# func_to_host_file_result to a simplistic fallback value (see below).
+func_convert_path_check ()
+{
+  $opt_debug
+  if test -z "$4" && test -n "$3"; then
+    func_error "Could not determine the host path corresponding to"
+    func_error "  \`$3'"
+    func_error "Continuing, but uninstalled executables may not work."
+    # Fallback.  This is a deliberately simplistic "conversion" and
+    # should not be "improved".  See libtool.info.
+    if test "x$1" != "x$2"; then
+      lt_replace_pathsep_chars="s|$1|$2|g"
+      func_to_host_path_result=`echo "$3" |
+        $SED -e "$lt_replace_pathsep_chars"`
+    else
+      func_to_host_path_result="$3"
+    fi
+  fi
+}
+# end func_convert_path_check
+
+
+# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG
+# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT
+# and appending REPL if ORIG matches BACKPAT.
+func_convert_path_front_back_pathsep ()
+{
+  $opt_debug
+  case $4 in
+  $1 ) func_to_host_path_result="$3$func_to_host_path_result"
+    ;;
+  esac
+  case $4 in
+  $2 ) func_append func_to_host_path_result "$3"
+    ;;
+  esac
+}
+# end func_convert_path_front_back_pathsep
+
+
+##################################################
+# $build to $host FILE NAME CONVERSION FUNCTIONS #
+##################################################
+# invoked via `$to_host_file_cmd ARG'
+#
+# In each case, ARG is the path to be converted from $build to $host format.
+# Result will be available in $func_to_host_file_result.
+
+
+# func_to_host_file ARG
+# Converts the file name ARG from $build format to $host format. Return result
+# in func_to_host_file_result.
+func_to_host_file ()
+{
+  $opt_debug
+  $to_host_file_cmd "$1"
+}
+# end func_to_host_file
+
+
+# func_to_tool_file ARG LAZY
+# converts the file name ARG from $build format to toolchain format. Return
+# result in func_to_tool_file_result.  If the conversion in use is listed
+# in (the comma separated) LAZY, no conversion takes place.
+func_to_tool_file ()
+{
+  $opt_debug
+  case ,$2, in
+    *,"$to_tool_file_cmd",*)
+      func_to_tool_file_result=$1
+      ;;
+    *)
+      $to_tool_file_cmd "$1"
+      func_to_tool_file_result=$func_to_host_file_result
+      ;;
+  esac
+}
+# end func_to_tool_file
+
+
+# func_convert_file_noop ARG
+# Copy ARG to func_to_host_file_result.
+func_convert_file_noop ()
+{
+  func_to_host_file_result="$1"
+}
+# end func_convert_file_noop
+
+
+# func_convert_file_msys_to_w32 ARG
+# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic
+# conversion to w32 is not available inside the cwrapper.  Returns result in
+# func_to_host_file_result.
+func_convert_file_msys_to_w32 ()
+{
+  $opt_debug
+  func_to_host_file_result="$1"
+  if test -n "$1"; then
+    func_convert_core_msys_to_w32 "$1"
+    func_to_host_file_result="$func_convert_core_msys_to_w32_result"
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_msys_to_w32
+
+
+# func_convert_file_cygwin_to_w32 ARG
+# Convert file name ARG from Cygwin to w32 format.  Returns result in
+# func_to_host_file_result.
+func_convert_file_cygwin_to_w32 ()
+{
+  $opt_debug
+  func_to_host_file_result="$1"
+  if test -n "$1"; then
+    # because $build is cygwin, we call "the" cygpath in $PATH; no need to use
+    # LT_CYGPATH in this case.
+    func_to_host_file_result=`cygpath -m "$1"`
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_cygwin_to_w32
+
+
+# func_convert_file_nix_to_w32 ARG
+# Convert file name ARG from *nix to w32 format.  Requires a wine environment
+# and a working winepath. Returns result in func_to_host_file_result.
+func_convert_file_nix_to_w32 ()
+{
+  $opt_debug
+  func_to_host_file_result="$1"
+  if test -n "$1"; then
+    func_convert_core_file_wine_to_w32 "$1"
+    func_to_host_file_result="$func_convert_core_file_wine_to_w32_result"
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_nix_to_w32
+
+
+# func_convert_file_msys_to_cygwin ARG
+# Convert file name ARG from MSYS to Cygwin format.  Requires LT_CYGPATH set.
+# Returns result in func_to_host_file_result.
+func_convert_file_msys_to_cygwin ()
+{
+  $opt_debug
+  func_to_host_file_result="$1"
+  if test -n "$1"; then
+    func_convert_core_msys_to_w32 "$1"
+    func_cygpath -u "$func_convert_core_msys_to_w32_result"
+    func_to_host_file_result="$func_cygpath_result"
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_msys_to_cygwin
+
+
+# func_convert_file_nix_to_cygwin ARG
+# Convert file name ARG from *nix to Cygwin format.  Requires Cygwin installed
+# in a wine environment, working winepath, and LT_CYGPATH set.  Returns result
+# in func_to_host_file_result.
+func_convert_file_nix_to_cygwin ()
+{
+  $opt_debug
+  func_to_host_file_result="$1"
+  if test -n "$1"; then
+    # convert from *nix to w32, then use cygpath to convert from w32 to cygwin.
+    func_convert_core_file_wine_to_w32 "$1"
+    func_cygpath -u "$func_convert_core_file_wine_to_w32_result"
+    func_to_host_file_result="$func_cygpath_result"
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_nix_to_cygwin
+
+
+#############################################
+# $build to $host PATH CONVERSION FUNCTIONS #
+#############################################
+# invoked via `$to_host_path_cmd ARG'
+#
+# In each case, ARG is the path to be converted from $build to $host format.
+# The result will be available in $func_to_host_path_result.
+#
+# Path separators are also converted from $build format to $host format.  If
+# ARG begins or ends with a path separator character, it is preserved (but
+# converted to $host format) on output.
+#
+# All path conversion functions are named using the following convention:
+#   file name conversion function    : func_convert_file_X_to_Y ()
+#   path conversion function         : func_convert_path_X_to_Y ()
+# where, for any given $build/$host combination the 'X_to_Y' value is the
+# same.  If conversion functions are added for new $build/$host combinations,
+# the two new functions must follow this pattern, or func_init_to_host_path_cmd
+# will break.
+
+
+# func_init_to_host_path_cmd
+# Ensures that function "pointer" variable $to_host_path_cmd is set to the
+# appropriate value, based on the value of $to_host_file_cmd.
+to_host_path_cmd=
+func_init_to_host_path_cmd ()
+{
+  $opt_debug
+  if test -z "$to_host_path_cmd"; then
+    func_stripname 'func_convert_file_' '' "$to_host_file_cmd"
+    to_host_path_cmd="func_convert_path_${func_stripname_result}"
+  fi
+}
+
+
+# func_to_host_path ARG
+# Converts the path ARG from $build format to $host format. Return result
+# in func_to_host_path_result.
+func_to_host_path ()
+{
+  $opt_debug
+  func_init_to_host_path_cmd
+  $to_host_path_cmd "$1"
+}
+# end func_to_host_path
+
+
+# func_convert_path_noop ARG
+# Copy ARG to func_to_host_path_result.
+func_convert_path_noop ()
+{
+  func_to_host_path_result="$1"
+}
+# end func_convert_path_noop
+
+
+# func_convert_path_msys_to_w32 ARG
+# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic
+# conversion to w32 is not available inside the cwrapper.  Returns result in
+# func_to_host_path_result.
+func_convert_path_msys_to_w32 ()
+{
+  $opt_debug
+  func_to_host_path_result="$1"
+  if test -n "$1"; then
+    # Remove leading and trailing path separator characters from ARG.  MSYS
+    # behavior is inconsistent here; cygpath turns them into '.;' and ';.';
+    # and winepath ignores them completely.
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_convert_core_msys_to_w32 "$func_to_host_path_tmp1"
+    func_to_host_path_result="$func_convert_core_msys_to_w32_result"
+    func_convert_path_check : ";" \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
+  fi
+}
+# end func_convert_path_msys_to_w32
+
+
+# func_convert_path_cygwin_to_w32 ARG
+# Convert path ARG from Cygwin to w32 format.  Returns result in
+# func_to_host_file_result.
+func_convert_path_cygwin_to_w32 ()
+{
+  $opt_debug
+  func_to_host_path_result="$1"
+  if test -n "$1"; then
+    # See func_convert_path_msys_to_w32:
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"`
+    func_convert_path_check : ";" \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
+  fi
+}
+# end func_convert_path_cygwin_to_w32
+
+
+# func_convert_path_nix_to_w32 ARG
+# Convert path ARG from *nix to w32 format.  Requires a wine environment and
+# a working winepath.  Returns result in func_to_host_file_result.
+func_convert_path_nix_to_w32 ()
+{
+  $opt_debug
+  func_to_host_path_result="$1"
+  if test -n "$1"; then
+    # See func_convert_path_msys_to_w32:
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1"
+    func_to_host_path_result="$func_convert_core_path_wine_to_w32_result"
+    func_convert_path_check : ";" \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
+  fi
+}
+# end func_convert_path_nix_to_w32
+
+
+# func_convert_path_msys_to_cygwin ARG
+# Convert path ARG from MSYS to Cygwin format.  Requires LT_CYGPATH set.
+# Returns result in func_to_host_file_result.
+func_convert_path_msys_to_cygwin ()
+{
+  $opt_debug
+  func_to_host_path_result="$1"
+  if test -n "$1"; then
+    # See func_convert_path_msys_to_w32:
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_convert_core_msys_to_w32 "$func_to_host_path_tmp1"
+    func_cygpath -u -p "$func_convert_core_msys_to_w32_result"
+    func_to_host_path_result="$func_cygpath_result"
+    func_convert_path_check : : \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" : "$1"
+  fi
+}
+# end func_convert_path_msys_to_cygwin
+
+
+# func_convert_path_nix_to_cygwin ARG
+# Convert path ARG from *nix to Cygwin format.  Requires Cygwin installed in a
+# a wine environment, working winepath, and LT_CYGPATH set.  Returns result in
+# func_to_host_file_result.
+func_convert_path_nix_to_cygwin ()
+{
+  $opt_debug
+  func_to_host_path_result="$1"
+  if test -n "$1"; then
+    # Remove leading and trailing path separator characters from
+    # ARG. msys behavior is inconsistent here, cygpath turns them
+    # into '.;' and ';.', and winepath ignores them completely.
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1"
+    func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result"
+    func_to_host_path_result="$func_cygpath_result"
+    func_convert_path_check : : \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" : "$1"
+  fi
+}
+# end func_convert_path_nix_to_cygwin
+
+
+# func_mode_compile arg...
+func_mode_compile ()
+{
+    $opt_debug
+    # Get the compilation command and the source file.
+    base_compile=
+    srcfile="$nonopt"  #  always keep a non-empty value in "srcfile"
+    suppress_opt=yes
+    suppress_output=
+    arg_mode=normal
+    libobj=
+    later=
+    pie_flag=
+
+    for arg
+    do
+      case $arg_mode in
+      arg  )
+	# do not "continue".  Instead, add this to base_compile
+	lastarg="$arg"
+	arg_mode=normal
+	;;
+
+      target )
+	libobj="$arg"
+	arg_mode=normal
+	continue
+	;;
+
+      normal )
+	# Accept any command-line options.
+	case $arg in
+	-o)
+	  test -n "$libobj" && \
+	    func_fatal_error "you cannot specify \`-o' more than once"
+	  arg_mode=target
+	  continue
+	  ;;
+
+	-pie | -fpie | -fPIE)
+          func_append pie_flag " $arg"
+	  continue
+	  ;;
+
+	-shared | -static | -prefer-pic | -prefer-non-pic)
+	  func_append later " $arg"
+	  continue
+	  ;;
+
+	-no-suppress)
+	  suppress_opt=no
+	  continue
+	  ;;
+
+	-Xcompiler)
+	  arg_mode=arg  #  the next one goes into the "base_compile" arg list
+	  continue      #  The current "srcfile" will either be retained or
+	  ;;            #  replaced later.  I would guess that would be a bug.
+
+	-Wc,*)
+	  func_stripname '-Wc,' '' "$arg"
+	  args=$func_stripname_result
+	  lastarg=
+	  save_ifs="$IFS"; IFS=','
+	  for arg in $args; do
+	    IFS="$save_ifs"
+	    func_append_quoted lastarg "$arg"
+	  done
+	  IFS="$save_ifs"
+	  func_stripname ' ' '' "$lastarg"
+	  lastarg=$func_stripname_result
+
+	  # Add the arguments to base_compile.
+	  func_append base_compile " $lastarg"
+	  continue
+	  ;;
+
+	*)
+	  # Accept the current argument as the source file.
+	  # The previous "srcfile" becomes the current argument.
+	  #
+	  lastarg="$srcfile"
+	  srcfile="$arg"
+	  ;;
+	esac  #  case $arg
+	;;
+      esac    #  case $arg_mode
+
+      # Aesthetically quote the previous argument.
+      func_append_quoted base_compile "$lastarg"
+    done # for arg
+
+    case $arg_mode in
+    arg)
+      func_fatal_error "you must specify an argument for -Xcompile"
+      ;;
+    target)
+      func_fatal_error "you must specify a target with \`-o'"
+      ;;
+    *)
+      # Get the name of the library object.
+      test -z "$libobj" && {
+	func_basename "$srcfile"
+	libobj="$func_basename_result"
+      }
+      ;;
+    esac
+
+    # Recognize several different file suffixes.
+    # If the user specifies -o file.o, it is replaced with file.lo
+    case $libobj in
+    *.[cCFSifmso] | \
+    *.ada | *.adb | *.ads | *.asm | \
+    *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \
+    *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup)
+      func_xform "$libobj"
+      libobj=$func_xform_result
+      ;;
+    esac
+
+    case $libobj in
+    *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;;
+    *)
+      func_fatal_error "cannot determine name of library object from \`$libobj'"
+      ;;
+    esac
+
+    func_infer_tag $base_compile
+
+    for arg in $later; do
+      case $arg in
+      -shared)
+	test "$build_libtool_libs" != yes && \
+	  func_fatal_configuration "can not build a shared library"
+	build_old_libs=no
+	continue
+	;;
+
+      -static)
+	build_libtool_libs=no
+	build_old_libs=yes
+	continue
+	;;
+
+      -prefer-pic)
+	pic_mode=yes
+	continue
+	;;
+
+      -prefer-non-pic)
+	pic_mode=no
+	continue
+	;;
+      esac
+    done
+
+    func_quote_for_eval "$libobj"
+    test "X$libobj" != "X$func_quote_for_eval_result" \
+      && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"'	 &()|`$[]' \
+      && func_warning "libobj name \`$libobj' may not contain shell special characters."
+    func_dirname_and_basename "$obj" "/" ""
+    objname="$func_basename_result"
+    xdir="$func_dirname_result"
+    lobj=${xdir}$objdir/$objname
+
+    test -z "$base_compile" && \
+      func_fatal_help "you must specify a compilation command"
+
+    # Delete any leftover library objects.
+    if test "$build_old_libs" = yes; then
+      removelist="$obj $lobj $libobj ${libobj}T"
+    else
+      removelist="$lobj $libobj ${libobj}T"
+    fi
+
+    # On Cygwin there's no "real" PIC flag so we must build both object types
+    case $host_os in
+    cygwin* | mingw* | pw32* | os2* | cegcc*)
+      pic_mode=default
+      ;;
+    esac
+    if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
+      # non-PIC code in shared libraries is not supported
+      pic_mode=default
+    fi
+
+    # Calculate the filename of the output object if compiler does
+    # not support -o with -c
+    if test "$compiler_c_o" = no; then
+      output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext}
+      lockfile="$output_obj.lock"
+    else
+      output_obj=
+      need_locks=no
+      lockfile=
+    fi
+
+    # Lock this critical section if it is needed
+    # We use this script file to make the link, it avoids creating a new file
+    if test "$need_locks" = yes; then
+      until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
+	func_echo "Waiting for $lockfile to be removed"
+	sleep 2
+      done
+    elif test "$need_locks" = warn; then
+      if test -f "$lockfile"; then
+	$ECHO "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$opt_dry_run || $RM $removelist
+	exit $EXIT_FAILURE
+      fi
+      func_append removelist " $output_obj"
+      $ECHO "$srcfile" > "$lockfile"
+    fi
+
+    $opt_dry_run || $RM $removelist
+    func_append removelist " $lockfile"
+    trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15
+
+    func_to_tool_file "$srcfile" func_convert_file_msys_to_w32
+    srcfile=$func_to_tool_file_result
+    func_quote_for_eval "$srcfile"
+    qsrcfile=$func_quote_for_eval_result
+
+    # Only build a PIC object if we are building libtool libraries.
+    if test "$build_libtool_libs" = yes; then
+      # Without this assignment, base_compile gets emptied.
+      fbsd_hideous_sh_bug=$base_compile
+
+      if test "$pic_mode" != no; then
+	command="$base_compile $qsrcfile $pic_flag"
+      else
+	# Don't build PIC code
+	command="$base_compile $qsrcfile"
+      fi
+
+      func_mkdir_p "$xdir$objdir"
+
+      if test -z "$output_obj"; then
+	# Place PIC objects in $objdir
+	func_append command " -o $lobj"
+      fi
+
+      func_show_eval_locale "$command"	\
+          'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE'
+
+      if test "$need_locks" = warn &&
+	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+	$ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$opt_dry_run || $RM $removelist
+	exit $EXIT_FAILURE
+      fi
+
+      # Just move the object if needed, then go on to compile the next one
+      if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
+	func_show_eval '$MV "$output_obj" "$lobj"' \
+	  'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+      fi
+
+      # Allow error messages only from the first compilation.
+      if test "$suppress_opt" = yes; then
+	suppress_output=' >/dev/null 2>&1'
+      fi
+    fi
+
+    # Only build a position-dependent object if we build old libraries.
+    if test "$build_old_libs" = yes; then
+      if test "$pic_mode" != yes; then
+	# Don't build PIC code
+	command="$base_compile $qsrcfile$pie_flag"
+      else
+	command="$base_compile $qsrcfile $pic_flag"
+      fi
+      if test "$compiler_c_o" = yes; then
+	func_append command " -o $obj"
+      fi
+
+      # Suppress compiler output if we already did a PIC compilation.
+      func_append command "$suppress_output"
+      func_show_eval_locale "$command" \
+        '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE'
+
+      if test "$need_locks" = warn &&
+	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+	$ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$opt_dry_run || $RM $removelist
+	exit $EXIT_FAILURE
+      fi
+
+      # Just move the object if needed
+      if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
+	func_show_eval '$MV "$output_obj" "$obj"' \
+	  'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+      fi
+    fi
+
+    $opt_dry_run || {
+      func_write_libtool_object "$libobj" "$objdir/$objname" "$objname"
+
+      # Unlock the critical section if it was locked
+      if test "$need_locks" != no; then
+	removelist=$lockfile
+        $RM "$lockfile"
+      fi
+    }
+
+    exit $EXIT_SUCCESS
+}
+
+$opt_help || {
+  test "$opt_mode" = compile && func_mode_compile ${1+"$@"}
+}
+
+func_mode_help ()
+{
+    # We need to display help for each of the modes.
+    case $opt_mode in
+      "")
+        # Generic help is extracted from the usage comments
+        # at the start of this file.
+        func_help
+        ;;
+
+      clean)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+        ;;
+
+      compile)
+      $ECHO \
+"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+  -o OUTPUT-FILE    set the output file name to OUTPUT-FILE
+  -no-suppress      do not suppress compiler output for multiple passes
+  -prefer-pic       try to build PIC objects only
+  -prefer-non-pic   try to build non-PIC objects only
+  -shared           do not build a \`.o' file suitable for static linking
+  -static           only build a \`.o' file suitable for static linking
+  -Wc,FLAG          pass FLAG directly to the compiler
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+        ;;
+
+      execute)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+  -dlopen FILE      add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+        ;;
+
+      finish)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges.  Use
+the \`--dry-run' option if you just want to see what would be executed."
+        ;;
+
+      install)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command.  The first component should be
+either the \`install' or \`cp' program.
+
+The following components of INSTALL-COMMAND are treated specially:
+
+  -inst-prefix-dir PREFIX-DIR  Use PREFIX-DIR as a staging area for installation
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+        ;;
+
+      link)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+  -all-static       do not do any dynamic linking at all
+  -avoid-version    do not add a version suffix if possible
+  -bindir BINDIR    specify path to binaries directory (for systems where
+                    libraries must be found in the PATH setting at runtime)
+  -dlopen FILE      \`-dlpreopen' FILE if it cannot be dlopened at runtime
+  -dlpreopen FILE   link in FILE and add its symbols to lt_preloaded_symbols
+  -export-dynamic   allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+  -export-symbols SYMFILE
+                    try to export only the symbols listed in SYMFILE
+  -export-symbols-regex REGEX
+                    try to export only the symbols matching REGEX
+  -LLIBDIR          search LIBDIR for required installed libraries
+  -lNAME            OUTPUT-FILE requires the installed library libNAME
+  -module           build a library that can dlopened
+  -no-fast-install  disable the fast-install mode
+  -no-install       link a not-installable executable
+  -no-undefined     declare that a library does not refer to external symbols
+  -o OUTPUT-FILE    create OUTPUT-FILE from the specified objects
+  -objectlist FILE  Use a list of object files found in FILE to specify objects
+  -precious-files-regex REGEX
+                    don't remove output files matching REGEX
+  -release RELEASE  specify package release information
+  -rpath LIBDIR     the created library will eventually be installed in LIBDIR
+  -R[ ]LIBDIR       add LIBDIR to the runtime path of programs and libraries
+  -shared           only do dynamic linking of libtool libraries
+  -shrext SUFFIX    override the standard shared library file extension
+  -static           do not do any dynamic linking of uninstalled libtool libraries
+  -static-libtool-libs
+                    do not do any dynamic linking of libtool libraries
+  -version-info CURRENT[:REVISION[:AGE]]
+                    specify library version info [each variable defaults to 0]
+  -weak LIBNAME     declare that the target provides the LIBNAME interface
+  -Wc,FLAG
+  -Xcompiler FLAG   pass linker-specific FLAG directly to the compiler
+  -Wl,FLAG
+  -Xlinker FLAG     pass linker-specific FLAG directly to the linker
+  -XCClinker FLAG   pass link-specific FLAG to the compiler driver (CC)
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename.  Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+        ;;
+
+      uninstall)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+        ;;
+
+      *)
+        func_fatal_help "invalid operation mode \`$opt_mode'"
+        ;;
+    esac
+
+    echo
+    $ECHO "Try \`$progname --help' for more information about other modes."
+}
+
+# Now that we've collected a possible --mode arg, show help if necessary
+if $opt_help; then
+  if test "$opt_help" = :; then
+    func_mode_help
+  else
+    {
+      func_help noexit
+      for opt_mode in compile link execute install finish uninstall clean; do
+	func_mode_help
+      done
+    } | sed -n '1p; 2,$s/^Usage:/  or: /p'
+    {
+      func_help noexit
+      for opt_mode in compile link execute install finish uninstall clean; do
+	echo
+	func_mode_help
+      done
+    } |
+    sed '1d
+      /^When reporting/,/^Report/{
+	H
+	d
+      }
+      $x
+      /information about other modes/d
+      /more detailed .*MODE/d
+      s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/'
+  fi
+  exit $?
+fi
+
+
+# func_mode_execute arg...
+func_mode_execute ()
+{
+    $opt_debug
+    # The first argument is the command name.
+    cmd="$nonopt"
+    test -z "$cmd" && \
+      func_fatal_help "you must specify a COMMAND"
+
+    # Handle -dlopen flags immediately.
+    for file in $opt_dlopen; do
+      test -f "$file" \
+	|| func_fatal_help "\`$file' is not a file"
+
+      dir=
+      case $file in
+      *.la)
+	func_resolve_sysroot "$file"
+	file=$func_resolve_sysroot_result
+
+	# Check to see that this really is a libtool archive.
+	func_lalib_unsafe_p "$file" \
+	  || func_fatal_help "\`$lib' is not a valid libtool archive"
+
+	# Read the libtool library.
+	dlname=
+	library_names=
+	func_source "$file"
+
+	# Skip this library if it cannot be dlopened.
+	if test -z "$dlname"; then
+	  # Warn if it was a shared library.
+	  test -n "$library_names" && \
+	    func_warning "\`$file' was not linked with \`-export-dynamic'"
+	  continue
+	fi
+
+	func_dirname "$file" "" "."
+	dir="$func_dirname_result"
+
+	if test -f "$dir/$objdir/$dlname"; then
+	  func_append dir "/$objdir"
+	else
+	  if test ! -f "$dir/$dlname"; then
+	    func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'"
+	  fi
+	fi
+	;;
+
+      *.lo)
+	# Just add the directory containing the .lo file.
+	func_dirname "$file" "" "."
+	dir="$func_dirname_result"
+	;;
+
+      *)
+	func_warning "\`-dlopen' is ignored for non-libtool libraries and objects"
+	continue
+	;;
+      esac
+
+      # Get the absolute pathname.
+      absdir=`cd "$dir" && pwd`
+      test -n "$absdir" && dir="$absdir"
+
+      # Now add the directory to shlibpath_var.
+      if eval "test -z \"\$$shlibpath_var\""; then
+	eval "$shlibpath_var=\"\$dir\""
+      else
+	eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+      fi
+    done
+
+    # This variable tells wrapper scripts just to set shlibpath_var
+    # rather than running their programs.
+    libtool_execute_magic="$magic"
+
+    # Check if any of the arguments is a wrapper script.
+    args=
+    for file
+    do
+      case $file in
+      -* | *.la | *.lo ) ;;
+      *)
+	# Do a test to see if this is really a libtool program.
+	if func_ltwrapper_script_p "$file"; then
+	  func_source "$file"
+	  # Transform arg to wrapped name.
+	  file="$progdir/$program"
+	elif func_ltwrapper_executable_p "$file"; then
+	  func_ltwrapper_scriptname "$file"
+	  func_source "$func_ltwrapper_scriptname_result"
+	  # Transform arg to wrapped name.
+	  file="$progdir/$program"
+	fi
+	;;
+      esac
+      # Quote arguments (to preserve shell metacharacters).
+      func_append_quoted args "$file"
+    done
+
+    if test "X$opt_dry_run" = Xfalse; then
+      if test -n "$shlibpath_var"; then
+	# Export the shlibpath_var.
+	eval "export $shlibpath_var"
+      fi
+
+      # Restore saved environment variables
+      for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+      do
+	eval "if test \"\${save_$lt_var+set}\" = set; then
+                $lt_var=\$save_$lt_var; export $lt_var
+	      else
+		$lt_unset $lt_var
+	      fi"
+      done
+
+      # Now prepare to actually exec the command.
+      exec_cmd="\$cmd$args"
+    else
+      # Display what would be done.
+      if test -n "$shlibpath_var"; then
+	eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\""
+	echo "export $shlibpath_var"
+      fi
+      $ECHO "$cmd$args"
+      exit $EXIT_SUCCESS
+    fi
+}
+
+test "$opt_mode" = execute && func_mode_execute ${1+"$@"}
+
+
+# func_mode_finish arg...
+func_mode_finish ()
+{
+    $opt_debug
+    libs=
+    libdirs=
+    admincmds=
+
+    for opt in "$nonopt" ${1+"$@"}
+    do
+      if test -d "$opt"; then
+	func_append libdirs " $opt"
+
+      elif test -f "$opt"; then
+	if func_lalib_unsafe_p "$opt"; then
+	  func_append libs " $opt"
+	else
+	  func_warning "\`$opt' is not a valid libtool archive"
+	fi
+
+      else
+	func_fatal_error "invalid argument \`$opt'"
+      fi
+    done
+
+    if test -n "$libs"; then
+      if test -n "$lt_sysroot"; then
+        sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"`
+        sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;"
+      else
+        sysroot_cmd=
+      fi
+
+      # Remove sysroot references
+      if $opt_dry_run; then
+        for lib in $libs; do
+          echo "removing references to $lt_sysroot and \`=' prefixes from $lib"
+        done
+      else
+        tmpdir=`func_mktempdir`
+        for lib in $libs; do
+	  sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \
+	    > $tmpdir/tmp-la
+	  mv -f $tmpdir/tmp-la $lib
+	done
+        ${RM}r "$tmpdir"
+      fi
+    fi
+
+    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+      for libdir in $libdirs; do
+	if test -n "$finish_cmds"; then
+	  # Do each command in the finish commands.
+	  func_execute_cmds "$finish_cmds" 'admincmds="$admincmds
+'"$cmd"'"'
+	fi
+	if test -n "$finish_eval"; then
+	  # Do the single finish_eval.
+	  eval cmds=\"$finish_eval\"
+	  $opt_dry_run || eval "$cmds" || func_append admincmds "
+       $cmds"
+	fi
+      done
+    fi
+
+    # Exit here if they wanted silent mode.
+    $opt_silent && exit $EXIT_SUCCESS
+
+    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+      echo "----------------------------------------------------------------------"
+      echo "Libraries have been installed in:"
+      for libdir in $libdirs; do
+	$ECHO "   $libdir"
+      done
+      echo
+      echo "If you ever happen to want to link against installed libraries"
+      echo "in a given directory, LIBDIR, you must either use libtool, and"
+      echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
+      echo "flag during linking and do at least one of the following:"
+      if test -n "$shlibpath_var"; then
+	echo "   - add LIBDIR to the \`$shlibpath_var' environment variable"
+	echo "     during execution"
+      fi
+      if test -n "$runpath_var"; then
+	echo "   - add LIBDIR to the \`$runpath_var' environment variable"
+	echo "     during linking"
+      fi
+      if test -n "$hardcode_libdir_flag_spec"; then
+	libdir=LIBDIR
+	eval flag=\"$hardcode_libdir_flag_spec\"
+
+	$ECHO "   - use the \`$flag' linker flag"
+      fi
+      if test -n "$admincmds"; then
+	$ECHO "   - have your system administrator run these commands:$admincmds"
+      fi
+      if test -f /etc/ld.so.conf; then
+	echo "   - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+      fi
+      echo
+
+      echo "See any operating system documentation about shared libraries for"
+      case $host in
+	solaris2.[6789]|solaris2.1[0-9])
+	  echo "more information, such as the ld(1), crle(1) and ld.so(8) manual"
+	  echo "pages."
+	  ;;
+	*)
+	  echo "more information, such as the ld(1) and ld.so(8) manual pages."
+	  ;;
+      esac
+      echo "----------------------------------------------------------------------"
+    fi
+    exit $EXIT_SUCCESS
+}
+
+test "$opt_mode" = finish && func_mode_finish ${1+"$@"}
+
+
+# func_mode_install arg...
+func_mode_install ()
+{
+    $opt_debug
+    # There may be an optional sh(1) argument at the beginning of
+    # install_prog (especially on Windows NT).
+    if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
+       # Allow the use of GNU shtool's install command.
+       case $nonopt in *shtool*) :;; *) false;; esac; then
+      # Aesthetically quote it.
+      func_quote_for_eval "$nonopt"
+      install_prog="$func_quote_for_eval_result "
+      arg=$1
+      shift
+    else
+      install_prog=
+      arg=$nonopt
+    fi
+
+    # The real first argument should be the name of the installation program.
+    # Aesthetically quote it.
+    func_quote_for_eval "$arg"
+    func_append install_prog "$func_quote_for_eval_result"
+    install_shared_prog=$install_prog
+    case " $install_prog " in
+      *[\\\ /]cp\ *) install_cp=: ;;
+      *) install_cp=false ;;
+    esac
+
+    # We need to accept at least all the BSD install flags.
+    dest=
+    files=
+    opts=
+    prev=
+    install_type=
+    isdir=no
+    stripme=
+    no_mode=:
+    for arg
+    do
+      arg2=
+      if test -n "$dest"; then
+	func_append files " $dest"
+	dest=$arg
+	continue
+      fi
+
+      case $arg in
+      -d) isdir=yes ;;
+      -f)
+	if $install_cp; then :; else
+	  prev=$arg
+	fi
+	;;
+      -g | -m | -o)
+	prev=$arg
+	;;
+      -s)
+	stripme=" -s"
+	continue
+	;;
+      -*)
+	;;
+      *)
+	# If the previous option needed an argument, then skip it.
+	if test -n "$prev"; then
+	  if test "x$prev" = x-m && test -n "$install_override_mode"; then
+	    arg2=$install_override_mode
+	    no_mode=false
+	  fi
+	  prev=
+	else
+	  dest=$arg
+	  continue
+	fi
+	;;
+      esac
+
+      # Aesthetically quote the argument.
+      func_quote_for_eval "$arg"
+      func_append install_prog " $func_quote_for_eval_result"
+      if test -n "$arg2"; then
+	func_quote_for_eval "$arg2"
+      fi
+      func_append install_shared_prog " $func_quote_for_eval_result"
+    done
+
+    test -z "$install_prog" && \
+      func_fatal_help "you must specify an install program"
+
+    test -n "$prev" && \
+      func_fatal_help "the \`$prev' option requires an argument"
+
+    if test -n "$install_override_mode" && $no_mode; then
+      if $install_cp; then :; else
+	func_quote_for_eval "$install_override_mode"
+	func_append install_shared_prog " -m $func_quote_for_eval_result"
+      fi
+    fi
+
+    if test -z "$files"; then
+      if test -z "$dest"; then
+	func_fatal_help "no file or destination specified"
+      else
+	func_fatal_help "you must specify a destination"
+      fi
+    fi
+
+    # Strip any trailing slash from the destination.
+    func_stripname '' '/' "$dest"
+    dest=$func_stripname_result
+
+    # Check to see that the destination is a directory.
+    test -d "$dest" && isdir=yes
+    if test "$isdir" = yes; then
+      destdir="$dest"
+      destname=
+    else
+      func_dirname_and_basename "$dest" "" "."
+      destdir="$func_dirname_result"
+      destname="$func_basename_result"
+
+      # Not a directory, so check to see that there is only one file specified.
+      set dummy $files; shift
+      test "$#" -gt 1 && \
+	func_fatal_help "\`$dest' is not a directory"
+    fi
+    case $destdir in
+    [\\/]* | [A-Za-z]:[\\/]*) ;;
+    *)
+      for file in $files; do
+	case $file in
+	*.lo) ;;
+	*)
+	  func_fatal_help "\`$destdir' must be an absolute directory name"
+	  ;;
+	esac
+      done
+      ;;
+    esac
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    staticlibs=
+    future_libdirs=
+    current_libdirs=
+    for file in $files; do
+
+      # Do each installation.
+      case $file in
+      *.$libext)
+	# Do the static libraries later.
+	func_append staticlibs " $file"
+	;;
+
+      *.la)
+	func_resolve_sysroot "$file"
+	file=$func_resolve_sysroot_result
+
+	# Check to see that this really is a libtool archive.
+	func_lalib_unsafe_p "$file" \
+	  || func_fatal_help "\`$file' is not a valid libtool archive"
+
+	library_names=
+	old_library=
+	relink_command=
+	func_source "$file"
+
+	# Add the libdir to current_libdirs if it is the destination.
+	if test "X$destdir" = "X$libdir"; then
+	  case "$current_libdirs " in
+	  *" $libdir "*) ;;
+	  *) func_append current_libdirs " $libdir" ;;
+	  esac
+	else
+	  # Note the libdir as a future libdir.
+	  case "$future_libdirs " in
+	  *" $libdir "*) ;;
+	  *) func_append future_libdirs " $libdir" ;;
+	  esac
+	fi
+
+	func_dirname "$file" "/" ""
+	dir="$func_dirname_result"
+	func_append dir "$objdir"
+
+	if test -n "$relink_command"; then
+	  # Determine the prefix the user has applied to our future dir.
+	  inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"`
+
+	  # Don't allow the user to place us outside of our expected
+	  # location b/c this prevents finding dependent libraries that
+	  # are installed to the same prefix.
+	  # At present, this check doesn't affect windows .dll's that
+	  # are installed into $libdir/../bin (currently, that works fine)
+	  # but it's something to keep an eye on.
+	  test "$inst_prefix_dir" = "$destdir" && \
+	    func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir"
+
+	  if test -n "$inst_prefix_dir"; then
+	    # Stick the inst_prefix_dir data into the link command.
+	    relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+	  else
+	    relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
+	  fi
+
+	  func_warning "relinking \`$file'"
+	  func_show_eval "$relink_command" \
+	    'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"'
+	fi
+
+	# See the names of the shared library.
+	set dummy $library_names; shift
+	if test -n "$1"; then
+	  realname="$1"
+	  shift
+
+	  srcname="$realname"
+	  test -n "$relink_command" && srcname="$realname"T
+
+	  # Install the shared library and build the symlinks.
+	  func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \
+	      'exit $?'
+	  tstripme="$stripme"
+	  case $host_os in
+	  cygwin* | mingw* | pw32* | cegcc*)
+	    case $realname in
+	    *.dll.a)
+	      tstripme=""
+	      ;;
+	    esac
+	    ;;
+	  esac
+	  if test -n "$tstripme" && test -n "$striplib"; then
+	    func_show_eval "$striplib $destdir/$realname" 'exit $?'
+	  fi
+
+	  if test "$#" -gt 0; then
+	    # Delete the old symlinks, and create new ones.
+	    # Try `ln -sf' first, because the `ln' binary might depend on
+	    # the symlink we replace!  Solaris /bin/ln does not understand -f,
+	    # so we also need to try rm && ln -s.
+	    for linkname
+	    do
+	      test "$linkname" != "$realname" \
+		&& func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })"
+	    done
+	  fi
+
+	  # Do each command in the postinstall commands.
+	  lib="$destdir/$realname"
+	  func_execute_cmds "$postinstall_cmds" 'exit $?'
+	fi
+
+	# Install the pseudo-library for information purposes.
+	func_basename "$file"
+	name="$func_basename_result"
+	instname="$dir/$name"i
+	func_show_eval "$install_prog $instname $destdir/$name" 'exit $?'
+
+	# Maybe install the static library, too.
+	test -n "$old_library" && func_append staticlibs " $dir/$old_library"
+	;;
+
+      *.lo)
+	# Install (i.e. copy) a libtool object.
+
+	# Figure out destination file name, if it wasn't already specified.
+	if test -n "$destname"; then
+	  destfile="$destdir/$destname"
+	else
+	  func_basename "$file"
+	  destfile="$func_basename_result"
+	  destfile="$destdir/$destfile"
+	fi
+
+	# Deduce the name of the destination old-style object file.
+	case $destfile in
+	*.lo)
+	  func_lo2o "$destfile"
+	  staticdest=$func_lo2o_result
+	  ;;
+	*.$objext)
+	  staticdest="$destfile"
+	  destfile=
+	  ;;
+	*)
+	  func_fatal_help "cannot copy a libtool object to \`$destfile'"
+	  ;;
+	esac
+
+	# Install the libtool object if requested.
+	test -n "$destfile" && \
+	  func_show_eval "$install_prog $file $destfile" 'exit $?'
+
+	# Install the old object if enabled.
+	if test "$build_old_libs" = yes; then
+	  # Deduce the name of the old-style object file.
+	  func_lo2o "$file"
+	  staticobj=$func_lo2o_result
+	  func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?'
+	fi
+	exit $EXIT_SUCCESS
+	;;
+
+      *)
+	# Figure out destination file name, if it wasn't already specified.
+	if test -n "$destname"; then
+	  destfile="$destdir/$destname"
+	else
+	  func_basename "$file"
+	  destfile="$func_basename_result"
+	  destfile="$destdir/$destfile"
+	fi
+
+	# If the file is missing, and there is a .exe on the end, strip it
+	# because it is most likely a libtool script we actually want to
+	# install
+	stripped_ext=""
+	case $file in
+	  *.exe)
+	    if test ! -f "$file"; then
+	      func_stripname '' '.exe' "$file"
+	      file=$func_stripname_result
+	      stripped_ext=".exe"
+	    fi
+	    ;;
+	esac
+
+	# Do a test to see if this is really a libtool program.
+	case $host in
+	*cygwin* | *mingw*)
+	    if func_ltwrapper_executable_p "$file"; then
+	      func_ltwrapper_scriptname "$file"
+	      wrapper=$func_ltwrapper_scriptname_result
+	    else
+	      func_stripname '' '.exe' "$file"
+	      wrapper=$func_stripname_result
+	    fi
+	    ;;
+	*)
+	    wrapper=$file
+	    ;;
+	esac
+	if func_ltwrapper_script_p "$wrapper"; then
+	  notinst_deplibs=
+	  relink_command=
+
+	  func_source "$wrapper"
+
+	  # Check the variables that should have been set.
+	  test -z "$generated_by_libtool_version" && \
+	    func_fatal_error "invalid libtool wrapper script \`$wrapper'"
+
+	  finalize=yes
+	  for lib in $notinst_deplibs; do
+	    # Check to see that each library is installed.
+	    libdir=
+	    if test -f "$lib"; then
+	      func_source "$lib"
+	    fi
+	    libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test
+	    if test -n "$libdir" && test ! -f "$libfile"; then
+	      func_warning "\`$lib' has not been installed in \`$libdir'"
+	      finalize=no
+	    fi
+	  done
+
+	  relink_command=
+	  func_source "$wrapper"
+
+	  outputname=
+	  if test "$fast_install" = no && test -n "$relink_command"; then
+	    $opt_dry_run || {
+	      if test "$finalize" = yes; then
+	        tmpdir=`func_mktempdir`
+		func_basename "$file$stripped_ext"
+		file="$func_basename_result"
+	        outputname="$tmpdir/$file"
+	        # Replace the output file specification.
+	        relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'`
+
+	        $opt_silent || {
+	          func_quote_for_expand "$relink_command"
+		  eval "func_echo $func_quote_for_expand_result"
+	        }
+	        if eval "$relink_command"; then :
+	          else
+		  func_error "error: relink \`$file' with the above command before installing it"
+		  $opt_dry_run || ${RM}r "$tmpdir"
+		  continue
+	        fi
+	        file="$outputname"
+	      else
+	        func_warning "cannot relink \`$file'"
+	      fi
+	    }
+	  else
+	    # Install the binary that we compiled earlier.
+	    file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"`
+	  fi
+	fi
+
+	# remove .exe since cygwin /usr/bin/install will append another
+	# one anyway
+	case $install_prog,$host in
+	*/usr/bin/install*,*cygwin*)
+	  case $file:$destfile in
+	  *.exe:*.exe)
+	    # this is ok
+	    ;;
+	  *.exe:*)
+	    destfile=$destfile.exe
+	    ;;
+	  *:*.exe)
+	    func_stripname '' '.exe' "$destfile"
+	    destfile=$func_stripname_result
+	    ;;
+	  esac
+	  ;;
+	esac
+	func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?'
+	$opt_dry_run || if test -n "$outputname"; then
+	  ${RM}r "$tmpdir"
+	fi
+	;;
+      esac
+    done
+
+    for file in $staticlibs; do
+      func_basename "$file"
+      name="$func_basename_result"
+
+      # Set up the ranlib parameters.
+      oldlib="$destdir/$name"
+      func_to_tool_file "$oldlib" func_convert_file_msys_to_w32
+      tool_oldlib=$func_to_tool_file_result
+
+      func_show_eval "$install_prog \$file \$oldlib" 'exit $?'
+
+      if test -n "$stripme" && test -n "$old_striplib"; then
+	func_show_eval "$old_striplib $tool_oldlib" 'exit $?'
+      fi
+
+      # Do each command in the postinstall commands.
+      func_execute_cmds "$old_postinstall_cmds" 'exit $?'
+    done
+
+    test -n "$future_libdirs" && \
+      func_warning "remember to run \`$progname --finish$future_libdirs'"
+
+    if test -n "$current_libdirs"; then
+      # Maybe just do a dry run.
+      $opt_dry_run && current_libdirs=" -n$current_libdirs"
+      exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
+    else
+      exit $EXIT_SUCCESS
+    fi
+}
+
+test "$opt_mode" = install && func_mode_install ${1+"$@"}
+
+
+# func_generate_dlsyms outputname originator pic_p
+# Extract symbols from dlprefiles and create ${outputname}S.o with
+# a dlpreopen symbol table.
+func_generate_dlsyms ()
+{
+    $opt_debug
+    my_outputname="$1"
+    my_originator="$2"
+    my_pic_p="${3-no}"
+    my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'`
+    my_dlsyms=
+
+    if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+      if test -n "$NM" && test -n "$global_symbol_pipe"; then
+	my_dlsyms="${my_outputname}S.c"
+      else
+	func_error "not configured to extract global symbols from dlpreopened files"
+      fi
+    fi
+
+    if test -n "$my_dlsyms"; then
+      case $my_dlsyms in
+      "") ;;
+      *.c)
+	# Discover the nlist of each of the dlfiles.
+	nlist="$output_objdir/${my_outputname}.nm"
+
+	func_show_eval "$RM $nlist ${nlist}S ${nlist}T"
+
+	# Parse the name list into a source file.
+	func_verbose "creating $output_objdir/$my_dlsyms"
+
+	$opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\
+/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */
+/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4))
+#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
+#endif
+
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE)
+/* DATA imports from DLLs on WIN32 con't be const, because runtime
+   relocations are performed -- see ld's documentation on pseudo-relocs.  */
+# define LT_DLSYM_CONST
+#elif defined(__osf__)
+/* This system does not cope well with relocations in const data.  */
+# define LT_DLSYM_CONST
+#else
+# define LT_DLSYM_CONST const
+#endif
+
+/* External symbol declarations for the compiler. */\
+"
+
+	if test "$dlself" = yes; then
+	  func_verbose "generating symbol list for \`$output'"
+
+	  $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist"
+
+	  # Add our own program objects to the symbol list.
+	  progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP`
+	  for progfile in $progfiles; do
+	    func_to_tool_file "$progfile" func_convert_file_msys_to_w32
+	    func_verbose "extracting global C symbols from \`$func_to_tool_file_result'"
+	    $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'"
+	  done
+
+	  if test -n "$exclude_expsyms"; then
+	    $opt_dry_run || {
+	      eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+	      eval '$MV "$nlist"T "$nlist"'
+	    }
+	  fi
+
+	  if test -n "$export_symbols_regex"; then
+	    $opt_dry_run || {
+	      eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+	      eval '$MV "$nlist"T "$nlist"'
+	    }
+	  fi
+
+	  # Prepare the list of exported symbols
+	  if test -z "$export_symbols"; then
+	    export_symbols="$output_objdir/$outputname.exp"
+	    $opt_dry_run || {
+	      $RM $export_symbols
+	      eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+	      case $host in
+	      *cygwin* | *mingw* | *cegcc* )
+                eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+                eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
+	        ;;
+	      esac
+	    }
+	  else
+	    $opt_dry_run || {
+	      eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
+	      eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
+	      eval '$MV "$nlist"T "$nlist"'
+	      case $host in
+	        *cygwin* | *mingw* | *cegcc* )
+	          eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+	          eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
+	          ;;
+	      esac
+	    }
+	  fi
+	fi
+
+	for dlprefile in $dlprefiles; do
+	  func_verbose "extracting global C symbols from \`$dlprefile'"
+	  func_basename "$dlprefile"
+	  name="$func_basename_result"
+          case $host in
+	    *cygwin* | *mingw* | *cegcc* )
+	      # if an import library, we need to obtain dlname
+	      if func_win32_import_lib_p "$dlprefile"; then
+	        func_tr_sh "$dlprefile"
+	        eval "curr_lafile=\$libfile_$func_tr_sh_result"
+	        dlprefile_dlbasename=""
+	        if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then
+	          # Use subshell, to avoid clobbering current variable values
+	          dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"`
+	          if test -n "$dlprefile_dlname" ; then
+	            func_basename "$dlprefile_dlname"
+	            dlprefile_dlbasename="$func_basename_result"
+	          else
+	            # no lafile. user explicitly requested -dlpreopen <import library>.
+	            $sharedlib_from_linklib_cmd "$dlprefile"
+	            dlprefile_dlbasename=$sharedlib_from_linklib_result
+	          fi
+	        fi
+	        $opt_dry_run || {
+	          if test -n "$dlprefile_dlbasename" ; then
+	            eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"'
+	          else
+	            func_warning "Could not compute DLL name from $name"
+	            eval '$ECHO ": $name " >> "$nlist"'
+	          fi
+	          func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
+	          eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe |
+	            $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'"
+	        }
+	      else # not an import lib
+	        $opt_dry_run || {
+	          eval '$ECHO ": $name " >> "$nlist"'
+	          func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
+	          eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'"
+	        }
+	      fi
+	    ;;
+	    *)
+	      $opt_dry_run || {
+	        eval '$ECHO ": $name " >> "$nlist"'
+	        func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
+	        eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'"
+	      }
+	    ;;
+          esac
+	done
+
+	$opt_dry_run || {
+	  # Make sure we have at least an empty file.
+	  test -f "$nlist" || : > "$nlist"
+
+	  if test -n "$exclude_expsyms"; then
+	    $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+	    $MV "$nlist"T "$nlist"
+	  fi
+
+	  # Try sorting and uniquifying the output.
+	  if $GREP -v "^: " < "$nlist" |
+	      if sort -k 3 </dev/null >/dev/null 2>&1; then
+		sort -k 3
+	      else
+		sort +2
+	      fi |
+	      uniq > "$nlist"S; then
+	    :
+	  else
+	    $GREP -v "^: " < "$nlist" > "$nlist"S
+	  fi
+
+	  if test -f "$nlist"S; then
+	    eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"'
+	  else
+	    echo '/* NONE */' >> "$output_objdir/$my_dlsyms"
+	  fi
+
+	  echo >> "$output_objdir/$my_dlsyms" "\
+
+/* The mapping between symbol names and symbols.  */
+typedef struct {
+  const char *name;
+  void *address;
+} lt_dlsymlist;
+extern LT_DLSYM_CONST lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[];
+LT_DLSYM_CONST lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[] =
+{\
+  { \"$my_originator\", (void *) 0 },"
+
+	  case $need_lib_prefix in
+	  no)
+	    eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms"
+	    ;;
+	  *)
+	    eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms"
+	    ;;
+	  esac
+	  echo >> "$output_objdir/$my_dlsyms" "\
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt_${my_prefix}_LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+	} # !$opt_dry_run
+
+	pic_flag_for_symtable=
+	case "$compile_command " in
+	*" -static "*) ;;
+	*)
+	  case $host in
+	  # compiling the symbol table file with pic_flag works around
+	  # a FreeBSD bug that causes programs to crash when -lm is
+	  # linked before any other PIC object.  But we must not use
+	  # pic_flag when linking with -static.  The problem exists in
+	  # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+	  *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+	    pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;;
+	  *-*-hpux*)
+	    pic_flag_for_symtable=" $pic_flag"  ;;
+	  *)
+	    if test "X$my_pic_p" != Xno; then
+	      pic_flag_for_symtable=" $pic_flag"
+	    fi
+	    ;;
+	  esac
+	  ;;
+	esac
+	symtab_cflags=
+	for arg in $LTCFLAGS; do
+	  case $arg in
+	  -pie | -fpie | -fPIE) ;;
+	  *) func_append symtab_cflags " $arg" ;;
+	  esac
+	done
+
+	# Now compile the dynamic symbol file.
+	func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?'
+
+	# Clean up the generated files.
+	func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"'
+
+	# Transform the symbol file into the correct name.
+	symfileobj="$output_objdir/${my_outputname}S.$objext"
+	case $host in
+	*cygwin* | *mingw* | *cegcc* )
+	  if test -f "$output_objdir/$my_outputname.def"; then
+	    compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+	    finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+	  else
+	    compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+	    finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+	  fi
+	  ;;
+	*)
+	  compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+	  finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+	  ;;
+	esac
+	;;
+      *)
+	func_fatal_error "unknown suffix for \`$my_dlsyms'"
+	;;
+      esac
+    else
+      # We keep going just in case the user didn't refer to
+      # lt_preloaded_symbols.  The linker will fail if global_symbol_pipe
+      # really was required.
+
+      # Nullify the symbol file.
+      compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"`
+      finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"`
+    fi
+}
+
+# func_win32_libid arg
+# return the library type of file 'arg'
+#
+# Need a lot of goo to handle *both* DLLs and import libs
+# Has to be a shell function in order to 'eat' the argument
+# that is supplied when $file_magic_command is called.
+# Despite the name, also deal with 64 bit binaries.
+func_win32_libid ()
+{
+  $opt_debug
+  win32_libid_type="unknown"
+  win32_fileres=`file -L $1 2>/dev/null`
+  case $win32_fileres in
+  *ar\ archive\ import\ library*) # definitely import
+    win32_libid_type="x86 archive import"
+    ;;
+  *ar\ archive*) # could be an import, or static
+    # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD.
+    if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null |
+       $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then
+      func_to_tool_file "$1" func_convert_file_msys_to_w32
+      win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" |
+	$SED -n -e '
+	    1,100{
+		/ I /{
+		    s,.*,import,
+		    p
+		    q
+		}
+	    }'`
+      case $win32_nmres in
+      import*)  win32_libid_type="x86 archive import";;
+      *)        win32_libid_type="x86 archive static";;
+      esac
+    fi
+    ;;
+  *DLL*)
+    win32_libid_type="x86 DLL"
+    ;;
+  *executable*) # but shell scripts are "executable" too...
+    case $win32_fileres in
+    *MS\ Windows\ PE\ Intel*)
+      win32_libid_type="x86 DLL"
+      ;;
+    esac
+    ;;
+  esac
+  $ECHO "$win32_libid_type"
+}
+
+# func_cygming_dll_for_implib ARG
+#
+# Platform-specific function to extract the
+# name of the DLL associated with the specified
+# import library ARG.
+# Invoked by eval'ing the libtool variable
+#    $sharedlib_from_linklib_cmd
+# Result is available in the variable
+#    $sharedlib_from_linklib_result
+func_cygming_dll_for_implib ()
+{
+  $opt_debug
+  sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"`
+}
+
+# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs
+#
+# The is the core of a fallback implementation of a
+# platform-specific function to extract the name of the
+# DLL associated with the specified import library LIBNAME.
+#
+# SECTION_NAME is either .idata$6 or .idata$7, depending
+# on the platform and compiler that created the implib.
+#
+# Echos the name of the DLL associated with the
+# specified import library.
+func_cygming_dll_for_implib_fallback_core ()
+{
+  $opt_debug
+  match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"`
+  $OBJDUMP -s --section "$1" "$2" 2>/dev/null |
+    $SED '/^Contents of section '"$match_literal"':/{
+      # Place marker at beginning of archive member dllname section
+      s/.*/====MARK====/
+      p
+      d
+    }
+    # These lines can sometimes be longer than 43 characters, but
+    # are always uninteresting
+    /:[	 ]*file format pe[i]\{,1\}-/d
+    /^In archive [^:]*:/d
+    # Ensure marker is printed
+    /^====MARK====/p
+    # Remove all lines with less than 43 characters
+    /^.\{43\}/!d
+    # From remaining lines, remove first 43 characters
+    s/^.\{43\}//' |
+    $SED -n '
+      # Join marker and all lines until next marker into a single line
+      /^====MARK====/ b para
+      H
+      $ b para
+      b
+      :para
+      x
+      s/\n//g
+      # Remove the marker
+      s/^====MARK====//
+      # Remove trailing dots and whitespace
+      s/[\. \t]*$//
+      # Print
+      /./p' |
+    # we now have a list, one entry per line, of the stringified
+    # contents of the appropriate section of all members of the
+    # archive which possess that section. Heuristic: eliminate
+    # all those which have a first or second character that is
+    # a '.' (that is, objdump's representation of an unprintable
+    # character.) This should work for all archives with less than
+    # 0x302f exports -- but will fail for DLLs whose name actually
+    # begins with a literal '.' or a single character followed by
+    # a '.'.
+    #
+    # Of those that remain, print the first one.
+    $SED -e '/^\./d;/^.\./d;q'
+}
+
+# func_cygming_gnu_implib_p ARG
+# This predicate returns with zero status (TRUE) if
+# ARG is a GNU/binutils-style import library. Returns
+# with nonzero status (FALSE) otherwise.
+func_cygming_gnu_implib_p ()
+{
+  $opt_debug
+  func_to_tool_file "$1" func_convert_file_msys_to_w32
+  func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'`
+  test -n "$func_cygming_gnu_implib_tmp"
+}
+
+# func_cygming_ms_implib_p ARG
+# This predicate returns with zero status (TRUE) if
+# ARG is an MS-style import library. Returns
+# with nonzero status (FALSE) otherwise.
+func_cygming_ms_implib_p ()
+{
+  $opt_debug
+  func_to_tool_file "$1" func_convert_file_msys_to_w32
+  func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'`
+  test -n "$func_cygming_ms_implib_tmp"
+}
+
+# func_cygming_dll_for_implib_fallback ARG
+# Platform-specific function to extract the
+# name of the DLL associated with the specified
+# import library ARG.
+#
+# This fallback implementation is for use when $DLLTOOL
+# does not support the --identify-strict option.
+# Invoked by eval'ing the libtool variable
+#    $sharedlib_from_linklib_cmd
+# Result is available in the variable
+#    $sharedlib_from_linklib_result
+func_cygming_dll_for_implib_fallback ()
+{
+  $opt_debug
+  if func_cygming_gnu_implib_p "$1" ; then
+    # binutils import library
+    sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"`
+  elif func_cygming_ms_implib_p "$1" ; then
+    # ms-generated import library
+    sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"`
+  else
+    # unknown
+    sharedlib_from_linklib_result=""
+  fi
+}
+
+
+# func_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+    $opt_debug
+    f_ex_an_ar_dir="$1"; shift
+    f_ex_an_ar_oldlib="$1"
+    if test "$lock_old_archive_extraction" = yes; then
+      lockfile=$f_ex_an_ar_oldlib.lock
+      until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
+	func_echo "Waiting for $lockfile to be removed"
+	sleep 2
+      done
+    fi
+    func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \
+		   'stat=$?; rm -f "$lockfile"; exit $stat'
+    if test "$lock_old_archive_extraction" = yes; then
+      $opt_dry_run || rm -f "$lockfile"
+    fi
+    if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
+     :
+    else
+      func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib"
+    fi
+}
+
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives ()
+{
+    $opt_debug
+    my_gentop="$1"; shift
+    my_oldlibs=${1+"$@"}
+    my_oldobjs=""
+    my_xlib=""
+    my_xabs=""
+    my_xdir=""
+
+    for my_xlib in $my_oldlibs; do
+      # Extract the objects.
+      case $my_xlib in
+	[\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
+	*) my_xabs=`pwd`"/$my_xlib" ;;
+      esac
+      func_basename "$my_xlib"
+      my_xlib="$func_basename_result"
+      my_xlib_u=$my_xlib
+      while :; do
+        case " $extracted_archives " in
+	*" $my_xlib_u "*)
+	  func_arith $extracted_serial + 1
+	  extracted_serial=$func_arith_result
+	  my_xlib_u=lt$extracted_serial-$my_xlib ;;
+	*) break ;;
+	esac
+      done
+      extracted_archives="$extracted_archives $my_xlib_u"
+      my_xdir="$my_gentop/$my_xlib_u"
+
+      func_mkdir_p "$my_xdir"
+
+      case $host in
+      *-darwin*)
+	func_verbose "Extracting $my_xabs"
+	# Do not bother doing anything if just a dry run
+	$opt_dry_run || {
+	  darwin_orig_dir=`pwd`
+	  cd $my_xdir || exit $?
+	  darwin_archive=$my_xabs
+	  darwin_curdir=`pwd`
+	  darwin_base_archive=`basename "$darwin_archive"`
+	  darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true`
+	  if test -n "$darwin_arches"; then
+	    darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'`
+	    darwin_arch=
+	    func_verbose "$darwin_base_archive has multiple architectures $darwin_arches"
+	    for darwin_arch in  $darwin_arches ; do
+	      func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+	      $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
+	      cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+	      func_extract_an_archive "`pwd`" "${darwin_base_archive}"
+	      cd "$darwin_curdir"
+	      $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
+	    done # $darwin_arches
+            ## Okay now we've a bunch of thin objects, gotta fatten them up :)
+	    darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u`
+	    darwin_file=
+	    darwin_files=
+	    for darwin_file in $darwin_filelist; do
+	      darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP`
+	      $LIPO -create -output "$darwin_file" $darwin_files
+	    done # $darwin_filelist
+	    $RM -rf unfat-$$
+	    cd "$darwin_orig_dir"
+	  else
+	    cd $darwin_orig_dir
+	    func_extract_an_archive "$my_xdir" "$my_xabs"
+	  fi # $darwin_arches
+	} # !$opt_dry_run
+	;;
+      *)
+        func_extract_an_archive "$my_xdir" "$my_xabs"
+	;;
+      esac
+      my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP`
+    done
+
+    func_extract_archives_result="$my_oldobjs"
+}
+
+
+# func_emit_wrapper [arg=no]
+#
+# Emit a libtool wrapper script on stdout.
+# Don't directly open a file because we may want to
+# incorporate the script contents within a cygwin/mingw
+# wrapper executable.  Must ONLY be called from within
+# func_mode_link because it depends on a number of variables
+# set therein.
+#
+# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR
+# variable will take.  If 'yes', then the emitted script
+# will assume that the directory in which it is stored is
+# the $objdir directory.  This is a cygwin/mingw-specific
+# behavior.
+func_emit_wrapper ()
+{
+	func_emit_wrapper_arg1=${1-no}
+
+	$ECHO "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='$sed_quote_subst'
+
+# Be Bourne compatible
+if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+  # install mode needs the following variables:
+  generated_by_libtool_version='$macro_version'
+  notinst_deplibs='$notinst_deplibs'
+else
+  # When we are sourced in execute mode, \$file and \$ECHO are already set.
+  if test \"\$libtool_execute_magic\" != \"$magic\"; then
+    file=\"\$0\""
+
+    qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"`
+    $ECHO "\
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+\$1
+_LTECHO_EOF'
+}
+    ECHO=\"$qECHO\"
+  fi
+
+# Very basic option parsing. These options are (a) specific to
+# the libtool wrapper, (b) are identical between the wrapper
+# /script/ and the wrapper /executable/ which is used only on
+# windows platforms, and (c) all begin with the string "--lt-"
+# (application programs are unlikely to have options which match
+# this pattern).
+#
+# There are only two supported options: --lt-debug and
+# --lt-dump-script. There is, deliberately, no --lt-help.
+#
+# The first argument to this parsing function should be the
+# script's $0 value, followed by "$@".
+lt_option_debug=
+func_parse_lt_options ()
+{
+  lt_script_arg0=\$0
+  shift
+  for lt_opt
+  do
+    case \"\$lt_opt\" in
+    --lt-debug) lt_option_debug=1 ;;
+    --lt-dump-script)
+        lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\`
+        test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=.
+        lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\`
+        cat \"\$lt_dump_D/\$lt_dump_F\"
+        exit 0
+      ;;
+    --lt-*)
+        \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2
+        exit 1
+      ;;
+    esac
+  done
+
+  # Print the debug banner immediately:
+  if test -n \"\$lt_option_debug\"; then
+    echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2
+  fi
+}
+
+# Used when --lt-debug. Prints its arguments to stdout
+# (redirection is the responsibility of the caller)
+func_lt_dump_args ()
+{
+  lt_dump_args_N=1;
+  for lt_arg
+  do
+    \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\"
+    lt_dump_args_N=\`expr \$lt_dump_args_N + 1\`
+  done
+}
+
+# Core function for launching the target application
+func_exec_program_core ()
+{
+"
+  case $host in
+  # Backslashes separate directories on plain windows
+  *-*-mingw | *-*-os2* | *-cegcc*)
+    $ECHO "\
+      if test -n \"\$lt_option_debug\"; then
+        \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2
+        func_lt_dump_args \${1+\"\$@\"} 1>&2
+      fi
+      exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
+"
+    ;;
+
+  *)
+    $ECHO "\
+      if test -n \"\$lt_option_debug\"; then
+        \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2
+        func_lt_dump_args \${1+\"\$@\"} 1>&2
+      fi
+      exec \"\$progdir/\$program\" \${1+\"\$@\"}
+"
+    ;;
+  esac
+  $ECHO "\
+      \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2
+      exit 1
+}
+
+# A function to encapsulate launching the target application
+# Strips options in the --lt-* namespace from \$@ and
+# launches target application with the remaining arguments.
+func_exec_program ()
+{
+  case \" \$* \" in
+  *\\ --lt-*)
+    for lt_wr_arg
+    do
+      case \$lt_wr_arg in
+      --lt-*) ;;
+      *) set x \"\$@\" \"\$lt_wr_arg\"; shift;;
+      esac
+      shift
+    done ;;
+  esac
+  func_exec_program_core \${1+\"\$@\"}
+}
+
+  # Parse options
+  func_parse_lt_options \"\$0\" \${1+\"\$@\"}
+
+  # Find the directory that this script lives in.
+  thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\`
+  test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+  # Follow symbolic links until we get to the real thisdir.
+  file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\`
+  while test -n \"\$file\"; do
+    destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\`
+
+    # If there was a directory component, then change thisdir.
+    if test \"x\$destdir\" != \"x\$file\"; then
+      case \"\$destdir\" in
+      [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+      *) thisdir=\"\$thisdir/\$destdir\" ;;
+      esac
+    fi
+
+    file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\`
+    file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\`
+  done
+
+  # Usually 'no', except on cygwin/mingw when embedded into
+  # the cwrapper.
+  WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1
+  if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then
+    # special case for '.'
+    if test \"\$thisdir\" = \".\"; then
+      thisdir=\`pwd\`
+    fi
+    # remove .libs from thisdir
+    case \"\$thisdir\" in
+    *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;;
+    $objdir )   thisdir=. ;;
+    esac
+  fi
+
+  # Try to get the absolute directory name.
+  absdir=\`cd \"\$thisdir\" && pwd\`
+  test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+	if test "$fast_install" = yes; then
+	  $ECHO "\
+  program=lt-'$outputname'$exeext
+  progdir=\"\$thisdir/$objdir\"
+
+  if test ! -f \"\$progdir/\$program\" ||
+     { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
+       test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+    file=\"\$\$-\$program\"
+
+    if test ! -d \"\$progdir\"; then
+      $MKDIR \"\$progdir\"
+    else
+      $RM \"\$progdir/\$file\"
+    fi"
+
+	  $ECHO "\
+
+    # relink executable if necessary
+    if test -n \"\$relink_command\"; then
+      if relink_command_output=\`eval \$relink_command 2>&1\`; then :
+      else
+	$ECHO \"\$relink_command_output\" >&2
+	$RM \"\$progdir/\$file\"
+	exit 1
+      fi
+    fi
+
+    $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+    { $RM \"\$progdir/\$program\";
+      $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+    $RM \"\$progdir/\$file\"
+  fi"
+	else
+	  $ECHO "\
+  program='$outputname'
+  progdir=\"\$thisdir/$objdir\"
+"
+	fi
+
+	$ECHO "\
+
+  if test -f \"\$progdir/\$program\"; then"
+
+	# fixup the dll searchpath if we need to.
+	#
+	# Fix the DLL searchpath if we need to.  Do this before prepending
+	# to shlibpath, because on Windows, both are PATH and uninstalled
+	# libraries must come first.
+	if test -n "$dllsearchpath"; then
+	  $ECHO "\
+    # Add the dll search path components to the executable PATH
+    PATH=$dllsearchpath:\$PATH
+"
+	fi
+
+	# Export our shlibpath_var if we have one.
+	if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+	  $ECHO "\
+    # Add our own library path to $shlibpath_var
+    $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+    # Some systems cannot cope with colon-terminated $shlibpath_var
+    # The second colon is a workaround for a bug in BeOS R4 sed
+    $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\`
+
+    export $shlibpath_var
+"
+	fi
+
+	$ECHO "\
+    if test \"\$libtool_execute_magic\" != \"$magic\"; then
+      # Run the actual program with our arguments.
+      func_exec_program \${1+\"\$@\"}
+    fi
+  else
+    # The program doesn't exist.
+    \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
+    \$ECHO \"This script is just a wrapper for \$program.\" 1>&2
+    \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2
+    exit 1
+  fi
+fi\
+"
+}
+
+
+# func_emit_cwrapperexe_src
+# emit the source code for a wrapper executable on stdout
+# Must ONLY be called from within func_mode_link because
+# it depends on a number of variable set therein.
+func_emit_cwrapperexe_src ()
+{
+	cat <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+   Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+
+   The $output program cannot be directly executed until all the libtool
+   libraries that it depends on are installed.
+
+   This wrapper executable should never be moved out of the build directory.
+   If it is, it will not operate correctly.
+*/
+EOF
+	    cat <<"EOF"
+#ifdef _MSC_VER
+# define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef _MSC_VER
+# include <direct.h>
+# include <process.h>
+# include <io.h>
+#else
+# include <unistd.h>
+# include <stdint.h>
+# ifdef __CYGWIN__
+#  include <io.h>
+# endif
+#endif
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+/* declarations of non-ANSI functions */
+#if defined(__MINGW32__)
+# ifdef __STRICT_ANSI__
+int _putenv (const char *);
+# endif
+#elif defined(__CYGWIN__)
+# ifdef __STRICT_ANSI__
+char *realpath (const char *, char *);
+int putenv (char *);
+int setenv (const char *, const char *, int);
+# endif
+/* #elif defined (other platforms) ... */
+#endif
+
+/* portability defines, excluding path handling macros */
+#if defined(_MSC_VER)
+# define setmode _setmode
+# define stat    _stat
+# define chmod   _chmod
+# define getcwd  _getcwd
+# define putenv  _putenv
+# define S_IXUSR _S_IEXEC
+# ifndef _INTPTR_T_DEFINED
+#  define _INTPTR_T_DEFINED
+#  define intptr_t int
+# endif
+#elif defined(__MINGW32__)
+# define setmode _setmode
+# define stat    _stat
+# define chmod   _chmod
+# define getcwd  _getcwd
+# define putenv  _putenv
+#elif defined(__CYGWIN__)
+# define HAVE_SETENV
+# define FOPEN_WB "wb"
+/* #elif defined (other platforms) ... */
+#endif
+
+#if defined(PATH_MAX)
+# define LT_PATHMAX PATH_MAX
+#elif defined(MAXPATHLEN)
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef S_IXOTH
+# define S_IXOTH 0
+#endif
+#ifndef S_IXGRP
+# define S_IXGRP 0
+#endif
+
+/* path handling portability macros */
+#ifndef DIR_SEPARATOR
+# define DIR_SEPARATOR '/'
+# define PATH_SEPARATOR ':'
+#endif
+
+#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
+  defined (__OS2__)
+# define HAVE_DOS_BASED_FILE_SYSTEM
+# define FOPEN_WB "wb"
+# ifndef DIR_SEPARATOR_2
+#  define DIR_SEPARATOR_2 '\\'
+# endif
+# ifndef PATH_SEPARATOR_2
+#  define PATH_SEPARATOR_2 ';'
+# endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+	(((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#ifndef PATH_SEPARATOR_2
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
+#else /* PATH_SEPARATOR_2 */
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
+#endif /* PATH_SEPARATOR_2 */
+
+#ifndef FOPEN_WB
+# define FOPEN_WB "w"
+#endif
+#ifndef _O_BINARY
+# define _O_BINARY 0
+#endif
+
+#define XMALLOC(type, num)      ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+  if (stale) { free ((void *) stale); stale = 0; } \
+} while (0)
+
+#if defined(LT_DEBUGWRAPPER)
+static int lt_debug = 1;
+#else
+static int lt_debug = 0;
+#endif
+
+const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */
+
+void *xmalloc (size_t num);
+char *xstrdup (const char *string);
+const char *base_name (const char *name);
+char *find_executable (const char *wrapper);
+char *chase_symlinks (const char *pathspec);
+int make_executable (const char *path);
+int check_executable (const char *path);
+char *strendzap (char *str, const char *pat);
+void lt_debugprintf (const char *file, int line, const char *fmt, ...);
+void lt_fatal (const char *file, int line, const char *message, ...);
+static const char *nonnull (const char *s);
+static const char *nonempty (const char *s);
+void lt_setenv (const char *name, const char *value);
+char *lt_extend_str (const char *orig_value, const char *add, int to_end);
+void lt_update_exe_path (const char *name, const char *value);
+void lt_update_lib_path (const char *name, const char *value);
+char **prepare_spawn (char **argv);
+void lt_dump_script (FILE *f);
+EOF
+
+	    cat <<EOF
+volatile const char * MAGIC_EXE = "$magic_exe";
+const char * LIB_PATH_VARNAME = "$shlibpath_var";
+EOF
+
+	    if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+              func_to_host_path "$temp_rpath"
+	      cat <<EOF
+const char * LIB_PATH_VALUE   = "$func_to_host_path_result";
+EOF
+	    else
+	      cat <<"EOF"
+const char * LIB_PATH_VALUE   = "";
+EOF
+	    fi
+
+	    if test -n "$dllsearchpath"; then
+              func_to_host_path "$dllsearchpath:"
+	      cat <<EOF
+const char * EXE_PATH_VARNAME = "PATH";
+const char * EXE_PATH_VALUE   = "$func_to_host_path_result";
+EOF
+	    else
+	      cat <<"EOF"
+const char * EXE_PATH_VARNAME = "";
+const char * EXE_PATH_VALUE   = "";
+EOF
+	    fi
+
+	    if test "$fast_install" = yes; then
+	      cat <<EOF
+const char * TARGET_PROGRAM_NAME = "lt-$outputname"; /* hopefully, no .exe */
+EOF
+	    else
+	      cat <<EOF
+const char * TARGET_PROGRAM_NAME = "$outputname"; /* hopefully, no .exe */
+EOF
+	    fi
+
+
+	    cat <<"EOF"
+
+#define LTWRAPPER_OPTION_PREFIX         "--lt-"
+
+static const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX;
+static const char *dumpscript_opt       = LTWRAPPER_OPTION_PREFIX "dump-script";
+static const char *debug_opt            = LTWRAPPER_OPTION_PREFIX "debug";
+
+int
+main (int argc, char *argv[])
+{
+  char **newargz;
+  int  newargc;
+  char *tmp_pathspec;
+  char *actual_cwrapper_path;
+  char *actual_cwrapper_name;
+  char *target_name;
+  char *lt_argv_zero;
+  intptr_t rval = 127;
+
+  int i;
+
+  program_name = (char *) xstrdup (base_name (argv[0]));
+  newargz = XMALLOC (char *, argc + 1);
+
+  /* very simple arg parsing; don't want to rely on getopt
+   * also, copy all non cwrapper options to newargz, except
+   * argz[0], which is handled differently
+   */
+  newargc=0;
+  for (i = 1; i < argc; i++)
+    {
+      if (strcmp (argv[i], dumpscript_opt) == 0)
+	{
+EOF
+	    case "$host" in
+	      *mingw* | *cygwin* )
+		# make stdout use "unix" line endings
+		echo "          setmode(1,_O_BINARY);"
+		;;
+	      esac
+
+	    cat <<"EOF"
+	  lt_dump_script (stdout);
+	  return 0;
+	}
+      if (strcmp (argv[i], debug_opt) == 0)
+	{
+          lt_debug = 1;
+          continue;
+	}
+      if (strcmp (argv[i], ltwrapper_option_prefix) == 0)
+        {
+          /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX
+             namespace, but it is not one of the ones we know about and
+             have already dealt with, above (inluding dump-script), then
+             report an error. Otherwise, targets might begin to believe
+             they are allowed to use options in the LTWRAPPER_OPTION_PREFIX
+             namespace. The first time any user complains about this, we'll
+             need to make LTWRAPPER_OPTION_PREFIX a configure-time option
+             or a configure.ac-settable value.
+           */
+          lt_fatal (__FILE__, __LINE__,
+		    "unrecognized %s option: '%s'",
+                    ltwrapper_option_prefix, argv[i]);
+        }
+      /* otherwise ... */
+      newargz[++newargc] = xstrdup (argv[i]);
+    }
+  newargz[++newargc] = NULL;
+
+EOF
+	    cat <<EOF
+  /* The GNU banner must be the first non-error debug message */
+  lt_debugprintf (__FILE__, __LINE__, "libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\n");
+EOF
+	    cat <<"EOF"
+  lt_debugprintf (__FILE__, __LINE__, "(main) argv[0]: %s\n", argv[0]);
+  lt_debugprintf (__FILE__, __LINE__, "(main) program_name: %s\n", program_name);
+
+  tmp_pathspec = find_executable (argv[0]);
+  if (tmp_pathspec == NULL)
+    lt_fatal (__FILE__, __LINE__, "couldn't find %s", argv[0]);
+  lt_debugprintf (__FILE__, __LINE__,
+                  "(main) found exe (before symlink chase) at: %s\n",
+		  tmp_pathspec);
+
+  actual_cwrapper_path = chase_symlinks (tmp_pathspec);
+  lt_debugprintf (__FILE__, __LINE__,
+                  "(main) found exe (after symlink chase) at: %s\n",
+		  actual_cwrapper_path);
+  XFREE (tmp_pathspec);
+
+  actual_cwrapper_name = xstrdup (base_name (actual_cwrapper_path));
+  strendzap (actual_cwrapper_path, actual_cwrapper_name);
+
+  /* wrapper name transforms */
+  strendzap (actual_cwrapper_name, ".exe");
+  tmp_pathspec = lt_extend_str (actual_cwrapper_name, ".exe", 1);
+  XFREE (actual_cwrapper_name);
+  actual_cwrapper_name = tmp_pathspec;
+  tmp_pathspec = 0;
+
+  /* target_name transforms -- use actual target program name; might have lt- prefix */
+  target_name = xstrdup (base_name (TARGET_PROGRAM_NAME));
+  strendzap (target_name, ".exe");
+  tmp_pathspec = lt_extend_str (target_name, ".exe", 1);
+  XFREE (target_name);
+  target_name = tmp_pathspec;
+  tmp_pathspec = 0;
+
+  lt_debugprintf (__FILE__, __LINE__,
+		  "(main) libtool target name: %s\n",
+		  target_name);
+EOF
+
+	    cat <<EOF
+  newargz[0] =
+    XMALLOC (char, (strlen (actual_cwrapper_path) +
+		    strlen ("$objdir") + 1 + strlen (actual_cwrapper_name) + 1));
+  strcpy (newargz[0], actual_cwrapper_path);
+  strcat (newargz[0], "$objdir");
+  strcat (newargz[0], "/");
+EOF
+
+	    cat <<"EOF"
+  /* stop here, and copy so we don't have to do this twice */
+  tmp_pathspec = xstrdup (newargz[0]);
+
+  /* do NOT want the lt- prefix here, so use actual_cwrapper_name */
+  strcat (newargz[0], actual_cwrapper_name);
+
+  /* DO want the lt- prefix here if it exists, so use target_name */
+  lt_argv_zero = lt_extend_str (tmp_pathspec, target_name, 1);
+  XFREE (tmp_pathspec);
+  tmp_pathspec = NULL;
+EOF
+
+	    case $host_os in
+	      mingw*)
+	    cat <<"EOF"
+  {
+    char* p;
+    while ((p = strchr (newargz[0], '\\')) != NULL)
+      {
+	*p = '/';
+      }
+    while ((p = strchr (lt_argv_zero, '\\')) != NULL)
+      {
+	*p = '/';
+      }
+  }
+EOF
+	    ;;
+	    esac
+
+	    cat <<"EOF"
+  XFREE (target_name);
+  XFREE (actual_cwrapper_path);
+  XFREE (actual_cwrapper_name);
+
+  lt_setenv ("BIN_SH", "xpg4"); /* for Tru64 */
+  lt_setenv ("DUALCASE", "1");  /* for MSK sh */
+  /* Update the DLL searchpath.  EXE_PATH_VALUE ($dllsearchpath) must
+     be prepended before (that is, appear after) LIB_PATH_VALUE ($temp_rpath)
+     because on Windows, both *_VARNAMEs are PATH but uninstalled
+     libraries must come first. */
+  lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE);
+  lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE);
+
+  lt_debugprintf (__FILE__, __LINE__, "(main) lt_argv_zero: %s\n",
+		  nonnull (lt_argv_zero));
+  for (i = 0; i < newargc; i++)
+    {
+      lt_debugprintf (__FILE__, __LINE__, "(main) newargz[%d]: %s\n",
+		      i, nonnull (newargz[i]));
+    }
+
+EOF
+
+	    case $host_os in
+	      mingw*)
+		cat <<"EOF"
+  /* execv doesn't actually work on mingw as expected on unix */
+  newargz = prepare_spawn (newargz);
+  rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz);
+  if (rval == -1)
+    {
+      /* failed to start process */
+      lt_debugprintf (__FILE__, __LINE__,
+		      "(main) failed to launch target \"%s\": %s\n",
+		      lt_argv_zero, nonnull (strerror (errno)));
+      return 127;
+    }
+  return rval;
+EOF
+		;;
+	      *)
+		cat <<"EOF"
+  execv (lt_argv_zero, newargz);
+  return rval; /* =127, but avoids unused variable warning */
+EOF
+		;;
+	    esac
+
+	    cat <<"EOF"
+}
+
+void *
+xmalloc (size_t num)
+{
+  void *p = (void *) malloc (num);
+  if (!p)
+    lt_fatal (__FILE__, __LINE__, "memory exhausted");
+
+  return p;
+}
+
+char *
+xstrdup (const char *string)
+{
+  return string ? strcpy ((char *) xmalloc (strlen (string) + 1),
+			  string) : NULL;
+}
+
+const char *
+base_name (const char *name)
+{
+  const char *base;
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  /* Skip over the disk name in MSDOS pathnames. */
+  if (isalpha ((unsigned char) name[0]) && name[1] == ':')
+    name += 2;
+#endif
+
+  for (base = name; *name; name++)
+    if (IS_DIR_SEPARATOR (*name))
+      base = name + 1;
+  return base;
+}
+
+int
+check_executable (const char *path)
+{
+  struct stat st;
+
+  lt_debugprintf (__FILE__, __LINE__, "(check_executable): %s\n",
+                  nonempty (path));
+  if ((!path) || (!*path))
+    return 0;
+
+  if ((stat (path, &st) >= 0)
+      && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+    return 1;
+  else
+    return 0;
+}
+
+int
+make_executable (const char *path)
+{
+  int rval = 0;
+  struct stat st;
+
+  lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n",
+                  nonempty (path));
+  if ((!path) || (!*path))
+    return 0;
+
+  if (stat (path, &st) >= 0)
+    {
+      rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR);
+    }
+  return rval;
+}
+
+/* Searches for the full path of the wrapper.  Returns
+   newly allocated full path name if found, NULL otherwise
+   Does not chase symlinks, even on platforms that support them.
+*/
+char *
+find_executable (const char *wrapper)
+{
+  int has_slash = 0;
+  const char *p;
+  const char *p_next;
+  /* static buffer for getcwd */
+  char tmp[LT_PATHMAX + 1];
+  int tmp_len;
+  char *concat_name;
+
+  lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n",
+                  nonempty (wrapper));
+
+  if ((wrapper == NULL) || (*wrapper == '\0'))
+    return NULL;
+
+  /* Absolute path? */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':')
+    {
+      concat_name = xstrdup (wrapper);
+      if (check_executable (concat_name))
+	return concat_name;
+      XFREE (concat_name);
+    }
+  else
+    {
+#endif
+      if (IS_DIR_SEPARATOR (wrapper[0]))
+	{
+	  concat_name = xstrdup (wrapper);
+	  if (check_executable (concat_name))
+	    return concat_name;
+	  XFREE (concat_name);
+	}
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+    }
+#endif
+
+  for (p = wrapper; *p; p++)
+    if (*p == '/')
+      {
+	has_slash = 1;
+	break;
+      }
+  if (!has_slash)
+    {
+      /* no slashes; search PATH */
+      const char *path = getenv ("PATH");
+      if (path != NULL)
+	{
+	  for (p = path; *p; p = p_next)
+	    {
+	      const char *q;
+	      size_t p_len;
+	      for (q = p; *q; q++)
+		if (IS_PATH_SEPARATOR (*q))
+		  break;
+	      p_len = q - p;
+	      p_next = (*q == '\0' ? q : q + 1);
+	      if (p_len == 0)
+		{
+		  /* empty path: current directory */
+		  if (getcwd (tmp, LT_PATHMAX) == NULL)
+		    lt_fatal (__FILE__, __LINE__, "getcwd failed: %s",
+                              nonnull (strerror (errno)));
+		  tmp_len = strlen (tmp);
+		  concat_name =
+		    XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+		  memcpy (concat_name, tmp, tmp_len);
+		  concat_name[tmp_len] = '/';
+		  strcpy (concat_name + tmp_len + 1, wrapper);
+		}
+	      else
+		{
+		  concat_name =
+		    XMALLOC (char, p_len + 1 + strlen (wrapper) + 1);
+		  memcpy (concat_name, p, p_len);
+		  concat_name[p_len] = '/';
+		  strcpy (concat_name + p_len + 1, wrapper);
+		}
+	      if (check_executable (concat_name))
+		return concat_name;
+	      XFREE (concat_name);
+	    }
+	}
+      /* not found in PATH; assume curdir */
+    }
+  /* Relative path | not found in path: prepend cwd */
+  if (getcwd (tmp, LT_PATHMAX) == NULL)
+    lt_fatal (__FILE__, __LINE__, "getcwd failed: %s",
+              nonnull (strerror (errno)));
+  tmp_len = strlen (tmp);
+  concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+  memcpy (concat_name, tmp, tmp_len);
+  concat_name[tmp_len] = '/';
+  strcpy (concat_name + tmp_len + 1, wrapper);
+
+  if (check_executable (concat_name))
+    return concat_name;
+  XFREE (concat_name);
+  return NULL;
+}
+
+char *
+chase_symlinks (const char *pathspec)
+{
+#ifndef S_ISLNK
+  return xstrdup (pathspec);
+#else
+  char buf[LT_PATHMAX];
+  struct stat s;
+  char *tmp_pathspec = xstrdup (pathspec);
+  char *p;
+  int has_symlinks = 0;
+  while (strlen (tmp_pathspec) && !has_symlinks)
+    {
+      lt_debugprintf (__FILE__, __LINE__,
+		      "checking path component for symlinks: %s\n",
+		      tmp_pathspec);
+      if (lstat (tmp_pathspec, &s) == 0)
+	{
+	  if (S_ISLNK (s.st_mode) != 0)
+	    {
+	      has_symlinks = 1;
+	      break;
+	    }
+
+	  /* search backwards for last DIR_SEPARATOR */
+	  p = tmp_pathspec + strlen (tmp_pathspec) - 1;
+	  while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+	    p--;
+	  if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+	    {
+	      /* no more DIR_SEPARATORS left */
+	      break;
+	    }
+	  *p = '\0';
+	}
+      else
+	{
+	  lt_fatal (__FILE__, __LINE__,
+		    "error accessing file \"%s\": %s",
+		    tmp_pathspec, nonnull (strerror (errno)));
+	}
+    }
+  XFREE (tmp_pathspec);
+
+  if (!has_symlinks)
+    {
+      return xstrdup (pathspec);
+    }
+
+  tmp_pathspec = realpath (pathspec, buf);
+  if (tmp_pathspec == 0)
+    {
+      lt_fatal (__FILE__, __LINE__,
+		"could not follow symlinks for %s", pathspec);
+    }
+  return xstrdup (tmp_pathspec);
+#endif
+}
+
+char *
+strendzap (char *str, const char *pat)
+{
+  size_t len, patlen;
+
+  assert (str != NULL);
+  assert (pat != NULL);
+
+  len = strlen (str);
+  patlen = strlen (pat);
+
+  if (patlen <= len)
+    {
+      str += len - patlen;
+      if (strcmp (str, pat) == 0)
+	*str = '\0';
+    }
+  return str;
+}
+
+void
+lt_debugprintf (const char *file, int line, const char *fmt, ...)
+{
+  va_list args;
+  if (lt_debug)
+    {
+      (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line);
+      va_start (args, fmt);
+      (void) vfprintf (stderr, fmt, args);
+      va_end (args);
+    }
+}
+
+static void
+lt_error_core (int exit_status, const char *file,
+	       int line, const char *mode,
+	       const char *message, va_list ap)
+{
+  fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode);
+  vfprintf (stderr, message, ap);
+  fprintf (stderr, ".\n");
+
+  if (exit_status >= 0)
+    exit (exit_status);
+}
+
+void
+lt_fatal (const char *file, int line, const char *message, ...)
+{
+  va_list ap;
+  va_start (ap, message);
+  lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap);
+  va_end (ap);
+}
+
+static const char *
+nonnull (const char *s)
+{
+  return s ? s : "(null)";
+}
+
+static const char *
+nonempty (const char *s)
+{
+  return (s && !*s) ? "(empty)" : nonnull (s);
+}
+
+void
+lt_setenv (const char *name, const char *value)
+{
+  lt_debugprintf (__FILE__, __LINE__,
+		  "(lt_setenv) setting '%s' to '%s'\n",
+                  nonnull (name), nonnull (value));
+  {
+#ifdef HAVE_SETENV
+    /* always make a copy, for consistency with !HAVE_SETENV */
+    char *str = xstrdup (value);
+    setenv (name, str, 1);
+#else
+    int len = strlen (name) + 1 + strlen (value) + 1;
+    char *str = XMALLOC (char, len);
+    sprintf (str, "%s=%s", name, value);
+    if (putenv (str) != EXIT_SUCCESS)
+      {
+        XFREE (str);
+      }
+#endif
+  }
+}
+
+char *
+lt_extend_str (const char *orig_value, const char *add, int to_end)
+{
+  char *new_value;
+  if (orig_value && *orig_value)
+    {
+      int orig_value_len = strlen (orig_value);
+      int add_len = strlen (add);
+      new_value = XMALLOC (char, add_len + orig_value_len + 1);
+      if (to_end)
+        {
+          strcpy (new_value, orig_value);
+          strcpy (new_value + orig_value_len, add);
+        }
+      else
+        {
+          strcpy (new_value, add);
+          strcpy (new_value + add_len, orig_value);
+        }
+    }
+  else
+    {
+      new_value = xstrdup (add);
+    }
+  return new_value;
+}
+
+void
+lt_update_exe_path (const char *name, const char *value)
+{
+  lt_debugprintf (__FILE__, __LINE__,
+		  "(lt_update_exe_path) modifying '%s' by prepending '%s'\n",
+                  nonnull (name), nonnull (value));
+
+  if (name && *name && value && *value)
+    {
+      char *new_value = lt_extend_str (getenv (name), value, 0);
+      /* some systems can't cope with a ':'-terminated path #' */
+      int len = strlen (new_value);
+      while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1]))
+        {
+          new_value[len-1] = '\0';
+        }
+      lt_setenv (name, new_value);
+      XFREE (new_value);
+    }
+}
+
+void
+lt_update_lib_path (const char *name, const char *value)
+{
+  lt_debugprintf (__FILE__, __LINE__,
+		  "(lt_update_lib_path) modifying '%s' by prepending '%s'\n",
+                  nonnull (name), nonnull (value));
+
+  if (name && *name && value && *value)
+    {
+      char *new_value = lt_extend_str (getenv (name), value, 0);
+      lt_setenv (name, new_value);
+      XFREE (new_value);
+    }
+}
+
+EOF
+	    case $host_os in
+	      mingw*)
+		cat <<"EOF"
+
+/* Prepares an argument vector before calling spawn().
+   Note that spawn() does not by itself call the command interpreter
+     (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
+      ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+         GetVersionEx(&v);
+         v.dwPlatformId == VER_PLATFORM_WIN32_NT;
+      }) ? "cmd.exe" : "command.com").
+   Instead it simply concatenates the arguments, separated by ' ', and calls
+   CreateProcess().  We must quote the arguments since Win32 CreateProcess()
+   interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
+   special way:
+   - Space and tab are interpreted as delimiters. They are not treated as
+     delimiters if they are surrounded by double quotes: "...".
+   - Unescaped double quotes are removed from the input. Their only effect is
+     that within double quotes, space and tab are treated like normal
+     characters.
+   - Backslashes not followed by double quotes are not special.
+   - But 2*n+1 backslashes followed by a double quote become
+     n backslashes followed by a double quote (n >= 0):
+       \" -> "
+       \\\" -> \"
+       \\\\\" -> \\"
+ */
+#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
+#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
+char **
+prepare_spawn (char **argv)
+{
+  size_t argc;
+  char **new_argv;
+  size_t i;
+
+  /* Count number of arguments.  */
+  for (argc = 0; argv[argc] != NULL; argc++)
+    ;
+
+  /* Allocate new argument vector.  */
+  new_argv = XMALLOC (char *, argc + 1);
+
+  /* Put quoted arguments into the new argument vector.  */
+  for (i = 0; i < argc; i++)
+    {
+      const char *string = argv[i];
+
+      if (string[0] == '\0')
+	new_argv[i] = xstrdup ("\"\"");
+      else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
+	{
+	  int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
+	  size_t length;
+	  unsigned int backslashes;
+	  const char *s;
+	  char *quoted_string;
+	  char *p;
+
+	  length = 0;
+	  backslashes = 0;
+	  if (quote_around)
+	    length++;
+	  for (s = string; *s != '\0'; s++)
+	    {
+	      char c = *s;
+	      if (c == '"')
+		length += backslashes + 1;
+	      length++;
+	      if (c == '\\')
+		backslashes++;
+	      else
+		backslashes = 0;
+	    }
+	  if (quote_around)
+	    length += backslashes + 1;
+
+	  quoted_string = XMALLOC (char, length + 1);
+
+	  p = quoted_string;
+	  backslashes = 0;
+	  if (quote_around)
+	    *p++ = '"';
+	  for (s = string; *s != '\0'; s++)
+	    {
+	      char c = *s;
+	      if (c == '"')
+		{
+		  unsigned int j;
+		  for (j = backslashes + 1; j > 0; j--)
+		    *p++ = '\\';
+		}
+	      *p++ = c;
+	      if (c == '\\')
+		backslashes++;
+	      else
+		backslashes = 0;
+	    }
+	  if (quote_around)
+	    {
+	      unsigned int j;
+	      for (j = backslashes; j > 0; j--)
+		*p++ = '\\';
+	      *p++ = '"';
+	    }
+	  *p = '\0';
+
+	  new_argv[i] = quoted_string;
+	}
+      else
+	new_argv[i] = (char *) string;
+    }
+  new_argv[argc] = NULL;
+
+  return new_argv;
+}
+EOF
+		;;
+	    esac
+
+            cat <<"EOF"
+void lt_dump_script (FILE* f)
+{
+EOF
+	    func_emit_wrapper yes |
+	      $SED -n -e '
+s/^\(.\{79\}\)\(..*\)/\1\
+\2/
+h
+s/\([\\"]\)/\\\1/g
+s/$/\\n/
+s/\([^\n]*\).*/  fputs ("\1", f);/p
+g
+D'
+            cat <<"EOF"
+}
+EOF
+}
+# end: func_emit_cwrapperexe_src
+
+# func_win32_import_lib_p ARG
+# True if ARG is an import lib, as indicated by $file_magic_cmd
+func_win32_import_lib_p ()
+{
+    $opt_debug
+    case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in
+    *import*) : ;;
+    *) false ;;
+    esac
+}
+
+# func_mode_link arg...
+func_mode_link ()
+{
+    $opt_debug
+    case $host in
+    *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+      # It is impossible to link a dll without this setting, and
+      # we shouldn't force the makefile maintainer to figure out
+      # which system we are compiling for in order to pass an extra
+      # flag for every libtool invocation.
+      # allow_undefined=no
+
+      # FIXME: Unfortunately, there are problems with the above when trying
+      # to make a dll which has undefined symbols, in which case not
+      # even a static library is built.  For now, we need to specify
+      # -no-undefined on the libtool link line when we can be certain
+      # that all symbols are satisfied, otherwise we get a static library.
+      allow_undefined=yes
+      ;;
+    *)
+      allow_undefined=yes
+      ;;
+    esac
+    libtool_args=$nonopt
+    base_compile="$nonopt $@"
+    compile_command=$nonopt
+    finalize_command=$nonopt
+
+    compile_rpath=
+    finalize_rpath=
+    compile_shlibpath=
+    finalize_shlibpath=
+    convenience=
+    old_convenience=
+    deplibs=
+    old_deplibs=
+    compiler_flags=
+    linker_flags=
+    dllsearchpath=
+    lib_search_path=`pwd`
+    inst_prefix_dir=
+    new_inherited_linker_flags=
+
+    avoid_version=no
+    bindir=
+    dlfiles=
+    dlprefiles=
+    dlself=no
+    export_dynamic=no
+    export_symbols=
+    export_symbols_regex=
+    generated=
+    libobjs=
+    ltlibs=
+    module=no
+    no_install=no
+    objs=
+    non_pic_objects=
+    precious_files_regex=
+    prefer_static_libs=no
+    preload=no
+    prev=
+    prevarg=
+    release=
+    rpath=
+    xrpath=
+    perm_rpath=
+    temp_rpath=
+    thread_safe=no
+    vinfo=
+    vinfo_number=no
+    weak_libs=
+    single_module="${wl}-single_module"
+    func_infer_tag $base_compile
+
+    # We need to know -static, to get the right output filenames.
+    for arg
+    do
+      case $arg in
+      -shared)
+	test "$build_libtool_libs" != yes && \
+	  func_fatal_configuration "can not build a shared library"
+	build_old_libs=no
+	break
+	;;
+      -all-static | -static | -static-libtool-libs)
+	case $arg in
+	-all-static)
+	  if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+	    func_warning "complete static linking is impossible in this configuration"
+	  fi
+	  if test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	  prefer_static_libs=yes
+	  ;;
+	-static)
+	  if test -z "$pic_flag" && test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	  prefer_static_libs=built
+	  ;;
+	-static-libtool-libs)
+	  if test -z "$pic_flag" && test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	  prefer_static_libs=yes
+	  ;;
+	esac
+	build_libtool_libs=no
+	build_old_libs=yes
+	break
+	;;
+      esac
+    done
+
+    # See if our shared archives depend on static archives.
+    test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+    # Go through the arguments, transforming them on the way.
+    while test "$#" -gt 0; do
+      arg="$1"
+      shift
+      func_quote_for_eval "$arg"
+      qarg=$func_quote_for_eval_unquoted_result
+      func_append libtool_args " $func_quote_for_eval_result"
+
+      # If the previous option needs an argument, assign it.
+      if test -n "$prev"; then
+	case $prev in
+	output)
+	  func_append compile_command " @OUTPUT@"
+	  func_append finalize_command " @OUTPUT@"
+	  ;;
+	esac
+
+	case $prev in
+	bindir)
+	  bindir="$arg"
+	  prev=
+	  continue
+	  ;;
+	dlfiles|dlprefiles)
+	  if test "$preload" = no; then
+	    # Add the symbol object into the linking commands.
+	    func_append compile_command " @SYMFILE@"
+	    func_append finalize_command " @SYMFILE@"
+	    preload=yes
+	  fi
+	  case $arg in
+	  *.la | *.lo) ;;  # We handle these cases below.
+	  force)
+	    if test "$dlself" = no; then
+	      dlself=needless
+	      export_dynamic=yes
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  self)
+	    if test "$prev" = dlprefiles; then
+	      dlself=yes
+	    elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+	      dlself=yes
+	    else
+	      dlself=needless
+	      export_dynamic=yes
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  *)
+	    if test "$prev" = dlfiles; then
+	      func_append dlfiles " $arg"
+	    else
+	      func_append dlprefiles " $arg"
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  esac
+	  ;;
+	expsyms)
+	  export_symbols="$arg"
+	  test -f "$arg" \
+	    || func_fatal_error "symbol file \`$arg' does not exist"
+	  prev=
+	  continue
+	  ;;
+	expsyms_regex)
+	  export_symbols_regex="$arg"
+	  prev=
+	  continue
+	  ;;
+	framework)
+	  case $host in
+	    *-*-darwin*)
+	      case "$deplibs " in
+		*" $qarg.ltframework "*) ;;
+		*) func_append deplibs " $qarg.ltframework" # this is fixed later
+		   ;;
+	      esac
+	      ;;
+	  esac
+	  prev=
+	  continue
+	  ;;
+	inst_prefix)
+	  inst_prefix_dir="$arg"
+	  prev=
+	  continue
+	  ;;
+	objectlist)
+	  if test -f "$arg"; then
+	    save_arg=$arg
+	    moreargs=
+	    for fil in `cat "$save_arg"`
+	    do
+#	      func_append moreargs " $fil"
+	      arg=$fil
+	      # A libtool-controlled object.
+
+	      # Check to see that this really is a libtool object.
+	      if func_lalib_unsafe_p "$arg"; then
+		pic_object=
+		non_pic_object=
+
+		# Read the .lo file
+		func_source "$arg"
+
+		if test -z "$pic_object" ||
+		   test -z "$non_pic_object" ||
+		   test "$pic_object" = none &&
+		   test "$non_pic_object" = none; then
+		  func_fatal_error "cannot find name of object for \`$arg'"
+		fi
+
+		# Extract subdirectory from the argument.
+		func_dirname "$arg" "/" ""
+		xdir="$func_dirname_result"
+
+		if test "$pic_object" != none; then
+		  # Prepend the subdirectory the object is found in.
+		  pic_object="$xdir$pic_object"
+
+		  if test "$prev" = dlfiles; then
+		    if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+		      func_append dlfiles " $pic_object"
+		      prev=
+		      continue
+		    else
+		      # If libtool objects are unsupported, then we need to preload.
+		      prev=dlprefiles
+		    fi
+		  fi
+
+		  # CHECK ME:  I think I busted this.  -Ossama
+		  if test "$prev" = dlprefiles; then
+		    # Preload the old-style object.
+		    func_append dlprefiles " $pic_object"
+		    prev=
+		  fi
+
+		  # A PIC object.
+		  func_append libobjs " $pic_object"
+		  arg="$pic_object"
+		fi
+
+		# Non-PIC object.
+		if test "$non_pic_object" != none; then
+		  # Prepend the subdirectory the object is found in.
+		  non_pic_object="$xdir$non_pic_object"
+
+		  # A standard non-PIC object
+		  func_append non_pic_objects " $non_pic_object"
+		  if test -z "$pic_object" || test "$pic_object" = none ; then
+		    arg="$non_pic_object"
+		  fi
+		else
+		  # If the PIC object exists, use it instead.
+		  # $xdir was prepended to $pic_object above.
+		  non_pic_object="$pic_object"
+		  func_append non_pic_objects " $non_pic_object"
+		fi
+	      else
+		# Only an error if not doing a dry-run.
+		if $opt_dry_run; then
+		  # Extract subdirectory from the argument.
+		  func_dirname "$arg" "/" ""
+		  xdir="$func_dirname_result"
+
+		  func_lo2o "$arg"
+		  pic_object=$xdir$objdir/$func_lo2o_result
+		  non_pic_object=$xdir$func_lo2o_result
+		  func_append libobjs " $pic_object"
+		  func_append non_pic_objects " $non_pic_object"
+	        else
+		  func_fatal_error "\`$arg' is not a valid libtool object"
+		fi
+	      fi
+	    done
+	  else
+	    func_fatal_error "link input file \`$arg' does not exist"
+	  fi
+	  arg=$save_arg
+	  prev=
+	  continue
+	  ;;
+	precious_regex)
+	  precious_files_regex="$arg"
+	  prev=
+	  continue
+	  ;;
+	release)
+	  release="-$arg"
+	  prev=
+	  continue
+	  ;;
+	rpath | xrpath)
+	  # We need an absolute path.
+	  case $arg in
+	  [\\/]* | [A-Za-z]:[\\/]*) ;;
+	  *)
+	    func_fatal_error "only absolute run-paths are allowed"
+	    ;;
+	  esac
+	  if test "$prev" = rpath; then
+	    case "$rpath " in
+	    *" $arg "*) ;;
+	    *) func_append rpath " $arg" ;;
+	    esac
+	  else
+	    case "$xrpath " in
+	    *" $arg "*) ;;
+	    *) func_append xrpath " $arg" ;;
+	    esac
+	  fi
+	  prev=
+	  continue
+	  ;;
+	shrext)
+	  shrext_cmds="$arg"
+	  prev=
+	  continue
+	  ;;
+	weak)
+	  func_append weak_libs " $arg"
+	  prev=
+	  continue
+	  ;;
+	xcclinker)
+	  func_append linker_flags " $qarg"
+	  func_append compiler_flags " $qarg"
+	  prev=
+	  func_append compile_command " $qarg"
+	  func_append finalize_command " $qarg"
+	  continue
+	  ;;
+	xcompiler)
+	  func_append compiler_flags " $qarg"
+	  prev=
+	  func_append compile_command " $qarg"
+	  func_append finalize_command " $qarg"
+	  continue
+	  ;;
+	xlinker)
+	  func_append linker_flags " $qarg"
+	  func_append compiler_flags " $wl$qarg"
+	  prev=
+	  func_append compile_command " $wl$qarg"
+	  func_append finalize_command " $wl$qarg"
+	  continue
+	  ;;
+	*)
+	  eval "$prev=\"\$arg\""
+	  prev=
+	  continue
+	  ;;
+	esac
+      fi # test -n "$prev"
+
+      prevarg="$arg"
+
+      case $arg in
+      -all-static)
+	if test -n "$link_static_flag"; then
+	  # See comment for -static flag below, for more details.
+	  func_append compile_command " $link_static_flag"
+	  func_append finalize_command " $link_static_flag"
+	fi
+	continue
+	;;
+
+      -allow-undefined)
+	# FIXME: remove this flag sometime in the future.
+	func_fatal_error "\`-allow-undefined' must not be used because it is the default"
+	;;
+
+      -avoid-version)
+	avoid_version=yes
+	continue
+	;;
+
+      -bindir)
+	prev=bindir
+	continue
+	;;
+
+      -dlopen)
+	prev=dlfiles
+	continue
+	;;
+
+      -dlpreopen)
+	prev=dlprefiles
+	continue
+	;;
+
+      -export-dynamic)
+	export_dynamic=yes
+	continue
+	;;
+
+      -export-symbols | -export-symbols-regex)
+	if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+	  func_fatal_error "more than one -exported-symbols argument is not allowed"
+	fi
+	if test "X$arg" = "X-export-symbols"; then
+	  prev=expsyms
+	else
+	  prev=expsyms_regex
+	fi
+	continue
+	;;
+
+      -framework)
+	prev=framework
+	continue
+	;;
+
+      -inst-prefix-dir)
+	prev=inst_prefix
+	continue
+	;;
+
+      # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+      # so, if we see these flags be careful not to treat them like -L
+      -L[A-Z][A-Z]*:*)
+	case $with_gcc/$host in
+	no/*-*-irix* | /*-*-irix*)
+	  func_append compile_command " $arg"
+	  func_append finalize_command " $arg"
+	  ;;
+	esac
+	continue
+	;;
+
+      -L*)
+	func_stripname "-L" '' "$arg"
+	if test -z "$func_stripname_result"; then
+	  if test "$#" -gt 0; then
+	    func_fatal_error "require no space between \`-L' and \`$1'"
+	  else
+	    func_fatal_error "need path for \`-L' option"
+	  fi
+	fi
+	func_resolve_sysroot "$func_stripname_result"
+	dir=$func_resolve_sysroot_result
+	# We need an absolute path.
+	case $dir in
+	[\\/]* | [A-Za-z]:[\\/]*) ;;
+	*)
+	  absdir=`cd "$dir" && pwd`
+	  test -z "$absdir" && \
+	    func_fatal_error "cannot determine absolute directory name of \`$dir'"
+	  dir="$absdir"
+	  ;;
+	esac
+	case "$deplibs " in
+	*" -L$dir "* | *" $arg "*)
+	  # Will only happen for absolute or sysroot arguments
+	  ;;
+	*)
+	  # Preserve sysroot, but never include relative directories
+	  case $dir in
+	    [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;;
+	    *) func_append deplibs " -L$dir" ;;
+	  esac
+	  func_append lib_search_path " $dir"
+	  ;;
+	esac
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+	  testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'`
+	  case :$dllsearchpath: in
+	  *":$dir:"*) ;;
+	  ::) dllsearchpath=$dir;;
+	  *) func_append dllsearchpath ":$dir";;
+	  esac
+	  case :$dllsearchpath: in
+	  *":$testbindir:"*) ;;
+	  ::) dllsearchpath=$testbindir;;
+	  *) func_append dllsearchpath ":$testbindir";;
+	  esac
+	  ;;
+	esac
+	continue
+	;;
+
+      -l*)
+	if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
+	  case $host in
+	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*)
+	    # These systems don't actually have a C or math library (as such)
+	    continue
+	    ;;
+	  *-*-os2*)
+	    # These systems don't actually have a C library (as such)
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+	    # Do not include libc due to us having libc/libc_r.
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-rhapsody* | *-*-darwin1.[012])
+	    # Rhapsody C and math libraries are in the System framework
+	    func_append deplibs " System.ltframework"
+	    continue
+	    ;;
+	  *-*-sco3.2v5* | *-*-sco5v6*)
+	    # Causes problems with __ctype
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+	    # Compiler inserts libc in the correct place for threads to work
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  esac
+	elif test "X$arg" = "X-lc_r"; then
+	 case $host in
+	 *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+	   # Do not include libc_r directly, use -pthread flag.
+	   continue
+	   ;;
+	 esac
+	fi
+	func_append deplibs " $arg"
+	continue
+	;;
+
+      -module)
+	module=yes
+	continue
+	;;
+
+      # Tru64 UNIX uses -model [arg] to determine the layout of C++
+      # classes, name mangling, and exception handling.
+      # Darwin uses the -arch flag to determine output architecture.
+      -model|-arch|-isysroot|--sysroot)
+	func_append compiler_flags " $arg"
+	func_append compile_command " $arg"
+	func_append finalize_command " $arg"
+	prev=xcompiler
+	continue
+	;;
+
+      -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \
+      |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
+	func_append compiler_flags " $arg"
+	func_append compile_command " $arg"
+	func_append finalize_command " $arg"
+	case "$new_inherited_linker_flags " in
+	    *" $arg "*) ;;
+	    * ) func_append new_inherited_linker_flags " $arg" ;;
+	esac
+	continue
+	;;
+
+      -multi_module)
+	single_module="${wl}-multi_module"
+	continue
+	;;
+
+      -no-fast-install)
+	fast_install=no
+	continue
+	;;
+
+      -no-install)
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*)
+	  # The PATH hackery in wrapper scripts is required on Windows
+	  # and Darwin in order for the loader to find any dlls it needs.
+	  func_warning "\`-no-install' is ignored for $host"
+	  func_warning "assuming \`-no-fast-install' instead"
+	  fast_install=no
+	  ;;
+	*) no_install=yes ;;
+	esac
+	continue
+	;;
+
+      -no-undefined)
+	allow_undefined=no
+	continue
+	;;
+
+      -objectlist)
+	prev=objectlist
+	continue
+	;;
+
+      -o) prev=output ;;
+
+      -precious-files-regex)
+	prev=precious_regex
+	continue
+	;;
+
+      -release)
+	prev=release
+	continue
+	;;
+
+      -rpath)
+	prev=rpath
+	continue
+	;;
+
+      -R)
+	prev=xrpath
+	continue
+	;;
+
+      -R*)
+	func_stripname '-R' '' "$arg"
+	dir=$func_stripname_result
+	# We need an absolute path.
+	case $dir in
+	[\\/]* | [A-Za-z]:[\\/]*) ;;
+	=*)
+	  func_stripname '=' '' "$dir"
+	  dir=$lt_sysroot$func_stripname_result
+	  ;;
+	*)
+	  func_fatal_error "only absolute run-paths are allowed"
+	  ;;
+	esac
+	case "$xrpath " in
+	*" $dir "*) ;;
+	*) func_append xrpath " $dir" ;;
+	esac
+	continue
+	;;
+
+      -shared)
+	# The effects of -shared are defined in a previous loop.
+	continue
+	;;
+
+      -shrext)
+	prev=shrext
+	continue
+	;;
+
+      -static | -static-libtool-libs)
+	# The effects of -static are defined in a previous loop.
+	# We used to do the same as -all-static on platforms that
+	# didn't have a PIC flag, but the assumption that the effects
+	# would be equivalent was wrong.  It would break on at least
+	# Digital Unix and AIX.
+	continue
+	;;
+
+      -thread-safe)
+	thread_safe=yes
+	continue
+	;;
+
+      -version-info)
+	prev=vinfo
+	continue
+	;;
+
+      -version-number)
+	prev=vinfo
+	vinfo_number=yes
+	continue
+	;;
+
+      -weak)
+        prev=weak
+	continue
+	;;
+
+      -Wc,*)
+	func_stripname '-Wc,' '' "$arg"
+	args=$func_stripname_result
+	arg=
+	save_ifs="$IFS"; IFS=','
+	for flag in $args; do
+	  IFS="$save_ifs"
+          func_quote_for_eval "$flag"
+	  func_append arg " $func_quote_for_eval_result"
+	  func_append compiler_flags " $func_quote_for_eval_result"
+	done
+	IFS="$save_ifs"
+	func_stripname ' ' '' "$arg"
+	arg=$func_stripname_result
+	;;
+
+      -Wl,*)
+	func_stripname '-Wl,' '' "$arg"
+	args=$func_stripname_result
+	arg=
+	save_ifs="$IFS"; IFS=','
+	for flag in $args; do
+	  IFS="$save_ifs"
+          func_quote_for_eval "$flag"
+	  func_append arg " $wl$func_quote_for_eval_result"
+	  func_append compiler_flags " $wl$func_quote_for_eval_result"
+	  func_append linker_flags " $func_quote_for_eval_result"
+	done
+	IFS="$save_ifs"
+	func_stripname ' ' '' "$arg"
+	arg=$func_stripname_result
+	;;
+
+      -Xcompiler)
+	prev=xcompiler
+	continue
+	;;
+
+      -Xlinker)
+	prev=xlinker
+	continue
+	;;
+
+      -XCClinker)
+	prev=xcclinker
+	continue
+	;;
+
+      # -msg_* for osf cc
+      -msg_*)
+	func_quote_for_eval "$arg"
+	arg="$func_quote_for_eval_result"
+	;;
+
+      # Flags to be passed through unchanged, with rationale:
+      # -64, -mips[0-9]      enable 64-bit mode for the SGI compiler
+      # -r[0-9][0-9]*        specify processor for the SGI compiler
+      # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler
+      # +DA*, +DD*           enable 64-bit mode for the HP compiler
+      # -q*                  compiler args for the IBM compiler
+      # -m*, -t[45]*, -txscale* architecture-specific flags for GCC
+      # -F/path              path to uninstalled frameworks, gcc on darwin
+      # -p, -pg, --coverage, -fprofile-*  profiling flags for GCC
+      # @file                GCC response files
+      # -tp=*                Portland pgcc target processor selection
+      # --sysroot=*          for sysroot support
+      # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization
+      -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
+      -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \
+      -O*|-flto*|-fwhopr*|-fuse-linker-plugin)
+        func_quote_for_eval "$arg"
+	arg="$func_quote_for_eval_result"
+        func_append compile_command " $arg"
+        func_append finalize_command " $arg"
+        func_append compiler_flags " $arg"
+        continue
+        ;;
+
+      # Some other compiler flag.
+      -* | +*)
+        func_quote_for_eval "$arg"
+	arg="$func_quote_for_eval_result"
+	;;
+
+      *.$objext)
+	# A standard object.
+	func_append objs " $arg"
+	;;
+
+      *.lo)
+	# A libtool-controlled object.
+
+	# Check to see that this really is a libtool object.
+	if func_lalib_unsafe_p "$arg"; then
+	  pic_object=
+	  non_pic_object=
+
+	  # Read the .lo file
+	  func_source "$arg"
+
+	  if test -z "$pic_object" ||
+	     test -z "$non_pic_object" ||
+	     test "$pic_object" = none &&
+	     test "$non_pic_object" = none; then
+	    func_fatal_error "cannot find name of object for \`$arg'"
+	  fi
+
+	  # Extract subdirectory from the argument.
+	  func_dirname "$arg" "/" ""
+	  xdir="$func_dirname_result"
+
+	  if test "$pic_object" != none; then
+	    # Prepend the subdirectory the object is found in.
+	    pic_object="$xdir$pic_object"
+
+	    if test "$prev" = dlfiles; then
+	      if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+		func_append dlfiles " $pic_object"
+		prev=
+		continue
+	      else
+		# If libtool objects are unsupported, then we need to preload.
+		prev=dlprefiles
+	      fi
+	    fi
+
+	    # CHECK ME:  I think I busted this.  -Ossama
+	    if test "$prev" = dlprefiles; then
+	      # Preload the old-style object.
+	      func_append dlprefiles " $pic_object"
+	      prev=
+	    fi
+
+	    # A PIC object.
+	    func_append libobjs " $pic_object"
+	    arg="$pic_object"
+	  fi
+
+	  # Non-PIC object.
+	  if test "$non_pic_object" != none; then
+	    # Prepend the subdirectory the object is found in.
+	    non_pic_object="$xdir$non_pic_object"
+
+	    # A standard non-PIC object
+	    func_append non_pic_objects " $non_pic_object"
+	    if test -z "$pic_object" || test "$pic_object" = none ; then
+	      arg="$non_pic_object"
+	    fi
+	  else
+	    # If the PIC object exists, use it instead.
+	    # $xdir was prepended to $pic_object above.
+	    non_pic_object="$pic_object"
+	    func_append non_pic_objects " $non_pic_object"
+	  fi
+	else
+	  # Only an error if not doing a dry-run.
+	  if $opt_dry_run; then
+	    # Extract subdirectory from the argument.
+	    func_dirname "$arg" "/" ""
+	    xdir="$func_dirname_result"
+
+	    func_lo2o "$arg"
+	    pic_object=$xdir$objdir/$func_lo2o_result
+	    non_pic_object=$xdir$func_lo2o_result
+	    func_append libobjs " $pic_object"
+	    func_append non_pic_objects " $non_pic_object"
+	  else
+	    func_fatal_error "\`$arg' is not a valid libtool object"
+	  fi
+	fi
+	;;
+
+      *.$libext)
+	# An archive.
+	func_append deplibs " $arg"
+	func_append old_deplibs " $arg"
+	continue
+	;;
+
+      *.la)
+	# A libtool-controlled library.
+
+	func_resolve_sysroot "$arg"
+	if test "$prev" = dlfiles; then
+	  # This library was specified with -dlopen.
+	  func_append dlfiles " $func_resolve_sysroot_result"
+	  prev=
+	elif test "$prev" = dlprefiles; then
+	  # The library was specified with -dlpreopen.
+	  func_append dlprefiles " $func_resolve_sysroot_result"
+	  prev=
+	else
+	  func_append deplibs " $func_resolve_sysroot_result"
+	fi
+	continue
+	;;
+
+      # Some other compiler argument.
+      *)
+	# Unknown arguments in both finalize_command and compile_command need
+	# to be aesthetically quoted because they are evaled later.
+	func_quote_for_eval "$arg"
+	arg="$func_quote_for_eval_result"
+	;;
+      esac # arg
+
+      # Now actually substitute the argument into the commands.
+      if test -n "$arg"; then
+	func_append compile_command " $arg"
+	func_append finalize_command " $arg"
+      fi
+    done # argument parsing loop
+
+    test -n "$prev" && \
+      func_fatal_help "the \`$prevarg' option requires an argument"
+
+    if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+      eval arg=\"$export_dynamic_flag_spec\"
+      func_append compile_command " $arg"
+      func_append finalize_command " $arg"
+    fi
+
+    oldlibs=
+    # calculate the name of the file, without its directory
+    func_basename "$output"
+    outputname="$func_basename_result"
+    libobjs_save="$libobjs"
+
+    if test -n "$shlibpath_var"; then
+      # get the directories listed in $shlibpath_var
+      eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\`
+    else
+      shlib_search_path=
+    fi
+    eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
+    eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+    func_dirname "$output" "/" ""
+    output_objdir="$func_dirname_result$objdir"
+    func_to_tool_file "$output_objdir/"
+    tool_output_objdir=$func_to_tool_file_result
+    # Create the object directory.
+    func_mkdir_p "$output_objdir"
+
+    # Determine the type of output
+    case $output in
+    "")
+      func_fatal_help "you must specify an output file"
+      ;;
+    *.$libext) linkmode=oldlib ;;
+    *.lo | *.$objext) linkmode=obj ;;
+    *.la) linkmode=lib ;;
+    *) linkmode=prog ;; # Anything else should be a program.
+    esac
+
+    specialdeplibs=
+
+    libs=
+    # Find all interdependent deplibs by searching for libraries
+    # that are linked more than once (e.g. -la -lb -la)
+    for deplib in $deplibs; do
+      if $opt_preserve_dup_deps ; then
+	case "$libs " in
+	*" $deplib "*) func_append specialdeplibs " $deplib" ;;
+	esac
+      fi
+      func_append libs " $deplib"
+    done
+
+    if test "$linkmode" = lib; then
+      libs="$predeps $libs $compiler_lib_search_path $postdeps"
+
+      # Compute libraries that are listed more than once in $predeps
+      # $postdeps and mark them as special (i.e., whose duplicates are
+      # not to be eliminated).
+      pre_post_deps=
+      if $opt_duplicate_compiler_generated_deps; then
+	for pre_post_dep in $predeps $postdeps; do
+	  case "$pre_post_deps " in
+	  *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;;
+	  esac
+	  func_append pre_post_deps " $pre_post_dep"
+	done
+      fi
+      pre_post_deps=
+    fi
+
+    deplibs=
+    newdependency_libs=
+    newlib_search_path=
+    need_relink=no # whether we're linking any uninstalled libtool libraries
+    notinst_deplibs= # not-installed libtool libraries
+    notinst_path= # paths that contain not-installed libtool libraries
+
+    case $linkmode in
+    lib)
+	passes="conv dlpreopen link"
+	for file in $dlfiles $dlprefiles; do
+	  case $file in
+	  *.la) ;;
+	  *)
+	    func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file"
+	    ;;
+	  esac
+	done
+	;;
+    prog)
+	compile_deplibs=
+	finalize_deplibs=
+	alldeplibs=no
+	newdlfiles=
+	newdlprefiles=
+	passes="conv scan dlopen dlpreopen link"
+	;;
+    *)  passes="conv"
+	;;
+    esac
+
+    for pass in $passes; do
+      # The preopen pass in lib mode reverses $deplibs; put it back here
+      # so that -L comes before libs that need it for instance...
+      if test "$linkmode,$pass" = "lib,link"; then
+	## FIXME: Find the place where the list is rebuilt in the wrong
+	##        order, and fix it there properly
+        tmp_deplibs=
+	for deplib in $deplibs; do
+	  tmp_deplibs="$deplib $tmp_deplibs"
+	done
+	deplibs="$tmp_deplibs"
+      fi
+
+      if test "$linkmode,$pass" = "lib,link" ||
+	 test "$linkmode,$pass" = "prog,scan"; then
+	libs="$deplibs"
+	deplibs=
+      fi
+      if test "$linkmode" = prog; then
+	case $pass in
+	dlopen) libs="$dlfiles" ;;
+	dlpreopen) libs="$dlprefiles" ;;
+	link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
+	esac
+      fi
+      if test "$linkmode,$pass" = "lib,dlpreopen"; then
+	# Collect and forward deplibs of preopened libtool libs
+	for lib in $dlprefiles; do
+	  # Ignore non-libtool-libs
+	  dependency_libs=
+	  func_resolve_sysroot "$lib"
+	  case $lib in
+	  *.la)	func_source "$func_resolve_sysroot_result" ;;
+	  esac
+
+	  # Collect preopened libtool deplibs, except any this library
+	  # has declared as weak libs
+	  for deplib in $dependency_libs; do
+	    func_basename "$deplib"
+            deplib_base=$func_basename_result
+	    case " $weak_libs " in
+	    *" $deplib_base "*) ;;
+	    *) func_append deplibs " $deplib" ;;
+	    esac
+	  done
+	done
+	libs="$dlprefiles"
+      fi
+      if test "$pass" = dlopen; then
+	# Collect dlpreopened libraries
+	save_deplibs="$deplibs"
+	deplibs=
+      fi
+
+      for deplib in $libs; do
+	lib=
+	found=no
+	case $deplib in
+	-mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \
+        |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
+	  if test "$linkmode,$pass" = "prog,link"; then
+	    compile_deplibs="$deplib $compile_deplibs"
+	    finalize_deplibs="$deplib $finalize_deplibs"
+	  else
+	    func_append compiler_flags " $deplib"
+	    if test "$linkmode" = lib ; then
+		case "$new_inherited_linker_flags " in
+		    *" $deplib "*) ;;
+		    * ) func_append new_inherited_linker_flags " $deplib" ;;
+		esac
+	    fi
+	  fi
+	  continue
+	  ;;
+	-l*)
+	  if test "$linkmode" != lib && test "$linkmode" != prog; then
+	    func_warning "\`-l' is ignored for archives/objects"
+	    continue
+	  fi
+	  func_stripname '-l' '' "$deplib"
+	  name=$func_stripname_result
+	  if test "$linkmode" = lib; then
+	    searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path"
+	  else
+	    searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path"
+	  fi
+	  for searchdir in $searchdirs; do
+	    for search_ext in .la $std_shrext .so .a; do
+	      # Search the libtool library
+	      lib="$searchdir/lib${name}${search_ext}"
+	      if test -f "$lib"; then
+		if test "$search_ext" = ".la"; then
+		  found=yes
+		else
+		  found=no
+		fi
+		break 2
+	      fi
+	    done
+	  done
+	  if test "$found" != yes; then
+	    # deplib doesn't seem to be a libtool library
+	    if test "$linkmode,$pass" = "prog,link"; then
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    else
+	      deplibs="$deplib $deplibs"
+	      test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+	    fi
+	    continue
+	  else # deplib is a libtool library
+	    # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
+	    # We need to do some special things here, and not later.
+	    if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+	      case " $predeps $postdeps " in
+	      *" $deplib "*)
+		if func_lalib_p "$lib"; then
+		  library_names=
+		  old_library=
+		  func_source "$lib"
+		  for l in $old_library $library_names; do
+		    ll="$l"
+		  done
+		  if test "X$ll" = "X$old_library" ; then # only static version available
+		    found=no
+		    func_dirname "$lib" "" "."
+		    ladir="$func_dirname_result"
+		    lib=$ladir/$old_library
+		    if test "$linkmode,$pass" = "prog,link"; then
+		      compile_deplibs="$deplib $compile_deplibs"
+		      finalize_deplibs="$deplib $finalize_deplibs"
+		    else
+		      deplibs="$deplib $deplibs"
+		      test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+		    fi
+		    continue
+		  fi
+		fi
+		;;
+	      *) ;;
+	      esac
+	    fi
+	  fi
+	  ;; # -l
+	*.ltframework)
+	  if test "$linkmode,$pass" = "prog,link"; then
+	    compile_deplibs="$deplib $compile_deplibs"
+	    finalize_deplibs="$deplib $finalize_deplibs"
+	  else
+	    deplibs="$deplib $deplibs"
+	    if test "$linkmode" = lib ; then
+		case "$new_inherited_linker_flags " in
+		    *" $deplib "*) ;;
+		    * ) func_append new_inherited_linker_flags " $deplib" ;;
+		esac
+	    fi
+	  fi
+	  continue
+	  ;;
+	-L*)
+	  case $linkmode in
+	  lib)
+	    deplibs="$deplib $deplibs"
+	    test "$pass" = conv && continue
+	    newdependency_libs="$deplib $newdependency_libs"
+	    func_stripname '-L' '' "$deplib"
+	    func_resolve_sysroot "$func_stripname_result"
+	    func_append newlib_search_path " $func_resolve_sysroot_result"
+	    ;;
+	  prog)
+	    if test "$pass" = conv; then
+	      deplibs="$deplib $deplibs"
+	      continue
+	    fi
+	    if test "$pass" = scan; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    fi
+	    func_stripname '-L' '' "$deplib"
+	    func_resolve_sysroot "$func_stripname_result"
+	    func_append newlib_search_path " $func_resolve_sysroot_result"
+	    ;;
+	  *)
+	    func_warning "\`-L' is ignored for archives/objects"
+	    ;;
+	  esac # linkmode
+	  continue
+	  ;; # -L
+	-R*)
+	  if test "$pass" = link; then
+	    func_stripname '-R' '' "$deplib"
+	    func_resolve_sysroot "$func_stripname_result"
+	    dir=$func_resolve_sysroot_result
+	    # Make sure the xrpath contains only unique directories.
+	    case "$xrpath " in
+	    *" $dir "*) ;;
+	    *) func_append xrpath " $dir" ;;
+	    esac
+	  fi
+	  deplibs="$deplib $deplibs"
+	  continue
+	  ;;
+	*.la)
+	  func_resolve_sysroot "$deplib"
+	  lib=$func_resolve_sysroot_result
+	  ;;
+	*.$libext)
+	  if test "$pass" = conv; then
+	    deplibs="$deplib $deplibs"
+	    continue
+	  fi
+	  case $linkmode in
+	  lib)
+	    # Linking convenience modules into shared libraries is allowed,
+	    # but linking other static libraries is non-portable.
+	    case " $dlpreconveniencelibs " in
+	    *" $deplib "*) ;;
+	    *)
+	      valid_a_lib=no
+	      case $deplibs_check_method in
+		match_pattern*)
+		  set dummy $deplibs_check_method; shift
+		  match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+		  if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \
+		    | $EGREP "$match_pattern_regex" > /dev/null; then
+		    valid_a_lib=yes
+		  fi
+		;;
+		pass_all)
+		  valid_a_lib=yes
+		;;
+	      esac
+	      if test "$valid_a_lib" != yes; then
+		echo
+		$ECHO "*** Warning: Trying to link with static lib archive $deplib."
+		echo "*** I have the capability to make that library automatically link in when"
+		echo "*** you link to this library.  But I can only do this if you have a"
+		echo "*** shared version of the library, which you do not appear to have"
+		echo "*** because the file extensions .$libext of this argument makes me believe"
+		echo "*** that it is just a static archive that I should not use here."
+	      else
+		echo
+		$ECHO "*** Warning: Linking the shared library $output against the"
+		$ECHO "*** static library $deplib is not portable!"
+		deplibs="$deplib $deplibs"
+	      fi
+	      ;;
+	    esac
+	    continue
+	    ;;
+	  prog)
+	    if test "$pass" != link; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    fi
+	    continue
+	    ;;
+	  esac # linkmode
+	  ;; # *.$libext
+	*.lo | *.$objext)
+	  if test "$pass" = conv; then
+	    deplibs="$deplib $deplibs"
+	  elif test "$linkmode" = prog; then
+	    if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+	      # If there is no dlopen support or we're linking statically,
+	      # we need to preload.
+	      func_append newdlprefiles " $deplib"
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    else
+	      func_append newdlfiles " $deplib"
+	    fi
+	  fi
+	  continue
+	  ;;
+	%DEPLIBS%)
+	  alldeplibs=yes
+	  continue
+	  ;;
+	esac # case $deplib
+
+	if test "$found" = yes || test -f "$lib"; then :
+	else
+	  func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'"
+	fi
+
+	# Check to see that this really is a libtool archive.
+	func_lalib_unsafe_p "$lib" \
+	  || func_fatal_error "\`$lib' is not a valid libtool archive"
+
+	func_dirname "$lib" "" "."
+	ladir="$func_dirname_result"
+
+	dlname=
+	dlopen=
+	dlpreopen=
+	libdir=
+	library_names=
+	old_library=
+	inherited_linker_flags=
+	# If the library was installed with an old release of libtool,
+	# it will not redefine variables installed, or shouldnotlink
+	installed=yes
+	shouldnotlink=no
+	avoidtemprpath=
+
+
+	# Read the .la file
+	func_source "$lib"
+
+	# Convert "-framework foo" to "foo.ltframework"
+	if test -n "$inherited_linker_flags"; then
+	  tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'`
+	  for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do
+	    case " $new_inherited_linker_flags " in
+	      *" $tmp_inherited_linker_flag "*) ;;
+	      *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";;
+	    esac
+	  done
+	fi
+	dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	if test "$linkmode,$pass" = "lib,link" ||
+	   test "$linkmode,$pass" = "prog,scan" ||
+	   { test "$linkmode" != prog && test "$linkmode" != lib; }; then
+	  test -n "$dlopen" && func_append dlfiles " $dlopen"
+	  test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen"
+	fi
+
+	if test "$pass" = conv; then
+	  # Only check for convenience libraries
+	  deplibs="$lib $deplibs"
+	  if test -z "$libdir"; then
+	    if test -z "$old_library"; then
+	      func_fatal_error "cannot find name of link library for \`$lib'"
+	    fi
+	    # It is a libtool convenience library, so add in its objects.
+	    func_append convenience " $ladir/$objdir/$old_library"
+	    func_append old_convenience " $ladir/$objdir/$old_library"
+	  elif test "$linkmode" != prog && test "$linkmode" != lib; then
+	    func_fatal_error "\`$lib' is not a convenience library"
+	  fi
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    deplibs="$deplib $deplibs"
+	    if $opt_preserve_dup_deps ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) func_append specialdeplibs " $deplib" ;;
+	      esac
+	    fi
+	    func_append tmp_libs " $deplib"
+	  done
+	  continue
+	fi # $pass = conv
+
+
+	# Get the name of the library we link against.
+	linklib=
+	if test -n "$old_library" &&
+	   { test "$prefer_static_libs" = yes ||
+	     test "$prefer_static_libs,$installed" = "built,no"; }; then
+	  linklib=$old_library
+	else
+	  for l in $old_library $library_names; do
+	    linklib="$l"
+	  done
+	fi
+	if test -z "$linklib"; then
+	  func_fatal_error "cannot find name of link library for \`$lib'"
+	fi
+
+	# This library was specified with -dlopen.
+	if test "$pass" = dlopen; then
+	  if test -z "$libdir"; then
+	    func_fatal_error "cannot -dlopen a convenience library: \`$lib'"
+	  fi
+	  if test -z "$dlname" ||
+	     test "$dlopen_support" != yes ||
+	     test "$build_libtool_libs" = no; then
+	    # If there is no dlname, no dlopen support or we're linking
+	    # statically, we need to preload.  We also need to preload any
+	    # dependent libraries so libltdl's deplib preloader doesn't
+	    # bomb out in the load deplibs phase.
+	    func_append dlprefiles " $lib $dependency_libs"
+	  else
+	    func_append newdlfiles " $lib"
+	  fi
+	  continue
+	fi # $pass = dlopen
+
+	# We need an absolute path.
+	case $ladir in
+	[\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
+	*)
+	  abs_ladir=`cd "$ladir" && pwd`
+	  if test -z "$abs_ladir"; then
+	    func_warning "cannot determine absolute directory name of \`$ladir'"
+	    func_warning "passing it literally to the linker, although it might fail"
+	    abs_ladir="$ladir"
+	  fi
+	  ;;
+	esac
+	func_basename "$lib"
+	laname="$func_basename_result"
+
+	# Find the relevant object directory and library name.
+	if test "X$installed" = Xyes; then
+	  if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+	    func_warning "library \`$lib' was moved."
+	    dir="$ladir"
+	    absdir="$abs_ladir"
+	    libdir="$abs_ladir"
+	  else
+	    dir="$lt_sysroot$libdir"
+	    absdir="$lt_sysroot$libdir"
+	  fi
+	  test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
+	else
+	  if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+	    dir="$ladir"
+	    absdir="$abs_ladir"
+	    # Remove this search path later
+	    func_append notinst_path " $abs_ladir"
+	  else
+	    dir="$ladir/$objdir"
+	    absdir="$abs_ladir/$objdir"
+	    # Remove this search path later
+	    func_append notinst_path " $abs_ladir"
+	  fi
+	fi # $installed = yes
+	func_stripname 'lib' '.la' "$laname"
+	name=$func_stripname_result
+
+	# This library was specified with -dlpreopen.
+	if test "$pass" = dlpreopen; then
+	  if test -z "$libdir" && test "$linkmode" = prog; then
+	    func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'"
+	  fi
+	  case "$host" in
+	    # special handling for platforms with PE-DLLs.
+	    *cygwin* | *mingw* | *cegcc* )
+	      # Linker will automatically link against shared library if both
+	      # static and shared are present.  Therefore, ensure we extract
+	      # symbols from the import library if a shared library is present
+	      # (otherwise, the dlopen module name will be incorrect).  We do
+	      # this by putting the import library name into $newdlprefiles.
+	      # We recover the dlopen module name by 'saving' the la file
+	      # name in a special purpose variable, and (later) extracting the
+	      # dlname from the la file.
+	      if test -n "$dlname"; then
+	        func_tr_sh "$dir/$linklib"
+	        eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname"
+	        func_append newdlprefiles " $dir/$linklib"
+	      else
+	        func_append newdlprefiles " $dir/$old_library"
+	        # Keep a list of preopened convenience libraries to check
+	        # that they are being used correctly in the link pass.
+	        test -z "$libdir" && \
+	          func_append dlpreconveniencelibs " $dir/$old_library"
+	      fi
+	    ;;
+	    * )
+	      # Prefer using a static library (so that no silly _DYNAMIC symbols
+	      # are required to link).
+	      if test -n "$old_library"; then
+	        func_append newdlprefiles " $dir/$old_library"
+	        # Keep a list of preopened convenience libraries to check
+	        # that they are being used correctly in the link pass.
+	        test -z "$libdir" && \
+	          func_append dlpreconveniencelibs " $dir/$old_library"
+	      # Otherwise, use the dlname, so that lt_dlopen finds it.
+	      elif test -n "$dlname"; then
+	        func_append newdlprefiles " $dir/$dlname"
+	      else
+	        func_append newdlprefiles " $dir/$linklib"
+	      fi
+	    ;;
+	  esac
+	fi # $pass = dlpreopen
+
+	if test -z "$libdir"; then
+	  # Link the convenience library
+	  if test "$linkmode" = lib; then
+	    deplibs="$dir/$old_library $deplibs"
+	  elif test "$linkmode,$pass" = "prog,link"; then
+	    compile_deplibs="$dir/$old_library $compile_deplibs"
+	    finalize_deplibs="$dir/$old_library $finalize_deplibs"
+	  else
+	    deplibs="$lib $deplibs" # used for prog,scan pass
+	  fi
+	  continue
+	fi
+
+
+	if test "$linkmode" = prog && test "$pass" != link; then
+	  func_append newlib_search_path " $ladir"
+	  deplibs="$lib $deplibs"
+
+	  linkalldeplibs=no
+	  if test "$link_all_deplibs" != no || test -z "$library_names" ||
+	     test "$build_libtool_libs" = no; then
+	    linkalldeplibs=yes
+	  fi
+
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    case $deplib in
+	    -L*) func_stripname '-L' '' "$deplib"
+	         func_resolve_sysroot "$func_stripname_result"
+	         func_append newlib_search_path " $func_resolve_sysroot_result"
+		 ;;
+	    esac
+	    # Need to link against all dependency_libs?
+	    if test "$linkalldeplibs" = yes; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      # Need to hardcode shared library paths
+	      # or/and link against static libraries
+	      newdependency_libs="$deplib $newdependency_libs"
+	    fi
+	    if $opt_preserve_dup_deps ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) func_append specialdeplibs " $deplib" ;;
+	      esac
+	    fi
+	    func_append tmp_libs " $deplib"
+	  done # for deplib
+	  continue
+	fi # $linkmode = prog...
+
+	if test "$linkmode,$pass" = "prog,link"; then
+	  if test -n "$library_names" &&
+	     { { test "$prefer_static_libs" = no ||
+	         test "$prefer_static_libs,$installed" = "built,yes"; } ||
+	       test -z "$old_library"; }; then
+	    # We need to hardcode the library path
+	    if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
+	      # Make sure the rpath contains only unique directories.
+	      case "$temp_rpath:" in
+	      *"$absdir:"*) ;;
+	      *) func_append temp_rpath "$absdir:" ;;
+	      esac
+	    fi
+
+	    # Hardcode the library path.
+	    # Skip directories that are in the system default run-time
+	    # search path.
+	    case " $sys_lib_dlsearch_path " in
+	    *" $absdir "*) ;;
+	    *)
+	      case "$compile_rpath " in
+	      *" $absdir "*) ;;
+	      *) func_append compile_rpath " $absdir" ;;
+	      esac
+	      ;;
+	    esac
+	    case " $sys_lib_dlsearch_path " in
+	    *" $libdir "*) ;;
+	    *)
+	      case "$finalize_rpath " in
+	      *" $libdir "*) ;;
+	      *) func_append finalize_rpath " $libdir" ;;
+	      esac
+	      ;;
+	    esac
+	  fi # $linkmode,$pass = prog,link...
+
+	  if test "$alldeplibs" = yes &&
+	     { test "$deplibs_check_method" = pass_all ||
+	       { test "$build_libtool_libs" = yes &&
+		 test -n "$library_names"; }; }; then
+	    # We only need to search for static libraries
+	    continue
+	  fi
+	fi
+
+	link_static=no # Whether the deplib will be linked statically
+	use_static_libs=$prefer_static_libs
+	if test "$use_static_libs" = built && test "$installed" = yes; then
+	  use_static_libs=no
+	fi
+	if test -n "$library_names" &&
+	   { test "$use_static_libs" = no || test -z "$old_library"; }; then
+	  case $host in
+	  *cygwin* | *mingw* | *cegcc*)
+	      # No point in relinking DLLs because paths are not encoded
+	      func_append notinst_deplibs " $lib"
+	      need_relink=no
+	    ;;
+	  *)
+	    if test "$installed" = no; then
+	      func_append notinst_deplibs " $lib"
+	      need_relink=yes
+	    fi
+	    ;;
+	  esac
+	  # This is a shared library
+
+	  # Warn about portability, can't link against -module's on some
+	  # systems (darwin).  Don't bleat about dlopened modules though!
+	  dlopenmodule=""
+	  for dlpremoduletest in $dlprefiles; do
+	    if test "X$dlpremoduletest" = "X$lib"; then
+	      dlopenmodule="$dlpremoduletest"
+	      break
+	    fi
+	  done
+	  if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then
+	    echo
+	    if test "$linkmode" = prog; then
+	      $ECHO "*** Warning: Linking the executable $output against the loadable module"
+	    else
+	      $ECHO "*** Warning: Linking the shared library $output against the loadable module"
+	    fi
+	    $ECHO "*** $linklib is not portable!"
+	  fi
+	  if test "$linkmode" = lib &&
+	     test "$hardcode_into_libs" = yes; then
+	    # Hardcode the library path.
+	    # Skip directories that are in the system default run-time
+	    # search path.
+	    case " $sys_lib_dlsearch_path " in
+	    *" $absdir "*) ;;
+	    *)
+	      case "$compile_rpath " in
+	      *" $absdir "*) ;;
+	      *) func_append compile_rpath " $absdir" ;;
+	      esac
+	      ;;
+	    esac
+	    case " $sys_lib_dlsearch_path " in
+	    *" $libdir "*) ;;
+	    *)
+	      case "$finalize_rpath " in
+	      *" $libdir "*) ;;
+	      *) func_append finalize_rpath " $libdir" ;;
+	      esac
+	      ;;
+	    esac
+	  fi
+
+	  if test -n "$old_archive_from_expsyms_cmds"; then
+	    # figure out the soname
+	    set dummy $library_names
+	    shift
+	    realname="$1"
+	    shift
+	    libname=`eval "\\$ECHO \"$libname_spec\""`
+	    # use dlname if we got it. it's perfectly good, no?
+	    if test -n "$dlname"; then
+	      soname="$dlname"
+	    elif test -n "$soname_spec"; then
+	      # bleh windows
+	      case $host in
+	      *cygwin* | mingw* | *cegcc*)
+	        func_arith $current - $age
+		major=$func_arith_result
+		versuffix="-$major"
+		;;
+	      esac
+	      eval soname=\"$soname_spec\"
+	    else
+	      soname="$realname"
+	    fi
+
+	    # Make a new name for the extract_expsyms_cmds to use
+	    soroot="$soname"
+	    func_basename "$soroot"
+	    soname="$func_basename_result"
+	    func_stripname 'lib' '.dll' "$soname"
+	    newlib=libimp-$func_stripname_result.a
+
+	    # If the library has no export list, then create one now
+	    if test -f "$output_objdir/$soname-def"; then :
+	    else
+	      func_verbose "extracting exported symbol list from \`$soname'"
+	      func_execute_cmds "$extract_expsyms_cmds" 'exit $?'
+	    fi
+
+	    # Create $newlib
+	    if test -f "$output_objdir/$newlib"; then :; else
+	      func_verbose "generating import library for \`$soname'"
+	      func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?'
+	    fi
+	    # make sure the library variables are pointing to the new library
+	    dir=$output_objdir
+	    linklib=$newlib
+	  fi # test -n "$old_archive_from_expsyms_cmds"
+
+	  if test "$linkmode" = prog || test "$opt_mode" != relink; then
+	    add_shlibpath=
+	    add_dir=
+	    add=
+	    lib_linked=yes
+	    case $hardcode_action in
+	    immediate | unsupported)
+	      if test "$hardcode_direct" = no; then
+		add="$dir/$linklib"
+		case $host in
+		  *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;;
+		  *-*-sysv4*uw2*) add_dir="-L$dir" ;;
+		  *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
+		    *-*-unixware7*) add_dir="-L$dir" ;;
+		  *-*-darwin* )
+		    # if the lib is a (non-dlopened) module then we can not
+		    # link against it, someone is ignoring the earlier warnings
+		    if /usr/bin/file -L $add 2> /dev/null |
+			 $GREP ": [^:]* bundle" >/dev/null ; then
+		      if test "X$dlopenmodule" != "X$lib"; then
+			$ECHO "*** Warning: lib $linklib is a module, not a shared library"
+			if test -z "$old_library" ; then
+			  echo
+			  echo "*** And there doesn't seem to be a static archive available"
+			  echo "*** The link will probably fail, sorry"
+			else
+			  add="$dir/$old_library"
+			fi
+		      elif test -n "$old_library"; then
+			add="$dir/$old_library"
+		      fi
+		    fi
+		esac
+	      elif test "$hardcode_minus_L" = no; then
+		case $host in
+		*-*-sunos*) add_shlibpath="$dir" ;;
+		esac
+		add_dir="-L$dir"
+		add="-l$name"
+	      elif test "$hardcode_shlibpath_var" = no; then
+		add_shlibpath="$dir"
+		add="-l$name"
+	      else
+		lib_linked=no
+	      fi
+	      ;;
+	    relink)
+	      if test "$hardcode_direct" = yes &&
+	         test "$hardcode_direct_absolute" = no; then
+		add="$dir/$linklib"
+	      elif test "$hardcode_minus_L" = yes; then
+		add_dir="-L$absdir"
+		# Try looking first in the location we're being installed to.
+		if test -n "$inst_prefix_dir"; then
+		  case $libdir in
+		    [\\/]*)
+		      func_append add_dir " -L$inst_prefix_dir$libdir"
+		      ;;
+		  esac
+		fi
+		add="-l$name"
+	      elif test "$hardcode_shlibpath_var" = yes; then
+		add_shlibpath="$dir"
+		add="-l$name"
+	      else
+		lib_linked=no
+	      fi
+	      ;;
+	    *) lib_linked=no ;;
+	    esac
+
+	    if test "$lib_linked" != yes; then
+	      func_fatal_configuration "unsupported hardcode properties"
+	    fi
+
+	    if test -n "$add_shlibpath"; then
+	      case :$compile_shlibpath: in
+	      *":$add_shlibpath:"*) ;;
+	      *) func_append compile_shlibpath "$add_shlibpath:" ;;
+	      esac
+	    fi
+	    if test "$linkmode" = prog; then
+	      test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+	      test -n "$add" && compile_deplibs="$add $compile_deplibs"
+	    else
+	      test -n "$add_dir" && deplibs="$add_dir $deplibs"
+	      test -n "$add" && deplibs="$add $deplibs"
+	      if test "$hardcode_direct" != yes &&
+		 test "$hardcode_minus_L" != yes &&
+		 test "$hardcode_shlibpath_var" = yes; then
+		case :$finalize_shlibpath: in
+		*":$libdir:"*) ;;
+		*) func_append finalize_shlibpath "$libdir:" ;;
+		esac
+	      fi
+	    fi
+	  fi
+
+	  if test "$linkmode" = prog || test "$opt_mode" = relink; then
+	    add_shlibpath=
+	    add_dir=
+	    add=
+	    # Finalize command for both is simple: just hardcode it.
+	    if test "$hardcode_direct" = yes &&
+	       test "$hardcode_direct_absolute" = no; then
+	      add="$libdir/$linklib"
+	    elif test "$hardcode_minus_L" = yes; then
+	      add_dir="-L$libdir"
+	      add="-l$name"
+	    elif test "$hardcode_shlibpath_var" = yes; then
+	      case :$finalize_shlibpath: in
+	      *":$libdir:"*) ;;
+	      *) func_append finalize_shlibpath "$libdir:" ;;
+	      esac
+	      add="-l$name"
+	    elif test "$hardcode_automatic" = yes; then
+	      if test -n "$inst_prefix_dir" &&
+		 test -f "$inst_prefix_dir$libdir/$linklib" ; then
+		add="$inst_prefix_dir$libdir/$linklib"
+	      else
+		add="$libdir/$linklib"
+	      fi
+	    else
+	      # We cannot seem to hardcode it, guess we'll fake it.
+	      add_dir="-L$libdir"
+	      # Try looking first in the location we're being installed to.
+	      if test -n "$inst_prefix_dir"; then
+		case $libdir in
+		  [\\/]*)
+		    func_append add_dir " -L$inst_prefix_dir$libdir"
+		    ;;
+		esac
+	      fi
+	      add="-l$name"
+	    fi
+
+	    if test "$linkmode" = prog; then
+	      test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+	      test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+	    else
+	      test -n "$add_dir" && deplibs="$add_dir $deplibs"
+	      test -n "$add" && deplibs="$add $deplibs"
+	    fi
+	  fi
+	elif test "$linkmode" = prog; then
+	  # Here we assume that one of hardcode_direct or hardcode_minus_L
+	  # is not unsupported.  This is valid on all known static and
+	  # shared platforms.
+	  if test "$hardcode_direct" != unsupported; then
+	    test -n "$old_library" && linklib="$old_library"
+	    compile_deplibs="$dir/$linklib $compile_deplibs"
+	    finalize_deplibs="$dir/$linklib $finalize_deplibs"
+	  else
+	    compile_deplibs="-l$name -L$dir $compile_deplibs"
+	    finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+	  fi
+	elif test "$build_libtool_libs" = yes; then
+	  # Not a shared library
+	  if test "$deplibs_check_method" != pass_all; then
+	    # We're trying link a shared library against a static one
+	    # but the system doesn't support it.
+
+	    # Just print a warning and add the library to dependency_libs so
+	    # that the program can be linked against the static library.
+	    echo
+	    $ECHO "*** Warning: This system can not link to static lib archive $lib."
+	    echo "*** I have the capability to make that library automatically link in when"
+	    echo "*** you link to this library.  But I can only do this if you have a"
+	    echo "*** shared version of the library, which you do not appear to have."
+	    if test "$module" = yes; then
+	      echo "*** But as you try to build a module library, libtool will still create "
+	      echo "*** a static module, that should work as long as the dlopening application"
+	      echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
+	      if test -z "$global_symbol_pipe"; then
+		echo
+		echo "*** However, this would only work if libtool was able to extract symbol"
+		echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+		echo "*** not find such a program.  So, this module is probably useless."
+		echo "*** \`nm' from GNU binutils and a full rebuild may help."
+	      fi
+	      if test "$build_old_libs" = no; then
+		build_libtool_libs=module
+		build_old_libs=yes
+	      else
+		build_libtool_libs=no
+	      fi
+	    fi
+	  else
+	    deplibs="$dir/$old_library $deplibs"
+	    link_static=yes
+	  fi
+	fi # link shared/static library?
+
+	if test "$linkmode" = lib; then
+	  if test -n "$dependency_libs" &&
+	     { test "$hardcode_into_libs" != yes ||
+	       test "$build_old_libs" = yes ||
+	       test "$link_static" = yes; }; then
+	    # Extract -R from dependency_libs
+	    temp_deplibs=
+	    for libdir in $dependency_libs; do
+	      case $libdir in
+	      -R*) func_stripname '-R' '' "$libdir"
+	           temp_xrpath=$func_stripname_result
+		   case " $xrpath " in
+		   *" $temp_xrpath "*) ;;
+		   *) func_append xrpath " $temp_xrpath";;
+		   esac;;
+	      *) func_append temp_deplibs " $libdir";;
+	      esac
+	    done
+	    dependency_libs="$temp_deplibs"
+	  fi
+
+	  func_append newlib_search_path " $absdir"
+	  # Link against this library
+	  test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+	  # ... and its dependency_libs
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    newdependency_libs="$deplib $newdependency_libs"
+	    case $deplib in
+              -L*) func_stripname '-L' '' "$deplib"
+                   func_resolve_sysroot "$func_stripname_result";;
+              *) func_resolve_sysroot "$deplib" ;;
+            esac
+	    if $opt_preserve_dup_deps ; then
+	      case "$tmp_libs " in
+	      *" $func_resolve_sysroot_result "*)
+                func_append specialdeplibs " $func_resolve_sysroot_result" ;;
+	      esac
+	    fi
+	    func_append tmp_libs " $func_resolve_sysroot_result"
+	  done
+
+	  if test "$link_all_deplibs" != no; then
+	    # Add the search paths of all dependency libraries
+	    for deplib in $dependency_libs; do
+	      path=
+	      case $deplib in
+	      -L*) path="$deplib" ;;
+	      *.la)
+	        func_resolve_sysroot "$deplib"
+	        deplib=$func_resolve_sysroot_result
+	        func_dirname "$deplib" "" "."
+		dir=$func_dirname_result
+		# We need an absolute path.
+		case $dir in
+		[\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+		*)
+		  absdir=`cd "$dir" && pwd`
+		  if test -z "$absdir"; then
+		    func_warning "cannot determine absolute directory name of \`$dir'"
+		    absdir="$dir"
+		  fi
+		  ;;
+		esac
+		if $GREP "^installed=no" $deplib > /dev/null; then
+		case $host in
+		*-*-darwin*)
+		  depdepl=
+		  eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
+		  if test -n "$deplibrary_names" ; then
+		    for tmp in $deplibrary_names ; do
+		      depdepl=$tmp
+		    done
+		    if test -f "$absdir/$objdir/$depdepl" ; then
+		      depdepl="$absdir/$objdir/$depdepl"
+		      darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
+                      if test -z "$darwin_install_name"; then
+                          darwin_install_name=`${OTOOL64} -L $depdepl  | awk '{if (NR == 2) {print $1;exit}}'`
+                      fi
+		      func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}"
+		      func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}"
+		      path=
+		    fi
+		  fi
+		  ;;
+		*)
+		  path="-L$absdir/$objdir"
+		  ;;
+		esac
+		else
+		  eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+		  test -z "$libdir" && \
+		    func_fatal_error "\`$deplib' is not a valid libtool archive"
+		  test "$absdir" != "$libdir" && \
+		    func_warning "\`$deplib' seems to be moved"
+
+		  path="-L$absdir"
+		fi
+		;;
+	      esac
+	      case " $deplibs " in
+	      *" $path "*) ;;
+	      *) deplibs="$path $deplibs" ;;
+	      esac
+	    done
+	  fi # link_all_deplibs != no
+	fi # linkmode = lib
+      done # for deplib in $libs
+      if test "$pass" = link; then
+	if test "$linkmode" = "prog"; then
+	  compile_deplibs="$new_inherited_linker_flags $compile_deplibs"
+	  finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs"
+	else
+	  compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	fi
+      fi
+      dependency_libs="$newdependency_libs"
+      if test "$pass" = dlpreopen; then
+	# Link the dlpreopened libraries before other libraries
+	for deplib in $save_deplibs; do
+	  deplibs="$deplib $deplibs"
+	done
+      fi
+      if test "$pass" != dlopen; then
+	if test "$pass" != conv; then
+	  # Make sure lib_search_path contains only unique directories.
+	  lib_search_path=
+	  for dir in $newlib_search_path; do
+	    case "$lib_search_path " in
+	    *" $dir "*) ;;
+	    *) func_append lib_search_path " $dir" ;;
+	    esac
+	  done
+	  newlib_search_path=
+	fi
+
+	if test "$linkmode,$pass" != "prog,link"; then
+	  vars="deplibs"
+	else
+	  vars="compile_deplibs finalize_deplibs"
+	fi
+	for var in $vars dependency_libs; do
+	  # Add libraries to $var in reverse order
+	  eval tmp_libs=\"\$$var\"
+	  new_libs=
+	  for deplib in $tmp_libs; do
+	    # FIXME: Pedantically, this is the right thing to do, so
+	    #        that some nasty dependency loop isn't accidentally
+	    #        broken:
+	    #new_libs="$deplib $new_libs"
+	    # Pragmatically, this seems to cause very few problems in
+	    # practice:
+	    case $deplib in
+	    -L*) new_libs="$deplib $new_libs" ;;
+	    -R*) ;;
+	    *)
+	      # And here is the reason: when a library appears more
+	      # than once as an explicit dependence of a library, or
+	      # is implicitly linked in more than once by the
+	      # compiler, it is considered special, and multiple
+	      # occurrences thereof are not removed.  Compare this
+	      # with having the same library being listed as a
+	      # dependency of multiple other libraries: in this case,
+	      # we know (pedantically, we assume) the library does not
+	      # need to be listed more than once, so we keep only the
+	      # last copy.  This is not always right, but it is rare
+	      # enough that we require users that really mean to play
+	      # such unportable linking tricks to link the library
+	      # using -Wl,-lname, so that libtool does not consider it
+	      # for duplicate removal.
+	      case " $specialdeplibs " in
+	      *" $deplib "*) new_libs="$deplib $new_libs" ;;
+	      *)
+		case " $new_libs " in
+		*" $deplib "*) ;;
+		*) new_libs="$deplib $new_libs" ;;
+		esac
+		;;
+	      esac
+	      ;;
+	    esac
+	  done
+	  tmp_libs=
+	  for deplib in $new_libs; do
+	    case $deplib in
+	    -L*)
+	      case " $tmp_libs " in
+	      *" $deplib "*) ;;
+	      *) func_append tmp_libs " $deplib" ;;
+	      esac
+	      ;;
+	    *) func_append tmp_libs " $deplib" ;;
+	    esac
+	  done
+	  eval $var=\"$tmp_libs\"
+	done # for var
+      fi
+      # Last step: remove runtime libs from dependency_libs
+      # (they stay in deplibs)
+      tmp_libs=
+      for i in $dependency_libs ; do
+	case " $predeps $postdeps $compiler_lib_search_path " in
+	*" $i "*)
+	  i=""
+	  ;;
+	esac
+	if test -n "$i" ; then
+	  func_append tmp_libs " $i"
+	fi
+      done
+      dependency_libs=$tmp_libs
+    done # for pass
+    if test "$linkmode" = prog; then
+      dlfiles="$newdlfiles"
+    fi
+    if test "$linkmode" = prog || test "$linkmode" = lib; then
+      dlprefiles="$newdlprefiles"
+    fi
+
+    case $linkmode in
+    oldlib)
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+	func_warning "\`-dlopen' is ignored for archives"
+      fi
+
+      case " $deplibs" in
+      *\ -l* | *\ -L*)
+	func_warning "\`-l' and \`-L' are ignored for archives" ;;
+      esac
+
+      test -n "$rpath" && \
+	func_warning "\`-rpath' is ignored for archives"
+
+      test -n "$xrpath" && \
+	func_warning "\`-R' is ignored for archives"
+
+      test -n "$vinfo" && \
+	func_warning "\`-version-info/-version-number' is ignored for archives"
+
+      test -n "$release" && \
+	func_warning "\`-release' is ignored for archives"
+
+      test -n "$export_symbols$export_symbols_regex" && \
+	func_warning "\`-export-symbols' is ignored for archives"
+
+      # Now set the variables for building old libraries.
+      build_libtool_libs=no
+      oldlibs="$output"
+      func_append objs "$old_deplibs"
+      ;;
+
+    lib)
+      # Make sure we only generate libraries of the form `libNAME.la'.
+      case $outputname in
+      lib*)
+	func_stripname 'lib' '.la' "$outputname"
+	name=$func_stripname_result
+	eval shared_ext=\"$shrext_cmds\"
+	eval libname=\"$libname_spec\"
+	;;
+      *)
+	test "$module" = no && \
+	  func_fatal_help "libtool library \`$output' must begin with \`lib'"
+
+	if test "$need_lib_prefix" != no; then
+	  # Add the "lib" prefix for modules if required
+	  func_stripname '' '.la' "$outputname"
+	  name=$func_stripname_result
+	  eval shared_ext=\"$shrext_cmds\"
+	  eval libname=\"$libname_spec\"
+	else
+	  func_stripname '' '.la' "$outputname"
+	  libname=$func_stripname_result
+	fi
+	;;
+      esac
+
+      if test -n "$objs"; then
+	if test "$deplibs_check_method" != pass_all; then
+	  func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs"
+	else
+	  echo
+	  $ECHO "*** Warning: Linking the shared library $output against the non-libtool"
+	  $ECHO "*** objects $objs is not portable!"
+	  func_append libobjs " $objs"
+	fi
+      fi
+
+      test "$dlself" != no && \
+	func_warning "\`-dlopen self' is ignored for libtool libraries"
+
+      set dummy $rpath
+      shift
+      test "$#" -gt 1 && \
+	func_warning "ignoring multiple \`-rpath's for a libtool library"
+
+      install_libdir="$1"
+
+      oldlibs=
+      if test -z "$rpath"; then
+	if test "$build_libtool_libs" = yes; then
+	  # Building a libtool convenience library.
+	  # Some compilers have problems with a `.al' extension so
+	  # convenience libraries should have the same extension an
+	  # archive normally would.
+	  oldlibs="$output_objdir/$libname.$libext $oldlibs"
+	  build_libtool_libs=convenience
+	  build_old_libs=yes
+	fi
+
+	test -n "$vinfo" && \
+	  func_warning "\`-version-info/-version-number' is ignored for convenience libraries"
+
+	test -n "$release" && \
+	  func_warning "\`-release' is ignored for convenience libraries"
+      else
+
+	# Parse the version information argument.
+	save_ifs="$IFS"; IFS=':'
+	set dummy $vinfo 0 0 0
+	shift
+	IFS="$save_ifs"
+
+	test -n "$7" && \
+	  func_fatal_help "too many parameters to \`-version-info'"
+
+	# convert absolute version numbers to libtool ages
+	# this retains compatibility with .la files and attempts
+	# to make the code below a bit more comprehensible
+
+	case $vinfo_number in
+	yes)
+	  number_major="$1"
+	  number_minor="$2"
+	  number_revision="$3"
+	  #
+	  # There are really only two kinds -- those that
+	  # use the current revision as the major version
+	  # and those that subtract age and use age as
+	  # a minor version.  But, then there is irix
+	  # which has an extra 1 added just for fun
+	  #
+	  case $version_type in
+	  # correct linux to gnu/linux during the next big refactor
+	  darwin|linux|osf|windows|none)
+	    func_arith $number_major + $number_minor
+	    current=$func_arith_result
+	    age="$number_minor"
+	    revision="$number_revision"
+	    ;;
+	  freebsd-aout|freebsd-elf|qnx|sunos)
+	    current="$number_major"
+	    revision="$number_minor"
+	    age="0"
+	    ;;
+	  irix|nonstopux)
+	    func_arith $number_major + $number_minor
+	    current=$func_arith_result
+	    age="$number_minor"
+	    revision="$number_minor"
+	    lt_irix_increment=no
+	    ;;
+	  esac
+	  ;;
+	no)
+	  current="$1"
+	  revision="$2"
+	  age="$3"
+	  ;;
+	esac
+
+	# Check that each of the things are valid numbers.
+	case $current in
+	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+	*)
+	  func_error "CURRENT \`$current' must be a nonnegative integer"
+	  func_fatal_error "\`$vinfo' is not valid version information"
+	  ;;
+	esac
+
+	case $revision in
+	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+	*)
+	  func_error "REVISION \`$revision' must be a nonnegative integer"
+	  func_fatal_error "\`$vinfo' is not valid version information"
+	  ;;
+	esac
+
+	case $age in
+	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+	*)
+	  func_error "AGE \`$age' must be a nonnegative integer"
+	  func_fatal_error "\`$vinfo' is not valid version information"
+	  ;;
+	esac
+
+	if test "$age" -gt "$current"; then
+	  func_error "AGE \`$age' is greater than the current interface number \`$current'"
+	  func_fatal_error "\`$vinfo' is not valid version information"
+	fi
+
+	# Calculate the version variables.
+	major=
+	versuffix=
+	verstring=
+	case $version_type in
+	none) ;;
+
+	darwin)
+	  # Like Linux, but with the current version available in
+	  # verstring for coding it into the library header
+	  func_arith $current - $age
+	  major=.$func_arith_result
+	  versuffix="$major.$age.$revision"
+	  # Darwin ld doesn't like 0 for these options...
+	  func_arith $current + 1
+	  minor_current=$func_arith_result
+	  xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
+	  verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+	  ;;
+
+	freebsd-aout)
+	  major=".$current"
+	  versuffix=".$current.$revision";
+	  ;;
+
+	freebsd-elf)
+	  major=".$current"
+	  versuffix=".$current"
+	  ;;
+
+	irix | nonstopux)
+	  if test "X$lt_irix_increment" = "Xno"; then
+	    func_arith $current - $age
+	  else
+	    func_arith $current - $age + 1
+	  fi
+	  major=$func_arith_result
+
+	  case $version_type in
+	    nonstopux) verstring_prefix=nonstopux ;;
+	    *)         verstring_prefix=sgi ;;
+	  esac
+	  verstring="$verstring_prefix$major.$revision"
+
+	  # Add in all the interfaces that we are compatible with.
+	  loop=$revision
+	  while test "$loop" -ne 0; do
+	    func_arith $revision - $loop
+	    iface=$func_arith_result
+	    func_arith $loop - 1
+	    loop=$func_arith_result
+	    verstring="$verstring_prefix$major.$iface:$verstring"
+	  done
+
+	  # Before this point, $major must not contain `.'.
+	  major=.$major
+	  versuffix="$major.$revision"
+	  ;;
+
+	linux) # correct to gnu/linux during the next big refactor
+	  func_arith $current - $age
+	  major=.$func_arith_result
+	  versuffix="$major.$age.$revision"
+	  ;;
+
+	osf)
+	  func_arith $current - $age
+	  major=.$func_arith_result
+	  versuffix=".$current.$age.$revision"
+	  verstring="$current.$age.$revision"
+
+	  # Add in all the interfaces that we are compatible with.
+	  loop=$age
+	  while test "$loop" -ne 0; do
+	    func_arith $current - $loop
+	    iface=$func_arith_result
+	    func_arith $loop - 1
+	    loop=$func_arith_result
+	    verstring="$verstring:${iface}.0"
+	  done
+
+	  # Make executables depend on our current version.
+	  func_append verstring ":${current}.0"
+	  ;;
+
+	qnx)
+	  major=".$current"
+	  versuffix=".$current"
+	  ;;
+
+	sunos)
+	  major=".$current"
+	  versuffix=".$current.$revision"
+	  ;;
+
+	windows)
+	  # Use '-' rather than '.', since we only want one
+	  # extension on DOS 8.3 filesystems.
+	  func_arith $current - $age
+	  major=$func_arith_result
+	  versuffix="-$major"
+	  ;;
+
+	*)
+	  func_fatal_configuration "unknown library version type \`$version_type'"
+	  ;;
+	esac
+
+	# Clear the version info if we defaulted, and they specified a release.
+	if test -z "$vinfo" && test -n "$release"; then
+	  major=
+	  case $version_type in
+	  darwin)
+	    # we can't check for "0.0" in archive_cmds due to quoting
+	    # problems, so we reset it completely
+	    verstring=
+	    ;;
+	  *)
+	    verstring="0.0"
+	    ;;
+	  esac
+	  if test "$need_version" = no; then
+	    versuffix=
+	  else
+	    versuffix=".0.0"
+	  fi
+	fi
+
+	# Remove version info from name if versioning should be avoided
+	if test "$avoid_version" = yes && test "$need_version" = no; then
+	  major=
+	  versuffix=
+	  verstring=""
+	fi
+
+	# Check to see if the archive will have undefined symbols.
+	if test "$allow_undefined" = yes; then
+	  if test "$allow_undefined_flag" = unsupported; then
+	    func_warning "undefined symbols not allowed in $host shared libraries"
+	    build_libtool_libs=no
+	    build_old_libs=yes
+	  fi
+	else
+	  # Don't allow undefined symbols.
+	  allow_undefined_flag="$no_undefined_flag"
+	fi
+
+      fi
+
+      func_generate_dlsyms "$libname" "$libname" "yes"
+      func_append libobjs " $symfileobj"
+      test "X$libobjs" = "X " && libobjs=
+
+      if test "$opt_mode" != relink; then
+	# Remove our outputs, but don't remove object files since they
+	# may have been created when compiling PIC objects.
+	removelist=
+	tempremovelist=`$ECHO "$output_objdir/*"`
+	for p in $tempremovelist; do
+	  case $p in
+	    *.$objext | *.gcno)
+	       ;;
+	    $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
+	       if test "X$precious_files_regex" != "X"; then
+		 if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
+		 then
+		   continue
+		 fi
+	       fi
+	       func_append removelist " $p"
+	       ;;
+	    *) ;;
+	  esac
+	done
+	test -n "$removelist" && \
+	  func_show_eval "${RM}r \$removelist"
+      fi
+
+      # Now set the variables for building old libraries.
+      if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+	func_append oldlibs " $output_objdir/$libname.$libext"
+
+	# Transform .lo files to .o files.
+	oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP`
+      fi
+
+      # Eliminate all temporary directories.
+      #for path in $notinst_path; do
+      #	lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"`
+      #	deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"`
+      #	dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"`
+      #done
+
+      if test -n "$xrpath"; then
+	# If the user specified any rpath flags, then add them.
+	temp_xrpath=
+	for libdir in $xrpath; do
+	  func_replace_sysroot "$libdir"
+	  func_append temp_xrpath " -R$func_replace_sysroot_result"
+	  case "$finalize_rpath " in
+	  *" $libdir "*) ;;
+	  *) func_append finalize_rpath " $libdir" ;;
+	  esac
+	done
+	if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
+	  dependency_libs="$temp_xrpath $dependency_libs"
+	fi
+      fi
+
+      # Make sure dlfiles contains only unique files that won't be dlpreopened
+      old_dlfiles="$dlfiles"
+      dlfiles=
+      for lib in $old_dlfiles; do
+	case " $dlprefiles $dlfiles " in
+	*" $lib "*) ;;
+	*) func_append dlfiles " $lib" ;;
+	esac
+      done
+
+      # Make sure dlprefiles contains only unique files
+      old_dlprefiles="$dlprefiles"
+      dlprefiles=
+      for lib in $old_dlprefiles; do
+	case "$dlprefiles " in
+	*" $lib "*) ;;
+	*) func_append dlprefiles " $lib" ;;
+	esac
+      done
+
+      if test "$build_libtool_libs" = yes; then
+	if test -n "$rpath"; then
+	  case $host in
+	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*)
+	    # these systems don't actually have a c library (as such)!
+	    ;;
+	  *-*-rhapsody* | *-*-darwin1.[012])
+	    # Rhapsody C library is in the System framework
+	    func_append deplibs " System.ltframework"
+	    ;;
+	  *-*-netbsd*)
+	    # Don't link with libc until the a.out ld.so is fixed.
+	    ;;
+	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+	    # Do not include libc due to us having libc/libc_r.
+	    ;;
+	  *-*-sco3.2v5* | *-*-sco5v6*)
+	    # Causes problems with __ctype
+	    ;;
+	  *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+	    # Compiler inserts libc in the correct place for threads to work
+	    ;;
+	  *)
+	    # Add libc to deplibs on all other systems if necessary.
+	    if test "$build_libtool_need_lc" = "yes"; then
+	      func_append deplibs " -lc"
+	    fi
+	    ;;
+	  esac
+	fi
+
+	# Transform deplibs into only deplibs that can be linked in shared.
+	name_save=$name
+	libname_save=$libname
+	release_save=$release
+	versuffix_save=$versuffix
+	major_save=$major
+	# I'm not sure if I'm treating the release correctly.  I think
+	# release should show up in the -l (ie -lgmp5) so we don't want to
+	# add it in twice.  Is that correct?
+	release=""
+	versuffix=""
+	major=""
+	newdeplibs=
+	droppeddeps=no
+	case $deplibs_check_method in
+	pass_all)
+	  # Don't check for shared/static.  Everything works.
+	  # This might be a little naive.  We might want to check
+	  # whether the library exists or not.  But this is on
+	  # osf3 & osf4 and I'm not really sure... Just
+	  # implementing what was already the behavior.
+	  newdeplibs=$deplibs
+	  ;;
+	test_compile)
+	  # This code stresses the "libraries are programs" paradigm to its
+	  # limits. Maybe even breaks it.  We compile a program, linking it
+	  # against the deplibs as a proxy for the library.  Then we can check
+	  # whether they linked in statically or dynamically with ldd.
+	  $opt_dry_run || $RM conftest.c
+	  cat > conftest.c <<EOF
+	  int main() { return 0; }
+EOF
+	  $opt_dry_run || $RM conftest
+	  if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
+	    ldd_output=`ldd conftest`
+	    for i in $deplibs; do
+	      case $i in
+	      -l*)
+		func_stripname -l '' "$i"
+		name=$func_stripname_result
+		if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		  case " $predeps $postdeps " in
+		  *" $i "*)
+		    func_append newdeplibs " $i"
+		    i=""
+		    ;;
+		  esac
+		fi
+		if test -n "$i" ; then
+		  libname=`eval "\\$ECHO \"$libname_spec\""`
+		  deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+		  set dummy $deplib_matches; shift
+		  deplib_match=$1
+		  if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+		    func_append newdeplibs " $i"
+		  else
+		    droppeddeps=yes
+		    echo
+		    $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+		    echo "*** I have the capability to make that library automatically link in when"
+		    echo "*** you link to this library.  But I can only do this if you have a"
+		    echo "*** shared version of the library, which I believe you do not have"
+		    echo "*** because a test_compile did reveal that the linker did not use it for"
+		    echo "*** its dynamic dependency list that programs get resolved with at runtime."
+		  fi
+		fi
+		;;
+	      *)
+		func_append newdeplibs " $i"
+		;;
+	      esac
+	    done
+	  else
+	    # Error occurred in the first compile.  Let's try to salvage
+	    # the situation: Compile a separate program for each library.
+	    for i in $deplibs; do
+	      case $i in
+	      -l*)
+		func_stripname -l '' "$i"
+		name=$func_stripname_result
+		$opt_dry_run || $RM conftest
+		if $LTCC $LTCFLAGS -o conftest conftest.c $i; then
+		  ldd_output=`ldd conftest`
+		  if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		    case " $predeps $postdeps " in
+		    *" $i "*)
+		      func_append newdeplibs " $i"
+		      i=""
+		      ;;
+		    esac
+		  fi
+		  if test -n "$i" ; then
+		    libname=`eval "\\$ECHO \"$libname_spec\""`
+		    deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+		    set dummy $deplib_matches; shift
+		    deplib_match=$1
+		    if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+		      func_append newdeplibs " $i"
+		    else
+		      droppeddeps=yes
+		      echo
+		      $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+		      echo "*** I have the capability to make that library automatically link in when"
+		      echo "*** you link to this library.  But I can only do this if you have a"
+		      echo "*** shared version of the library, which you do not appear to have"
+		      echo "*** because a test_compile did reveal that the linker did not use this one"
+		      echo "*** as a dynamic dependency that programs can get resolved with at runtime."
+		    fi
+		  fi
+		else
+		  droppeddeps=yes
+		  echo
+		  $ECHO "*** Warning!  Library $i is needed by this library but I was not able to"
+		  echo "*** make it link in!  You will probably need to install it or some"
+		  echo "*** library that it depends on before this library will be fully"
+		  echo "*** functional.  Installing it before continuing would be even better."
+		fi
+		;;
+	      *)
+		func_append newdeplibs " $i"
+		;;
+	      esac
+	    done
+	  fi
+	  ;;
+	file_magic*)
+	  set dummy $deplibs_check_method; shift
+	  file_magic_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+	  for a_deplib in $deplibs; do
+	    case $a_deplib in
+	    -l*)
+	      func_stripname -l '' "$a_deplib"
+	      name=$func_stripname_result
+	      if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		case " $predeps $postdeps " in
+		*" $a_deplib "*)
+		  func_append newdeplibs " $a_deplib"
+		  a_deplib=""
+		  ;;
+		esac
+	      fi
+	      if test -n "$a_deplib" ; then
+		libname=`eval "\\$ECHO \"$libname_spec\""`
+		if test -n "$file_magic_glob"; then
+		  libnameglob=`func_echo_all "$libname" | $SED -e $file_magic_glob`
+		else
+		  libnameglob=$libname
+		fi
+		test "$want_nocaseglob" = yes && nocaseglob=`shopt -p nocaseglob`
+		for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+		  if test "$want_nocaseglob" = yes; then
+		    shopt -s nocaseglob
+		    potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null`
+		    $nocaseglob
+		  else
+		    potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null`
+		  fi
+		  for potent_lib in $potential_libs; do
+		      # Follow soft links.
+		      if ls -lLd "$potent_lib" 2>/dev/null |
+			 $GREP " -> " >/dev/null; then
+			continue
+		      fi
+		      # The statement above tries to avoid entering an
+		      # endless loop below, in case of cyclic links.
+		      # We might still enter an endless loop, since a link
+		      # loop can be closed while we follow links,
+		      # but so what?
+		      potlib="$potent_lib"
+		      while test -h "$potlib" 2>/dev/null; do
+			potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
+			case $potliblink in
+			[\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+			*) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";;
+			esac
+		      done
+		      if eval $file_magic_cmd \"\$potlib\" 2>/dev/null |
+			 $SED -e 10q |
+			 $EGREP "$file_magic_regex" > /dev/null; then
+			func_append newdeplibs " $a_deplib"
+			a_deplib=""
+			break 2
+		      fi
+		  done
+		done
+	      fi
+	      if test -n "$a_deplib" ; then
+		droppeddeps=yes
+		echo
+		$ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+		echo "*** I have the capability to make that library automatically link in when"
+		echo "*** you link to this library.  But I can only do this if you have a"
+		echo "*** shared version of the library, which you do not appear to have"
+		echo "*** because I did check the linker path looking for a file starting"
+		if test -z "$potlib" ; then
+		  $ECHO "*** with $libname but no candidates were found. (...for file magic test)"
+		else
+		  $ECHO "*** with $libname and none of the candidates passed a file format test"
+		  $ECHO "*** using a file magic. Last file checked: $potlib"
+		fi
+	      fi
+	      ;;
+	    *)
+	      # Add a -L argument.
+	      func_append newdeplibs " $a_deplib"
+	      ;;
+	    esac
+	  done # Gone through all deplibs.
+	  ;;
+	match_pattern*)
+	  set dummy $deplibs_check_method; shift
+	  match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+	  for a_deplib in $deplibs; do
+	    case $a_deplib in
+	    -l*)
+	      func_stripname -l '' "$a_deplib"
+	      name=$func_stripname_result
+	      if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		case " $predeps $postdeps " in
+		*" $a_deplib "*)
+		  func_append newdeplibs " $a_deplib"
+		  a_deplib=""
+		  ;;
+		esac
+	      fi
+	      if test -n "$a_deplib" ; then
+		libname=`eval "\\$ECHO \"$libname_spec\""`
+		for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+		  potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+		  for potent_lib in $potential_libs; do
+		    potlib="$potent_lib" # see symlink-check above in file_magic test
+		    if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \
+		       $EGREP "$match_pattern_regex" > /dev/null; then
+		      func_append newdeplibs " $a_deplib"
+		      a_deplib=""
+		      break 2
+		    fi
+		  done
+		done
+	      fi
+	      if test -n "$a_deplib" ; then
+		droppeddeps=yes
+		echo
+		$ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+		echo "*** I have the capability to make that library automatically link in when"
+		echo "*** you link to this library.  But I can only do this if you have a"
+		echo "*** shared version of the library, which you do not appear to have"
+		echo "*** because I did check the linker path looking for a file starting"
+		if test -z "$potlib" ; then
+		  $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)"
+		else
+		  $ECHO "*** with $libname and none of the candidates passed a file format test"
+		  $ECHO "*** using a regex pattern. Last file checked: $potlib"
+		fi
+	      fi
+	      ;;
+	    *)
+	      # Add a -L argument.
+	      func_append newdeplibs " $a_deplib"
+	      ;;
+	    esac
+	  done # Gone through all deplibs.
+	  ;;
+	none | unknown | *)
+	  newdeplibs=""
+	  tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'`
+	  if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+	    for i in $predeps $postdeps ; do
+	      # can't use Xsed below, because $i might contain '/'
+	      tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"`
+	    done
+	  fi
+	  case $tmp_deplibs in
+	  *[!\	\ ]*)
+	    echo
+	    if test "X$deplibs_check_method" = "Xnone"; then
+	      echo "*** Warning: inter-library dependencies are not supported in this platform."
+	    else
+	      echo "*** Warning: inter-library dependencies are not known to be supported."
+	    fi
+	    echo "*** All declared inter-library dependencies are being dropped."
+	    droppeddeps=yes
+	    ;;
+	  esac
+	  ;;
+	esac
+	versuffix=$versuffix_save
+	major=$major_save
+	release=$release_save
+	libname=$libname_save
+	name=$name_save
+
+	case $host in
+	*-*-rhapsody* | *-*-darwin1.[012])
+	  # On Rhapsody replace the C library with the System framework
+	  newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'`
+	  ;;
+	esac
+
+	if test "$droppeddeps" = yes; then
+	  if test "$module" = yes; then
+	    echo
+	    echo "*** Warning: libtool could not satisfy all declared inter-library"
+	    $ECHO "*** dependencies of module $libname.  Therefore, libtool will create"
+	    echo "*** a static module, that should work as long as the dlopening"
+	    echo "*** application is linked with the -dlopen flag."
+	    if test -z "$global_symbol_pipe"; then
+	      echo
+	      echo "*** However, this would only work if libtool was able to extract symbol"
+	      echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+	      echo "*** not find such a program.  So, this module is probably useless."
+	      echo "*** \`nm' from GNU binutils and a full rebuild may help."
+	    fi
+	    if test "$build_old_libs" = no; then
+	      oldlibs="$output_objdir/$libname.$libext"
+	      build_libtool_libs=module
+	      build_old_libs=yes
+	    else
+	      build_libtool_libs=no
+	    fi
+	  else
+	    echo "*** The inter-library dependencies that have been dropped here will be"
+	    echo "*** automatically added whenever a program is linked with this library"
+	    echo "*** or is declared to -dlopen it."
+
+	    if test "$allow_undefined" = no; then
+	      echo
+	      echo "*** Since this library must not contain undefined symbols,"
+	      echo "*** because either the platform does not support them or"
+	      echo "*** it was explicitly requested with -no-undefined,"
+	      echo "*** libtool will only create a static version of it."
+	      if test "$build_old_libs" = no; then
+		oldlibs="$output_objdir/$libname.$libext"
+		build_libtool_libs=module
+		build_old_libs=yes
+	      else
+		build_libtool_libs=no
+	      fi
+	    fi
+	  fi
+	fi
+	# Done checking deplibs!
+	deplibs=$newdeplibs
+      fi
+      # Time to change all our "foo.ltframework" stuff back to "-framework foo"
+      case $host in
+	*-*-darwin*)
+	  newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	  ;;
+      esac
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+	case " $new_libs " in
+	*" -L$path/$objdir "*) ;;
+	*)
+	  case " $deplibs " in
+	  *" -L$path/$objdir "*)
+	    func_append new_libs " -L$path/$objdir" ;;
+	  esac
+	  ;;
+	esac
+      done
+      for deplib in $deplibs; do
+	case $deplib in
+	-L*)
+	  case " $new_libs " in
+	  *" $deplib "*) ;;
+	  *) func_append new_libs " $deplib" ;;
+	  esac
+	  ;;
+	*) func_append new_libs " $deplib" ;;
+	esac
+      done
+      deplibs="$new_libs"
+
+      # All the library-specific variables (install_libdir is set above).
+      library_names=
+      old_library=
+      dlname=
+
+      # Test again, we may have decided not to build it any more
+      if test "$build_libtool_libs" = yes; then
+	# Remove ${wl} instances when linking with ld.
+	# FIXME: should test the right _cmds variable.
+	case $archive_cmds in
+	  *\$LD\ *) wl= ;;
+        esac
+	if test "$hardcode_into_libs" = yes; then
+	  # Hardcode the library paths
+	  hardcode_libdirs=
+	  dep_rpath=
+	  rpath="$finalize_rpath"
+	  test "$opt_mode" != relink && rpath="$compile_rpath$rpath"
+	  for libdir in $rpath; do
+	    if test -n "$hardcode_libdir_flag_spec"; then
+	      if test -n "$hardcode_libdir_separator"; then
+		func_replace_sysroot "$libdir"
+		libdir=$func_replace_sysroot_result
+		if test -z "$hardcode_libdirs"; then
+		  hardcode_libdirs="$libdir"
+		else
+		  # Just accumulate the unique libdirs.
+		  case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+		  *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		    ;;
+		  *)
+		    func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
+		    ;;
+		  esac
+		fi
+	      else
+		eval flag=\"$hardcode_libdir_flag_spec\"
+		func_append dep_rpath " $flag"
+	      fi
+	    elif test -n "$runpath_var"; then
+	      case "$perm_rpath " in
+	      *" $libdir "*) ;;
+	      *) func_append perm_rpath " $libdir" ;;
+	      esac
+	    fi
+	  done
+	  # Substitute the hardcoded libdirs into the rpath.
+	  if test -n "$hardcode_libdir_separator" &&
+	     test -n "$hardcode_libdirs"; then
+	    libdir="$hardcode_libdirs"
+	    eval "dep_rpath=\"$hardcode_libdir_flag_spec\""
+	  fi
+	  if test -n "$runpath_var" && test -n "$perm_rpath"; then
+	    # We should set the runpath_var.
+	    rpath=
+	    for dir in $perm_rpath; do
+	      func_append rpath "$dir:"
+	    done
+	    eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
+	  fi
+	  test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+	fi
+
+	shlibpath="$finalize_shlibpath"
+	test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
+	if test -n "$shlibpath"; then
+	  eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
+	fi
+
+	# Get the real and link names of the library.
+	eval shared_ext=\"$shrext_cmds\"
+	eval library_names=\"$library_names_spec\"
+	set dummy $library_names
+	shift
+	realname="$1"
+	shift
+
+	if test -n "$soname_spec"; then
+	  eval soname=\"$soname_spec\"
+	else
+	  soname="$realname"
+	fi
+	if test -z "$dlname"; then
+	  dlname=$soname
+	fi
+
+	lib="$output_objdir/$realname"
+	linknames=
+	for link
+	do
+	  func_append linknames " $link"
+	done
+
+	# Use standard objects if they are pic
+	test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP`
+	test "X$libobjs" = "X " && libobjs=
+
+	delfiles=
+	if test -n "$export_symbols" && test -n "$include_expsyms"; then
+	  $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp"
+	  export_symbols="$output_objdir/$libname.uexp"
+	  func_append delfiles " $export_symbols"
+	fi
+
+	orig_export_symbols=
+	case $host_os in
+	cygwin* | mingw* | cegcc*)
+	  if test -n "$export_symbols" && test -z "$export_symbols_regex"; then
+	    # exporting using user supplied symfile
+	    if test "x`$SED 1q $export_symbols`" != xEXPORTS; then
+	      # and it's NOT already a .def file. Must figure out
+	      # which of the given symbols are data symbols and tag
+	      # them as such. So, trigger use of export_symbols_cmds.
+	      # export_symbols gets reassigned inside the "prepare
+	      # the list of exported symbols" if statement, so the
+	      # include_expsyms logic still works.
+	      orig_export_symbols="$export_symbols"
+	      export_symbols=
+	      always_export_symbols=yes
+	    fi
+	  fi
+	  ;;
+	esac
+
+	# Prepare the list of exported symbols
+	if test -z "$export_symbols"; then
+	  if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+	    func_verbose "generating symbol list for \`$libname.la'"
+	    export_symbols="$output_objdir/$libname.exp"
+	    $opt_dry_run || $RM $export_symbols
+	    cmds=$export_symbols_cmds
+	    save_ifs="$IFS"; IFS='~'
+	    for cmd1 in $cmds; do
+	      IFS="$save_ifs"
+	      # Take the normal branch if the nm_file_list_spec branch
+	      # doesn't work or if tool conversion is not needed.
+	      case $nm_file_list_spec~$to_tool_file_cmd in
+		*~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*)
+		  try_normal_branch=yes
+		  eval cmd=\"$cmd1\"
+		  func_len " $cmd"
+		  len=$func_len_result
+		  ;;
+		*)
+		  try_normal_branch=no
+		  ;;
+	      esac
+	      if test "$try_normal_branch" = yes \
+		 && { test "$len" -lt "$max_cmd_len" \
+		      || test "$max_cmd_len" -le -1; }
+	      then
+		func_show_eval "$cmd" 'exit $?'
+		skipped_export=false
+	      elif test -n "$nm_file_list_spec"; then
+		func_basename "$output"
+		output_la=$func_basename_result
+		save_libobjs=$libobjs
+		save_output=$output
+		output=${output_objdir}/${output_la}.nm
+		func_to_tool_file "$output"
+		libobjs=$nm_file_list_spec$func_to_tool_file_result
+		func_append delfiles " $output"
+		func_verbose "creating $NM input file list: $output"
+		for obj in $save_libobjs; do
+		  func_to_tool_file "$obj"
+		  $ECHO "$func_to_tool_file_result"
+		done > "$output"
+		eval cmd=\"$cmd1\"
+		func_show_eval "$cmd" 'exit $?'
+		output=$save_output
+		libobjs=$save_libobjs
+		skipped_export=false
+	      else
+		# The command line is too long to execute in one step.
+		func_verbose "using reloadable object file for export list..."
+		skipped_export=:
+		# Break out early, otherwise skipped_export may be
+		# set to false by a later but shorter cmd.
+		break
+	      fi
+	    done
+	    IFS="$save_ifs"
+	    if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then
+	      func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+	      func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+	    fi
+	  fi
+	fi
+
+	if test -n "$export_symbols" && test -n "$include_expsyms"; then
+	  tmp_export_symbols="$export_symbols"
+	  test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
+	  $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"'
+	fi
+
+	if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then
+	  # The given exports_symbols file has to be filtered, so filter it.
+	  func_verbose "filter symbol list for \`$libname.la' to tag DATA exports"
+	  # FIXME: $output_objdir/$libname.filter potentially contains lots of
+	  # 's' commands which not all seds can handle. GNU sed should be fine
+	  # though. Also, the filter scales superlinearly with the number of
+	  # global variables. join(1) would be nice here, but unfortunately
+	  # isn't a blessed tool.
+	  $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+	  func_append delfiles " $export_symbols $output_objdir/$libname.filter"
+	  export_symbols=$output_objdir/$libname.def
+	  $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+	fi
+
+	tmp_deplibs=
+	for test_deplib in $deplibs; do
+	  case " $convenience " in
+	  *" $test_deplib "*) ;;
+	  *)
+	    func_append tmp_deplibs " $test_deplib"
+	    ;;
+	  esac
+	done
+	deplibs="$tmp_deplibs"
+
+	if test -n "$convenience"; then
+	  if test -n "$whole_archive_flag_spec" &&
+	    test "$compiler_needs_object" = yes &&
+	    test -z "$libobjs"; then
+	    # extract the archives, so we have objects to list.
+	    # TODO: could optimize this to just extract one archive.
+	    whole_archive_flag_spec=
+	  fi
+	  if test -n "$whole_archive_flag_spec"; then
+	    save_libobjs=$libobjs
+	    eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+	    test "X$libobjs" = "X " && libobjs=
+	  else
+	    gentop="$output_objdir/${outputname}x"
+	    func_append generated " $gentop"
+
+	    func_extract_archives $gentop $convenience
+	    func_append libobjs " $func_extract_archives_result"
+	    test "X$libobjs" = "X " && libobjs=
+	  fi
+	fi
+
+	if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+	  eval flag=\"$thread_safe_flag_spec\"
+	  func_append linker_flags " $flag"
+	fi
+
+	# Make a backup of the uninstalled library when relinking
+	if test "$opt_mode" = relink; then
+	  $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $?
+	fi
+
+	# Do each of the archive commands.
+	if test "$module" = yes && test -n "$module_cmds" ; then
+	  if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+	    eval test_cmds=\"$module_expsym_cmds\"
+	    cmds=$module_expsym_cmds
+	  else
+	    eval test_cmds=\"$module_cmds\"
+	    cmds=$module_cmds
+	  fi
+	else
+	  if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+	    eval test_cmds=\"$archive_expsym_cmds\"
+	    cmds=$archive_expsym_cmds
+	  else
+	    eval test_cmds=\"$archive_cmds\"
+	    cmds=$archive_cmds
+	  fi
+	fi
+
+	if test "X$skipped_export" != "X:" &&
+	   func_len " $test_cmds" &&
+	   len=$func_len_result &&
+	   test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+	  :
+	else
+	  # The command line is too long to link in one step, link piecewise
+	  # or, if using GNU ld and skipped_export is not :, use a linker
+	  # script.
+
+	  # Save the value of $output and $libobjs because we want to
+	  # use them later.  If we have whole_archive_flag_spec, we
+	  # want to use save_libobjs as it was before
+	  # whole_archive_flag_spec was expanded, because we can't
+	  # assume the linker understands whole_archive_flag_spec.
+	  # This may have to be revisited, in case too many
+	  # convenience libraries get linked in and end up exceeding
+	  # the spec.
+	  if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
+	    save_libobjs=$libobjs
+	  fi
+	  save_output=$output
+	  func_basename "$output"
+	  output_la=$func_basename_result
+
+	  # Clear the reloadable object creation command queue and
+	  # initialize k to one.
+	  test_cmds=
+	  concat_cmds=
+	  objlist=
+	  last_robj=
+	  k=1
+
+	  if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then
+	    output=${output_objdir}/${output_la}.lnkscript
+	    func_verbose "creating GNU ld script: $output"
+	    echo 'INPUT (' > $output
+	    for obj in $save_libobjs
+	    do
+	      func_to_tool_file "$obj"
+	      $ECHO "$func_to_tool_file_result" >> $output
+	    done
+	    echo ')' >> $output
+	    func_append delfiles " $output"
+	    func_to_tool_file "$output"
+	    output=$func_to_tool_file_result
+	  elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then
+	    output=${output_objdir}/${output_la}.lnk
+	    func_verbose "creating linker input file list: $output"
+	    : > $output
+	    set x $save_libobjs
+	    shift
+	    firstobj=
+	    if test "$compiler_needs_object" = yes; then
+	      firstobj="$1 "
+	      shift
+	    fi
+	    for obj
+	    do
+	      func_to_tool_file "$obj"
+	      $ECHO "$func_to_tool_file_result" >> $output
+	    done
+	    func_append delfiles " $output"
+	    func_to_tool_file "$output"
+	    output=$firstobj\"$file_list_spec$func_to_tool_file_result\"
+	  else
+	    if test -n "$save_libobjs"; then
+	      func_verbose "creating reloadable object files..."
+	      output=$output_objdir/$output_la-${k}.$objext
+	      eval test_cmds=\"$reload_cmds\"
+	      func_len " $test_cmds"
+	      len0=$func_len_result
+	      len=$len0
+
+	      # Loop over the list of objects to be linked.
+	      for obj in $save_libobjs
+	      do
+		func_len " $obj"
+		func_arith $len + $func_len_result
+		len=$func_arith_result
+		if test "X$objlist" = X ||
+		   test "$len" -lt "$max_cmd_len"; then
+		  func_append objlist " $obj"
+		else
+		  # The command $test_cmds is almost too long, add a
+		  # command to the queue.
+		  if test "$k" -eq 1 ; then
+		    # The first file doesn't have a previous command to add.
+		    reload_objs=$objlist
+		    eval concat_cmds=\"$reload_cmds\"
+		  else
+		    # All subsequent reloadable object files will link in
+		    # the last one created.
+		    reload_objs="$objlist $last_robj"
+		    eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\"
+		  fi
+		  last_robj=$output_objdir/$output_la-${k}.$objext
+		  func_arith $k + 1
+		  k=$func_arith_result
+		  output=$output_objdir/$output_la-${k}.$objext
+		  objlist=" $obj"
+		  func_len " $last_robj"
+		  func_arith $len0 + $func_len_result
+		  len=$func_arith_result
+		fi
+	      done
+	      # Handle the remaining objects by creating one last
+	      # reloadable object file.  All subsequent reloadable object
+	      # files will link in the last one created.
+	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	      reload_objs="$objlist $last_robj"
+	      eval concat_cmds=\"\${concat_cmds}$reload_cmds\"
+	      if test -n "$last_robj"; then
+	        eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\"
+	      fi
+	      func_append delfiles " $output"
+
+	    else
+	      output=
+	    fi
+
+	    if ${skipped_export-false}; then
+	      func_verbose "generating symbol list for \`$libname.la'"
+	      export_symbols="$output_objdir/$libname.exp"
+	      $opt_dry_run || $RM $export_symbols
+	      libobjs=$output
+	      # Append the command to create the export file.
+	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	      eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\"
+	      if test -n "$last_robj"; then
+		eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\"
+	      fi
+	    fi
+
+	    test -n "$save_libobjs" &&
+	      func_verbose "creating a temporary reloadable object file: $output"
+
+	    # Loop through the commands generated above and execute them.
+	    save_ifs="$IFS"; IFS='~'
+	    for cmd in $concat_cmds; do
+	      IFS="$save_ifs"
+	      $opt_silent || {
+		  func_quote_for_expand "$cmd"
+		  eval "func_echo $func_quote_for_expand_result"
+	      }
+	      $opt_dry_run || eval "$cmd" || {
+		lt_exit=$?
+
+		# Restore the uninstalled library and exit
+		if test "$opt_mode" = relink; then
+		  ( cd "$output_objdir" && \
+		    $RM "${realname}T" && \
+		    $MV "${realname}U" "$realname" )
+		fi
+
+		exit $lt_exit
+	      }
+	    done
+	    IFS="$save_ifs"
+
+	    if test -n "$export_symbols_regex" && ${skipped_export-false}; then
+	      func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+	      func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+	    fi
+	  fi
+
+          if ${skipped_export-false}; then
+	    if test -n "$export_symbols" && test -n "$include_expsyms"; then
+	      tmp_export_symbols="$export_symbols"
+	      test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
+	      $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"'
+	    fi
+
+	    if test -n "$orig_export_symbols"; then
+	      # The given exports_symbols file has to be filtered, so filter it.
+	      func_verbose "filter symbol list for \`$libname.la' to tag DATA exports"
+	      # FIXME: $output_objdir/$libname.filter potentially contains lots of
+	      # 's' commands which not all seds can handle. GNU sed should be fine
+	      # though. Also, the filter scales superlinearly with the number of
+	      # global variables. join(1) would be nice here, but unfortunately
+	      # isn't a blessed tool.
+	      $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+	      func_append delfiles " $export_symbols $output_objdir/$libname.filter"
+	      export_symbols=$output_objdir/$libname.def
+	      $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+	    fi
+	  fi
+
+	  libobjs=$output
+	  # Restore the value of output.
+	  output=$save_output
+
+	  if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
+	    eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+	    test "X$libobjs" = "X " && libobjs=
+	  fi
+	  # Expand the library linking commands again to reset the
+	  # value of $libobjs for piecewise linking.
+
+	  # Do each of the archive commands.
+	  if test "$module" = yes && test -n "$module_cmds" ; then
+	    if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+	      cmds=$module_expsym_cmds
+	    else
+	      cmds=$module_cmds
+	    fi
+	  else
+	    if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+	      cmds=$archive_expsym_cmds
+	    else
+	      cmds=$archive_cmds
+	    fi
+	  fi
+	fi
+
+	if test -n "$delfiles"; then
+	  # Append the command to remove temporary files to $cmds.
+	  eval cmds=\"\$cmds~\$RM $delfiles\"
+	fi
+
+	# Add any objects from preloaded convenience libraries
+	if test -n "$dlprefiles"; then
+	  gentop="$output_objdir/${outputname}x"
+	  func_append generated " $gentop"
+
+	  func_extract_archives $gentop $dlprefiles
+	  func_append libobjs " $func_extract_archives_result"
+	  test "X$libobjs" = "X " && libobjs=
+	fi
+
+	save_ifs="$IFS"; IFS='~'
+	for cmd in $cmds; do
+	  IFS="$save_ifs"
+	  eval cmd=\"$cmd\"
+	  $opt_silent || {
+	    func_quote_for_expand "$cmd"
+	    eval "func_echo $func_quote_for_expand_result"
+	  }
+	  $opt_dry_run || eval "$cmd" || {
+	    lt_exit=$?
+
+	    # Restore the uninstalled library and exit
+	    if test "$opt_mode" = relink; then
+	      ( cd "$output_objdir" && \
+	        $RM "${realname}T" && \
+		$MV "${realname}U" "$realname" )
+	    fi
+
+	    exit $lt_exit
+	  }
+	done
+	IFS="$save_ifs"
+
+	# Restore the uninstalled library and exit
+	if test "$opt_mode" = relink; then
+	  $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $?
+
+	  if test -n "$convenience"; then
+	    if test -z "$whole_archive_flag_spec"; then
+	      func_show_eval '${RM}r "$gentop"'
+	    fi
+	  fi
+
+	  exit $EXIT_SUCCESS
+	fi
+
+	# Create links to the real library.
+	for linkname in $linknames; do
+	  if test "$realname" != "$linkname"; then
+	    func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?'
+	  fi
+	done
+
+	# If -module or -export-dynamic was specified, set the dlname.
+	if test "$module" = yes || test "$export_dynamic" = yes; then
+	  # On all known operating systems, these are identical.
+	  dlname="$soname"
+	fi
+      fi
+      ;;
+
+    obj)
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+	func_warning "\`-dlopen' is ignored for objects"
+      fi
+
+      case " $deplibs" in
+      *\ -l* | *\ -L*)
+	func_warning "\`-l' and \`-L' are ignored for objects" ;;
+      esac
+
+      test -n "$rpath" && \
+	func_warning "\`-rpath' is ignored for objects"
+
+      test -n "$xrpath" && \
+	func_warning "\`-R' is ignored for objects"
+
+      test -n "$vinfo" && \
+	func_warning "\`-version-info' is ignored for objects"
+
+      test -n "$release" && \
+	func_warning "\`-release' is ignored for objects"
+
+      case $output in
+      *.lo)
+	test -n "$objs$old_deplibs" && \
+	  func_fatal_error "cannot build library object \`$output' from non-libtool objects"
+
+	libobj=$output
+	func_lo2o "$libobj"
+	obj=$func_lo2o_result
+	;;
+      *)
+	libobj=
+	obj="$output"
+	;;
+      esac
+
+      # Delete the old objects.
+      $opt_dry_run || $RM $obj $libobj
+
+      # Objects from convenience libraries.  This assumes
+      # single-version convenience libraries.  Whenever we create
+      # different ones for PIC/non-PIC, this we'll have to duplicate
+      # the extraction.
+      reload_conv_objs=
+      gentop=
+      # reload_cmds runs $LD directly, so let us get rid of
+      # -Wl from whole_archive_flag_spec and hope we can get by with
+      # turning comma into space..
+      wl=
+
+      if test -n "$convenience"; then
+	if test -n "$whole_archive_flag_spec"; then
+	  eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
+	  reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'`
+	else
+	  gentop="$output_objdir/${obj}x"
+	  func_append generated " $gentop"
+
+	  func_extract_archives $gentop $convenience
+	  reload_conv_objs="$reload_objs $func_extract_archives_result"
+	fi
+      fi
+
+      # If we're not building shared, we need to use non_pic_objs
+      test "$build_libtool_libs" != yes && libobjs="$non_pic_objects"
+
+      # Create the old-style object.
+      reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
+
+      output="$obj"
+      func_execute_cmds "$reload_cmds" 'exit $?'
+
+      # Exit if we aren't doing a library object file.
+      if test -z "$libobj"; then
+	if test -n "$gentop"; then
+	  func_show_eval '${RM}r "$gentop"'
+	fi
+
+	exit $EXIT_SUCCESS
+      fi
+
+      if test "$build_libtool_libs" != yes; then
+	if test -n "$gentop"; then
+	  func_show_eval '${RM}r "$gentop"'
+	fi
+
+	# Create an invalid libtool object if no PIC, so that we don't
+	# accidentally link it into a program.
+	# $show "echo timestamp > $libobj"
+	# $opt_dry_run || eval "echo timestamp > $libobj" || exit $?
+	exit $EXIT_SUCCESS
+      fi
+
+      if test -n "$pic_flag" || test "$pic_mode" != default; then
+	# Only do commands if we really have different PIC objects.
+	reload_objs="$libobjs $reload_conv_objs"
+	output="$libobj"
+	func_execute_cmds "$reload_cmds" 'exit $?'
+      fi
+
+      if test -n "$gentop"; then
+	func_show_eval '${RM}r "$gentop"'
+      fi
+
+      exit $EXIT_SUCCESS
+      ;;
+
+    prog)
+      case $host in
+	*cygwin*) func_stripname '' '.exe' "$output"
+	          output=$func_stripname_result.exe;;
+      esac
+      test -n "$vinfo" && \
+	func_warning "\`-version-info' is ignored for programs"
+
+      test -n "$release" && \
+	func_warning "\`-release' is ignored for programs"
+
+      test "$preload" = yes \
+        && test "$dlopen_support" = unknown \
+	&& test "$dlopen_self" = unknown \
+	&& test "$dlopen_self_static" = unknown && \
+	  func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support."
+
+      case $host in
+      *-*-rhapsody* | *-*-darwin1.[012])
+	# On Rhapsody replace the C library is the System framework
+	compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'`
+	finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'`
+	;;
+      esac
+
+      case $host in
+      *-*-darwin*)
+	# Don't allow lazy linking, it breaks C++ global constructors
+	# But is supposedly fixed on 10.4 or later (yay!).
+	if test "$tagname" = CXX ; then
+	  case ${MACOSX_DEPLOYMENT_TARGET-10.0} in
+	    10.[0123])
+	      func_append compile_command " ${wl}-bind_at_load"
+	      func_append finalize_command " ${wl}-bind_at_load"
+	    ;;
+	  esac
+	fi
+	# Time to change all our "foo.ltframework" stuff back to "-framework foo"
+	compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+	;;
+      esac
+
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+	case " $new_libs " in
+	*" -L$path/$objdir "*) ;;
+	*)
+	  case " $compile_deplibs " in
+	  *" -L$path/$objdir "*)
+	    func_append new_libs " -L$path/$objdir" ;;
+	  esac
+	  ;;
+	esac
+      done
+      for deplib in $compile_deplibs; do
+	case $deplib in
+	-L*)
+	  case " $new_libs " in
+	  *" $deplib "*) ;;
+	  *) func_append new_libs " $deplib" ;;
+	  esac
+	  ;;
+	*) func_append new_libs " $deplib" ;;
+	esac
+      done
+      compile_deplibs="$new_libs"
+
+
+      func_append compile_command " $compile_deplibs"
+      func_append finalize_command " $finalize_deplibs"
+
+      if test -n "$rpath$xrpath"; then
+	# If the user specified any rpath flags, then add them.
+	for libdir in $rpath $xrpath; do
+	  # This is the magic to use -rpath.
+	  case "$finalize_rpath " in
+	  *" $libdir "*) ;;
+	  *) func_append finalize_rpath " $libdir" ;;
+	  esac
+	done
+      fi
+
+      # Now hardcode the library paths
+      rpath=
+      hardcode_libdirs=
+      for libdir in $compile_rpath $finalize_rpath; do
+	if test -n "$hardcode_libdir_flag_spec"; then
+	  if test -n "$hardcode_libdir_separator"; then
+	    if test -z "$hardcode_libdirs"; then
+	      hardcode_libdirs="$libdir"
+	    else
+	      # Just accumulate the unique libdirs.
+	      case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		;;
+	      *)
+		func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
+		;;
+	      esac
+	    fi
+	  else
+	    eval flag=\"$hardcode_libdir_flag_spec\"
+	    func_append rpath " $flag"
+	  fi
+	elif test -n "$runpath_var"; then
+	  case "$perm_rpath " in
+	  *" $libdir "*) ;;
+	  *) func_append perm_rpath " $libdir" ;;
+	  esac
+	fi
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+	  testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'`
+	  case :$dllsearchpath: in
+	  *":$libdir:"*) ;;
+	  ::) dllsearchpath=$libdir;;
+	  *) func_append dllsearchpath ":$libdir";;
+	  esac
+	  case :$dllsearchpath: in
+	  *":$testbindir:"*) ;;
+	  ::) dllsearchpath=$testbindir;;
+	  *) func_append dllsearchpath ":$testbindir";;
+	  esac
+	  ;;
+	esac
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+	 test -n "$hardcode_libdirs"; then
+	libdir="$hardcode_libdirs"
+	eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      compile_rpath="$rpath"
+
+      rpath=
+      hardcode_libdirs=
+      for libdir in $finalize_rpath; do
+	if test -n "$hardcode_libdir_flag_spec"; then
+	  if test -n "$hardcode_libdir_separator"; then
+	    if test -z "$hardcode_libdirs"; then
+	      hardcode_libdirs="$libdir"
+	    else
+	      # Just accumulate the unique libdirs.
+	      case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		;;
+	      *)
+		func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
+		;;
+	      esac
+	    fi
+	  else
+	    eval flag=\"$hardcode_libdir_flag_spec\"
+	    func_append rpath " $flag"
+	  fi
+	elif test -n "$runpath_var"; then
+	  case "$finalize_perm_rpath " in
+	  *" $libdir "*) ;;
+	  *) func_append finalize_perm_rpath " $libdir" ;;
+	  esac
+	fi
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+	 test -n "$hardcode_libdirs"; then
+	libdir="$hardcode_libdirs"
+	eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      finalize_rpath="$rpath"
+
+      if test -n "$libobjs" && test "$build_old_libs" = yes; then
+	# Transform all the library objects into standard objects.
+	compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
+	finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
+      fi
+
+      func_generate_dlsyms "$outputname" "@PROGRAM@" "no"
+
+      # template prelinking step
+      if test -n "$prelink_cmds"; then
+	func_execute_cmds "$prelink_cmds" 'exit $?'
+      fi
+
+      wrappers_required=yes
+      case $host in
+      *cegcc* | *mingw32ce*)
+        # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway.
+        wrappers_required=no
+        ;;
+      *cygwin* | *mingw* )
+        if test "$build_libtool_libs" != yes; then
+          wrappers_required=no
+        fi
+        ;;
+      *)
+        if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
+          wrappers_required=no
+        fi
+        ;;
+      esac
+      if test "$wrappers_required" = no; then
+	# Replace the output file specification.
+	compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
+	link_command="$compile_command$compile_rpath"
+
+	# We have no uninstalled library dependencies, so finalize right now.
+	exit_status=0
+	func_show_eval "$link_command" 'exit_status=$?'
+
+	if test -n "$postlink_cmds"; then
+	  func_to_tool_file "$output"
+	  postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
+	  func_execute_cmds "$postlink_cmds" 'exit $?'
+	fi
+
+	# Delete the generated files.
+	if test -f "$output_objdir/${outputname}S.${objext}"; then
+	  func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"'
+	fi
+
+	exit $exit_status
+      fi
+
+      if test -n "$compile_shlibpath$finalize_shlibpath"; then
+	compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+      fi
+      if test -n "$finalize_shlibpath"; then
+	finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+      fi
+
+      compile_var=
+      finalize_var=
+      if test -n "$runpath_var"; then
+	if test -n "$perm_rpath"; then
+	  # We should set the runpath_var.
+	  rpath=
+	  for dir in $perm_rpath; do
+	    func_append rpath "$dir:"
+	  done
+	  compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+	fi
+	if test -n "$finalize_perm_rpath"; then
+	  # We should set the runpath_var.
+	  rpath=
+	  for dir in $finalize_perm_rpath; do
+	    func_append rpath "$dir:"
+	  done
+	  finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+	fi
+      fi
+
+      if test "$no_install" = yes; then
+	# We don't need to create a wrapper script.
+	link_command="$compile_var$compile_command$compile_rpath"
+	# Replace the output file specification.
+	link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
+	# Delete the old output file.
+	$opt_dry_run || $RM $output
+	# Link the executable and exit
+	func_show_eval "$link_command" 'exit $?'
+
+	if test -n "$postlink_cmds"; then
+	  func_to_tool_file "$output"
+	  postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
+	  func_execute_cmds "$postlink_cmds" 'exit $?'
+	fi
+
+	exit $EXIT_SUCCESS
+      fi
+
+      if test "$hardcode_action" = relink; then
+	# Fast installation is not supported
+	link_command="$compile_var$compile_command$compile_rpath"
+	relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+	func_warning "this platform does not like uninstalled shared libraries"
+	func_warning "\`$output' will be relinked during installation"
+      else
+	if test "$fast_install" != no; then
+	  link_command="$finalize_var$compile_command$finalize_rpath"
+	  if test "$fast_install" = yes; then
+	    relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'`
+	  else
+	    # fast_install is set to needless
+	    relink_command=
+	  fi
+	else
+	  link_command="$compile_var$compile_command$compile_rpath"
+	  relink_command="$finalize_var$finalize_command$finalize_rpath"
+	fi
+      fi
+
+      # Replace the output file specification.
+      link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+      # Delete the old output files.
+      $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+      func_show_eval "$link_command" 'exit $?'
+
+      if test -n "$postlink_cmds"; then
+	func_to_tool_file "$output_objdir/$outputname"
+	postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
+	func_execute_cmds "$postlink_cmds" 'exit $?'
+      fi
+
+      # Now create the wrapper script.
+      func_verbose "creating $output"
+
+      # Quote the relink command for shipping.
+      if test -n "$relink_command"; then
+	# Preserve any variables that may affect compiler behavior
+	for var in $variables_saved_for_relink; do
+	  if eval test -z \"\${$var+set}\"; then
+	    relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+	  elif eval var_value=\$$var; test -z "$var_value"; then
+	    relink_command="$var=; export $var; $relink_command"
+	  else
+	    func_quote_for_eval "$var_value"
+	    relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
+	  fi
+	done
+	relink_command="(cd `pwd`; $relink_command)"
+	relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"`
+      fi
+
+      # Only actually do things if not in dry run mode.
+      $opt_dry_run || {
+	# win32 will think the script is a binary if it has
+	# a .exe suffix, so we strip it off here.
+	case $output in
+	  *.exe) func_stripname '' '.exe' "$output"
+	         output=$func_stripname_result ;;
+	esac
+	# test for cygwin because mv fails w/o .exe extensions
+	case $host in
+	  *cygwin*)
+	    exeext=.exe
+	    func_stripname '' '.exe' "$outputname"
+	    outputname=$func_stripname_result ;;
+	  *) exeext= ;;
+	esac
+	case $host in
+	  *cygwin* | *mingw* )
+	    func_dirname_and_basename "$output" "" "."
+	    output_name=$func_basename_result
+	    output_path=$func_dirname_result
+	    cwrappersource="$output_path/$objdir/lt-$output_name.c"
+	    cwrapper="$output_path/$output_name.exe"
+	    $RM $cwrappersource $cwrapper
+	    trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+
+	    func_emit_cwrapperexe_src > $cwrappersource
+
+	    # The wrapper executable is built using the $host compiler,
+	    # because it contains $host paths and files. If cross-
+	    # compiling, it, like the target executable, must be
+	    # executed on the $host or under an emulation environment.
+	    $opt_dry_run || {
+	      $LTCC $LTCFLAGS -o $cwrapper $cwrappersource
+	      $STRIP $cwrapper
+	    }
+
+	    # Now, create the wrapper script for func_source use:
+	    func_ltwrapper_scriptname $cwrapper
+	    $RM $func_ltwrapper_scriptname_result
+	    trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15
+	    $opt_dry_run || {
+	      # note: this script will not be executed, so do not chmod.
+	      if test "x$build" = "x$host" ; then
+		$cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result
+	      else
+		func_emit_wrapper no > $func_ltwrapper_scriptname_result
+	      fi
+	    }
+	  ;;
+	  * )
+	    $RM $output
+	    trap "$RM $output; exit $EXIT_FAILURE" 1 2 15
+
+	    func_emit_wrapper no > $output
+	    chmod +x $output
+	  ;;
+	esac
+      }
+      exit $EXIT_SUCCESS
+      ;;
+    esac
+
+    # See if we need to build an old-fashioned archive.
+    for oldlib in $oldlibs; do
+
+      if test "$build_libtool_libs" = convenience; then
+	oldobjs="$libobjs_save $symfileobj"
+	addlibs="$convenience"
+	build_libtool_libs=no
+      else
+	if test "$build_libtool_libs" = module; then
+	  oldobjs="$libobjs_save"
+	  build_libtool_libs=no
+	else
+	  oldobjs="$old_deplibs $non_pic_objects"
+	  if test "$preload" = yes && test -f "$symfileobj"; then
+	    func_append oldobjs " $symfileobj"
+	  fi
+	fi
+	addlibs="$old_convenience"
+      fi
+
+      if test -n "$addlibs"; then
+	gentop="$output_objdir/${outputname}x"
+	func_append generated " $gentop"
+
+	func_extract_archives $gentop $addlibs
+	func_append oldobjs " $func_extract_archives_result"
+      fi
+
+      # Do each command in the archive commands.
+      if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+	cmds=$old_archive_from_new_cmds
+      else
+
+	# Add any objects from preloaded convenience libraries
+	if test -n "$dlprefiles"; then
+	  gentop="$output_objdir/${outputname}x"
+	  func_append generated " $gentop"
+
+	  func_extract_archives $gentop $dlprefiles
+	  func_append oldobjs " $func_extract_archives_result"
+	fi
+
+	# POSIX demands no paths to be encoded in archives.  We have
+	# to avoid creating archives with duplicate basenames if we
+	# might have to extract them afterwards, e.g., when creating a
+	# static archive out of a convenience library, or when linking
+	# the entirety of a libtool archive into another (currently
+	# not supported by libtool).
+	if (for obj in $oldobjs
+	    do
+	      func_basename "$obj"
+	      $ECHO "$func_basename_result"
+	    done | sort | sort -uc >/dev/null 2>&1); then
+	  :
+	else
+	  echo "copying selected object files to avoid basename conflicts..."
+	  gentop="$output_objdir/${outputname}x"
+	  func_append generated " $gentop"
+	  func_mkdir_p "$gentop"
+	  save_oldobjs=$oldobjs
+	  oldobjs=
+	  counter=1
+	  for obj in $save_oldobjs
+	  do
+	    func_basename "$obj"
+	    objbase="$func_basename_result"
+	    case " $oldobjs " in
+	    " ") oldobjs=$obj ;;
+	    *[\ /]"$objbase "*)
+	      while :; do
+		# Make sure we don't pick an alternate name that also
+		# overlaps.
+		newobj=lt$counter-$objbase
+		func_arith $counter + 1
+		counter=$func_arith_result
+		case " $oldobjs " in
+		*[\ /]"$newobj "*) ;;
+		*) if test ! -f "$gentop/$newobj"; then break; fi ;;
+		esac
+	      done
+	      func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+	      func_append oldobjs " $gentop/$newobj"
+	      ;;
+	    *) func_append oldobjs " $obj" ;;
+	    esac
+	  done
+	fi
+	func_to_tool_file "$oldlib" func_convert_file_msys_to_w32
+	tool_oldlib=$func_to_tool_file_result
+	eval cmds=\"$old_archive_cmds\"
+
+	func_len " $cmds"
+	len=$func_len_result
+	if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+	  cmds=$old_archive_cmds
+	elif test -n "$archiver_list_spec"; then
+	  func_verbose "using command file archive linking..."
+	  for obj in $oldobjs
+	  do
+	    func_to_tool_file "$obj"
+	    $ECHO "$func_to_tool_file_result"
+	  done > $output_objdir/$libname.libcmd
+	  func_to_tool_file "$output_objdir/$libname.libcmd"
+	  oldobjs=" $archiver_list_spec$func_to_tool_file_result"
+	  cmds=$old_archive_cmds
+	else
+	  # the command line is too long to link in one step, link in parts
+	  func_verbose "using piecewise archive linking..."
+	  save_RANLIB=$RANLIB
+	  RANLIB=:
+	  objlist=
+	  concat_cmds=
+	  save_oldobjs=$oldobjs
+	  oldobjs=
+	  # Is there a better way of finding the last object in the list?
+	  for obj in $save_oldobjs
+	  do
+	    last_oldobj=$obj
+	  done
+	  eval test_cmds=\"$old_archive_cmds\"
+	  func_len " $test_cmds"
+	  len0=$func_len_result
+	  len=$len0
+	  for obj in $save_oldobjs
+	  do
+	    func_len " $obj"
+	    func_arith $len + $func_len_result
+	    len=$func_arith_result
+	    func_append objlist " $obj"
+	    if test "$len" -lt "$max_cmd_len"; then
+	      :
+	    else
+	      # the above command should be used before it gets too long
+	      oldobjs=$objlist
+	      if test "$obj" = "$last_oldobj" ; then
+		RANLIB=$save_RANLIB
+	      fi
+	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	      eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
+	      objlist=
+	      len=$len0
+	    fi
+	  done
+	  RANLIB=$save_RANLIB
+	  oldobjs=$objlist
+	  if test "X$oldobjs" = "X" ; then
+	    eval cmds=\"\$concat_cmds\"
+	  else
+	    eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
+	  fi
+	fi
+      fi
+      func_execute_cmds "$cmds" 'exit $?'
+    done
+
+    test -n "$generated" && \
+      func_show_eval "${RM}r$generated"
+
+    # Now create the libtool archive.
+    case $output in
+    *.la)
+      old_library=
+      test "$build_old_libs" = yes && old_library="$libname.$libext"
+      func_verbose "creating $output"
+
+      # Preserve any variables that may affect compiler behavior
+      for var in $variables_saved_for_relink; do
+	if eval test -z \"\${$var+set}\"; then
+	  relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+	elif eval var_value=\$$var; test -z "$var_value"; then
+	  relink_command="$var=; export $var; $relink_command"
+	else
+	  func_quote_for_eval "$var_value"
+	  relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
+	fi
+      done
+      # Quote the link command for shipping.
+      relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
+      relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"`
+      if test "$hardcode_automatic" = yes ; then
+	relink_command=
+      fi
+
+      # Only create the output if not a dry run.
+      $opt_dry_run || {
+	for installed in no yes; do
+	  if test "$installed" = yes; then
+	    if test -z "$install_libdir"; then
+	      break
+	    fi
+	    output="$output_objdir/$outputname"i
+	    # Replace all uninstalled libtool libraries with the installed ones
+	    newdependency_libs=
+	    for deplib in $dependency_libs; do
+	      case $deplib in
+	      *.la)
+		func_basename "$deplib"
+		name="$func_basename_result"
+		func_resolve_sysroot "$deplib"
+		eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result`
+		test -z "$libdir" && \
+		  func_fatal_error "\`$deplib' is not a valid libtool archive"
+		func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name"
+		;;
+	      -L*)
+		func_stripname -L '' "$deplib"
+		func_replace_sysroot "$func_stripname_result"
+		func_append newdependency_libs " -L$func_replace_sysroot_result"
+		;;
+	      -R*)
+		func_stripname -R '' "$deplib"
+		func_replace_sysroot "$func_stripname_result"
+		func_append newdependency_libs " -R$func_replace_sysroot_result"
+		;;
+	      *) func_append newdependency_libs " $deplib" ;;
+	      esac
+	    done
+	    dependency_libs="$newdependency_libs"
+	    newdlfiles=
+
+	    for lib in $dlfiles; do
+	      case $lib in
+	      *.la)
+	        func_basename "$lib"
+		name="$func_basename_result"
+		eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+		test -z "$libdir" && \
+		  func_fatal_error "\`$lib' is not a valid libtool archive"
+		func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name"
+		;;
+	      *) func_append newdlfiles " $lib" ;;
+	      esac
+	    done
+	    dlfiles="$newdlfiles"
+	    newdlprefiles=
+	    for lib in $dlprefiles; do
+	      case $lib in
+	      *.la)
+		# Only pass preopened files to the pseudo-archive (for
+		# eventual linking with the app. that links it) if we
+		# didn't already link the preopened objects directly into
+		# the library:
+		func_basename "$lib"
+		name="$func_basename_result"
+		eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+		test -z "$libdir" && \
+		  func_fatal_error "\`$lib' is not a valid libtool archive"
+		func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name"
+		;;
+	      esac
+	    done
+	    dlprefiles="$newdlprefiles"
+	  else
+	    newdlfiles=
+	    for lib in $dlfiles; do
+	      case $lib in
+		[\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+		*) abs=`pwd`"/$lib" ;;
+	      esac
+	      func_append newdlfiles " $abs"
+	    done
+	    dlfiles="$newdlfiles"
+	    newdlprefiles=
+	    for lib in $dlprefiles; do
+	      case $lib in
+		[\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+		*) abs=`pwd`"/$lib" ;;
+	      esac
+	      func_append newdlprefiles " $abs"
+	    done
+	    dlprefiles="$newdlprefiles"
+	  fi
+	  $RM $output
+	  # place dlname in correct position for cygwin
+	  # In fact, it would be nice if we could use this code for all target
+	  # systems that can't hard-code library paths into their executables
+	  # and that have no shared library path variable independent of PATH,
+	  # but it turns out we can't easily determine that from inspecting
+	  # libtool variables, so we have to hard-code the OSs to which it
+	  # applies here; at the moment, that means platforms that use the PE
+	  # object format with DLL files.  See the long comment at the top of
+	  # tests/bindir.at for full details.
+	  tdlname=$dlname
+	  case $host,$output,$installed,$module,$dlname in
+	    *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll)
+	      # If a -bindir argument was supplied, place the dll there.
+	      if test "x$bindir" != x ;
+	      then
+		func_relative_path "$install_libdir" "$bindir"
+		tdlname=$func_relative_path_result$dlname
+	      else
+		# Otherwise fall back on heuristic.
+		tdlname=../bin/$dlname
+	      fi
+	      ;;
+	  esac
+	  $ECHO > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Linker flags that can not go in dependency_libs.
+inherited_linker_flags='$new_inherited_linker_flags'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Names of additional weak libraries provided by this library
+weak_library_names='$weak_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=$module
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+	  if test "$installed" = no && test "$need_relink" = yes; then
+	    $ECHO >> $output "\
+relink_command=\"$relink_command\""
+	  fi
+	done
+      }
+
+      # Do a symbolic link so that the libtool archive can be found in
+      # LD_LIBRARY_PATH before the program is installed.
+      func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?'
+      ;;
+    esac
+    exit $EXIT_SUCCESS
+}
+
+{ test "$opt_mode" = link || test "$opt_mode" = relink; } &&
+    func_mode_link ${1+"$@"}
+
+
+# func_mode_uninstall arg...
+func_mode_uninstall ()
+{
+    $opt_debug
+    RM="$nonopt"
+    files=
+    rmforce=
+    exit_status=0
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    for arg
+    do
+      case $arg in
+      -f) func_append RM " $arg"; rmforce=yes ;;
+      -*) func_append RM " $arg" ;;
+      *) func_append files " $arg" ;;
+      esac
+    done
+
+    test -z "$RM" && \
+      func_fatal_help "you must specify an RM program"
+
+    rmdirs=
+
+    for file in $files; do
+      func_dirname "$file" "" "."
+      dir="$func_dirname_result"
+      if test "X$dir" = X.; then
+	odir="$objdir"
+      else
+	odir="$dir/$objdir"
+      fi
+      func_basename "$file"
+      name="$func_basename_result"
+      test "$opt_mode" = uninstall && odir="$dir"
+
+      # Remember odir for removal later, being careful to avoid duplicates
+      if test "$opt_mode" = clean; then
+	case " $rmdirs " in
+	  *" $odir "*) ;;
+	  *) func_append rmdirs " $odir" ;;
+	esac
+      fi
+
+      # Don't error if the file doesn't exist and rm -f was used.
+      if { test -L "$file"; } >/dev/null 2>&1 ||
+	 { test -h "$file"; } >/dev/null 2>&1 ||
+	 test -f "$file"; then
+	:
+      elif test -d "$file"; then
+	exit_status=1
+	continue
+      elif test "$rmforce" = yes; then
+	continue
+      fi
+
+      rmfiles="$file"
+
+      case $name in
+      *.la)
+	# Possibly a libtool archive, so verify it.
+	if func_lalib_p "$file"; then
+	  func_source $dir/$name
+
+	  # Delete the libtool libraries and symlinks.
+	  for n in $library_names; do
+	    func_append rmfiles " $odir/$n"
+	  done
+	  test -n "$old_library" && func_append rmfiles " $odir/$old_library"
+
+	  case "$opt_mode" in
+	  clean)
+	    case " $library_names " in
+	    *" $dlname "*) ;;
+	    *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;;
+	    esac
+	    test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i"
+	    ;;
+	  uninstall)
+	    if test -n "$library_names"; then
+	      # Do each command in the postuninstall commands.
+	      func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
+	    fi
+
+	    if test -n "$old_library"; then
+	      # Do each command in the old_postuninstall commands.
+	      func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
+	    fi
+	    # FIXME: should reinstall the best remaining shared library.
+	    ;;
+	  esac
+	fi
+	;;
+
+      *.lo)
+	# Possibly a libtool object, so verify it.
+	if func_lalib_p "$file"; then
+
+	  # Read the .lo file
+	  func_source $dir/$name
+
+	  # Add PIC object to the list of files to remove.
+	  if test -n "$pic_object" &&
+	     test "$pic_object" != none; then
+	    func_append rmfiles " $dir/$pic_object"
+	  fi
+
+	  # Add non-PIC object to the list of files to remove.
+	  if test -n "$non_pic_object" &&
+	     test "$non_pic_object" != none; then
+	    func_append rmfiles " $dir/$non_pic_object"
+	  fi
+	fi
+	;;
+
+      *)
+	if test "$opt_mode" = clean ; then
+	  noexename=$name
+	  case $file in
+	  *.exe)
+	    func_stripname '' '.exe' "$file"
+	    file=$func_stripname_result
+	    func_stripname '' '.exe' "$name"
+	    noexename=$func_stripname_result
+	    # $file with .exe has already been added to rmfiles,
+	    # add $file without .exe
+	    func_append rmfiles " $file"
+	    ;;
+	  esac
+	  # Do a test to see if this is a libtool program.
+	  if func_ltwrapper_p "$file"; then
+	    if func_ltwrapper_executable_p "$file"; then
+	      func_ltwrapper_scriptname "$file"
+	      relink_command=
+	      func_source $func_ltwrapper_scriptname_result
+	      func_append rmfiles " $func_ltwrapper_scriptname_result"
+	    else
+	      relink_command=
+	      func_source $dir/$noexename
+	    fi
+
+	    # note $name still contains .exe if it was in $file originally
+	    # as does the version of $file that was added into $rmfiles
+	    func_append rmfiles " $odir/$name $odir/${name}S.${objext}"
+	    if test "$fast_install" = yes && test -n "$relink_command"; then
+	      func_append rmfiles " $odir/lt-$name"
+	    fi
+	    if test "X$noexename" != "X$name" ; then
+	      func_append rmfiles " $odir/lt-${noexename}.c"
+	    fi
+	  fi
+	fi
+	;;
+      esac
+      func_show_eval "$RM $rmfiles" 'exit_status=1'
+    done
+
+    # Try to remove the ${objdir}s in the directories where we deleted files
+    for dir in $rmdirs; do
+      if test -d "$dir"; then
+	func_show_eval "rmdir $dir >/dev/null 2>&1"
+      fi
+    done
+
+    exit $exit_status
+}
+
+{ test "$opt_mode" = uninstall || test "$opt_mode" = clean; } &&
+    func_mode_uninstall ${1+"$@"}
+
+test -z "$opt_mode" && {
+  help="$generic_help"
+  func_fatal_help "you must specify a MODE"
+}
+
+test -z "$exec_cmd" && \
+  func_fatal_help "invalid operation mode \`$opt_mode'"
+
+if test -n "$exec_cmd"; then
+  eval exec "$exec_cmd"
+  exit $EXIT_FAILURE
+fi
+
+exit $exit_status
+
+
+# The TAGs below are defined such that we never get into a situation
+# in which we disable both kinds of libraries.  Given conflicting
+# choices, we go for a static library, that is the most portable,
+# since we can't tell whether shared libraries were disabled because
+# the user asked for that or because the platform doesn't support
+# them.  This is particularly important on AIX, because we don't
+# support having both static and shared libraries enabled at the same
+# time on that platform, so we default to a shared-only configuration.
+# If a disable-shared tag is given, we'll fallback to a static-only
+# configuration.  But we'll never go from static-only to shared-only.
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
+build_libtool_libs=no
+build_old_libs=yes
+# ### END LIBTOOL TAG CONFIG: disable-shared
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
+build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
+# ### END LIBTOOL TAG CONFIG: disable-static
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
+# vi:sw=2
+
diff --git a/missing b/missing
new file mode 100755
index 0000000000000000000000000000000000000000..db98974ff5d59295d7e0edfec2eb2069dc78ef1a
--- /dev/null
+++ b/missing
@@ -0,0 +1,215 @@
+#! /bin/sh
+# Common wrapper for a few potentially missing GNU programs.
+
+scriptversion=2013-10-28.13; # UTC
+
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
+# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+  echo 1>&2 "Try '$0 --help' for more information"
+  exit 1
+fi
+
+case $1 in
+
+  --is-lightweight)
+    # Used by our autoconf macros to check whether the available missing
+    # script is modern enough.
+    exit 0
+    ;;
+
+  --run)
+    # Back-compat with the calling convention used by older automake.
+    shift
+    ;;
+
+  -h|--h|--he|--hel|--help)
+    echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
+to PROGRAM being missing or too old.
+
+Options:
+  -h, --help      display this help and exit
+  -v, --version   output version information and exit
+
+Supported PROGRAM values:
+  aclocal   autoconf  autoheader   autom4te  automake  makeinfo
+  bison     yacc      flex         lex       help2man
+
+Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
+'g' are ignored when checking the name.
+
+Send bug reports to <bug-automake@gnu.org>."
+    exit $?
+    ;;
+
+  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+    echo "missing $scriptversion (GNU Automake)"
+    exit $?
+    ;;
+
+  -*)
+    echo 1>&2 "$0: unknown '$1' option"
+    echo 1>&2 "Try '$0 --help' for more information"
+    exit 1
+    ;;
+
+esac
+
+# Run the given program, remember its exit status.
+"$@"; st=$?
+
+# If it succeeded, we are done.
+test $st -eq 0 && exit 0
+
+# Also exit now if we it failed (or wasn't found), and '--version' was
+# passed; such an option is passed most likely to detect whether the
+# program is present and works.
+case $2 in --version|--help) exit $st;; esac
+
+# Exit code 63 means version mismatch.  This often happens when the user
+# tries to use an ancient version of a tool on a file that requires a
+# minimum version.
+if test $st -eq 63; then
+  msg="probably too old"
+elif test $st -eq 127; then
+  # Program was missing.
+  msg="missing on your system"
+else
+  # Program was found and executed, but failed.  Give up.
+  exit $st
+fi
+
+perl_URL=http://www.perl.org/
+flex_URL=http://flex.sourceforge.net/
+gnu_software_URL=http://www.gnu.org/software
+
+program_details ()
+{
+  case $1 in
+    aclocal|automake)
+      echo "The '$1' program is part of the GNU Automake package:"
+      echo "<$gnu_software_URL/automake>"
+      echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
+      echo "<$gnu_software_URL/autoconf>"
+      echo "<$gnu_software_URL/m4/>"
+      echo "<$perl_URL>"
+      ;;
+    autoconf|autom4te|autoheader)
+      echo "The '$1' program is part of the GNU Autoconf package:"
+      echo "<$gnu_software_URL/autoconf/>"
+      echo "It also requires GNU m4 and Perl in order to run:"
+      echo "<$gnu_software_URL/m4/>"
+      echo "<$perl_URL>"
+      ;;
+  esac
+}
+
+give_advice ()
+{
+  # Normalize program name to check for.
+  normalized_program=`echo "$1" | sed '
+    s/^gnu-//; t
+    s/^gnu//; t
+    s/^g//; t'`
+
+  printf '%s\n' "'$1' is $msg."
+
+  configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
+  case $normalized_program in
+    autoconf*)
+      echo "You should only need it if you modified 'configure.ac',"
+      echo "or m4 files included by it."
+      program_details 'autoconf'
+      ;;
+    autoheader*)
+      echo "You should only need it if you modified 'acconfig.h' or"
+      echo "$configure_deps."
+      program_details 'autoheader'
+      ;;
+    automake*)
+      echo "You should only need it if you modified 'Makefile.am' or"
+      echo "$configure_deps."
+      program_details 'automake'
+      ;;
+    aclocal*)
+      echo "You should only need it if you modified 'acinclude.m4' or"
+      echo "$configure_deps."
+      program_details 'aclocal'
+      ;;
+   autom4te*)
+      echo "You might have modified some maintainer files that require"
+      echo "the 'autom4te' program to be rebuilt."
+      program_details 'autom4te'
+      ;;
+    bison*|yacc*)
+      echo "You should only need it if you modified a '.y' file."
+      echo "You may want to install the GNU Bison package:"
+      echo "<$gnu_software_URL/bison/>"
+      ;;
+    lex*|flex*)
+      echo "You should only need it if you modified a '.l' file."
+      echo "You may want to install the Fast Lexical Analyzer package:"
+      echo "<$flex_URL>"
+      ;;
+    help2man*)
+      echo "You should only need it if you modified a dependency" \
+           "of a man page."
+      echo "You may want to install the GNU Help2man package:"
+      echo "<$gnu_software_URL/help2man/>"
+    ;;
+    makeinfo*)
+      echo "You should only need it if you modified a '.texi' file, or"
+      echo "any other file indirectly affecting the aspect of the manual."
+      echo "You might want to install the Texinfo package:"
+      echo "<$gnu_software_URL/texinfo/>"
+      echo "The spurious makeinfo call might also be the consequence of"
+      echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
+      echo "want to install GNU make:"
+      echo "<$gnu_software_URL/make/>"
+      ;;
+    *)
+      echo "You might have modified some files without having the proper"
+      echo "tools for further handling them.  Check the 'README' file, it"
+      echo "often tells you about the needed prerequisites for installing"
+      echo "this package.  You may also peek at any GNU archive site, in"
+      echo "case some other package contains this missing '$1' program."
+      ;;
+  esac
+}
+
+give_advice "$1" | sed -e '1s/^/WARNING: /' \
+                       -e '2,$s/^/         /' >&2
+
+# Propagate the correct exit status (expected to be 127 for a program
+# not found, 63 for a program that failed due to version mismatch).
+exit $st
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/ntfsprogs/Android.mk b/ntfsprogs/Android.mk
new file mode 100755
index 0000000000000000000000000000000000000000..4c73531a1a971f1cfcf5ef4932330d98153a7b1e
--- /dev/null
+++ b/ntfsprogs/Android.mk
@@ -0,0 +1,47 @@
+LOCAL_PATH := $(call my-dir)
+
+#########################
+# Build the mkntfs binary
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES :=  \
+	attrdef.c \
+	boot.c \
+	sd.c \
+	mkntfs.c \
+	utils.c 
+
+LOCAL_MODULE := mkntfs
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := libntfs-3g
+
+LOCAL_C_INCLUDES :=  \
+	$(LOCAL_PATH)/../include/ntfs-3g \
+	$(LOCAL_PATH)/..
+
+LOCAL_CFLAGS := -O2 -W -Wall -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -DHAVE_CONFIG_H
+
+include $(BUILD_EXECUTABLE)
+
+#########################
+# Build the ntfsfix binary
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES :=  \
+	ntfsfix.c \
+	utils.c
+
+LOCAL_MODULE := ntfsfix
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := libntfs-3g
+
+LOCAL_C_INCLUDES :=  \
+	$(LOCAL_PATH)/../include/ntfs-3g \
+	$(LOCAL_PATH)/..
+
+LOCAL_CFLAGS := -O2 -g -W -Wall -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -DHAVE_CONFIG_H
+
+include $(BUILD_EXECUTABLE)
+
diff --git a/ntfsprogs/Makefile b/ntfsprogs/Makefile
new file mode 100755
index 0000000000000000000000000000000000000000..561f4bc0d6d8ca134a04030b2dac48cd61af2a20
--- /dev/null
+++ b/ntfsprogs/Makefile
@@ -0,0 +1,1364 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# ntfsprogs/Makefile.  Generated from Makefile.in by configure.
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/ntfs-3g
+pkgincludedir = $(includedir)/ntfs-3g
+pkglibdir = $(libdir)/ntfs-3g
+pkglibexecdir = $(libexecdir)/ntfs-3g
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = x86_64-unknown-linux-gnu
+host_triplet = x86_64-unknown-linux-gnu
+target_triplet = x86_64-unknown-linux-gnu
+bin_PROGRAMS = ntfsfix$(EXEEXT) \
+	ntfsinfo$(EXEEXT) ntfscluster$(EXEEXT) \
+	ntfsls$(EXEEXT) ntfscat$(EXEEXT) \
+	ntfscmp$(EXEEXT) $(am__EXEEXT_3) \
+	$(am__EXEEXT_5)
+sbin_PROGRAMS = mkntfs$(EXEEXT) \
+	ntfslabel$(EXEEXT) \
+	ntfsundelete$(EXEEXT) \
+	ntfsresize$(EXEEXT) ntfsclone$(EXEEXT) \
+	ntfscp$(EXEEXT)
+#am__append_1 = ntfsdecrypt
+#am__append_2 = $(EXTRA_PROGRAM_NAMES)
+##am__append_3 = $(QUARANTINED_PROGRAM_NAMES)
+EXTRA_PROGRAMS =  \
+	$(am__EXEEXT_2)
+subdir = ntfsprogs
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+	$(srcdir)/mkntfs.8.in $(srcdir)/ntfscat.8.in \
+	$(srcdir)/ntfsclone.8.in $(srcdir)/ntfscluster.8.in \
+	$(srcdir)/ntfscmp.8.in $(srcdir)/ntfscp.8.in \
+	$(srcdir)/ntfsfix.8.in $(srcdir)/ntfsinfo.8.in \
+	$(srcdir)/ntfslabel.8.in $(srcdir)/ntfsls.8.in \
+	$(srcdir)/ntfsprogs.8.in $(srcdir)/ntfsresize.8.in \
+	$(srcdir)/ntfsundelete.8.in $(srcdir)/ntfsdecrypt.8.in \
+	$(srcdir)/ntfswipe.8.in $(srcdir)/ntfstruncate.8.in \
+	$(srcdir)/ntfsfallocate.8.in $(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = mkntfs.8 ntfscat.8 ntfsclone.8 ntfscluster.8 \
+	ntfscmp.8 ntfscp.8 ntfsfix.8 ntfsinfo.8 ntfslabel.8 ntfsls.8 \
+	ntfsprogs.8 ntfsresize.8 ntfsundelete.8 ntfsdecrypt.8 \
+	ntfswipe.8 ntfstruncate.8 ntfsfallocate.8
+CONFIG_CLEAN_VPATH_FILES =
+#am__EXEEXT_1 = ntfsdecrypt$(EXEEXT)
+am__EXEEXT_2 = ntfswipe$(EXEEXT) \
+	ntfstruncate$(EXEEXT) $(am__EXEEXT_1)
+#am__EXEEXT_3 =  \
+#	$(am__EXEEXT_2)
+am__EXEEXT_4 = ntfsdump_logfile$(EXEEXT) \
+	ntfsmftalloc$(EXEEXT) ntfsmove$(EXEEXT) \
+	ntfsck$(EXEEXT) ntfsfallocate$(EXEEXT)
+##am__EXEEXT_5 = $(am__EXEEXT_4)
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" \
+	"$(DESTDIR)$(man8dir)"
+PROGRAMS = $(bin_PROGRAMS) $(sbin_PROGRAMS)
+am__mkntfs_SOURCES_DIST = attrdef.c attrdef.h boot.c boot.h sd.c sd.h \
+	mkntfs.c utils.c utils.h
+am_mkntfs_OBJECTS = mkntfs-attrdef.$(OBJEXT) \
+	mkntfs-boot.$(OBJEXT) \
+	mkntfs-sd.$(OBJEXT) \
+	mkntfs-mkntfs.$(OBJEXT) \
+	mkntfs-utils.$(OBJEXT)
+mkntfs_OBJECTS = $(am_mkntfs_OBJECTS)
+am__DEPENDENCIES_1 =
+am__DEPENDENCIES_2 =  \
+	$(top_builddir)/libntfs-3g/libntfs-3g.la
+#am__DEPENDENCIES_2 = $(top_builddir)/libntfs-3g/.libs/libntfs-3g.a \
+#	$(am__DEPENDENCIES_1)
+mkntfs_DEPENDENCIES = $(am__DEPENDENCIES_2) \
+	$(am__DEPENDENCIES_1)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+am__v_lt_1 = 
+mkntfs_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(mkntfs_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfscat_SOURCES_DIST = ntfscat.c ntfscat.h utils.c utils.h
+am_ntfscat_OBJECTS = ntfscat.$(OBJEXT) \
+	utils.$(OBJEXT)
+ntfscat_OBJECTS = $(am_ntfscat_OBJECTS)
+ntfscat_DEPENDENCIES = $(am__DEPENDENCIES_2)
+ntfscat_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfscat_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfsck_SOURCES_DIST = ntfsck.c utils.c utils.h
+am_ntfsck_OBJECTS = ntfsck.$(OBJEXT) \
+	utils.$(OBJEXT)
+ntfsck_OBJECTS = $(am_ntfsck_OBJECTS)
+ntfsck_DEPENDENCIES = $(am__DEPENDENCIES_2)
+ntfsck_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfsck_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfsclone_SOURCES_DIST = ntfsclone.c utils.c utils.h
+am_ntfsclone_OBJECTS = ntfsclone.$(OBJEXT) \
+	utils.$(OBJEXT)
+ntfsclone_OBJECTS = $(am_ntfsclone_OBJECTS)
+ntfsclone_DEPENDENCIES = $(am__DEPENDENCIES_2)
+ntfsclone_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfsclone_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfscluster_SOURCES_DIST = ntfscluster.c ntfscluster.h cluster.c \
+	cluster.h utils.c utils.h
+am_ntfscluster_OBJECTS = ntfscluster.$(OBJEXT) \
+	cluster.$(OBJEXT) utils.$(OBJEXT)
+ntfscluster_OBJECTS = $(am_ntfscluster_OBJECTS)
+ntfscluster_DEPENDENCIES =  \
+	$(am__DEPENDENCIES_2)
+ntfscluster_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfscluster_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfscmp_SOURCES_DIST = ntfscmp.c utils.c utils.h
+am_ntfscmp_OBJECTS = ntfscmp.$(OBJEXT) \
+	utils.$(OBJEXT)
+ntfscmp_OBJECTS = $(am_ntfscmp_OBJECTS)
+ntfscmp_DEPENDENCIES = $(am__DEPENDENCIES_2)
+ntfscmp_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfscmp_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfscp_SOURCES_DIST = ntfscp.c utils.c utils.h
+am_ntfscp_OBJECTS = ntfscp.$(OBJEXT) \
+	utils.$(OBJEXT)
+ntfscp_OBJECTS = $(am_ntfscp_OBJECTS)
+ntfscp_DEPENDENCIES = $(am__DEPENDENCIES_2)
+ntfscp_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfscp_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfsdecrypt_SOURCES_DIST = ntfsdecrypt.c utils.c utils.h
+#am_ntfsdecrypt_OBJECTS = ntfsdecrypt-ntfsdecrypt.$(OBJEXT) \
+#	ntfsdecrypt-utils.$(OBJEXT)
+ntfsdecrypt_OBJECTS = $(am_ntfsdecrypt_OBJECTS)
+#ntfsdecrypt_DEPENDENCIES = $(am__DEPENDENCIES_2) \
+#	$(am__DEPENDENCIES_1) \
+#	$(am__DEPENDENCIES_1)
+ntfsdecrypt_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ntfsdecrypt_CFLAGS) \
+	$(CFLAGS) $(ntfsdecrypt_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfsdump_logfile_SOURCES_DIST = ntfsdump_logfile.c
+am_ntfsdump_logfile_OBJECTS =  \
+	ntfsdump_logfile.$(OBJEXT)
+ntfsdump_logfile_OBJECTS = $(am_ntfsdump_logfile_OBJECTS)
+ntfsdump_logfile_DEPENDENCIES =  \
+	$(am__DEPENDENCIES_2)
+ntfsdump_logfile_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(AM_CFLAGS) $(CFLAGS) $(ntfsdump_logfile_LDFLAGS) $(LDFLAGS) \
+	-o $@
+am__ntfsfallocate_SOURCES_DIST = ntfsfallocate.c utils.c utils.h
+am_ntfsfallocate_OBJECTS =  \
+	ntfsfallocate.$(OBJEXT) utils.$(OBJEXT)
+ntfsfallocate_OBJECTS = $(am_ntfsfallocate_OBJECTS)
+ntfsfallocate_DEPENDENCIES =  \
+	$(am__DEPENDENCIES_2)
+ntfsfallocate_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfsfallocate_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfsfix_SOURCES_DIST = ntfsfix.c utils.c utils.h
+am_ntfsfix_OBJECTS = ntfsfix.$(OBJEXT) \
+	utils.$(OBJEXT)
+ntfsfix_OBJECTS = $(am_ntfsfix_OBJECTS)
+ntfsfix_DEPENDENCIES = $(am__DEPENDENCIES_2)
+ntfsfix_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfsfix_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfsinfo_SOURCES_DIST = ntfsinfo.c utils.c utils.h
+am_ntfsinfo_OBJECTS = ntfsinfo.$(OBJEXT) \
+	utils.$(OBJEXT)
+ntfsinfo_OBJECTS = $(am_ntfsinfo_OBJECTS)
+ntfsinfo_DEPENDENCIES = $(am__DEPENDENCIES_2)
+ntfsinfo_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfsinfo_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfslabel_SOURCES_DIST = ntfslabel.c utils.c utils.h
+am_ntfslabel_OBJECTS = ntfslabel.$(OBJEXT) \
+	utils.$(OBJEXT)
+ntfslabel_OBJECTS = $(am_ntfslabel_OBJECTS)
+ntfslabel_DEPENDENCIES = $(am__DEPENDENCIES_2)
+ntfslabel_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfslabel_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfsls_SOURCES_DIST = ntfsls.c utils.c utils.h list.h
+am_ntfsls_OBJECTS = ntfsls.$(OBJEXT) \
+	utils.$(OBJEXT)
+ntfsls_OBJECTS = $(am_ntfsls_OBJECTS)
+ntfsls_DEPENDENCIES = $(am__DEPENDENCIES_2)
+ntfsls_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfsls_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfsmftalloc_SOURCES_DIST = ntfsmftalloc.c utils.c utils.h
+am_ntfsmftalloc_OBJECTS =  \
+	ntfsmftalloc.$(OBJEXT) utils.$(OBJEXT)
+ntfsmftalloc_OBJECTS = $(am_ntfsmftalloc_OBJECTS)
+ntfsmftalloc_DEPENDENCIES =  \
+	$(am__DEPENDENCIES_2)
+ntfsmftalloc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfsmftalloc_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfsmove_SOURCES_DIST = ntfsmove.c ntfsmove.h utils.c utils.h
+am_ntfsmove_OBJECTS = ntfsmove.$(OBJEXT) \
+	utils.$(OBJEXT)
+ntfsmove_OBJECTS = $(am_ntfsmove_OBJECTS)
+ntfsmove_DEPENDENCIES = $(am__DEPENDENCIES_2)
+ntfsmove_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfsmove_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfsresize_SOURCES_DIST = ntfsresize.c utils.c utils.h
+am_ntfsresize_OBJECTS = ntfsresize.$(OBJEXT) \
+	utils.$(OBJEXT)
+ntfsresize_OBJECTS = $(am_ntfsresize_OBJECTS)
+ntfsresize_DEPENDENCIES =  \
+	$(am__DEPENDENCIES_2)
+ntfsresize_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfsresize_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfstruncate_SOURCES_DIST = attrdef.c ntfstruncate.c utils.c \
+	utils.h
+am_ntfstruncate_OBJECTS = attrdef.$(OBJEXT) \
+	ntfstruncate.$(OBJEXT) utils.$(OBJEXT)
+ntfstruncate_OBJECTS = $(am_ntfstruncate_OBJECTS)
+ntfstruncate_DEPENDENCIES =  \
+	$(am__DEPENDENCIES_2)
+ntfstruncate_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfstruncate_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfsundelete_SOURCES_DIST = ntfsundelete.c ntfsundelete.h utils.c \
+	utils.h list.h
+am_ntfsundelete_OBJECTS =  \
+	ntfsundelete.$(OBJEXT) utils.$(OBJEXT)
+ntfsundelete_OBJECTS = $(am_ntfsundelete_OBJECTS)
+ntfsundelete_DEPENDENCIES =  \
+	$(am__DEPENDENCIES_2)
+ntfsundelete_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfsundelete_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfswipe_SOURCES_DIST = ntfswipe.c ntfswipe.h utils.c utils.h
+am_ntfswipe_OBJECTS = ntfswipe.$(OBJEXT) \
+	utils.$(OBJEXT)
+ntfswipe_OBJECTS = $(am_ntfswipe_OBJECTS)
+ntfswipe_DEPENDENCIES = $(am__DEPENDENCIES_2)
+ntfswipe_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfswipe_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_$(V))
+am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY))
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+am__v_at_1 = 
+DEFAULT_INCLUDES = -I. -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
+CCLD = $(CC)
+AM_V_CCLD = $(am__v_CCLD_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
+SOURCES = $(mkntfs_SOURCES) $(ntfscat_SOURCES) $(ntfsck_SOURCES) \
+	$(ntfsclone_SOURCES) $(ntfscluster_SOURCES) $(ntfscmp_SOURCES) \
+	$(ntfscp_SOURCES) $(ntfsdecrypt_SOURCES) \
+	$(ntfsdump_logfile_SOURCES) $(ntfsfallocate_SOURCES) \
+	$(ntfsfix_SOURCES) $(ntfsinfo_SOURCES) $(ntfslabel_SOURCES) \
+	$(ntfsls_SOURCES) $(ntfsmftalloc_SOURCES) $(ntfsmove_SOURCES) \
+	$(ntfsresize_SOURCES) $(ntfstruncate_SOURCES) \
+	$(ntfsundelete_SOURCES) $(ntfswipe_SOURCES)
+DIST_SOURCES = $(am__mkntfs_SOURCES_DIST) $(am__ntfscat_SOURCES_DIST) \
+	$(am__ntfsck_SOURCES_DIST) $(am__ntfsclone_SOURCES_DIST) \
+	$(am__ntfscluster_SOURCES_DIST) $(am__ntfscmp_SOURCES_DIST) \
+	$(am__ntfscp_SOURCES_DIST) $(am__ntfsdecrypt_SOURCES_DIST) \
+	$(am__ntfsdump_logfile_SOURCES_DIST) \
+	$(am__ntfsfallocate_SOURCES_DIST) $(am__ntfsfix_SOURCES_DIST) \
+	$(am__ntfsinfo_SOURCES_DIST) $(am__ntfslabel_SOURCES_DIST) \
+	$(am__ntfsls_SOURCES_DIST) $(am__ntfsmftalloc_SOURCES_DIST) \
+	$(am__ntfsmove_SOURCES_DIST) $(am__ntfsresize_SOURCES_DIST) \
+	$(am__ntfstruncate_SOURCES_DIST) \
+	$(am__ntfsundelete_SOURCES_DIST) $(am__ntfswipe_SOURCES_DIST)
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+man8dir = $(mandir)/man8
+NROFF = nroff
+MANS = $(man_MANS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = ${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing aclocal-1.14
+AMTAR = $${TAR-tar}
+AM_DEFAULT_VERBOSITY = 1
+AR = ar
+AUTOCONF = ${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing autoconf
+AUTOHEADER = ${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing autoheader
+AUTOMAKE = ${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing automake-1.14
+AWK = gawk
+CC = gcc
+CCDEPMODE = depmode=gcc3
+CFLAGS = -g -O2 -Wall
+CPP = gcc -E
+CPPFLAGS = 
+CYGPATH_W = echo
+DEFS = -DHAVE_CONFIG_H
+DEPDIR = .deps
+DLLTOOL = false
+DSYMUTIL = 
+DUMPBIN = 
+ECHO_C = 
+ECHO_N = -n
+ECHO_T = 
+EGREP = /bin/grep -E
+EXEEXT = 
+FGREP = /bin/grep -F
+FUSE_MODULE_CFLAGS = 
+FUSE_MODULE_LIBS = 
+GNUTLS_CFLAGS = 
+GNUTLS_LIBS = 
+GREP = /bin/grep
+INSTALL = /usr/bin/install -c
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
+LD = /usr/bin/ld -m elf_x86_64
+LDCONFIG = /sbin/ldconfig
+LDFLAGS = 
+LIBFUSE_LITE_CFLAGS = 
+LIBFUSE_LITE_LIBS =  -lpthread
+LIBGCRYPT_CFLAGS = 
+LIBGCRYPT_CONFIG = 
+LIBGCRYPT_LIBS = 
+LIBNTFS_3G_VERSION = 86
+LIBNTFS_CPPFLAGS = 
+LIBNTFS_LIBS = 
+LIBOBJS = 
+LIBS = 
+LIBTOOL = $(SHELL) $(top_builddir)/libtool
+LIPO = 
+LN_S = ln -s
+LTLIBOBJS = 
+MAINT = #
+MAKEINFO = ${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/missing makeinfo
+MANIFEST_TOOL = :
+MKDIR_P = /bin/mkdir -p
+MKNTFS_CPPFLAGS = 
+MKNTFS_LIBS = 
+MV = /bin/mv
+NM = /usr/bin/nm -B
+NMEDIT = 
+NTFSPROGS_STATIC_LIBS = 
+OBJDUMP = objdump
+OBJEXT = o
+OTOOL = 
+OTOOL64 = 
+OUTPUT_FORMAT = 
+PACKAGE = ntfs-3g
+PACKAGE_BUGREPORT = ntfs-3g-devel@lists.sf.net
+PACKAGE_NAME = ntfs-3g
+PACKAGE_STRING = ntfs-3g 2015.3.14
+PACKAGE_TARNAME = ntfs-3g
+PACKAGE_URL = 
+PACKAGE_VERSION = 2015.3.14
+PATH_SEPARATOR = :
+PKG_CONFIG = /usr/bin/pkg-config
+PKG_CONFIG_LIBDIR = 
+PKG_CONFIG_PATH = 
+RANLIB = ranlib
+RM = /bin/rm
+SED = /bin/sed
+SET_MAKE = 
+SHELL = /bin/bash
+STRIP = strip
+VERSION = 2015.3.14
+abs_builddir = /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/ntfsprogs
+abs_srcdir = /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/ntfsprogs
+abs_top_builddir = /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14
+abs_top_srcdir = /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14
+ac_ct_AR = ar
+ac_ct_CC = gcc
+ac_ct_DUMPBIN = 
+all_includes =  
+all_libraries =  
+am__include = include
+am__leading_dot = .
+am__quote = 
+am__tar = $${TAR-tar} chof - "$$tardir"
+am__untar = $${TAR-tar} xf -
+bindir = ${exec_prefix}/bin
+build = x86_64-unknown-linux-gnu
+build_alias = 
+build_cpu = x86_64
+build_os = linux-gnu
+build_vendor = unknown
+builddir = .
+datadir = ${datarootdir}
+datarootdir = ${prefix}/share
+docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
+dvidir = ${docdir}
+exec_prefix = ${prefix}
+host = x86_64-unknown-linux-gnu
+host_alias = 
+host_cpu = x86_64
+host_os = linux-gnu
+host_vendor = unknown
+htmldir = ${docdir}
+includedir = ${prefix}/include
+infodir = ${datarootdir}/info
+install_sh = ${SHELL} /home/cmc/share/rockchip/llolipop_flash/external/ntfs-3g_ntfsprogs-2015.3.14/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localedir = ${datarootdir}/locale
+localstatedir = ${prefix}/var
+mandir = ${datarootdir}/man
+mkdir_p = $(MKDIR_P)
+ntfs3gincludedir = $(includedir)/ntfs-3g
+oldincludedir = /usr/include
+pdfdir = ${docdir}
+pkgconfigdir = $(libdir)/pkgconfig
+prefix = /usr/local
+program_transform_name = s,x,x,
+psdir = ${docdir}
+rootbindir = /bin
+rootlibdir = /lib
+rootsbindir = /sbin
+sbindir = ${exec_prefix}/sbin
+sharedstatedir = ${prefix}/com
+srcdir = .
+sysconfdir = ${prefix}/etc
+target = x86_64-unknown-linux-gnu
+target_alias = 
+target_cpu = x86_64
+target_os = linux-gnu
+target_vendor = unknown
+top_build_prefix = ../
+top_builddir = ..
+top_srcdir = ..
+AM_LIBS = $(top_builddir)/libntfs-3g/libntfs-3g.la
+#AM_LIBS = $(top_builddir)/libntfs-3g/.libs/libntfs-3g.a $(NTFSPROGS_STATIC_LIBS)
+AM_LFLAGS = $(all_libraries)
+# older builds may need -static instead of newer -all-static
+#AM_LFLAGS = -static
+#STATIC_LINK = $(CC) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+LIBTOOL_LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+
+# Workaround to make REALLYSTATIC work with automake 1.5.
+LINK = $(STATIC_LINK) $(LIBTOOL_LINK)
+EXTRA_PROGRAM_NAMES = ntfswipe ntfstruncate \
+	$(am__append_1)
+QUARANTINED_PROGRAM_NAMES = ntfsdump_logfile ntfsmftalloc ntfsmove ntfsck \
+			   ntfsfallocate
+
+man_MANS = mkntfs.8 ntfsfix.8 ntfslabel.8 ntfsinfo.8 \
+			  ntfsundelete.8 ntfsresize.8 ntfsprogs.8 ntfsls.8 \
+			  ntfsclone.8 ntfscluster.8 ntfscat.8 ntfscp.8 \
+			  ntfscmp.8 ntfswipe.8 ntfstruncate.8 \
+			  ntfsdecrypt.8 ntfsfallocate.8
+
+EXTRA_MANS = 
+CLEANFILES = $(EXTRA_PROGRAMS)
+MAINTAINERCLEANFILES = Makefile.in
+
+# Set the include path.
+AM_CPPFLAGS = -I$(top_srcdir)/include/ntfs-3g $(all_includes)
+ntfsfix_SOURCES = ntfsfix.c utils.c utils.h
+ntfsfix_LDADD = $(AM_LIBS)
+ntfsfix_LDFLAGS = $(AM_LFLAGS)
+mkntfs_CPPFLAGS = $(AM_CPPFLAGS) $(MKNTFS_CPPFLAGS)
+mkntfs_SOURCES = attrdef.c attrdef.h boot.c boot.h sd.c sd.h mkntfs.c utils.c utils.h
+mkntfs_LDADD = $(AM_LIBS) $(MKNTFS_LIBS)
+mkntfs_LDFLAGS = $(AM_LFLAGS)
+ntfslabel_SOURCES = ntfslabel.c utils.c utils.h
+ntfslabel_LDADD = $(AM_LIBS)
+ntfslabel_LDFLAGS = $(AM_LFLAGS)
+ntfsinfo_SOURCES = ntfsinfo.c utils.c utils.h
+ntfsinfo_LDADD = $(AM_LIBS)
+ntfsinfo_LDFLAGS = $(AM_LFLAGS)
+ntfsundelete_SOURCES = ntfsundelete.c ntfsundelete.h utils.c utils.h list.h
+ntfsundelete_LDADD = $(AM_LIBS)
+ntfsundelete_LDFLAGS = $(AM_LFLAGS)
+ntfsresize_SOURCES = ntfsresize.c utils.c utils.h
+ntfsresize_LDADD = $(AM_LIBS)
+ntfsresize_LDFLAGS = $(AM_LFLAGS)
+ntfsclone_SOURCES = ntfsclone.c utils.c utils.h
+ntfsclone_LDADD = $(AM_LIBS)
+ntfsclone_LDFLAGS = $(AM_LFLAGS)
+ntfscluster_SOURCES = ntfscluster.c ntfscluster.h cluster.c cluster.h utils.c utils.h
+ntfscluster_LDADD = $(AM_LIBS)
+ntfscluster_LDFLAGS = $(AM_LFLAGS)
+ntfsls_SOURCES = ntfsls.c utils.c utils.h list.h
+ntfsls_LDADD = $(AM_LIBS)
+ntfsls_LDFLAGS = $(AM_LFLAGS)
+ntfscat_SOURCES = ntfscat.c ntfscat.h utils.c utils.h
+ntfscat_LDADD = $(AM_LIBS)
+ntfscat_LDFLAGS = $(AM_LFLAGS)
+ntfscp_SOURCES = ntfscp.c utils.c utils.h
+ntfscp_LDADD = $(AM_LIBS)
+ntfscp_LDFLAGS = $(AM_LFLAGS)
+ntfsck_SOURCES = ntfsck.c utils.c utils.h
+ntfsck_LDADD = $(AM_LIBS)
+ntfsck_LDFLAGS = $(AM_LFLAGS)
+ntfscmp_SOURCES = ntfscmp.c utils.c utils.h
+ntfscmp_LDADD = $(AM_LIBS)
+ntfscmp_LDFLAGS = $(AM_LFLAGS)
+
+# We don't distribute these
+ntfstruncate_SOURCES = attrdef.c ntfstruncate.c utils.c utils.h
+ntfstruncate_LDADD = $(AM_LIBS)
+ntfstruncate_LDFLAGS = $(AM_LFLAGS)
+ntfsmftalloc_SOURCES = ntfsmftalloc.c utils.c utils.h
+ntfsmftalloc_LDADD = $(AM_LIBS)
+ntfsmftalloc_LDFLAGS = $(AM_LFLAGS)
+ntfsmove_SOURCES = ntfsmove.c ntfsmove.h utils.c utils.h
+ntfsmove_LDADD = $(AM_LIBS)
+ntfsmove_LDFLAGS = $(AM_LFLAGS)
+ntfswipe_SOURCES = ntfswipe.c ntfswipe.h utils.c utils.h
+ntfswipe_LDADD = $(AM_LIBS)
+ntfswipe_LDFLAGS = $(AM_LFLAGS)
+ntfsdump_logfile_SOURCES = ntfsdump_logfile.c
+ntfsdump_logfile_LDADD = $(AM_LIBS)
+ntfsdump_logfile_LDFLAGS = $(AM_LFLAGS)
+ntfsfallocate_SOURCES = ntfsfallocate.c utils.c utils.h
+ntfsfallocate_LDADD = $(AM_LIBS)
+ntfsfallocate_LDFLAGS = $(AM_LFLAGS)
+#ntfsdecrypt_SOURCES = ntfsdecrypt.c utils.c utils.h
+#ntfsdecrypt_LDADD = $(AM_LIBS) $(GNUTLS_LIBS) $(LIBGCRYPT_LIBS)
+#ntfsdecrypt_LDFLAGS = $(AM_LFLAGS)
+#ntfsdecrypt_CFLAGS = $(GNUTLS_CFLAGS) $(LIBGCRYPT_CFLAGS)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: # $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu ntfsprogs/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu ntfsprogs/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: # $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): # $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+mkntfs.8: $(top_builddir)/config.status $(srcdir)/mkntfs.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfscat.8: $(top_builddir)/config.status $(srcdir)/ntfscat.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfsclone.8: $(top_builddir)/config.status $(srcdir)/ntfsclone.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfscluster.8: $(top_builddir)/config.status $(srcdir)/ntfscluster.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfscmp.8: $(top_builddir)/config.status $(srcdir)/ntfscmp.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfscp.8: $(top_builddir)/config.status $(srcdir)/ntfscp.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfsfix.8: $(top_builddir)/config.status $(srcdir)/ntfsfix.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfsinfo.8: $(top_builddir)/config.status $(srcdir)/ntfsinfo.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfslabel.8: $(top_builddir)/config.status $(srcdir)/ntfslabel.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfsls.8: $(top_builddir)/config.status $(srcdir)/ntfsls.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfsprogs.8: $(top_builddir)/config.status $(srcdir)/ntfsprogs.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfsresize.8: $(top_builddir)/config.status $(srcdir)/ntfsresize.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfsundelete.8: $(top_builddir)/config.status $(srcdir)/ntfsundelete.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfsdecrypt.8: $(top_builddir)/config.status $(srcdir)/ntfsdecrypt.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfswipe.8: $(top_builddir)/config.status $(srcdir)/ntfswipe.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfstruncate.8: $(top_builddir)/config.status $(srcdir)/ntfstruncate.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfsfallocate.8: $(top_builddir)/config.status $(srcdir)/ntfsfallocate.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+	fi; \
+	for p in $$list; do echo "$$p $$p"; done | \
+	sed 's/$(EXEEXT)$$//' | \
+	while read p p1; do if test -f $$p \
+	 || test -f $$p1 \
+	  ; then echo "$$p"; echo "$$p"; else :; fi; \
+	done | \
+	sed -e 'p;s,.*/,,;n;h' \
+	    -e 's|.*|.|' \
+	    -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+	sed 'N;N;N;s,\n, ,g' | \
+	$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+	  { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+	    if ($$2 == $$4) files[d] = files[d] " " $$1; \
+	    else { print "f", $$3 "/" $$4, $$1; } } \
+	  END { for (d in files) print "f", d, files[d] }' | \
+	while read type dir files; do \
+	    if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+	    test -z "$$files" || { \
+	    echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+	    $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+	    } \
+	; done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+	files=`for p in $$list; do echo "$$p"; done | \
+	  sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+	      -e 's/$$/$(EXEEXT)/' \
+	`; \
+	test -n "$$list" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+	@list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
+	echo " rm -f" $$list; \
+	rm -f $$list || exit $$?; \
+	test -n "$(EXEEXT)" || exit 0; \
+	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+	echo " rm -f" $$list; \
+	rm -f $$list
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
+	fi; \
+	for p in $$list; do echo "$$p $$p"; done | \
+	sed 's/$(EXEEXT)$$//' | \
+	while read p p1; do if test -f $$p \
+	 || test -f $$p1 \
+	  ; then echo "$$p"; echo "$$p"; else :; fi; \
+	done | \
+	sed -e 'p;s,.*/,,;n;h' \
+	    -e 's|.*|.|' \
+	    -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+	sed 'N;N;N;s,\n, ,g' | \
+	$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+	  { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+	    if ($$2 == $$4) files[d] = files[d] " " $$1; \
+	    else { print "f", $$3 "/" $$4, $$1; } } \
+	  END { for (d in files) print "f", d, files[d] }' | \
+	while read type dir files; do \
+	    if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+	    test -z "$$files" || { \
+	    echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
+	    $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
+	    } \
+	; done
+
+uninstall-sbinPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+	files=`for p in $$list; do echo "$$p"; done | \
+	  sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+	      -e 's/$$/$(EXEEXT)/' \
+	`; \
+	test -n "$$list" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(sbindir)" && rm -f $$files
+
+clean-sbinPROGRAMS:
+	@list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \
+	echo " rm -f" $$list; \
+	rm -f $$list || exit $$?; \
+	test -n "$(EXEEXT)" || exit 0; \
+	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+	echo " rm -f" $$list; \
+	rm -f $$list
+
+mkntfs$(EXEEXT): $(mkntfs_OBJECTS) $(mkntfs_DEPENDENCIES) $(EXTRA_mkntfs_DEPENDENCIES) 
+	@rm -f mkntfs$(EXEEXT)
+	$(AM_V_CCLD)$(mkntfs_LINK) $(mkntfs_OBJECTS) $(mkntfs_LDADD) $(LIBS)
+
+ntfscat$(EXEEXT): $(ntfscat_OBJECTS) $(ntfscat_DEPENDENCIES) $(EXTRA_ntfscat_DEPENDENCIES) 
+	@rm -f ntfscat$(EXEEXT)
+	$(AM_V_CCLD)$(ntfscat_LINK) $(ntfscat_OBJECTS) $(ntfscat_LDADD) $(LIBS)
+
+ntfsck$(EXEEXT): $(ntfsck_OBJECTS) $(ntfsck_DEPENDENCIES) $(EXTRA_ntfsck_DEPENDENCIES) 
+	@rm -f ntfsck$(EXEEXT)
+	$(AM_V_CCLD)$(ntfsck_LINK) $(ntfsck_OBJECTS) $(ntfsck_LDADD) $(LIBS)
+
+ntfsclone$(EXEEXT): $(ntfsclone_OBJECTS) $(ntfsclone_DEPENDENCIES) $(EXTRA_ntfsclone_DEPENDENCIES) 
+	@rm -f ntfsclone$(EXEEXT)
+	$(AM_V_CCLD)$(ntfsclone_LINK) $(ntfsclone_OBJECTS) $(ntfsclone_LDADD) $(LIBS)
+
+ntfscluster$(EXEEXT): $(ntfscluster_OBJECTS) $(ntfscluster_DEPENDENCIES) $(EXTRA_ntfscluster_DEPENDENCIES) 
+	@rm -f ntfscluster$(EXEEXT)
+	$(AM_V_CCLD)$(ntfscluster_LINK) $(ntfscluster_OBJECTS) $(ntfscluster_LDADD) $(LIBS)
+
+ntfscmp$(EXEEXT): $(ntfscmp_OBJECTS) $(ntfscmp_DEPENDENCIES) $(EXTRA_ntfscmp_DEPENDENCIES) 
+	@rm -f ntfscmp$(EXEEXT)
+	$(AM_V_CCLD)$(ntfscmp_LINK) $(ntfscmp_OBJECTS) $(ntfscmp_LDADD) $(LIBS)
+
+ntfscp$(EXEEXT): $(ntfscp_OBJECTS) $(ntfscp_DEPENDENCIES) $(EXTRA_ntfscp_DEPENDENCIES) 
+	@rm -f ntfscp$(EXEEXT)
+	$(AM_V_CCLD)$(ntfscp_LINK) $(ntfscp_OBJECTS) $(ntfscp_LDADD) $(LIBS)
+
+ntfsdecrypt$(EXEEXT): $(ntfsdecrypt_OBJECTS) $(ntfsdecrypt_DEPENDENCIES) $(EXTRA_ntfsdecrypt_DEPENDENCIES) 
+	@rm -f ntfsdecrypt$(EXEEXT)
+	$(AM_V_CCLD)$(ntfsdecrypt_LINK) $(ntfsdecrypt_OBJECTS) $(ntfsdecrypt_LDADD) $(LIBS)
+
+ntfsdump_logfile$(EXEEXT): $(ntfsdump_logfile_OBJECTS) $(ntfsdump_logfile_DEPENDENCIES) $(EXTRA_ntfsdump_logfile_DEPENDENCIES) 
+	@rm -f ntfsdump_logfile$(EXEEXT)
+	$(AM_V_CCLD)$(ntfsdump_logfile_LINK) $(ntfsdump_logfile_OBJECTS) $(ntfsdump_logfile_LDADD) $(LIBS)
+
+ntfsfallocate$(EXEEXT): $(ntfsfallocate_OBJECTS) $(ntfsfallocate_DEPENDENCIES) $(EXTRA_ntfsfallocate_DEPENDENCIES) 
+	@rm -f ntfsfallocate$(EXEEXT)
+	$(AM_V_CCLD)$(ntfsfallocate_LINK) $(ntfsfallocate_OBJECTS) $(ntfsfallocate_LDADD) $(LIBS)
+
+ntfsfix$(EXEEXT): $(ntfsfix_OBJECTS) $(ntfsfix_DEPENDENCIES) $(EXTRA_ntfsfix_DEPENDENCIES) 
+	@rm -f ntfsfix$(EXEEXT)
+	$(AM_V_CCLD)$(ntfsfix_LINK) $(ntfsfix_OBJECTS) $(ntfsfix_LDADD) $(LIBS)
+
+ntfsinfo$(EXEEXT): $(ntfsinfo_OBJECTS) $(ntfsinfo_DEPENDENCIES) $(EXTRA_ntfsinfo_DEPENDENCIES) 
+	@rm -f ntfsinfo$(EXEEXT)
+	$(AM_V_CCLD)$(ntfsinfo_LINK) $(ntfsinfo_OBJECTS) $(ntfsinfo_LDADD) $(LIBS)
+
+ntfslabel$(EXEEXT): $(ntfslabel_OBJECTS) $(ntfslabel_DEPENDENCIES) $(EXTRA_ntfslabel_DEPENDENCIES) 
+	@rm -f ntfslabel$(EXEEXT)
+	$(AM_V_CCLD)$(ntfslabel_LINK) $(ntfslabel_OBJECTS) $(ntfslabel_LDADD) $(LIBS)
+
+ntfsls$(EXEEXT): $(ntfsls_OBJECTS) $(ntfsls_DEPENDENCIES) $(EXTRA_ntfsls_DEPENDENCIES) 
+	@rm -f ntfsls$(EXEEXT)
+	$(AM_V_CCLD)$(ntfsls_LINK) $(ntfsls_OBJECTS) $(ntfsls_LDADD) $(LIBS)
+
+ntfsmftalloc$(EXEEXT): $(ntfsmftalloc_OBJECTS) $(ntfsmftalloc_DEPENDENCIES) $(EXTRA_ntfsmftalloc_DEPENDENCIES) 
+	@rm -f ntfsmftalloc$(EXEEXT)
+	$(AM_V_CCLD)$(ntfsmftalloc_LINK) $(ntfsmftalloc_OBJECTS) $(ntfsmftalloc_LDADD) $(LIBS)
+
+ntfsmove$(EXEEXT): $(ntfsmove_OBJECTS) $(ntfsmove_DEPENDENCIES) $(EXTRA_ntfsmove_DEPENDENCIES) 
+	@rm -f ntfsmove$(EXEEXT)
+	$(AM_V_CCLD)$(ntfsmove_LINK) $(ntfsmove_OBJECTS) $(ntfsmove_LDADD) $(LIBS)
+
+ntfsresize$(EXEEXT): $(ntfsresize_OBJECTS) $(ntfsresize_DEPENDENCIES) $(EXTRA_ntfsresize_DEPENDENCIES) 
+	@rm -f ntfsresize$(EXEEXT)
+	$(AM_V_CCLD)$(ntfsresize_LINK) $(ntfsresize_OBJECTS) $(ntfsresize_LDADD) $(LIBS)
+
+ntfstruncate$(EXEEXT): $(ntfstruncate_OBJECTS) $(ntfstruncate_DEPENDENCIES) $(EXTRA_ntfstruncate_DEPENDENCIES) 
+	@rm -f ntfstruncate$(EXEEXT)
+	$(AM_V_CCLD)$(ntfstruncate_LINK) $(ntfstruncate_OBJECTS) $(ntfstruncate_LDADD) $(LIBS)
+
+ntfsundelete$(EXEEXT): $(ntfsundelete_OBJECTS) $(ntfsundelete_DEPENDENCIES) $(EXTRA_ntfsundelete_DEPENDENCIES) 
+	@rm -f ntfsundelete$(EXEEXT)
+	$(AM_V_CCLD)$(ntfsundelete_LINK) $(ntfsundelete_OBJECTS) $(ntfsundelete_LDADD) $(LIBS)
+
+ntfswipe$(EXEEXT): $(ntfswipe_OBJECTS) $(ntfswipe_DEPENDENCIES) $(EXTRA_ntfswipe_DEPENDENCIES) 
+	@rm -f ntfswipe$(EXEEXT)
+	$(AM_V_CCLD)$(ntfswipe_LINK) $(ntfswipe_OBJECTS) $(ntfswipe_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+include ./$(DEPDIR)/attrdef.Po
+include ./$(DEPDIR)/cluster.Po
+include ./$(DEPDIR)/mkntfs-attrdef.Po
+include ./$(DEPDIR)/mkntfs-boot.Po
+include ./$(DEPDIR)/mkntfs-mkntfs.Po
+include ./$(DEPDIR)/mkntfs-sd.Po
+include ./$(DEPDIR)/mkntfs-utils.Po
+include ./$(DEPDIR)/ntfscat.Po
+include ./$(DEPDIR)/ntfsck.Po
+include ./$(DEPDIR)/ntfsclone.Po
+include ./$(DEPDIR)/ntfscluster.Po
+include ./$(DEPDIR)/ntfscmp.Po
+include ./$(DEPDIR)/ntfscp.Po
+include ./$(DEPDIR)/ntfsdecrypt-ntfsdecrypt.Po
+include ./$(DEPDIR)/ntfsdecrypt-utils.Po
+include ./$(DEPDIR)/ntfsdump_logfile.Po
+include ./$(DEPDIR)/ntfsfallocate.Po
+include ./$(DEPDIR)/ntfsfix.Po
+include ./$(DEPDIR)/ntfsinfo.Po
+include ./$(DEPDIR)/ntfslabel.Po
+include ./$(DEPDIR)/ntfsls.Po
+include ./$(DEPDIR)/ntfsmftalloc.Po
+include ./$(DEPDIR)/ntfsmove.Po
+include ./$(DEPDIR)/ntfsresize.Po
+include ./$(DEPDIR)/ntfstruncate.Po
+include ./$(DEPDIR)/ntfsundelete.Po
+include ./$(DEPDIR)/ntfswipe.Po
+include ./$(DEPDIR)/utils.Po
+
+.c.o:
+	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+#	$(AM_V_CC)source='$<' object='$@' libtool=no \
+#	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+#	$(AM_V_CC_no)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+#	$(AM_V_CC)source='$<' object='$@' libtool=no \
+#	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+#	$(AM_V_CC_no)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+	$(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+#	$(AM_V_CC)source='$<' object='$@' libtool=yes \
+#	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+#	$(AM_V_CC_no)$(LTCOMPILE) -c -o $@ $<
+
+mkntfs-attrdef.o: attrdef.c
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mkntfs-attrdef.o -MD -MP -MF $(DEPDIR)/mkntfs-attrdef.Tpo -c -o mkntfs-attrdef.o `test -f 'attrdef.c' || echo '$(srcdir)/'`attrdef.c
+	$(AM_V_at)$(am__mv) $(DEPDIR)/mkntfs-attrdef.Tpo $(DEPDIR)/mkntfs-attrdef.Po
+#	$(AM_V_CC)source='attrdef.c' object='mkntfs-attrdef.o' libtool=no \
+#	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+#	$(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mkntfs-attrdef.o `test -f 'attrdef.c' || echo '$(srcdir)/'`attrdef.c
+
+mkntfs-attrdef.obj: attrdef.c
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mkntfs-attrdef.obj -MD -MP -MF $(DEPDIR)/mkntfs-attrdef.Tpo -c -o mkntfs-attrdef.obj `if test -f 'attrdef.c'; then $(CYGPATH_W) 'attrdef.c'; else $(CYGPATH_W) '$(srcdir)/attrdef.c'; fi`
+	$(AM_V_at)$(am__mv) $(DEPDIR)/mkntfs-attrdef.Tpo $(DEPDIR)/mkntfs-attrdef.Po
+#	$(AM_V_CC)source='attrdef.c' object='mkntfs-attrdef.obj' libtool=no \
+#	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+#	$(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mkntfs-attrdef.obj `if test -f 'attrdef.c'; then $(CYGPATH_W) 'attrdef.c'; else $(CYGPATH_W) '$(srcdir)/attrdef.c'; fi`
+
+mkntfs-boot.o: boot.c
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mkntfs-boot.o -MD -MP -MF $(DEPDIR)/mkntfs-boot.Tpo -c -o mkntfs-boot.o `test -f 'boot.c' || echo '$(srcdir)/'`boot.c
+	$(AM_V_at)$(am__mv) $(DEPDIR)/mkntfs-boot.Tpo $(DEPDIR)/mkntfs-boot.Po
+#	$(AM_V_CC)source='boot.c' object='mkntfs-boot.o' libtool=no \
+#	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+#	$(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mkntfs-boot.o `test -f 'boot.c' || echo '$(srcdir)/'`boot.c
+
+mkntfs-boot.obj: boot.c
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mkntfs-boot.obj -MD -MP -MF $(DEPDIR)/mkntfs-boot.Tpo -c -o mkntfs-boot.obj `if test -f 'boot.c'; then $(CYGPATH_W) 'boot.c'; else $(CYGPATH_W) '$(srcdir)/boot.c'; fi`
+	$(AM_V_at)$(am__mv) $(DEPDIR)/mkntfs-boot.Tpo $(DEPDIR)/mkntfs-boot.Po
+#	$(AM_V_CC)source='boot.c' object='mkntfs-boot.obj' libtool=no \
+#	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+#	$(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mkntfs-boot.obj `if test -f 'boot.c'; then $(CYGPATH_W) 'boot.c'; else $(CYGPATH_W) '$(srcdir)/boot.c'; fi`
+
+mkntfs-sd.o: sd.c
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mkntfs-sd.o -MD -MP -MF $(DEPDIR)/mkntfs-sd.Tpo -c -o mkntfs-sd.o `test -f 'sd.c' || echo '$(srcdir)/'`sd.c
+	$(AM_V_at)$(am__mv) $(DEPDIR)/mkntfs-sd.Tpo $(DEPDIR)/mkntfs-sd.Po
+#	$(AM_V_CC)source='sd.c' object='mkntfs-sd.o' libtool=no \
+#	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+#	$(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mkntfs-sd.o `test -f 'sd.c' || echo '$(srcdir)/'`sd.c
+
+mkntfs-sd.obj: sd.c
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mkntfs-sd.obj -MD -MP -MF $(DEPDIR)/mkntfs-sd.Tpo -c -o mkntfs-sd.obj `if test -f 'sd.c'; then $(CYGPATH_W) 'sd.c'; else $(CYGPATH_W) '$(srcdir)/sd.c'; fi`
+	$(AM_V_at)$(am__mv) $(DEPDIR)/mkntfs-sd.Tpo $(DEPDIR)/mkntfs-sd.Po
+#	$(AM_V_CC)source='sd.c' object='mkntfs-sd.obj' libtool=no \
+#	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+#	$(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mkntfs-sd.obj `if test -f 'sd.c'; then $(CYGPATH_W) 'sd.c'; else $(CYGPATH_W) '$(srcdir)/sd.c'; fi`
+
+mkntfs-mkntfs.o: mkntfs.c
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mkntfs-mkntfs.o -MD -MP -MF $(DEPDIR)/mkntfs-mkntfs.Tpo -c -o mkntfs-mkntfs.o `test -f 'mkntfs.c' || echo '$(srcdir)/'`mkntfs.c
+	$(AM_V_at)$(am__mv) $(DEPDIR)/mkntfs-mkntfs.Tpo $(DEPDIR)/mkntfs-mkntfs.Po
+#	$(AM_V_CC)source='mkntfs.c' object='mkntfs-mkntfs.o' libtool=no \
+#	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+#	$(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mkntfs-mkntfs.o `test -f 'mkntfs.c' || echo '$(srcdir)/'`mkntfs.c
+
+mkntfs-mkntfs.obj: mkntfs.c
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mkntfs-mkntfs.obj -MD -MP -MF $(DEPDIR)/mkntfs-mkntfs.Tpo -c -o mkntfs-mkntfs.obj `if test -f 'mkntfs.c'; then $(CYGPATH_W) 'mkntfs.c'; else $(CYGPATH_W) '$(srcdir)/mkntfs.c'; fi`
+	$(AM_V_at)$(am__mv) $(DEPDIR)/mkntfs-mkntfs.Tpo $(DEPDIR)/mkntfs-mkntfs.Po
+#	$(AM_V_CC)source='mkntfs.c' object='mkntfs-mkntfs.obj' libtool=no \
+#	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+#	$(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mkntfs-mkntfs.obj `if test -f 'mkntfs.c'; then $(CYGPATH_W) 'mkntfs.c'; else $(CYGPATH_W) '$(srcdir)/mkntfs.c'; fi`
+
+mkntfs-utils.o: utils.c
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mkntfs-utils.o -MD -MP -MF $(DEPDIR)/mkntfs-utils.Tpo -c -o mkntfs-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c
+	$(AM_V_at)$(am__mv) $(DEPDIR)/mkntfs-utils.Tpo $(DEPDIR)/mkntfs-utils.Po
+#	$(AM_V_CC)source='utils.c' object='mkntfs-utils.o' libtool=no \
+#	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+#	$(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mkntfs-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c
+
+mkntfs-utils.obj: utils.c
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mkntfs-utils.obj -MD -MP -MF $(DEPDIR)/mkntfs-utils.Tpo -c -o mkntfs-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi`
+	$(AM_V_at)$(am__mv) $(DEPDIR)/mkntfs-utils.Tpo $(DEPDIR)/mkntfs-utils.Po
+#	$(AM_V_CC)source='utils.c' object='mkntfs-utils.obj' libtool=no \
+#	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+#	$(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mkntfs-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi`
+
+ntfsdecrypt-ntfsdecrypt.o: ntfsdecrypt.c
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfsdecrypt_CFLAGS) $(CFLAGS) -MT ntfsdecrypt-ntfsdecrypt.o -MD -MP -MF $(DEPDIR)/ntfsdecrypt-ntfsdecrypt.Tpo -c -o ntfsdecrypt-ntfsdecrypt.o `test -f 'ntfsdecrypt.c' || echo '$(srcdir)/'`ntfsdecrypt.c
+	$(AM_V_at)$(am__mv) $(DEPDIR)/ntfsdecrypt-ntfsdecrypt.Tpo $(DEPDIR)/ntfsdecrypt-ntfsdecrypt.Po
+#	$(AM_V_CC)source='ntfsdecrypt.c' object='ntfsdecrypt-ntfsdecrypt.o' libtool=no \
+#	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+#	$(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfsdecrypt_CFLAGS) $(CFLAGS) -c -o ntfsdecrypt-ntfsdecrypt.o `test -f 'ntfsdecrypt.c' || echo '$(srcdir)/'`ntfsdecrypt.c
+
+ntfsdecrypt-ntfsdecrypt.obj: ntfsdecrypt.c
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfsdecrypt_CFLAGS) $(CFLAGS) -MT ntfsdecrypt-ntfsdecrypt.obj -MD -MP -MF $(DEPDIR)/ntfsdecrypt-ntfsdecrypt.Tpo -c -o ntfsdecrypt-ntfsdecrypt.obj `if test -f 'ntfsdecrypt.c'; then $(CYGPATH_W) 'ntfsdecrypt.c'; else $(CYGPATH_W) '$(srcdir)/ntfsdecrypt.c'; fi`
+	$(AM_V_at)$(am__mv) $(DEPDIR)/ntfsdecrypt-ntfsdecrypt.Tpo $(DEPDIR)/ntfsdecrypt-ntfsdecrypt.Po
+#	$(AM_V_CC)source='ntfsdecrypt.c' object='ntfsdecrypt-ntfsdecrypt.obj' libtool=no \
+#	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+#	$(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfsdecrypt_CFLAGS) $(CFLAGS) -c -o ntfsdecrypt-ntfsdecrypt.obj `if test -f 'ntfsdecrypt.c'; then $(CYGPATH_W) 'ntfsdecrypt.c'; else $(CYGPATH_W) '$(srcdir)/ntfsdecrypt.c'; fi`
+
+ntfsdecrypt-utils.o: utils.c
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfsdecrypt_CFLAGS) $(CFLAGS) -MT ntfsdecrypt-utils.o -MD -MP -MF $(DEPDIR)/ntfsdecrypt-utils.Tpo -c -o ntfsdecrypt-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c
+	$(AM_V_at)$(am__mv) $(DEPDIR)/ntfsdecrypt-utils.Tpo $(DEPDIR)/ntfsdecrypt-utils.Po
+#	$(AM_V_CC)source='utils.c' object='ntfsdecrypt-utils.o' libtool=no \
+#	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+#	$(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfsdecrypt_CFLAGS) $(CFLAGS) -c -o ntfsdecrypt-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c
+
+ntfsdecrypt-utils.obj: utils.c
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfsdecrypt_CFLAGS) $(CFLAGS) -MT ntfsdecrypt-utils.obj -MD -MP -MF $(DEPDIR)/ntfsdecrypt-utils.Tpo -c -o ntfsdecrypt-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi`
+	$(AM_V_at)$(am__mv) $(DEPDIR)/ntfsdecrypt-utils.Tpo $(DEPDIR)/ntfsdecrypt-utils.Po
+#	$(AM_V_CC)source='utils.c' object='ntfsdecrypt-utils.obj' libtool=no \
+#	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+#	$(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfsdecrypt_CFLAGS) $(CFLAGS) -c -o ntfsdecrypt-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi`
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+install-man8: $(man_MANS)
+	@$(NORMAL_INSTALL)
+	@list1=''; \
+	list2='$(man_MANS)'; \
+	test -n "$(man8dir)" \
+	  && test -n "`echo $$list1$$list2`" \
+	  || exit 0; \
+	echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
+	$(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \
+	{ for i in $$list1; do echo "$$i"; done;  \
+	if test -n "$$list2"; then \
+	  for i in $$list2; do echo "$$i"; done \
+	    | sed -n '/\.8[a-z]*$$/p'; \
+	fi; \
+	} | while read p; do \
+	  if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; echo "$$p"; \
+	done | \
+	sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+	sed 'N;N;s,\n, ,g' | { \
+	list=; while read file base inst; do \
+	  if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+	    echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
+	    $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \
+	  fi; \
+	done; \
+	for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+	while read files; do \
+	  test -z "$$files" || { \
+	    echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \
+	    $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
+	done; }
+
+uninstall-man8:
+	@$(NORMAL_UNINSTALL)
+	@list=''; test -n "$(man8dir)" || exit 0; \
+	files=`{ for i in $$list; do echo "$$i"; done; \
+	l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+	  sed -n '/\.8[a-z]*$$/p'; \
+	} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+	dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) $(MANS)
+installdirs:
+	for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+#uninstall-local:
+#install-exec-hook:
+#install-data-hook:
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool \
+	clean-sbinPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-man
+	@$(NORMAL_INSTALL)
+	$(MAKE) $(AM_MAKEFLAGS) install-data-hook
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS install-sbinPROGRAMS
+	@$(NORMAL_INSTALL)
+	$(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man: install-man8
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-local uninstall-man \
+	uninstall-sbinPROGRAMS
+
+uninstall-man: uninstall-man8
+
+.MAKE: install-am install-data-am install-exec-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
+	clean-binPROGRAMS clean-generic clean-libtool \
+	clean-sbinPROGRAMS cscopelist-am ctags ctags-am distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-binPROGRAMS install-data \
+	install-data-am install-data-hook install-dvi install-dvi-am \
+	install-exec install-exec-am install-exec-hook install-html \
+	install-html-am install-info install-info-am install-man \
+	install-man8 install-pdf install-pdf-am install-ps \
+	install-ps-am install-sbinPROGRAMS install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	tags tags-am uninstall uninstall-am uninstall-binPROGRAMS \
+	uninstall-local uninstall-man uninstall-man8 \
+	uninstall-sbinPROGRAMS
+
+
+# Extra targets
+
+strip:	$(bin_PROGRAMS) $(sbin_PROGRAMS)
+	$(STRIP) $^
+
+libs:
+	(cd ../libntfs-3g && $(MAKE) libs) || exit 1;
+
+extra:	extras
+
+extras:	libs $(EXTRA_PROGRAMS)
+
+# mkfs.ntfs[.8] hard link
+
+install-exec-hook:
+	$(INSTALL) -d $(DESTDIR)/sbin
+	$(LN_S) -f $(sbindir)/mkntfs $(DESTDIR)/sbin/mkfs.ntfs
+
+install-data-hook:
+	$(INSTALL) -d $(DESTDIR)$(man8dir)
+	$(LN_S) -f mkntfs.8 $(DESTDIR)$(man8dir)/mkfs.ntfs.8
+
+uninstall-local:
+	$(RM) -f $(DESTDIR)/sbin/mkfs.ntfs
+	$(RM) -f $(DESTDIR)$(man8dir)/mkfs.ntfs.8
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/ntfsprogs/Makefile.am b/ntfsprogs/Makefile.am
new file mode 100755
index 0000000000000000000000000000000000000000..cbc7ce50dba220da0bbfb6554072d0dabc8b13e1
--- /dev/null
+++ b/ntfsprogs/Makefile.am
@@ -0,0 +1,164 @@
+if REALLYSTATIC
+AM_LIBS		= $(top_builddir)/libntfs-3g/.libs/libntfs-3g.a $(NTFSPROGS_STATIC_LIBS)
+# older builds may need -static instead of newer -all-static
+AM_LFLAGS	= -static
+STATIC_LINK     = $(CC) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+else
+AM_LIBS		= $(top_builddir)/libntfs-3g/libntfs-3g.la
+AM_LFLAGS	= $(all_libraries)
+LIBTOOL_LINK    = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+endif
+
+# Workaround to make REALLYSTATIC work with automake 1.5.
+LINK=$(STATIC_LINK) $(LIBTOOL_LINK)
+
+if ENABLE_NTFSPROGS
+
+bin_PROGRAMS		= ntfsfix ntfsinfo ntfscluster ntfsls ntfscat ntfscmp
+sbin_PROGRAMS		= mkntfs ntfslabel ntfsundelete ntfsresize ntfsclone \
+			  ntfscp
+EXTRA_PROGRAM_NAMES	= ntfswipe ntfstruncate
+
+QUARANTINED_PROGRAM_NAMES = ntfsdump_logfile ntfsmftalloc ntfsmove ntfsck \
+			   ntfsfallocate
+
+man_MANS		= mkntfs.8 ntfsfix.8 ntfslabel.8 ntfsinfo.8 \
+			  ntfsundelete.8 ntfsresize.8 ntfsprogs.8 ntfsls.8 \
+			  ntfsclone.8 ntfscluster.8 ntfscat.8 ntfscp.8 \
+			  ntfscmp.8 ntfswipe.8 ntfstruncate.8 \
+			  ntfsdecrypt.8 ntfsfallocate.8
+EXTRA_MANS		=
+
+CLEANFILES		= $(EXTRA_PROGRAMS)
+
+MAINTAINERCLEANFILES = Makefile.in
+
+if ENABLE_CRYPTO
+EXTRA_PROGRAM_NAMES	+= ntfsdecrypt
+endif
+
+if ENABLE_EXTRAS
+bin_PROGRAMS		+= $(EXTRA_PROGRAM_NAMES)
+if ENABLE_QUARANTINED
+bin_PROGRAMS		+= $(QUARANTINED_PROGRAM_NAMES)
+endif
+else
+EXTRA_PROGRAMS		= $(EXTRA_PROGRAM_NAMES)
+endif
+
+# Set the include path.
+AM_CPPFLAGS		= -I$(top_srcdir)/include/ntfs-3g $(all_includes)
+
+ntfsfix_SOURCES		= ntfsfix.c utils.c utils.h
+ntfsfix_LDADD		= $(AM_LIBS)
+ntfsfix_LDFLAGS		= $(AM_LFLAGS)
+
+mkntfs_CPPFLAGS		= $(AM_CPPFLAGS) $(MKNTFS_CPPFLAGS)
+mkntfs_SOURCES		= attrdef.c attrdef.h boot.c boot.h sd.c sd.h mkntfs.c utils.c utils.h
+mkntfs_LDADD		= $(AM_LIBS) $(MKNTFS_LIBS)
+mkntfs_LDFLAGS		= $(AM_LFLAGS)
+
+ntfslabel_SOURCES	= ntfslabel.c utils.c utils.h
+ntfslabel_LDADD		= $(AM_LIBS)
+ntfslabel_LDFLAGS	= $(AM_LFLAGS)
+
+ntfsinfo_SOURCES	= ntfsinfo.c utils.c utils.h
+ntfsinfo_LDADD		= $(AM_LIBS)
+ntfsinfo_LDFLAGS	= $(AM_LFLAGS)
+
+ntfsundelete_SOURCES	= ntfsundelete.c ntfsundelete.h utils.c utils.h list.h
+ntfsundelete_LDADD	= $(AM_LIBS)
+ntfsundelete_LDFLAGS	= $(AM_LFLAGS)
+
+ntfsresize_SOURCES	= ntfsresize.c utils.c utils.h
+ntfsresize_LDADD	= $(AM_LIBS)
+ntfsresize_LDFLAGS	= $(AM_LFLAGS)
+
+ntfsclone_SOURCES	= ntfsclone.c utils.c utils.h
+ntfsclone_LDADD		= $(AM_LIBS)
+ntfsclone_LDFLAGS	= $(AM_LFLAGS)
+
+ntfscluster_SOURCES	= ntfscluster.c ntfscluster.h cluster.c cluster.h utils.c utils.h
+ntfscluster_LDADD	= $(AM_LIBS)
+ntfscluster_LDFLAGS	= $(AM_LFLAGS)
+
+ntfsls_SOURCES		= ntfsls.c utils.c utils.h list.h
+ntfsls_LDADD		= $(AM_LIBS)
+ntfsls_LDFLAGS		= $(AM_LFLAGS)
+
+ntfscat_SOURCES		= ntfscat.c ntfscat.h utils.c utils.h
+ntfscat_LDADD		= $(AM_LIBS)
+ntfscat_LDFLAGS		= $(AM_LFLAGS)
+
+ntfscp_SOURCES		= ntfscp.c utils.c utils.h
+ntfscp_LDADD		= $(AM_LIBS)
+ntfscp_LDFLAGS		= $(AM_LFLAGS)
+
+ntfsck_SOURCES		= ntfsck.c utils.c utils.h
+ntfsck_LDADD		= $(AM_LIBS)
+ntfsck_LDFLAGS		= $(AM_LFLAGS)
+
+ntfscmp_SOURCES		= ntfscmp.c utils.c utils.h
+ntfscmp_LDADD		= $(AM_LIBS)
+ntfscmp_LDFLAGS		= $(AM_LFLAGS)
+
+# We don't distribute these
+
+ntfstruncate_SOURCES	= attrdef.c ntfstruncate.c utils.c utils.h
+ntfstruncate_LDADD	= $(AM_LIBS)
+ntfstruncate_LDFLAGS	= $(AM_LFLAGS)
+
+ntfsmftalloc_SOURCES	= ntfsmftalloc.c utils.c utils.h
+ntfsmftalloc_LDADD	= $(AM_LIBS)
+ntfsmftalloc_LDFLAGS	= $(AM_LFLAGS)
+
+ntfsmove_SOURCES	= ntfsmove.c ntfsmove.h utils.c utils.h
+ntfsmove_LDADD		= $(AM_LIBS)
+ntfsmove_LDFLAGS	= $(AM_LFLAGS)
+
+ntfswipe_SOURCES	= ntfswipe.c ntfswipe.h utils.c utils.h
+ntfswipe_LDADD		= $(AM_LIBS)
+ntfswipe_LDFLAGS	= $(AM_LFLAGS)
+
+ntfsdump_logfile_SOURCES= ntfsdump_logfile.c
+ntfsdump_logfile_LDADD	= $(AM_LIBS)
+ntfsdump_logfile_LDFLAGS= $(AM_LFLAGS)
+
+ntfsfallocate_SOURCES	= ntfsfallocate.c utils.c utils.h
+ntfsfallocate_LDADD	= $(AM_LIBS)
+ntfsfallocate_LDFLAGS	= $(AM_LFLAGS)
+
+if ENABLE_CRYPTO
+ntfsdecrypt_SOURCES	= ntfsdecrypt.c utils.c utils.h
+ntfsdecrypt_LDADD	= $(AM_LIBS) $(GNUTLS_LIBS) $(LIBGCRYPT_LIBS)
+ntfsdecrypt_LDFLAGS	= $(AM_LFLAGS)
+ntfsdecrypt_CFLAGS	= $(GNUTLS_CFLAGS) $(LIBGCRYPT_CFLAGS)
+endif
+
+# Extra targets
+
+strip:	$(bin_PROGRAMS) $(sbin_PROGRAMS)
+	$(STRIP) $^
+
+libs:
+	(cd ../libntfs-3g && $(MAKE) libs) || exit 1;
+
+extra:	extras
+
+extras:	libs $(EXTRA_PROGRAMS)
+
+# mkfs.ntfs[.8] hard link
+
+install-exec-hook:
+	$(INSTALL) -d $(DESTDIR)/sbin
+	$(LN_S) -f $(sbindir)/mkntfs $(DESTDIR)/sbin/mkfs.ntfs
+
+install-data-hook:
+	$(INSTALL) -d $(DESTDIR)$(man8dir)
+	$(LN_S) -f mkntfs.8 $(DESTDIR)$(man8dir)/mkfs.ntfs.8
+
+uninstall-local:
+	$(RM) -f $(DESTDIR)/sbin/mkfs.ntfs
+	$(RM) -f $(DESTDIR)$(man8dir)/mkfs.ntfs.8
+
+endif
diff --git a/ntfsprogs/Makefile.in b/ntfsprogs/Makefile.in
new file mode 100755
index 0000000000000000000000000000000000000000..8ab3ad734a01ac7e7e144d8ff0296988a24b4457
--- /dev/null
+++ b/ntfsprogs/Makefile.in
@@ -0,0 +1,1364 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@ENABLE_NTFSPROGS_TRUE@bin_PROGRAMS = ntfsfix$(EXEEXT) \
+@ENABLE_NTFSPROGS_TRUE@	ntfsinfo$(EXEEXT) ntfscluster$(EXEEXT) \
+@ENABLE_NTFSPROGS_TRUE@	ntfsls$(EXEEXT) ntfscat$(EXEEXT) \
+@ENABLE_NTFSPROGS_TRUE@	ntfscmp$(EXEEXT) $(am__EXEEXT_3) \
+@ENABLE_NTFSPROGS_TRUE@	$(am__EXEEXT_5)
+@ENABLE_NTFSPROGS_TRUE@sbin_PROGRAMS = mkntfs$(EXEEXT) \
+@ENABLE_NTFSPROGS_TRUE@	ntfslabel$(EXEEXT) \
+@ENABLE_NTFSPROGS_TRUE@	ntfsundelete$(EXEEXT) \
+@ENABLE_NTFSPROGS_TRUE@	ntfsresize$(EXEEXT) ntfsclone$(EXEEXT) \
+@ENABLE_NTFSPROGS_TRUE@	ntfscp$(EXEEXT)
+@ENABLE_CRYPTO_TRUE@@ENABLE_NTFSPROGS_TRUE@am__append_1 = ntfsdecrypt
+@ENABLE_EXTRAS_TRUE@@ENABLE_NTFSPROGS_TRUE@am__append_2 = $(EXTRA_PROGRAM_NAMES)
+@ENABLE_EXTRAS_TRUE@@ENABLE_NTFSPROGS_TRUE@@ENABLE_QUARANTINED_TRUE@am__append_3 = $(QUARANTINED_PROGRAM_NAMES)
+@ENABLE_EXTRAS_FALSE@@ENABLE_NTFSPROGS_TRUE@EXTRA_PROGRAMS =  \
+@ENABLE_EXTRAS_FALSE@@ENABLE_NTFSPROGS_TRUE@	$(am__EXEEXT_2)
+subdir = ntfsprogs
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+	$(srcdir)/mkntfs.8.in $(srcdir)/ntfscat.8.in \
+	$(srcdir)/ntfsclone.8.in $(srcdir)/ntfscluster.8.in \
+	$(srcdir)/ntfscmp.8.in $(srcdir)/ntfscp.8.in \
+	$(srcdir)/ntfsfix.8.in $(srcdir)/ntfsinfo.8.in \
+	$(srcdir)/ntfslabel.8.in $(srcdir)/ntfsls.8.in \
+	$(srcdir)/ntfsprogs.8.in $(srcdir)/ntfsresize.8.in \
+	$(srcdir)/ntfsundelete.8.in $(srcdir)/ntfsdecrypt.8.in \
+	$(srcdir)/ntfswipe.8.in $(srcdir)/ntfstruncate.8.in \
+	$(srcdir)/ntfsfallocate.8.in $(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = mkntfs.8 ntfscat.8 ntfsclone.8 ntfscluster.8 \
+	ntfscmp.8 ntfscp.8 ntfsfix.8 ntfsinfo.8 ntfslabel.8 ntfsls.8 \
+	ntfsprogs.8 ntfsresize.8 ntfsundelete.8 ntfsdecrypt.8 \
+	ntfswipe.8 ntfstruncate.8 ntfsfallocate.8
+CONFIG_CLEAN_VPATH_FILES =
+@ENABLE_CRYPTO_TRUE@@ENABLE_NTFSPROGS_TRUE@am__EXEEXT_1 = ntfsdecrypt$(EXEEXT)
+@ENABLE_NTFSPROGS_TRUE@am__EXEEXT_2 = ntfswipe$(EXEEXT) \
+@ENABLE_NTFSPROGS_TRUE@	ntfstruncate$(EXEEXT) $(am__EXEEXT_1)
+@ENABLE_EXTRAS_TRUE@@ENABLE_NTFSPROGS_TRUE@am__EXEEXT_3 =  \
+@ENABLE_EXTRAS_TRUE@@ENABLE_NTFSPROGS_TRUE@	$(am__EXEEXT_2)
+@ENABLE_NTFSPROGS_TRUE@am__EXEEXT_4 = ntfsdump_logfile$(EXEEXT) \
+@ENABLE_NTFSPROGS_TRUE@	ntfsmftalloc$(EXEEXT) ntfsmove$(EXEEXT) \
+@ENABLE_NTFSPROGS_TRUE@	ntfsck$(EXEEXT) ntfsfallocate$(EXEEXT)
+@ENABLE_EXTRAS_TRUE@@ENABLE_NTFSPROGS_TRUE@@ENABLE_QUARANTINED_TRUE@am__EXEEXT_5 = $(am__EXEEXT_4)
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" \
+	"$(DESTDIR)$(man8dir)"
+PROGRAMS = $(bin_PROGRAMS) $(sbin_PROGRAMS)
+am__mkntfs_SOURCES_DIST = attrdef.c attrdef.h boot.c boot.h sd.c sd.h \
+	mkntfs.c utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@am_mkntfs_OBJECTS = mkntfs-attrdef.$(OBJEXT) \
+@ENABLE_NTFSPROGS_TRUE@	mkntfs-boot.$(OBJEXT) \
+@ENABLE_NTFSPROGS_TRUE@	mkntfs-sd.$(OBJEXT) \
+@ENABLE_NTFSPROGS_TRUE@	mkntfs-mkntfs.$(OBJEXT) \
+@ENABLE_NTFSPROGS_TRUE@	mkntfs-utils.$(OBJEXT)
+mkntfs_OBJECTS = $(am_mkntfs_OBJECTS)
+am__DEPENDENCIES_1 =
+@REALLYSTATIC_FALSE@am__DEPENDENCIES_2 =  \
+@REALLYSTATIC_FALSE@	$(top_builddir)/libntfs-3g/libntfs-3g.la
+@REALLYSTATIC_TRUE@am__DEPENDENCIES_2 = $(top_builddir)/libntfs-3g/.libs/libntfs-3g.a \
+@REALLYSTATIC_TRUE@	$(am__DEPENDENCIES_1)
+@ENABLE_NTFSPROGS_TRUE@mkntfs_DEPENDENCIES = $(am__DEPENDENCIES_2) \
+@ENABLE_NTFSPROGS_TRUE@	$(am__DEPENDENCIES_1)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
+mkntfs_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(mkntfs_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfscat_SOURCES_DIST = ntfscat.c ntfscat.h utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@am_ntfscat_OBJECTS = ntfscat.$(OBJEXT) \
+@ENABLE_NTFSPROGS_TRUE@	utils.$(OBJEXT)
+ntfscat_OBJECTS = $(am_ntfscat_OBJECTS)
+@ENABLE_NTFSPROGS_TRUE@ntfscat_DEPENDENCIES = $(am__DEPENDENCIES_2)
+ntfscat_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfscat_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfsck_SOURCES_DIST = ntfsck.c utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@am_ntfsck_OBJECTS = ntfsck.$(OBJEXT) \
+@ENABLE_NTFSPROGS_TRUE@	utils.$(OBJEXT)
+ntfsck_OBJECTS = $(am_ntfsck_OBJECTS)
+@ENABLE_NTFSPROGS_TRUE@ntfsck_DEPENDENCIES = $(am__DEPENDENCIES_2)
+ntfsck_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfsck_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfsclone_SOURCES_DIST = ntfsclone.c utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@am_ntfsclone_OBJECTS = ntfsclone.$(OBJEXT) \
+@ENABLE_NTFSPROGS_TRUE@	utils.$(OBJEXT)
+ntfsclone_OBJECTS = $(am_ntfsclone_OBJECTS)
+@ENABLE_NTFSPROGS_TRUE@ntfsclone_DEPENDENCIES = $(am__DEPENDENCIES_2)
+ntfsclone_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfsclone_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfscluster_SOURCES_DIST = ntfscluster.c ntfscluster.h cluster.c \
+	cluster.h utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@am_ntfscluster_OBJECTS = ntfscluster.$(OBJEXT) \
+@ENABLE_NTFSPROGS_TRUE@	cluster.$(OBJEXT) utils.$(OBJEXT)
+ntfscluster_OBJECTS = $(am_ntfscluster_OBJECTS)
+@ENABLE_NTFSPROGS_TRUE@ntfscluster_DEPENDENCIES =  \
+@ENABLE_NTFSPROGS_TRUE@	$(am__DEPENDENCIES_2)
+ntfscluster_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfscluster_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfscmp_SOURCES_DIST = ntfscmp.c utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@am_ntfscmp_OBJECTS = ntfscmp.$(OBJEXT) \
+@ENABLE_NTFSPROGS_TRUE@	utils.$(OBJEXT)
+ntfscmp_OBJECTS = $(am_ntfscmp_OBJECTS)
+@ENABLE_NTFSPROGS_TRUE@ntfscmp_DEPENDENCIES = $(am__DEPENDENCIES_2)
+ntfscmp_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfscmp_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfscp_SOURCES_DIST = ntfscp.c utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@am_ntfscp_OBJECTS = ntfscp.$(OBJEXT) \
+@ENABLE_NTFSPROGS_TRUE@	utils.$(OBJEXT)
+ntfscp_OBJECTS = $(am_ntfscp_OBJECTS)
+@ENABLE_NTFSPROGS_TRUE@ntfscp_DEPENDENCIES = $(am__DEPENDENCIES_2)
+ntfscp_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfscp_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfsdecrypt_SOURCES_DIST = ntfsdecrypt.c utils.c utils.h
+@ENABLE_CRYPTO_TRUE@@ENABLE_NTFSPROGS_TRUE@am_ntfsdecrypt_OBJECTS = ntfsdecrypt-ntfsdecrypt.$(OBJEXT) \
+@ENABLE_CRYPTO_TRUE@@ENABLE_NTFSPROGS_TRUE@	ntfsdecrypt-utils.$(OBJEXT)
+ntfsdecrypt_OBJECTS = $(am_ntfsdecrypt_OBJECTS)
+@ENABLE_CRYPTO_TRUE@@ENABLE_NTFSPROGS_TRUE@ntfsdecrypt_DEPENDENCIES = $(am__DEPENDENCIES_2) \
+@ENABLE_CRYPTO_TRUE@@ENABLE_NTFSPROGS_TRUE@	$(am__DEPENDENCIES_1) \
+@ENABLE_CRYPTO_TRUE@@ENABLE_NTFSPROGS_TRUE@	$(am__DEPENDENCIES_1)
+ntfsdecrypt_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ntfsdecrypt_CFLAGS) \
+	$(CFLAGS) $(ntfsdecrypt_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfsdump_logfile_SOURCES_DIST = ntfsdump_logfile.c
+@ENABLE_NTFSPROGS_TRUE@am_ntfsdump_logfile_OBJECTS =  \
+@ENABLE_NTFSPROGS_TRUE@	ntfsdump_logfile.$(OBJEXT)
+ntfsdump_logfile_OBJECTS = $(am_ntfsdump_logfile_OBJECTS)
+@ENABLE_NTFSPROGS_TRUE@ntfsdump_logfile_DEPENDENCIES =  \
+@ENABLE_NTFSPROGS_TRUE@	$(am__DEPENDENCIES_2)
+ntfsdump_logfile_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(AM_CFLAGS) $(CFLAGS) $(ntfsdump_logfile_LDFLAGS) $(LDFLAGS) \
+	-o $@
+am__ntfsfallocate_SOURCES_DIST = ntfsfallocate.c utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@am_ntfsfallocate_OBJECTS =  \
+@ENABLE_NTFSPROGS_TRUE@	ntfsfallocate.$(OBJEXT) utils.$(OBJEXT)
+ntfsfallocate_OBJECTS = $(am_ntfsfallocate_OBJECTS)
+@ENABLE_NTFSPROGS_TRUE@ntfsfallocate_DEPENDENCIES =  \
+@ENABLE_NTFSPROGS_TRUE@	$(am__DEPENDENCIES_2)
+ntfsfallocate_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfsfallocate_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfsfix_SOURCES_DIST = ntfsfix.c utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@am_ntfsfix_OBJECTS = ntfsfix.$(OBJEXT) \
+@ENABLE_NTFSPROGS_TRUE@	utils.$(OBJEXT)
+ntfsfix_OBJECTS = $(am_ntfsfix_OBJECTS)
+@ENABLE_NTFSPROGS_TRUE@ntfsfix_DEPENDENCIES = $(am__DEPENDENCIES_2)
+ntfsfix_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfsfix_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfsinfo_SOURCES_DIST = ntfsinfo.c utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@am_ntfsinfo_OBJECTS = ntfsinfo.$(OBJEXT) \
+@ENABLE_NTFSPROGS_TRUE@	utils.$(OBJEXT)
+ntfsinfo_OBJECTS = $(am_ntfsinfo_OBJECTS)
+@ENABLE_NTFSPROGS_TRUE@ntfsinfo_DEPENDENCIES = $(am__DEPENDENCIES_2)
+ntfsinfo_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfsinfo_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfslabel_SOURCES_DIST = ntfslabel.c utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@am_ntfslabel_OBJECTS = ntfslabel.$(OBJEXT) \
+@ENABLE_NTFSPROGS_TRUE@	utils.$(OBJEXT)
+ntfslabel_OBJECTS = $(am_ntfslabel_OBJECTS)
+@ENABLE_NTFSPROGS_TRUE@ntfslabel_DEPENDENCIES = $(am__DEPENDENCIES_2)
+ntfslabel_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfslabel_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfsls_SOURCES_DIST = ntfsls.c utils.c utils.h list.h
+@ENABLE_NTFSPROGS_TRUE@am_ntfsls_OBJECTS = ntfsls.$(OBJEXT) \
+@ENABLE_NTFSPROGS_TRUE@	utils.$(OBJEXT)
+ntfsls_OBJECTS = $(am_ntfsls_OBJECTS)
+@ENABLE_NTFSPROGS_TRUE@ntfsls_DEPENDENCIES = $(am__DEPENDENCIES_2)
+ntfsls_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfsls_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfsmftalloc_SOURCES_DIST = ntfsmftalloc.c utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@am_ntfsmftalloc_OBJECTS =  \
+@ENABLE_NTFSPROGS_TRUE@	ntfsmftalloc.$(OBJEXT) utils.$(OBJEXT)
+ntfsmftalloc_OBJECTS = $(am_ntfsmftalloc_OBJECTS)
+@ENABLE_NTFSPROGS_TRUE@ntfsmftalloc_DEPENDENCIES =  \
+@ENABLE_NTFSPROGS_TRUE@	$(am__DEPENDENCIES_2)
+ntfsmftalloc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfsmftalloc_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfsmove_SOURCES_DIST = ntfsmove.c ntfsmove.h utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@am_ntfsmove_OBJECTS = ntfsmove.$(OBJEXT) \
+@ENABLE_NTFSPROGS_TRUE@	utils.$(OBJEXT)
+ntfsmove_OBJECTS = $(am_ntfsmove_OBJECTS)
+@ENABLE_NTFSPROGS_TRUE@ntfsmove_DEPENDENCIES = $(am__DEPENDENCIES_2)
+ntfsmove_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfsmove_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfsresize_SOURCES_DIST = ntfsresize.c utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@am_ntfsresize_OBJECTS = ntfsresize.$(OBJEXT) \
+@ENABLE_NTFSPROGS_TRUE@	utils.$(OBJEXT)
+ntfsresize_OBJECTS = $(am_ntfsresize_OBJECTS)
+@ENABLE_NTFSPROGS_TRUE@ntfsresize_DEPENDENCIES =  \
+@ENABLE_NTFSPROGS_TRUE@	$(am__DEPENDENCIES_2)
+ntfsresize_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfsresize_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfstruncate_SOURCES_DIST = attrdef.c ntfstruncate.c utils.c \
+	utils.h
+@ENABLE_NTFSPROGS_TRUE@am_ntfstruncate_OBJECTS = attrdef.$(OBJEXT) \
+@ENABLE_NTFSPROGS_TRUE@	ntfstruncate.$(OBJEXT) utils.$(OBJEXT)
+ntfstruncate_OBJECTS = $(am_ntfstruncate_OBJECTS)
+@ENABLE_NTFSPROGS_TRUE@ntfstruncate_DEPENDENCIES =  \
+@ENABLE_NTFSPROGS_TRUE@	$(am__DEPENDENCIES_2)
+ntfstruncate_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfstruncate_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfsundelete_SOURCES_DIST = ntfsundelete.c ntfsundelete.h utils.c \
+	utils.h list.h
+@ENABLE_NTFSPROGS_TRUE@am_ntfsundelete_OBJECTS =  \
+@ENABLE_NTFSPROGS_TRUE@	ntfsundelete.$(OBJEXT) utils.$(OBJEXT)
+ntfsundelete_OBJECTS = $(am_ntfsundelete_OBJECTS)
+@ENABLE_NTFSPROGS_TRUE@ntfsundelete_DEPENDENCIES =  \
+@ENABLE_NTFSPROGS_TRUE@	$(am__DEPENDENCIES_2)
+ntfsundelete_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfsundelete_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfswipe_SOURCES_DIST = ntfswipe.c ntfswipe.h utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@am_ntfswipe_OBJECTS = ntfswipe.$(OBJEXT) \
+@ENABLE_NTFSPROGS_TRUE@	utils.$(OBJEXT)
+ntfswipe_OBJECTS = $(am_ntfswipe_OBJECTS)
+@ENABLE_NTFSPROGS_TRUE@ntfswipe_DEPENDENCIES = $(am__DEPENDENCIES_2)
+ntfswipe_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(ntfswipe_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
+CCLD = $(CC)
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
+SOURCES = $(mkntfs_SOURCES) $(ntfscat_SOURCES) $(ntfsck_SOURCES) \
+	$(ntfsclone_SOURCES) $(ntfscluster_SOURCES) $(ntfscmp_SOURCES) \
+	$(ntfscp_SOURCES) $(ntfsdecrypt_SOURCES) \
+	$(ntfsdump_logfile_SOURCES) $(ntfsfallocate_SOURCES) \
+	$(ntfsfix_SOURCES) $(ntfsinfo_SOURCES) $(ntfslabel_SOURCES) \
+	$(ntfsls_SOURCES) $(ntfsmftalloc_SOURCES) $(ntfsmove_SOURCES) \
+	$(ntfsresize_SOURCES) $(ntfstruncate_SOURCES) \
+	$(ntfsundelete_SOURCES) $(ntfswipe_SOURCES)
+DIST_SOURCES = $(am__mkntfs_SOURCES_DIST) $(am__ntfscat_SOURCES_DIST) \
+	$(am__ntfsck_SOURCES_DIST) $(am__ntfsclone_SOURCES_DIST) \
+	$(am__ntfscluster_SOURCES_DIST) $(am__ntfscmp_SOURCES_DIST) \
+	$(am__ntfscp_SOURCES_DIST) $(am__ntfsdecrypt_SOURCES_DIST) \
+	$(am__ntfsdump_logfile_SOURCES_DIST) \
+	$(am__ntfsfallocate_SOURCES_DIST) $(am__ntfsfix_SOURCES_DIST) \
+	$(am__ntfsinfo_SOURCES_DIST) $(am__ntfslabel_SOURCES_DIST) \
+	$(am__ntfsls_SOURCES_DIST) $(am__ntfsmftalloc_SOURCES_DIST) \
+	$(am__ntfsmove_SOURCES_DIST) $(am__ntfsresize_SOURCES_DIST) \
+	$(am__ntfstruncate_SOURCES_DIST) \
+	$(am__ntfsundelete_SOURCES_DIST) $(am__ntfswipe_SOURCES_DIST)
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+man8dir = $(mandir)/man8
+NROFF = nroff
+MANS = $(man_MANS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FUSE_MODULE_CFLAGS = @FUSE_MODULE_CFLAGS@
+FUSE_MODULE_LIBS = @FUSE_MODULE_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDCONFIG = @LDCONFIG@
+LDFLAGS = @LDFLAGS@
+LIBFUSE_LITE_CFLAGS = @LIBFUSE_LITE_CFLAGS@
+LIBFUSE_LITE_LIBS = @LIBFUSE_LITE_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBNTFS_3G_VERSION = @LIBNTFS_3G_VERSION@
+LIBNTFS_CPPFLAGS = @LIBNTFS_CPPFLAGS@
+LIBNTFS_LIBS = @LIBNTFS_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MKNTFS_CPPFLAGS = @MKNTFS_CPPFLAGS@
+MKNTFS_LIBS = @MKNTFS_LIBS@
+MV = @MV@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NTFSPROGS_STATIC_LIBS = @NTFSPROGS_STATIC_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+OUTPUT_FORMAT = @OUTPUT_FORMAT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+RM = @RM@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+all_includes = @all_includes@
+all_libraries = @all_libraries@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+ntfs3gincludedir = @ntfs3gincludedir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgconfigdir = @pkgconfigdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+rootbindir = @rootbindir@
+rootlibdir = @rootlibdir@
+rootsbindir = @rootsbindir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+@REALLYSTATIC_FALSE@AM_LIBS = $(top_builddir)/libntfs-3g/libntfs-3g.la
+@REALLYSTATIC_TRUE@AM_LIBS = $(top_builddir)/libntfs-3g/.libs/libntfs-3g.a $(NTFSPROGS_STATIC_LIBS)
+@REALLYSTATIC_FALSE@AM_LFLAGS = $(all_libraries)
+# older builds may need -static instead of newer -all-static
+@REALLYSTATIC_TRUE@AM_LFLAGS = -static
+@REALLYSTATIC_TRUE@STATIC_LINK = $(CC) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+@REALLYSTATIC_FALSE@LIBTOOL_LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+
+# Workaround to make REALLYSTATIC work with automake 1.5.
+LINK = $(STATIC_LINK) $(LIBTOOL_LINK)
+@ENABLE_NTFSPROGS_TRUE@EXTRA_PROGRAM_NAMES = ntfswipe ntfstruncate \
+@ENABLE_NTFSPROGS_TRUE@	$(am__append_1)
+@ENABLE_NTFSPROGS_TRUE@QUARANTINED_PROGRAM_NAMES = ntfsdump_logfile ntfsmftalloc ntfsmove ntfsck \
+@ENABLE_NTFSPROGS_TRUE@			   ntfsfallocate
+
+@ENABLE_NTFSPROGS_TRUE@man_MANS = mkntfs.8 ntfsfix.8 ntfslabel.8 ntfsinfo.8 \
+@ENABLE_NTFSPROGS_TRUE@			  ntfsundelete.8 ntfsresize.8 ntfsprogs.8 ntfsls.8 \
+@ENABLE_NTFSPROGS_TRUE@			  ntfsclone.8 ntfscluster.8 ntfscat.8 ntfscp.8 \
+@ENABLE_NTFSPROGS_TRUE@			  ntfscmp.8 ntfswipe.8 ntfstruncate.8 \
+@ENABLE_NTFSPROGS_TRUE@			  ntfsdecrypt.8 ntfsfallocate.8
+
+@ENABLE_NTFSPROGS_TRUE@EXTRA_MANS = 
+@ENABLE_NTFSPROGS_TRUE@CLEANFILES = $(EXTRA_PROGRAMS)
+@ENABLE_NTFSPROGS_TRUE@MAINTAINERCLEANFILES = Makefile.in
+
+# Set the include path.
+@ENABLE_NTFSPROGS_TRUE@AM_CPPFLAGS = -I$(top_srcdir)/include/ntfs-3g $(all_includes)
+@ENABLE_NTFSPROGS_TRUE@ntfsfix_SOURCES = ntfsfix.c utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@ntfsfix_LDADD = $(AM_LIBS)
+@ENABLE_NTFSPROGS_TRUE@ntfsfix_LDFLAGS = $(AM_LFLAGS)
+@ENABLE_NTFSPROGS_TRUE@mkntfs_CPPFLAGS = $(AM_CPPFLAGS) $(MKNTFS_CPPFLAGS)
+@ENABLE_NTFSPROGS_TRUE@mkntfs_SOURCES = attrdef.c attrdef.h boot.c boot.h sd.c sd.h mkntfs.c utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@mkntfs_LDADD = $(AM_LIBS) $(MKNTFS_LIBS)
+@ENABLE_NTFSPROGS_TRUE@mkntfs_LDFLAGS = $(AM_LFLAGS)
+@ENABLE_NTFSPROGS_TRUE@ntfslabel_SOURCES = ntfslabel.c utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@ntfslabel_LDADD = $(AM_LIBS)
+@ENABLE_NTFSPROGS_TRUE@ntfslabel_LDFLAGS = $(AM_LFLAGS)
+@ENABLE_NTFSPROGS_TRUE@ntfsinfo_SOURCES = ntfsinfo.c utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@ntfsinfo_LDADD = $(AM_LIBS)
+@ENABLE_NTFSPROGS_TRUE@ntfsinfo_LDFLAGS = $(AM_LFLAGS)
+@ENABLE_NTFSPROGS_TRUE@ntfsundelete_SOURCES = ntfsundelete.c ntfsundelete.h utils.c utils.h list.h
+@ENABLE_NTFSPROGS_TRUE@ntfsundelete_LDADD = $(AM_LIBS)
+@ENABLE_NTFSPROGS_TRUE@ntfsundelete_LDFLAGS = $(AM_LFLAGS)
+@ENABLE_NTFSPROGS_TRUE@ntfsresize_SOURCES = ntfsresize.c utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@ntfsresize_LDADD = $(AM_LIBS)
+@ENABLE_NTFSPROGS_TRUE@ntfsresize_LDFLAGS = $(AM_LFLAGS)
+@ENABLE_NTFSPROGS_TRUE@ntfsclone_SOURCES = ntfsclone.c utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@ntfsclone_LDADD = $(AM_LIBS)
+@ENABLE_NTFSPROGS_TRUE@ntfsclone_LDFLAGS = $(AM_LFLAGS)
+@ENABLE_NTFSPROGS_TRUE@ntfscluster_SOURCES = ntfscluster.c ntfscluster.h cluster.c cluster.h utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@ntfscluster_LDADD = $(AM_LIBS)
+@ENABLE_NTFSPROGS_TRUE@ntfscluster_LDFLAGS = $(AM_LFLAGS)
+@ENABLE_NTFSPROGS_TRUE@ntfsls_SOURCES = ntfsls.c utils.c utils.h list.h
+@ENABLE_NTFSPROGS_TRUE@ntfsls_LDADD = $(AM_LIBS)
+@ENABLE_NTFSPROGS_TRUE@ntfsls_LDFLAGS = $(AM_LFLAGS)
+@ENABLE_NTFSPROGS_TRUE@ntfscat_SOURCES = ntfscat.c ntfscat.h utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@ntfscat_LDADD = $(AM_LIBS)
+@ENABLE_NTFSPROGS_TRUE@ntfscat_LDFLAGS = $(AM_LFLAGS)
+@ENABLE_NTFSPROGS_TRUE@ntfscp_SOURCES = ntfscp.c utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@ntfscp_LDADD = $(AM_LIBS)
+@ENABLE_NTFSPROGS_TRUE@ntfscp_LDFLAGS = $(AM_LFLAGS)
+@ENABLE_NTFSPROGS_TRUE@ntfsck_SOURCES = ntfsck.c utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@ntfsck_LDADD = $(AM_LIBS)
+@ENABLE_NTFSPROGS_TRUE@ntfsck_LDFLAGS = $(AM_LFLAGS)
+@ENABLE_NTFSPROGS_TRUE@ntfscmp_SOURCES = ntfscmp.c utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@ntfscmp_LDADD = $(AM_LIBS)
+@ENABLE_NTFSPROGS_TRUE@ntfscmp_LDFLAGS = $(AM_LFLAGS)
+
+# We don't distribute these
+@ENABLE_NTFSPROGS_TRUE@ntfstruncate_SOURCES = attrdef.c ntfstruncate.c utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@ntfstruncate_LDADD = $(AM_LIBS)
+@ENABLE_NTFSPROGS_TRUE@ntfstruncate_LDFLAGS = $(AM_LFLAGS)
+@ENABLE_NTFSPROGS_TRUE@ntfsmftalloc_SOURCES = ntfsmftalloc.c utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@ntfsmftalloc_LDADD = $(AM_LIBS)
+@ENABLE_NTFSPROGS_TRUE@ntfsmftalloc_LDFLAGS = $(AM_LFLAGS)
+@ENABLE_NTFSPROGS_TRUE@ntfsmove_SOURCES = ntfsmove.c ntfsmove.h utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@ntfsmove_LDADD = $(AM_LIBS)
+@ENABLE_NTFSPROGS_TRUE@ntfsmove_LDFLAGS = $(AM_LFLAGS)
+@ENABLE_NTFSPROGS_TRUE@ntfswipe_SOURCES = ntfswipe.c ntfswipe.h utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@ntfswipe_LDADD = $(AM_LIBS)
+@ENABLE_NTFSPROGS_TRUE@ntfswipe_LDFLAGS = $(AM_LFLAGS)
+@ENABLE_NTFSPROGS_TRUE@ntfsdump_logfile_SOURCES = ntfsdump_logfile.c
+@ENABLE_NTFSPROGS_TRUE@ntfsdump_logfile_LDADD = $(AM_LIBS)
+@ENABLE_NTFSPROGS_TRUE@ntfsdump_logfile_LDFLAGS = $(AM_LFLAGS)
+@ENABLE_NTFSPROGS_TRUE@ntfsfallocate_SOURCES = ntfsfallocate.c utils.c utils.h
+@ENABLE_NTFSPROGS_TRUE@ntfsfallocate_LDADD = $(AM_LIBS)
+@ENABLE_NTFSPROGS_TRUE@ntfsfallocate_LDFLAGS = $(AM_LFLAGS)
+@ENABLE_CRYPTO_TRUE@@ENABLE_NTFSPROGS_TRUE@ntfsdecrypt_SOURCES = ntfsdecrypt.c utils.c utils.h
+@ENABLE_CRYPTO_TRUE@@ENABLE_NTFSPROGS_TRUE@ntfsdecrypt_LDADD = $(AM_LIBS) $(GNUTLS_LIBS) $(LIBGCRYPT_LIBS)
+@ENABLE_CRYPTO_TRUE@@ENABLE_NTFSPROGS_TRUE@ntfsdecrypt_LDFLAGS = $(AM_LFLAGS)
+@ENABLE_CRYPTO_TRUE@@ENABLE_NTFSPROGS_TRUE@ntfsdecrypt_CFLAGS = $(GNUTLS_CFLAGS) $(LIBGCRYPT_CFLAGS)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu ntfsprogs/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu ntfsprogs/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+mkntfs.8: $(top_builddir)/config.status $(srcdir)/mkntfs.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfscat.8: $(top_builddir)/config.status $(srcdir)/ntfscat.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfsclone.8: $(top_builddir)/config.status $(srcdir)/ntfsclone.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfscluster.8: $(top_builddir)/config.status $(srcdir)/ntfscluster.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfscmp.8: $(top_builddir)/config.status $(srcdir)/ntfscmp.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfscp.8: $(top_builddir)/config.status $(srcdir)/ntfscp.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfsfix.8: $(top_builddir)/config.status $(srcdir)/ntfsfix.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfsinfo.8: $(top_builddir)/config.status $(srcdir)/ntfsinfo.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfslabel.8: $(top_builddir)/config.status $(srcdir)/ntfslabel.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfsls.8: $(top_builddir)/config.status $(srcdir)/ntfsls.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfsprogs.8: $(top_builddir)/config.status $(srcdir)/ntfsprogs.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfsresize.8: $(top_builddir)/config.status $(srcdir)/ntfsresize.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfsundelete.8: $(top_builddir)/config.status $(srcdir)/ntfsundelete.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfsdecrypt.8: $(top_builddir)/config.status $(srcdir)/ntfsdecrypt.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfswipe.8: $(top_builddir)/config.status $(srcdir)/ntfswipe.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfstruncate.8: $(top_builddir)/config.status $(srcdir)/ntfstruncate.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfsfallocate.8: $(top_builddir)/config.status $(srcdir)/ntfsfallocate.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+	fi; \
+	for p in $$list; do echo "$$p $$p"; done | \
+	sed 's/$(EXEEXT)$$//' | \
+	while read p p1; do if test -f $$p \
+	 || test -f $$p1 \
+	  ; then echo "$$p"; echo "$$p"; else :; fi; \
+	done | \
+	sed -e 'p;s,.*/,,;n;h' \
+	    -e 's|.*|.|' \
+	    -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+	sed 'N;N;N;s,\n, ,g' | \
+	$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+	  { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+	    if ($$2 == $$4) files[d] = files[d] " " $$1; \
+	    else { print "f", $$3 "/" $$4, $$1; } } \
+	  END { for (d in files) print "f", d, files[d] }' | \
+	while read type dir files; do \
+	    if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+	    test -z "$$files" || { \
+	    echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+	    $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+	    } \
+	; done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+	files=`for p in $$list; do echo "$$p"; done | \
+	  sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+	      -e 's/$$/$(EXEEXT)/' \
+	`; \
+	test -n "$$list" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+	@list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
+	echo " rm -f" $$list; \
+	rm -f $$list || exit $$?; \
+	test -n "$(EXEEXT)" || exit 0; \
+	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+	echo " rm -f" $$list; \
+	rm -f $$list
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
+	fi; \
+	for p in $$list; do echo "$$p $$p"; done | \
+	sed 's/$(EXEEXT)$$//' | \
+	while read p p1; do if test -f $$p \
+	 || test -f $$p1 \
+	  ; then echo "$$p"; echo "$$p"; else :; fi; \
+	done | \
+	sed -e 'p;s,.*/,,;n;h' \
+	    -e 's|.*|.|' \
+	    -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+	sed 'N;N;N;s,\n, ,g' | \
+	$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+	  { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+	    if ($$2 == $$4) files[d] = files[d] " " $$1; \
+	    else { print "f", $$3 "/" $$4, $$1; } } \
+	  END { for (d in files) print "f", d, files[d] }' | \
+	while read type dir files; do \
+	    if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+	    test -z "$$files" || { \
+	    echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
+	    $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
+	    } \
+	; done
+
+uninstall-sbinPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+	files=`for p in $$list; do echo "$$p"; done | \
+	  sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+	      -e 's/$$/$(EXEEXT)/' \
+	`; \
+	test -n "$$list" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(sbindir)" && rm -f $$files
+
+clean-sbinPROGRAMS:
+	@list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \
+	echo " rm -f" $$list; \
+	rm -f $$list || exit $$?; \
+	test -n "$(EXEEXT)" || exit 0; \
+	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+	echo " rm -f" $$list; \
+	rm -f $$list
+
+mkntfs$(EXEEXT): $(mkntfs_OBJECTS) $(mkntfs_DEPENDENCIES) $(EXTRA_mkntfs_DEPENDENCIES) 
+	@rm -f mkntfs$(EXEEXT)
+	$(AM_V_CCLD)$(mkntfs_LINK) $(mkntfs_OBJECTS) $(mkntfs_LDADD) $(LIBS)
+
+ntfscat$(EXEEXT): $(ntfscat_OBJECTS) $(ntfscat_DEPENDENCIES) $(EXTRA_ntfscat_DEPENDENCIES) 
+	@rm -f ntfscat$(EXEEXT)
+	$(AM_V_CCLD)$(ntfscat_LINK) $(ntfscat_OBJECTS) $(ntfscat_LDADD) $(LIBS)
+
+ntfsck$(EXEEXT): $(ntfsck_OBJECTS) $(ntfsck_DEPENDENCIES) $(EXTRA_ntfsck_DEPENDENCIES) 
+	@rm -f ntfsck$(EXEEXT)
+	$(AM_V_CCLD)$(ntfsck_LINK) $(ntfsck_OBJECTS) $(ntfsck_LDADD) $(LIBS)
+
+ntfsclone$(EXEEXT): $(ntfsclone_OBJECTS) $(ntfsclone_DEPENDENCIES) $(EXTRA_ntfsclone_DEPENDENCIES) 
+	@rm -f ntfsclone$(EXEEXT)
+	$(AM_V_CCLD)$(ntfsclone_LINK) $(ntfsclone_OBJECTS) $(ntfsclone_LDADD) $(LIBS)
+
+ntfscluster$(EXEEXT): $(ntfscluster_OBJECTS) $(ntfscluster_DEPENDENCIES) $(EXTRA_ntfscluster_DEPENDENCIES) 
+	@rm -f ntfscluster$(EXEEXT)
+	$(AM_V_CCLD)$(ntfscluster_LINK) $(ntfscluster_OBJECTS) $(ntfscluster_LDADD) $(LIBS)
+
+ntfscmp$(EXEEXT): $(ntfscmp_OBJECTS) $(ntfscmp_DEPENDENCIES) $(EXTRA_ntfscmp_DEPENDENCIES) 
+	@rm -f ntfscmp$(EXEEXT)
+	$(AM_V_CCLD)$(ntfscmp_LINK) $(ntfscmp_OBJECTS) $(ntfscmp_LDADD) $(LIBS)
+
+ntfscp$(EXEEXT): $(ntfscp_OBJECTS) $(ntfscp_DEPENDENCIES) $(EXTRA_ntfscp_DEPENDENCIES) 
+	@rm -f ntfscp$(EXEEXT)
+	$(AM_V_CCLD)$(ntfscp_LINK) $(ntfscp_OBJECTS) $(ntfscp_LDADD) $(LIBS)
+
+ntfsdecrypt$(EXEEXT): $(ntfsdecrypt_OBJECTS) $(ntfsdecrypt_DEPENDENCIES) $(EXTRA_ntfsdecrypt_DEPENDENCIES) 
+	@rm -f ntfsdecrypt$(EXEEXT)
+	$(AM_V_CCLD)$(ntfsdecrypt_LINK) $(ntfsdecrypt_OBJECTS) $(ntfsdecrypt_LDADD) $(LIBS)
+
+ntfsdump_logfile$(EXEEXT): $(ntfsdump_logfile_OBJECTS) $(ntfsdump_logfile_DEPENDENCIES) $(EXTRA_ntfsdump_logfile_DEPENDENCIES) 
+	@rm -f ntfsdump_logfile$(EXEEXT)
+	$(AM_V_CCLD)$(ntfsdump_logfile_LINK) $(ntfsdump_logfile_OBJECTS) $(ntfsdump_logfile_LDADD) $(LIBS)
+
+ntfsfallocate$(EXEEXT): $(ntfsfallocate_OBJECTS) $(ntfsfallocate_DEPENDENCIES) $(EXTRA_ntfsfallocate_DEPENDENCIES) 
+	@rm -f ntfsfallocate$(EXEEXT)
+	$(AM_V_CCLD)$(ntfsfallocate_LINK) $(ntfsfallocate_OBJECTS) $(ntfsfallocate_LDADD) $(LIBS)
+
+ntfsfix$(EXEEXT): $(ntfsfix_OBJECTS) $(ntfsfix_DEPENDENCIES) $(EXTRA_ntfsfix_DEPENDENCIES) 
+	@rm -f ntfsfix$(EXEEXT)
+	$(AM_V_CCLD)$(ntfsfix_LINK) $(ntfsfix_OBJECTS) $(ntfsfix_LDADD) $(LIBS)
+
+ntfsinfo$(EXEEXT): $(ntfsinfo_OBJECTS) $(ntfsinfo_DEPENDENCIES) $(EXTRA_ntfsinfo_DEPENDENCIES) 
+	@rm -f ntfsinfo$(EXEEXT)
+	$(AM_V_CCLD)$(ntfsinfo_LINK) $(ntfsinfo_OBJECTS) $(ntfsinfo_LDADD) $(LIBS)
+
+ntfslabel$(EXEEXT): $(ntfslabel_OBJECTS) $(ntfslabel_DEPENDENCIES) $(EXTRA_ntfslabel_DEPENDENCIES) 
+	@rm -f ntfslabel$(EXEEXT)
+	$(AM_V_CCLD)$(ntfslabel_LINK) $(ntfslabel_OBJECTS) $(ntfslabel_LDADD) $(LIBS)
+
+ntfsls$(EXEEXT): $(ntfsls_OBJECTS) $(ntfsls_DEPENDENCIES) $(EXTRA_ntfsls_DEPENDENCIES) 
+	@rm -f ntfsls$(EXEEXT)
+	$(AM_V_CCLD)$(ntfsls_LINK) $(ntfsls_OBJECTS) $(ntfsls_LDADD) $(LIBS)
+
+ntfsmftalloc$(EXEEXT): $(ntfsmftalloc_OBJECTS) $(ntfsmftalloc_DEPENDENCIES) $(EXTRA_ntfsmftalloc_DEPENDENCIES) 
+	@rm -f ntfsmftalloc$(EXEEXT)
+	$(AM_V_CCLD)$(ntfsmftalloc_LINK) $(ntfsmftalloc_OBJECTS) $(ntfsmftalloc_LDADD) $(LIBS)
+
+ntfsmove$(EXEEXT): $(ntfsmove_OBJECTS) $(ntfsmove_DEPENDENCIES) $(EXTRA_ntfsmove_DEPENDENCIES) 
+	@rm -f ntfsmove$(EXEEXT)
+	$(AM_V_CCLD)$(ntfsmove_LINK) $(ntfsmove_OBJECTS) $(ntfsmove_LDADD) $(LIBS)
+
+ntfsresize$(EXEEXT): $(ntfsresize_OBJECTS) $(ntfsresize_DEPENDENCIES) $(EXTRA_ntfsresize_DEPENDENCIES) 
+	@rm -f ntfsresize$(EXEEXT)
+	$(AM_V_CCLD)$(ntfsresize_LINK) $(ntfsresize_OBJECTS) $(ntfsresize_LDADD) $(LIBS)
+
+ntfstruncate$(EXEEXT): $(ntfstruncate_OBJECTS) $(ntfstruncate_DEPENDENCIES) $(EXTRA_ntfstruncate_DEPENDENCIES) 
+	@rm -f ntfstruncate$(EXEEXT)
+	$(AM_V_CCLD)$(ntfstruncate_LINK) $(ntfstruncate_OBJECTS) $(ntfstruncate_LDADD) $(LIBS)
+
+ntfsundelete$(EXEEXT): $(ntfsundelete_OBJECTS) $(ntfsundelete_DEPENDENCIES) $(EXTRA_ntfsundelete_DEPENDENCIES) 
+	@rm -f ntfsundelete$(EXEEXT)
+	$(AM_V_CCLD)$(ntfsundelete_LINK) $(ntfsundelete_OBJECTS) $(ntfsundelete_LDADD) $(LIBS)
+
+ntfswipe$(EXEEXT): $(ntfswipe_OBJECTS) $(ntfswipe_DEPENDENCIES) $(EXTRA_ntfswipe_DEPENDENCIES) 
+	@rm -f ntfswipe$(EXEEXT)
+	$(AM_V_CCLD)$(ntfswipe_LINK) $(ntfswipe_OBJECTS) $(ntfswipe_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attrdef.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cluster.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkntfs-attrdef.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkntfs-boot.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkntfs-mkntfs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkntfs-sd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkntfs-utils.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfscat.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfsck.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfsclone.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfscluster.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfscmp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfscp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfsdecrypt-ntfsdecrypt.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfsdecrypt-utils.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfsdump_logfile.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfsfallocate.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfsfix.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfsinfo.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfslabel.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfsls.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfsmftalloc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfsmove.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfsresize.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfstruncate.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfsundelete.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfswipe.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mkntfs-attrdef.o: attrdef.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mkntfs-attrdef.o -MD -MP -MF $(DEPDIR)/mkntfs-attrdef.Tpo -c -o mkntfs-attrdef.o `test -f 'attrdef.c' || echo '$(srcdir)/'`attrdef.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/mkntfs-attrdef.Tpo $(DEPDIR)/mkntfs-attrdef.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='attrdef.c' object='mkntfs-attrdef.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mkntfs-attrdef.o `test -f 'attrdef.c' || echo '$(srcdir)/'`attrdef.c
+
+mkntfs-attrdef.obj: attrdef.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mkntfs-attrdef.obj -MD -MP -MF $(DEPDIR)/mkntfs-attrdef.Tpo -c -o mkntfs-attrdef.obj `if test -f 'attrdef.c'; then $(CYGPATH_W) 'attrdef.c'; else $(CYGPATH_W) '$(srcdir)/attrdef.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/mkntfs-attrdef.Tpo $(DEPDIR)/mkntfs-attrdef.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='attrdef.c' object='mkntfs-attrdef.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mkntfs-attrdef.obj `if test -f 'attrdef.c'; then $(CYGPATH_W) 'attrdef.c'; else $(CYGPATH_W) '$(srcdir)/attrdef.c'; fi`
+
+mkntfs-boot.o: boot.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mkntfs-boot.o -MD -MP -MF $(DEPDIR)/mkntfs-boot.Tpo -c -o mkntfs-boot.o `test -f 'boot.c' || echo '$(srcdir)/'`boot.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/mkntfs-boot.Tpo $(DEPDIR)/mkntfs-boot.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='boot.c' object='mkntfs-boot.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mkntfs-boot.o `test -f 'boot.c' || echo '$(srcdir)/'`boot.c
+
+mkntfs-boot.obj: boot.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mkntfs-boot.obj -MD -MP -MF $(DEPDIR)/mkntfs-boot.Tpo -c -o mkntfs-boot.obj `if test -f 'boot.c'; then $(CYGPATH_W) 'boot.c'; else $(CYGPATH_W) '$(srcdir)/boot.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/mkntfs-boot.Tpo $(DEPDIR)/mkntfs-boot.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='boot.c' object='mkntfs-boot.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mkntfs-boot.obj `if test -f 'boot.c'; then $(CYGPATH_W) 'boot.c'; else $(CYGPATH_W) '$(srcdir)/boot.c'; fi`
+
+mkntfs-sd.o: sd.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mkntfs-sd.o -MD -MP -MF $(DEPDIR)/mkntfs-sd.Tpo -c -o mkntfs-sd.o `test -f 'sd.c' || echo '$(srcdir)/'`sd.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/mkntfs-sd.Tpo $(DEPDIR)/mkntfs-sd.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='sd.c' object='mkntfs-sd.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mkntfs-sd.o `test -f 'sd.c' || echo '$(srcdir)/'`sd.c
+
+mkntfs-sd.obj: sd.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mkntfs-sd.obj -MD -MP -MF $(DEPDIR)/mkntfs-sd.Tpo -c -o mkntfs-sd.obj `if test -f 'sd.c'; then $(CYGPATH_W) 'sd.c'; else $(CYGPATH_W) '$(srcdir)/sd.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/mkntfs-sd.Tpo $(DEPDIR)/mkntfs-sd.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='sd.c' object='mkntfs-sd.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mkntfs-sd.obj `if test -f 'sd.c'; then $(CYGPATH_W) 'sd.c'; else $(CYGPATH_W) '$(srcdir)/sd.c'; fi`
+
+mkntfs-mkntfs.o: mkntfs.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mkntfs-mkntfs.o -MD -MP -MF $(DEPDIR)/mkntfs-mkntfs.Tpo -c -o mkntfs-mkntfs.o `test -f 'mkntfs.c' || echo '$(srcdir)/'`mkntfs.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/mkntfs-mkntfs.Tpo $(DEPDIR)/mkntfs-mkntfs.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='mkntfs.c' object='mkntfs-mkntfs.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mkntfs-mkntfs.o `test -f 'mkntfs.c' || echo '$(srcdir)/'`mkntfs.c
+
+mkntfs-mkntfs.obj: mkntfs.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mkntfs-mkntfs.obj -MD -MP -MF $(DEPDIR)/mkntfs-mkntfs.Tpo -c -o mkntfs-mkntfs.obj `if test -f 'mkntfs.c'; then $(CYGPATH_W) 'mkntfs.c'; else $(CYGPATH_W) '$(srcdir)/mkntfs.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/mkntfs-mkntfs.Tpo $(DEPDIR)/mkntfs-mkntfs.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='mkntfs.c' object='mkntfs-mkntfs.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mkntfs-mkntfs.obj `if test -f 'mkntfs.c'; then $(CYGPATH_W) 'mkntfs.c'; else $(CYGPATH_W) '$(srcdir)/mkntfs.c'; fi`
+
+mkntfs-utils.o: utils.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mkntfs-utils.o -MD -MP -MF $(DEPDIR)/mkntfs-utils.Tpo -c -o mkntfs-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/mkntfs-utils.Tpo $(DEPDIR)/mkntfs-utils.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='utils.c' object='mkntfs-utils.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mkntfs-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c
+
+mkntfs-utils.obj: utils.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mkntfs-utils.obj -MD -MP -MF $(DEPDIR)/mkntfs-utils.Tpo -c -o mkntfs-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/mkntfs-utils.Tpo $(DEPDIR)/mkntfs-utils.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='utils.c' object='mkntfs-utils.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mkntfs_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mkntfs-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi`
+
+ntfsdecrypt-ntfsdecrypt.o: ntfsdecrypt.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfsdecrypt_CFLAGS) $(CFLAGS) -MT ntfsdecrypt-ntfsdecrypt.o -MD -MP -MF $(DEPDIR)/ntfsdecrypt-ntfsdecrypt.Tpo -c -o ntfsdecrypt-ntfsdecrypt.o `test -f 'ntfsdecrypt.c' || echo '$(srcdir)/'`ntfsdecrypt.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/ntfsdecrypt-ntfsdecrypt.Tpo $(DEPDIR)/ntfsdecrypt-ntfsdecrypt.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ntfsdecrypt.c' object='ntfsdecrypt-ntfsdecrypt.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfsdecrypt_CFLAGS) $(CFLAGS) -c -o ntfsdecrypt-ntfsdecrypt.o `test -f 'ntfsdecrypt.c' || echo '$(srcdir)/'`ntfsdecrypt.c
+
+ntfsdecrypt-ntfsdecrypt.obj: ntfsdecrypt.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfsdecrypt_CFLAGS) $(CFLAGS) -MT ntfsdecrypt-ntfsdecrypt.obj -MD -MP -MF $(DEPDIR)/ntfsdecrypt-ntfsdecrypt.Tpo -c -o ntfsdecrypt-ntfsdecrypt.obj `if test -f 'ntfsdecrypt.c'; then $(CYGPATH_W) 'ntfsdecrypt.c'; else $(CYGPATH_W) '$(srcdir)/ntfsdecrypt.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/ntfsdecrypt-ntfsdecrypt.Tpo $(DEPDIR)/ntfsdecrypt-ntfsdecrypt.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ntfsdecrypt.c' object='ntfsdecrypt-ntfsdecrypt.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfsdecrypt_CFLAGS) $(CFLAGS) -c -o ntfsdecrypt-ntfsdecrypt.obj `if test -f 'ntfsdecrypt.c'; then $(CYGPATH_W) 'ntfsdecrypt.c'; else $(CYGPATH_W) '$(srcdir)/ntfsdecrypt.c'; fi`
+
+ntfsdecrypt-utils.o: utils.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfsdecrypt_CFLAGS) $(CFLAGS) -MT ntfsdecrypt-utils.o -MD -MP -MF $(DEPDIR)/ntfsdecrypt-utils.Tpo -c -o ntfsdecrypt-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/ntfsdecrypt-utils.Tpo $(DEPDIR)/ntfsdecrypt-utils.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='utils.c' object='ntfsdecrypt-utils.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfsdecrypt_CFLAGS) $(CFLAGS) -c -o ntfsdecrypt-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c
+
+ntfsdecrypt-utils.obj: utils.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfsdecrypt_CFLAGS) $(CFLAGS) -MT ntfsdecrypt-utils.obj -MD -MP -MF $(DEPDIR)/ntfsdecrypt-utils.Tpo -c -o ntfsdecrypt-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/ntfsdecrypt-utils.Tpo $(DEPDIR)/ntfsdecrypt-utils.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='utils.c' object='ntfsdecrypt-utils.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfsdecrypt_CFLAGS) $(CFLAGS) -c -o ntfsdecrypt-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi`
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+install-man8: $(man_MANS)
+	@$(NORMAL_INSTALL)
+	@list1=''; \
+	list2='$(man_MANS)'; \
+	test -n "$(man8dir)" \
+	  && test -n "`echo $$list1$$list2`" \
+	  || exit 0; \
+	echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
+	$(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \
+	{ for i in $$list1; do echo "$$i"; done;  \
+	if test -n "$$list2"; then \
+	  for i in $$list2; do echo "$$i"; done \
+	    | sed -n '/\.8[a-z]*$$/p'; \
+	fi; \
+	} | while read p; do \
+	  if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; echo "$$p"; \
+	done | \
+	sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+	sed 'N;N;s,\n, ,g' | { \
+	list=; while read file base inst; do \
+	  if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+	    echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
+	    $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \
+	  fi; \
+	done; \
+	for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+	while read files; do \
+	  test -z "$$files" || { \
+	    echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \
+	    $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
+	done; }
+
+uninstall-man8:
+	@$(NORMAL_UNINSTALL)
+	@list=''; test -n "$(man8dir)" || exit 0; \
+	files=`{ for i in $$list; do echo "$$i"; done; \
+	l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+	  sed -n '/\.8[a-z]*$$/p'; \
+	} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+	dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) $(MANS)
+installdirs:
+	for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+@ENABLE_NTFSPROGS_FALSE@uninstall-local:
+@ENABLE_NTFSPROGS_FALSE@install-exec-hook:
+@ENABLE_NTFSPROGS_FALSE@install-data-hook:
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool \
+	clean-sbinPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-man
+	@$(NORMAL_INSTALL)
+	$(MAKE) $(AM_MAKEFLAGS) install-data-hook
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS install-sbinPROGRAMS
+	@$(NORMAL_INSTALL)
+	$(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man: install-man8
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-local uninstall-man \
+	uninstall-sbinPROGRAMS
+
+uninstall-man: uninstall-man8
+
+.MAKE: install-am install-data-am install-exec-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
+	clean-binPROGRAMS clean-generic clean-libtool \
+	clean-sbinPROGRAMS cscopelist-am ctags ctags-am distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-binPROGRAMS install-data \
+	install-data-am install-data-hook install-dvi install-dvi-am \
+	install-exec install-exec-am install-exec-hook install-html \
+	install-html-am install-info install-info-am install-man \
+	install-man8 install-pdf install-pdf-am install-ps \
+	install-ps-am install-sbinPROGRAMS install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	tags tags-am uninstall uninstall-am uninstall-binPROGRAMS \
+	uninstall-local uninstall-man uninstall-man8 \
+	uninstall-sbinPROGRAMS
+
+
+# Extra targets
+
+@ENABLE_NTFSPROGS_TRUE@strip:	$(bin_PROGRAMS) $(sbin_PROGRAMS)
+@ENABLE_NTFSPROGS_TRUE@	$(STRIP) $^
+
+@ENABLE_NTFSPROGS_TRUE@libs:
+@ENABLE_NTFSPROGS_TRUE@	(cd ../libntfs-3g && $(MAKE) libs) || exit 1;
+
+@ENABLE_NTFSPROGS_TRUE@extra:	extras
+
+@ENABLE_NTFSPROGS_TRUE@extras:	libs $(EXTRA_PROGRAMS)
+
+# mkfs.ntfs[.8] hard link
+
+@ENABLE_NTFSPROGS_TRUE@install-exec-hook:
+@ENABLE_NTFSPROGS_TRUE@	$(INSTALL) -d $(DESTDIR)/sbin
+@ENABLE_NTFSPROGS_TRUE@	$(LN_S) -f $(sbindir)/mkntfs $(DESTDIR)/sbin/mkfs.ntfs
+
+@ENABLE_NTFSPROGS_TRUE@install-data-hook:
+@ENABLE_NTFSPROGS_TRUE@	$(INSTALL) -d $(DESTDIR)$(man8dir)
+@ENABLE_NTFSPROGS_TRUE@	$(LN_S) -f mkntfs.8 $(DESTDIR)$(man8dir)/mkfs.ntfs.8
+
+@ENABLE_NTFSPROGS_TRUE@uninstall-local:
+@ENABLE_NTFSPROGS_TRUE@	$(RM) -f $(DESTDIR)/sbin/mkfs.ntfs
+@ENABLE_NTFSPROGS_TRUE@	$(RM) -f $(DESTDIR)$(man8dir)/mkfs.ntfs.8
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/ntfsprogs/attrdef.c b/ntfsprogs/attrdef.c
new file mode 100755
index 0000000000000000000000000000000000000000..36501e5c276c474e7bd700f28ba22bcc2cadfd88
--- /dev/null
+++ b/ntfsprogs/attrdef.c
@@ -0,0 +1,168 @@
+#include "attrdef.h"
+
+/**
+ * attrdef_ntfs3x_array
+ */
+const unsigned char attrdef_ntfs3x_array[2560] = {
+0x24, 0x00, 0x53, 0x00, 0x54, 0x00, 0x41, 0x00, 0x4E, 0x00, 0x44, 0x00, 0x41, 0x00, 0x52, 0x00,
+0x44, 0x00, 0x5F, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x46, 0x00, 0x4F, 0x00, 0x52, 0x00, 0x4D, 0x00,
+0x41, 0x00, 0x54, 0x00, 0x49, 0x00, 0x4F, 0x00, 0x4E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x24, 0x00, 0x41, 0x00, 0x54, 0x00, 0x54, 0x00, 0x52, 0x00, 0x49, 0x00, 0x42, 0x00, 0x55, 0x00,
+0x54, 0x00, 0x45, 0x00, 0x5F, 0x00, 0x4C, 0x00, 0x49, 0x00, 0x53, 0x00, 0x54, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+0x24, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4C, 0x00, 0x45, 0x00, 0x5F, 0x00, 0x4E, 0x00, 0x41, 0x00,
+0x4D, 0x00, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00,
+0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x24, 0x00, 0x4F, 0x00, 0x42, 0x00, 0x4A, 0x00, 0x45, 0x00, 0x43, 0x00, 0x54, 0x00, 0x5F, 0x00,
+0x49, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x24, 0x00, 0x53, 0x00, 0x45, 0x00, 0x43, 0x00, 0x55, 0x00, 0x52, 0x00, 0x49, 0x00, 0x54, 0x00,
+0x59, 0x00, 0x5F, 0x00, 0x44, 0x00, 0x45, 0x00, 0x53, 0x00, 0x43, 0x00, 0x52, 0x00, 0x49, 0x00,
+0x50, 0x00, 0x54, 0x00, 0x4F, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+0x24, 0x00, 0x56, 0x00, 0x4F, 0x00, 0x4C, 0x00, 0x55, 0x00, 0x4D, 0x00, 0x45, 0x00, 0x5F, 0x00,
+0x4E, 0x00, 0x41, 0x00, 0x4D, 0x00, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x24, 0x00, 0x56, 0x00, 0x4F, 0x00, 0x4C, 0x00, 0x55, 0x00, 0x4D, 0x00, 0x45, 0x00, 0x5F, 0x00,
+0x49, 0x00, 0x4E, 0x00, 0x46, 0x00, 0x4F, 0x00, 0x52, 0x00, 0x4D, 0x00, 0x41, 0x00, 0x54, 0x00,
+0x49, 0x00, 0x4F, 0x00, 0x4E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x24, 0x00, 0x44, 0x00, 0x41, 0x00, 0x54, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+0x24, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x44, 0x00, 0x45, 0x00, 0x58, 0x00, 0x5F, 0x00, 0x52, 0x00,
+0x4F, 0x00, 0x4F, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+0x24, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x44, 0x00, 0x45, 0x00, 0x58, 0x00, 0x5F, 0x00, 0x41, 0x00,
+0x4C, 0x00, 0x4C, 0x00, 0x4F, 0x00, 0x43, 0x00, 0x41, 0x00, 0x54, 0x00, 0x49, 0x00, 0x4F, 0x00,
+0x4E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+0x24, 0x00, 0x42, 0x00, 0x49, 0x00, 0x54, 0x00, 0x4D, 0x00, 0x41, 0x00, 0x50, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+0x24, 0x00, 0x52, 0x00, 0x45, 0x00, 0x50, 0x00, 0x41, 0x00, 0x52, 0x00, 0x53, 0x00, 0x45, 0x00,
+0x5F, 0x00, 0x50, 0x00, 0x4F, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x24, 0x00, 0x45, 0x00, 0x41, 0x00, 0x5F, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x46, 0x00, 0x4F, 0x00,
+0x52, 0x00, 0x4D, 0x00, 0x41, 0x00, 0x54, 0x00, 0x49, 0x00, 0x4F, 0x00, 0x4E, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x24, 0x00, 0x45, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x24, 0x00, 0x4C, 0x00, 0x4F, 0x00, 0x47, 0x00, 0x47, 0x00, 0x45, 0x00, 0x44, 0x00, 0x5F, 0x00,
+0x55, 0x00, 0x54, 0x00, 0x49, 0x00, 0x4C, 0x00, 0x49, 0x00, 0x54, 0x00, 0x59, 0x00, 0x5F, 0x00,
+0x53, 0x00, 0x54, 0x00, 0x52, 0x00, 0x45, 0x00, 0x41, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
diff --git a/ntfsprogs/attrdef.h b/ntfsprogs/attrdef.h
new file mode 100755
index 0000000000000000000000000000000000000000..0c664394e0ccf7d09938f92010756d9c83499918
--- /dev/null
+++ b/ntfsprogs/attrdef.h
@@ -0,0 +1,7 @@
+#ifndef _NTFS_ATTRDEF_H_
+#define _NTFS_ATTRDEF_H_
+
+extern const unsigned char attrdef_ntfs3x_array[2560];
+
+#endif /* _NTFS_ATTRDEF_H_ */
+
diff --git a/ntfsprogs/boot.c b/ntfsprogs/boot.c
new file mode 100755
index 0000000000000000000000000000000000000000..9272be9fb1d2fb0e69f763f3b2f78e85b503fac6
--- /dev/null
+++ b/ntfsprogs/boot.c
@@ -0,0 +1,268 @@
+#include "boot.h"
+
+/**
+ * boot_array - the first 4136 bytes of $Boot
+ *
+ * The first 4136 bytes of $Boot. The rest is just zero. Total 8192 bytes.
+ */
+const unsigned char boot_array[4136] = {
+235,  82, 144,  78,  84,  70,  83,  32,  32,  32,  32,   0,   0,   0,   0,   0,
+  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  0,   0,   0,   0, 250,  51, 192, 142, 208, 188,   0, 124, 251, 104, 192,   7,
+ 31,  30, 104, 102,   0, 203, 136,  22,  14,   0, 102, 129,  62,   3,   0,  78,
+ 84,  70,  83, 117,  21, 180,  65, 187, 170,  85, 205,  19, 114,  12, 129, 251,
+ 85, 170, 117,   6, 247, 193,   1,   0, 117,   3, 233, 210,   0,  30, 131, 236,
+ 24, 104,  26,   0, 180,  72, 138,  22,  14,   0, 139, 244,  22,  31, 205,  19,
+159, 131, 196,  24, 158,  88,  31, 114, 225,  59,   6,  11,   0, 117, 219, 163,
+ 15,   0, 193,  46,  15,   0,   4,  30,  90,  51, 219, 185,   0,  32,  43, 200,
+102, 255,   6,  17,   0,   3,  22,  15,   0, 142, 194, 255,   6,  22,   0, 232,
+ 64,   0,  43, 200, 119, 239, 184,   0, 187, 205,  26, 102,  35, 192, 117,  45,
+102, 129, 251,  84,  67,  80,  65, 117,  36, 129, 249,   2,   1, 114,  30,  22,
+104,   7, 187,  22, 104, 112,  14,  22, 104,   9,   0, 102,  83, 102,  83, 102,
+ 85,  22,  22,  22, 104, 184,   1, 102,  97,  14,   7, 205,  26, 233, 106,   1,
+144, 144, 102,  96,  30,   6, 102, 161,  17,   0, 102,   3,   6,  28,   0,  30,
+102, 104,   0,   0,   0,   0, 102,  80,   6,  83, 104,   1,   0, 104,  16,   0,
+180,  66, 138,  22,  14,   0,  22,  31, 139, 244, 205,  19, 102,  89,  91,  90,
+102,  89, 102,  89,  31,  15, 130,  22,   0, 102, 255,   6,  17,   0,   3,  22,
+ 15,   0, 142, 194, 255,  14,  22,   0, 117, 188,   7,  31, 102,  97, 195, 160,
+248,   1, 232,   8,   0, 160, 251,   1, 232,   2,   0, 235, 254, 180,   1, 139,
+240, 172,  60,   0, 116,   9, 180,  14, 187,   7,   0, 205,  16, 235, 242, 195,
+ 13,  10,  65,  32, 100, 105, 115, 107,  32, 114, 101,  97, 100,  32, 101, 114,
+114, 111, 114,  32, 111,  99,  99, 117, 114, 114, 101, 100,   0,  13,  10,  66,
+ 79,  79,  84,  77,  71,  82,  32, 105, 115,  32, 109, 105, 115, 115, 105, 110,
+103,   0,  13,  10,  66,  79,  79,  84,  77,  71,  82,  32, 105, 115,  32,  99,
+111, 109, 112, 114, 101, 115, 115, 101, 100,   0,  13,  10,  80, 114, 101, 115,
+115,  32,  67, 116, 114, 108,  43,  65, 108, 116,  43,  68, 101, 108,  32, 116,
+111,  32, 114, 101, 115, 116,  97, 114, 116,  13,  10,   0,   0,   0,   0,   0,
+  0,   0,   0,   0,   0,   0,   0,   0, 128, 157, 178, 202,   0,   0,  85, 170,
+  7,   0,  66,   0,  79,   0,  79,   0,  84,   0,  77,   0,  71,   0,  82,   0,
+  4,   0,  36,   0,  73,   0,  51,   0,  48,   0,   0, 224,   0,   0,   0,  48,
+  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  0,   0,   0,   0,   0,   0, 235,  34, 144, 144,   5,   0,  78,   0,  84,   0,
+ 76,   0,  68,   0,  82,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 102,  15, 183,   6,  11,   0,
+102,  15, 182,  30,  13,   0, 102, 247, 227, 102, 163,  82,   2, 102, 139,  14,
+ 64,   0, 128, 249,   0,  15, 143,  14,   0, 246, 217, 102, 184,   1,   0,   0,
+  0, 102, 211, 224, 235,   8, 144, 102, 161,  82,   2, 102, 247, 225, 102, 163,
+102,   2, 102,  15, 183,  30,  11,   0, 102,  51, 210, 102, 247, 243, 102, 163,
+ 86,   2, 232, 149,   4, 102, 139,  14,  78,   2, 102, 137,  14,  38,   2, 102,
+  3,  14, 102,   2, 102, 137,  14,  42,   2, 102,   3,  14, 102,   2, 102, 137,
+ 14,  46,   2, 102,   3,  14, 102,   2, 102, 137,  14,  62,   2, 102,   3,  14,
+102,   2, 102, 137,  14,  70,   2, 102, 184, 144,   0,   0,   0, 102, 139,  14,
+ 38,   2, 232, 131,   9, 102,  11, 192,  15, 132,  83, 254, 102, 163,  50,   2,
+102, 184, 160,   0,   0,   0, 102, 139,  14,  42,   2, 232, 106,   9, 102, 163,
+ 54,   2, 102, 184, 176,   0,   0,   0, 102, 139,  14,  46,   2, 232,  88,   9,
+102, 163,  58,   2, 102, 161,  50,   2, 102,  11, 192,  15, 132,  32, 254, 103,
+128, 120,   8,   0,  15, 133,  23, 254, 103, 102, 141,  80,  16, 103,   3,  66,
+  4, 103, 102,  15, 182,  72,  12, 102, 137,  14, 114,   2, 103, 102, 139,  72,
+  8, 102, 137,  14, 110,   2, 102, 161, 110,   2, 102,  15, 183,  14,  11,   0,
+102,  51, 210, 102, 247, 241, 102, 163, 118,   2, 102, 161,  70,   2, 102,   3,
+  6, 110,   2, 102, 163,  74,   2, 102, 131,  62,  54,   2,   0,  15, 132,  29,
+  0, 102, 131,  62,  58,   2,   0,  15, 132, 196, 253, 102, 139,  30,  58,   2,
+ 30,   7, 102, 139,  62,  74,   2, 102, 161,  46,   2, 232, 224,   1, 102,  15,
+183,  14,   0,   2, 102, 184,   2,   2,   0,   0, 232,  34,   8, 102,  11, 192,
+ 15, 133,  22,   0, 102,  15, 183,  14,  90,   2, 102, 184,  92,   2,   0,   0,
+232,  12,   8, 102,  11, 192,  15, 132,  66,  12, 103, 102, 139,   0,  30,   7,
+102, 139,  62,  62,   2, 232,  63,   6, 102, 161,  62,   2, 102, 187,  32,   0,
+  0,   0, 102, 185,   0,   0,   0,   0, 102, 186,   0,   0,   0,   0, 232, 228,
+  0, 102, 133, 192,  15, 133,  35,   0, 102, 161,  62,   2, 102, 187, 128,   0,
+  0,   0, 102, 185,   0,   0,   0,   0, 102, 186,   0,   0,   0,   0, 232, 196,
+  0, 102,  11, 192,  15, 133,  68,   0, 233, 241,  11, 102,  51, 210, 102, 185,
+128,   0,   0,   0, 102, 161,  62,   2, 232, 202,   8, 102,  11, 192,  15, 132,
+218,  11,  30,   7, 102, 139,  62,  62,   2, 232, 219,   5, 102, 161,  62,   2,
+102, 187, 128,   0,   0,   0, 102, 185,   0,   0,   0,   0, 102, 186,   0,   0,
+  0,   0, 232, 128,   0, 102,  11, 192,  15, 132, 176,  11, 103, 102,  15, 183,
+ 88,  12, 102, 129, 227, 255,   0,   0,   0,  15, 133, 165,  11, 102, 139, 216,
+104,   0,  32,   7, 102,  43, 255, 102, 161,  62,   2, 232,   0,   1, 104,   0,
+ 32,   7, 102,  43, 255, 102, 161,  62,   2, 232, 172,  10, 138,  22,  14,   0,
+184, 232,   3, 142, 192, 141,  54,  11,   0,  43, 192, 104,   0,  32,  80, 203,
+  6,  30, 102,  96, 102, 139, 218, 102,  15, 182,  14,  13,   0, 102, 247, 225,
+102, 163,  17,   0, 102, 139, 195, 102, 247, 225, 163,  22,   0, 139, 223, 131,
+227,  15, 140, 192, 102, 193, 239,   4,   3, 199,  80,   7, 232,  51, 252, 102,
+ 97, 144,  31,   7, 195, 103,   3,  64,  20, 103, 102, 131,  56, 255,  15, 132,
+ 76,   0, 103, 102,  57,  24,  15, 133,  51,   0, 102,  11, 201,  15, 133,  10,
+  0, 103, 128, 120,   9,   0,  15, 133,  35,   0, 195, 103,  58,  72,   9,  15,
+133,  26,   0, 102, 139, 240, 103,   3, 112,  10, 232, 151,   6, 102,  81,  30,
+  7, 102, 139, 250, 243, 167, 102,  89,  15, 133,   1,   0, 195, 103, 102, 131,
+120,   4,   0,  15, 132,   7,   0, 103, 102,   3,  64,   4, 235, 171, 102,  43,
+192, 195, 102, 139, 243, 232, 108,   6, 103, 102,   3,   0, 103, 247,  64,  12,
+  2,   0,  15, 133,  52,   0, 103, 102, 141,  80,  16, 103,  58,  74,  64,  15,
+133,  24,   0, 103, 102, 141, 114,  66, 232,  73,   6, 102,  81,  30,   7, 102,
+139, 251, 243, 167, 102,  89,  15, 133,   1,   0, 195, 103, 131, 120,   8,   0,
+ 15, 132,   6,   0, 103,   3,  64,   8, 235, 194, 102,  51, 192, 195, 103, 128,
+123,   8,   0,  15, 133,  28,   0,   6,  30, 102,  96, 103, 102, 141,  83,  16,
+103, 102, 139,  10, 102, 139, 243, 103,   3, 114,   4, 243, 164, 102,  97, 144,
+ 31,   7, 195, 102,  80, 103, 102, 141,  83,  16, 102, 133, 192,  15, 133,  10,
+  0, 103, 102, 139,  74,   8, 102,  65, 235,  17, 144, 103, 102, 139,  66,  24,
+102,  51, 210, 102, 247,  54,  82,   2, 102, 139, 200, 102,  43, 192, 102,  94,
+232,   1,   0, 195,   6,  30, 102,  96, 103, 128, 123,   8,   1,  15, 132,   3,
+  0, 233, 107, 251, 102, 131, 249,   0,  15, 133,   6,   0, 102,  97, 144,  31,
+  7, 195, 102,  83, 102,  80, 102,  81, 102,  86, 102,  87,   6, 232, 145,   4,
+102, 139, 209,   7, 102,  95, 102,  94, 102,  89, 102, 133, 192,  15, 132,  52,
+  0, 102,  59, 202,  15, 141,   3,   0, 102, 139, 209, 232, 130, 254, 102,  43,
+202, 102, 139, 218, 102, 139, 194, 102,  15, 182,  22,  13,   0, 102, 247, 226,
+102,  15, 183,  22,  11,   0, 102, 247, 226, 102,   3, 248, 102,  88, 102,   3,
+195, 102,  91, 235, 159, 102, 133, 246,  15, 132,   3, 251, 102,  81, 102,  87,
+  6, 103, 102,  15, 182,  67,   9, 102, 133, 192,  15, 132,  32,   0, 102, 209,
+224, 102,  43, 224, 102, 139, 252, 102,  84, 102,  86, 103, 102,  15, 183, 115,
+ 10, 102,   3, 243, 102, 139, 200, 243, 164, 102,  94, 235,   3, 144, 102,  80,
+102,  80, 103, 102, 139,   3, 102,  80, 103, 102, 139,  67,  24, 102,  80, 103,
+102, 139,  86,  32, 102, 133, 210,  15, 132,  11,   0, 102, 139, 254,  30,   7,
+102, 139, 194, 232, 113,   3, 102, 139, 198, 102,  90, 102,  89, 102,  66, 102,
+ 81, 102,  86, 232,  63,   6, 102, 133, 192,  15, 132, 146, 250, 102,  94, 102,
+ 89, 102, 139, 254,  30,   7, 232,  78,   3, 102, 139, 198, 102, 139, 217, 102,
+ 89, 102,  90, 102,  81, 102,  86, 102, 209, 233, 232, 248, 253, 102, 133, 192,
+ 15, 132, 107, 250, 102,  94, 102,  89, 102,   3, 225,   7, 102,  95, 102,  89,
+102, 139, 208, 102,  88, 102,  91, 102, 139, 218, 233, 245, 254,   6,  30, 102,
+ 96,  38, 103, 102,  15, 183,  95,   4,  38, 103, 102,  15, 183,  79,   6, 102,
+ 11, 201,  15, 132,  57, 250, 102,   3, 223, 102, 131, 195,   2, 102, 129, 199,
+254,   1,   0,   0, 102,  73, 102,  11, 201,  15, 132,  23,   0,  38, 103, 139,
+  3,  38, 103, 137,   7, 102, 131, 195,   2, 102, 129, 199,   0,   2,   0,   0,
+102,  73, 235, 226, 102,  97, 144,  31,   7, 195,   6,  30, 102,  96, 102, 184,
+  1,   0,   0,   0, 102, 163,  34,   2, 102, 161,  30,   2, 102,   3,   6, 102,
+  2, 102, 163, 106,   2, 102,   3,   6, 102,   2, 102, 163,  78,   2, 102, 161,
+ 48,   0, 102,  15, 182,  30,  13,   0, 102, 247, 227, 102, 139,  30,  78,   2,
+102, 137,   7, 102, 163,  17,   0, 131, 195,   4, 102, 161,  86,   2, 102, 137,
+  7, 163,  22,   0, 131, 195,   4, 102, 137,  30,  78,   2, 102, 139,  30,  30,
+  2,  30,   7, 232,  92, 249, 102, 139, 251, 232,  81, 255, 102, 161,  30,   2,
+102, 187,  32,   0,   0,   0, 102, 185,   0,   0,   0,   0, 102, 186,   0,   0,
+  0,   0, 232,  16, 253, 102,  11, 192,  15, 132,  25,   1, 102, 139, 216,  30,
+  7, 102, 139,  62,  26,   2, 102,  51, 192, 232, 162, 253, 102, 139,  30,  26,
+  2, 102, 129,  63, 128,   0,   0,   0,  15, 132, 235,   0,   3,  95,   4, 235,
+240, 102,  83, 102, 139,  71,  16, 102, 247,  38,  86,   2, 102,  80, 102,  51,
+210, 102,  15, 182,  30,  13,   0, 102, 247, 243, 102,  82, 232, 220,   0, 102,
+ 11, 192,  15, 132,  57, 249, 102, 139,  14,  86,   2, 102,  15, 182,  30,  13,
+  0, 102, 247, 227, 102,  90, 102,   3, 194, 102, 139,  30,  78,   2, 102, 137,
+  7, 131, 195,   4, 102,  15, 182,   6,  13,   0, 102,  43, 194, 102,  59, 193,
+ 15, 134,   3,   0, 102, 139, 193, 102, 137,   7, 102,  43, 200, 102,  90,  15,
+132, 117,   0, 102,   3, 194, 102,  80, 102,  51, 210, 102,  15, 182,  30,  13,
+  0, 102, 247, 243, 102,  81, 232, 130,   0, 102,  89, 102,  11, 192,  15, 132,
+221, 248, 102,  15, 182,  30,  13,   0, 102, 247, 227, 102, 139,  30,  78,   2,
+102, 139,  23, 131, 195,   4, 102,   3,  23, 102,  59, 208,  15, 133,  21,   0,
+102,  15, 182,   6,  13,   0, 102,  59, 193,  15, 134,   3,   0, 102, 139, 193,
+102,   1,   7, 235, 165, 131, 195,   4, 102, 137,  30,  78,   2, 102, 137,   7,
+131, 195,   4, 102,  15, 182,   6,  13,   0, 102,  59, 193,  15, 134,   3,   0,
+102, 139, 193, 102, 137,   7, 235, 130, 131, 195,   4, 102, 255,   6,  34,   2,
+102, 137,  30,  78,   2, 102,  91,   3,  95,   4, 102, 129,  63, 128,   0,   0,
+  0,  15, 132,  12, 255, 102,  97, 144,  31,   7, 195, 102, 139, 208, 102, 139,
+ 14,  34,   2, 102, 139,  54, 106,   2, 102,   3,  54, 102,   2, 102,  82, 102,
+ 81, 102,  82, 102, 139,  30, 106,   2, 102, 139,  62,  86,   2, 102, 139,   4,
+102, 163,  17,   0, 131, 198,   4, 102, 139,   4, 163,  22,   0, 131, 198,   4,
+ 30,   7, 232, 221, 247, 102,  43, 248,  15, 132,   8,   0, 247,  38,  11,   0,
+  3, 216, 235, 217, 102, 139,  62, 106,   2,  30,   7, 232, 191, 253, 102, 161,
+106,   2, 102, 187, 128,   0,   0,   0, 102, 185,   0,   0,   0,   0, 102, 139,
+209, 232, 129, 251, 102,  11, 192,  15, 132, 244, 247, 102, 139, 216, 102,  88,
+102,  86, 232,  44,   1, 102,  94, 102,  11, 192,  15, 132,   5,   0, 102,  91,
+102,  91, 195, 102,  89, 102,  90, 226, 132, 102,  51, 192, 195,   6,  30, 102,
+ 96, 102,  80, 102,  81, 102,  51, 210, 102,  15, 182,  30,  13,   0, 102, 247,
+243, 102,  82, 102,  87, 232,  83, 255, 102,  95, 102,  11, 192,  15, 132, 174,
+247, 102,  15, 182,  30,  13,   0, 102, 247, 227, 102,  90, 102,   3, 194, 102,
+163,  17,   0, 102,  89, 102,  15, 182,  30,  13,   0, 102,  59, 203,  15, 142,
+ 19,   0, 137,  30,  22,   0, 102,  43, 203, 102,  88, 102,   3, 195, 102,  80,
+102,  81, 235,  20, 144, 102,  88, 102,   3, 193, 102,  80, 137,  14,  22,   0,
+102, 185,   0,   0,   0,   0, 102,  81,   6, 102,  87, 139, 223, 131, 227,  15,
+140, 192, 102, 193, 239,   4,   3, 199,  80,   7, 232,   5, 247, 102,  95,   7,
+102,   3,  62,  82,   2, 102,  89, 102,  88, 102, 131, 249,   0,  15, 143, 112,
+255, 102,  97, 144,  31,   7, 195,   6,  30, 102,  96, 102, 247,  38,  86,   2,
+102, 139,  14,  86,   2, 232,  85, 255, 232, 210, 252, 102,  97, 144,  31,   7,
+195,   6,  30, 102,  96, 102, 247,  38, 114,   2, 102, 139,  30,  54,   2, 102,
+139,  14, 114,   2, 102, 139,  54,  42,   2,  30,   7, 102, 139,  62,  70,   2,
+232, 129, 251, 232, 167, 252, 102,  97, 144,  31,   7, 195, 102,  80, 102,  83,
+102,  81, 102, 139,  30,  74,   2, 102, 139, 200, 102, 193, 232,   3, 102, 131,
+225,   7, 102,   3, 216, 102, 184,   1,   0,   0,   0, 102, 211, 224, 103, 132,
+  3,  15, 132,   4,   0, 248, 235,   2, 144, 249, 102,  89, 102,  91, 102,  88,
+195, 103, 128, 123,   8,   1,  15, 132,   4,   0, 102,  43, 192, 195, 103, 102,
+141, 115,  16, 103, 102, 139,  86,   8, 102,  59, 194,  15, 135,  11,   0, 103,
+102, 139,  22, 102,  59, 194,  15, 131,   4,   0, 102,  43, 192, 195, 103,   3,
+ 94,  16, 102,  43, 246, 103, 128,  59,   0,  15, 132,  62,   0, 232, 129,   0,
+102,   3, 241, 232,  57,   0, 102,   3, 202, 102,  59, 193,  15, 140,  33,   0,
+102, 139, 209, 102,  80, 103, 102,  15, 182,  11, 102, 139, 193, 102, 131, 224,
+ 15, 102, 193, 233,   4, 102,   3, 217, 102,   3, 216, 102,  67, 102,  88, 235,
+196, 102,  43, 200, 102,  43, 194, 102,   3, 198, 195, 102,  43, 192, 195, 102,
+ 43, 201, 103, 138,  11, 128, 225,  15, 102, 131, 249,   0,  15, 133,   4,   0,
+102,  43, 201, 195, 102,  83, 102,  82, 102,   3, 217, 103, 102,  15, 190,  19,
+102,  73, 102,  75, 102, 131, 249,   0,  15, 132,  13,   0, 102, 193, 226,   8,
+103, 138,  19, 102,  75, 102,  73, 235, 235, 102, 139, 202, 102,  90, 102,  91,
+195, 102,  83, 102,  82, 102,  43, 210, 103, 138,  19, 102, 131, 226,  15, 102,
+ 43, 201, 103, 138,  11, 192, 233,   4, 102, 131, 249,   0,  15, 133,   8,   0,
+102,  43, 201, 102,  90, 102,  91, 195, 102,   3, 218, 102,   3, 217, 103, 102,
+ 15, 190,  19, 102,  73, 102,  75, 102, 131, 249,   0,  15, 132,  13,   0, 102,
+193, 226,   8, 103, 138,  19, 102,  75, 102,  73, 235, 235, 102, 139, 202, 102,
+ 90, 102,  91, 195, 102,  11, 201,  15, 133,   1,   0, 195, 102,  81, 102,  86,
+103, 131,  62,  97,  15, 140,  12,   0, 103, 131,  62, 122,  15, 143,   4,   0,
+103, 131,  46,  32, 102, 131, 198,   2, 226, 230, 102,  94, 102,  89, 195, 102,
+ 80, 102,  81, 102, 139, 208, 102, 161,  50,   2, 103, 102, 141,  88,  16, 103,
+  3,  67,   4, 103, 102, 141,  64,  16, 102, 139, 218, 232,  68, 249, 102,  11,
+192,  15, 132,   5,   0, 102,  89, 102,  89, 195, 102, 161,  54,   2, 102,  11,
+192,  15, 133,   8,   0, 102,  89, 102,  89, 102,  51, 192, 195, 102, 139,  22,
+ 54,   2, 103, 102, 141,  82,  16, 103, 102, 139,  66,  24, 102,  51, 210, 102,
+247,  54, 110,   2, 102,  51, 246, 102,  80, 102,  86, 102,  88, 102,  94, 102,
+ 59, 198,  15, 132,  58,   0, 102,  86, 102,  64, 102,  80, 102,  72, 232,  27,
+254, 114, 232, 232, 235, 253, 102,  90, 102,  94, 102,  89, 102,  91, 102,  83,
+102,  81, 102,  86, 102,  82, 102, 161,  70,   2, 103, 102, 141,  64,  24, 232,
+208, 248, 102,  11, 192, 116, 196, 102,  89, 102,  89, 102,  89, 102,  89, 195,
+102,  89, 102,  89, 102,  51, 192, 195, 102,  81, 102,  80, 102, 184,   5,   0,
+  0,   0,  30,   7, 102, 139, 249, 232, 141, 253, 102, 139, 193, 102, 187,  32,
+  0,   0,   0, 102, 185,   0,   0,   0,   0, 102, 186,   0,   0,   0,   0, 232,
+ 51, 248, 102,  91, 102,  89, 102, 133, 192,  15, 133,  21,   0, 102, 139, 193,
+102,  15, 183,  14,  16,   2, 102, 186,  18,   2,   0,   0, 232,  22, 248, 235,
+ 51, 144, 102,  51, 210, 102, 139, 193, 102, 139, 203, 102,  80, 102,  83, 232,
+ 35,   0, 102,  91, 102,  95, 102,  11, 192,  15, 132,  23,   0,  30,   7, 232,
+ 53, 253, 102, 139, 199, 102,  15, 183,  14,  16,   2, 102, 186,  18,   2,   0,
+  0, 232, 225, 247, 195, 102,  82, 102,  81, 102, 187,  32,   0,   0,   0, 102,
+185,   0,   0,   0,   0, 102, 186,   0,   0,   0,   0, 232, 199, 247, 102,  11,
+192,  15, 132,  99,   0, 102, 139, 216,  30,   7, 102, 139,  62,  26,   2, 102,
+ 51, 192, 232,  89, 248,  30,   7, 102, 139,  30,  26,   2, 102,  89, 102,  90,
+ 38, 102,  57,  15,  15, 133,  12,   0,  38, 102,  57,  87,   8,  15, 132,  49,
+  0, 235,  19, 144,  38, 102, 131,  63, 255,  15, 132,  47,   0,  38, 131, 127,
+  4,   0,  15, 132,  38,   0,  38, 102,  15, 183,  71,   4,   3, 216, 139, 195,
+ 37,   0, 128, 116, 203, 140, 192,   5,   0,   8, 142, 192, 129, 227, 255, 127,
+235, 190,  38, 102, 139,  71,  16, 195, 102,  89, 102,  90, 102,  51, 192, 195,
+102,  80, 102,  81, 102, 139, 199, 102, 193, 232,   4,   6,  89,   3, 200,  81,
+  7, 102, 131, 231,  15, 102,  89, 102,  88, 195,  96,   6, 190, 189,  13, 191,
+  0,  32,  30,   7, 185,  13,   0, 144, 243, 165,   7,  97, 195,   1,  35,  69,
+103, 137, 171, 205, 239, 254, 220, 186, 152, 118,  84,  50,  16, 240, 225, 210,
+195,   0,   0,   0,   0,  32,  32,  96, 139,  54,  24,  32,  38, 138,   5, 136,
+  4,  71,  70, 102, 255,   6,  20,  32, 129, 254,  96,  32, 117,   6, 232,  91,
+  0, 190,  32,  32, 226, 230, 137,  54,  24,  32,  97, 195, 102,  96, 139,  54,
+ 24,  32, 176, 128, 136,   4,  70,  50, 192, 129, 254,  96,  32, 117,   6, 232,
+ 58,   0, 190,  32,  32, 129, 254,  88,  32, 117, 233, 102,  51, 192, 102, 163,
+ 88,  32, 102, 161,  20,  32, 102, 193, 224,   3, 102,  15, 200, 102, 163,  92,
+ 32, 232,  24,   0, 187,   0,  32, 102, 139,   7, 102,  15, 200, 102, 137,   7,
+131, 195,   4, 129, 251,  52,  32, 117, 238, 102,  97, 195, 102,  96, 187,  32,
+ 32, 102, 139,   7, 102,  15, 200, 102, 137,   7, 131, 195,   4, 129, 251,  96,
+ 32, 117, 238, 187,   0,  32, 102, 139,  15, 102, 139,  87,   4, 102, 139, 119,
+  8, 102, 139, 127,  12, 102, 139, 111,  16, 187,  32,  32, 199,   6,  26,  32,
+ 48,  15, 198,   6,  28,  32,  20, 144,  83, 139,  30,  26,  32, 255,  23, 102,
+  3,  71,   2,  91, 102,   3, 232, 102,   3,  47, 102, 139, 193, 102, 193, 192,
+  5, 102,   3, 197, 102, 139, 239, 102, 139, 254, 102, 139, 242, 102, 193, 198,
+ 30, 102, 139, 209, 102, 139, 200, 102, 139,   7, 102,  51,  71,   8, 102,  51,
+ 71,  32, 102,  51,  71,  52, 102, 209, 192, 102, 137,  71,  64, 131, 195,   4,
+254,  14,  28,  32, 117, 178, 131,   6,  26,  32,   6, 129,  62,  26,  32,  72,
+ 15, 117, 159, 187,   0,  32, 102,   1,  15, 102,   1,  87,   4, 102,   1, 119,
+  8, 102,   1, 127,  12, 102,   1, 111,  16, 102,  97, 195, 102, 139, 198, 102,
+ 51, 199, 102,  35, 194, 102,  51, 199, 195, 102, 139, 194, 102,  51, 198, 102,
+ 51, 199, 195, 102,  83, 102, 139, 194, 102,  35, 198, 102, 139, 218, 102,  35,
+223, 102,  11, 195, 102, 139, 222, 102,  35, 223, 102,  11, 195, 102,  91, 195,
+252,  14, 153, 121, 130,  90,   9,  15, 161, 235, 217, 110,  19,  15, 220, 188,
+ 27, 143,   9,  15, 214, 193,  98, 202,   6,  30, 102,  96, 102,  51, 219, 184,
+  0, 187, 205,  26, 102,  35, 192,  15, 133, 187,   0, 102, 129, 251,  84,  67,
+ 80,  65,  15, 133, 176,   0, 129, 249,   2,   1,  15, 130, 168,   0, 102,  97,
+144,  31,   7,   6,  30, 102,  96, 103, 128, 123,   8,   0,  15, 133,  12,   0,
+103, 102, 141,  83,  16, 103, 102, 139,  10, 235,  37, 144, 103, 102, 141,  83,
+ 16, 103, 102, 139,  74,  40, 102, 129, 249,   0,   0,   8,   0,  15, 131,  12,
+  0, 103, 102, 139,  66,  44, 102,  35, 192,  15, 132,   3,   0, 102,  51, 201,
+ 14,  31, 232, 245, 253, 102,  35, 201,  15, 132,  50,   0, 102, 186,   0, 128,
+  0,   0, 102,  59, 202,  15, 134,  31,   0, 102,  43, 202,   6, 102,  81, 102,
+ 87, 102,  82, 102, 139, 202, 232, 183, 253, 232, 251, 253, 102,  90, 102,  95,
+102,  89,   7, 102,   3, 250, 235, 218, 232, 165, 253, 232, 233, 253, 232,  11,
+254,  14,   7, 102, 187,  84,  67,  80,  65, 102, 191,   0,  32,   0,   0, 102,
+185,  20,   0,   0,   0, 102, 184,   7, 187,   0,   0, 102, 186,  10,   0,   0,
+  0, 102,  51, 246, 205,  26, 102,  97, 144,  31,   7, 195, 160, 249,   1, 233,
+ 64, 241, 160, 250,   1, 233,  58, 241
+};
diff --git a/ntfsprogs/boot.h b/ntfsprogs/boot.h
new file mode 100755
index 0000000000000000000000000000000000000000..45d79927f4526d02715f12506f29e14af6f37b3e
--- /dev/null
+++ b/ntfsprogs/boot.h
@@ -0,0 +1,7 @@
+#ifndef _NTFS_BOOT_H_
+#define _NTFS_BOOT_H_
+
+extern const unsigned char boot_array[4136];
+
+#endif /* _NTFS_BOOT_H_ */
+
diff --git a/ntfsprogs/cluster.c b/ntfsprogs/cluster.c
new file mode 100755
index 0000000000000000000000000000000000000000..82188f4cabf5a6e169fb48c5986c6d10a19e9588
--- /dev/null
+++ b/ntfsprogs/cluster.c
@@ -0,0 +1,132 @@
+/**
+ * cluster - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2002-2003 Richard Russon
+ * Copyright (c) 2014      Jean-Pierre Andre
+ *
+ * This function will locate the owner of any given sector or cluster range.
+ *
+ * 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 Linux-NTFS
+ * 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_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include "cluster.h"
+#include "utils.h"
+#include "logging.h"
+
+/**
+ * cluster_find
+ */
+int cluster_find(ntfs_volume *vol, LCN c_begin, LCN c_end, cluster_cb *cb, void *data)
+{
+	int j;
+	int result = -1;
+	struct mft_search_ctx *m_ctx = NULL;
+	ntfs_attr_search_ctx  *a_ctx = NULL;
+	s64 count;
+	BOOL found;
+	ATTR_RECORD *rec;
+	runlist *runs;
+
+	if (!vol || !cb)
+		return -1;
+
+	m_ctx = mft_get_search_ctx(vol);
+	m_ctx->flags_search = FEMR_IN_USE | FEMR_BASE_RECORD;
+	count = 0;
+
+	while (mft_next_record(m_ctx) == 0) {
+
+		if (!(m_ctx->flags_match & FEMR_BASE_RECORD))
+			continue;
+
+		ntfs_log_verbose("Inode: %llu\n", (unsigned long long)
+				m_ctx->inode->mft_no);
+
+		a_ctx = ntfs_attr_get_search_ctx(m_ctx->inode, NULL);
+
+		found = FALSE;
+		while ((rec = find_attribute(AT_UNUSED, a_ctx))) {
+
+			if (!rec->non_resident) {
+				ntfs_log_verbose("0x%02x skipped - attr is resident\n",
+					(int)le32_to_cpu(a_ctx->attr->type));
+				continue;
+			}
+
+			runs = ntfs_mapping_pairs_decompress(vol, a_ctx->attr, NULL);
+			if (!runs) {
+				ntfs_log_error("Couldn't read the data runs.\n");
+				goto done;
+			}
+
+			ntfs_log_verbose("\t[0x%02X]\n",
+					(int)le32_to_cpu(a_ctx->attr->type));
+
+			ntfs_log_verbose("\t\tVCN\tLCN\tLength\n");
+			for (j = 0; runs[j].length > 0; j++) {
+				LCN a_begin = runs[j].lcn;
+				LCN a_end   = a_begin + runs[j].length - 1;
+
+				if (a_begin < 0)
+					continue;	// sparse, discontiguous, etc
+
+				ntfs_log_verbose("\t\t%lld\t%lld-%lld (%lld)\n",
+						(long long)runs[j].vcn,
+						(long long)runs[j].lcn,
+						(long long)(runs[j].lcn +
+						runs[j].length - 1),
+						(long long)runs[j].length);
+				//dprint list
+
+				if ((a_begin > c_end) || (a_end < c_begin))
+					continue;	// before or after search range
+
+				if ((*cb) (m_ctx->inode, a_ctx->attr, runs+j, data))
+					return 1;
+				found = TRUE;
+			}
+		}
+
+		ntfs_attr_put_search_ctx(a_ctx);
+		a_ctx = NULL;
+		if (found)
+			count++;
+	}
+
+	if (count > 1)
+		ntfs_log_info("* %lld inodes found\n",(long long)count);
+	else
+		ntfs_log_info("* %s inode found\n", (count ? "one" : "no"));
+	result = 0;
+done:
+	ntfs_attr_put_search_ctx(a_ctx);
+	mft_put_search_ctx(m_ctx);
+
+	return result;
+}
+
diff --git a/ntfsprogs/cluster.h b/ntfsprogs/cluster.h
new file mode 100755
index 0000000000000000000000000000000000000000..4bc18276a54696317a5dd1513d17e55d0e5b7b3b
--- /dev/null
+++ b/ntfsprogs/cluster.h
@@ -0,0 +1,39 @@
+/*
+ * cluster - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2003 Richard Russon
+ *
+ * This function will locate the owner of any given sector or cluster range.
+ *
+ * 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 Linux-NTFS
+ * 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 _CLUSTER_H_
+#define _CLUSTER_H_
+
+#include "types.h"
+#include "volume.h"
+
+typedef struct {
+	int x;
+} ntfs_cluster;
+
+typedef int (cluster_cb)(ntfs_inode *ino, ATTR_RECORD *attr, runlist_element *run, void *data);
+
+int cluster_find(ntfs_volume *vol, LCN c_begin, LCN c_end, cluster_cb *cb, void *data);
+
+#endif /* _CLUSTER_H_ */
+
diff --git a/ntfsprogs/list.h b/ntfsprogs/list.h
new file mode 100755
index 0000000000000000000000000000000000000000..4db45d4ee589714a7c9972558184633855218dbd
--- /dev/null
+++ b/ntfsprogs/list.h
@@ -0,0 +1,194 @@
+/*
+ * list.h - Linked list implementation. Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2000-2002 Anton Altaparmakov and others
+ *
+ * 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 Linux-NTFS
+ * 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_LIST_H
+#define _NTFS_LIST_H
+
+/**
+ * struct ntfs_list_head - Simple doubly linked list implementation.
+ *
+ * Copied from Linux kernel 2.4.2-ac18 into Linux-NTFS (with minor
+ * modifications). - AIA
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * 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;
+};
+
+#define NTFS_LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define NTFS_LIST_HEAD(name) \
+	struct ntfs_list_head name = NTFS_LIST_HEAD_INIT(name)
+
+#define NTFS_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.
+ * @new:
+ * @prev:
+ * @next:
+ *
+ * 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)
+{
+	next->prev = new;
+	new->next = next;
+	new->prev = prev;
+	prev->next = new;
+}
+
+/**
+ * ntfs_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)
+{
+	__ntfs_list_add(new, head, head->next);
+}
+
+/**
+ * ntfs_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)
+{
+	__ntfs_list_add(new, head->prev, head);
+}
+
+/**
+ * __ntfs_list_del -
+ * @prev:
+ * @next:
+ *
+ * Delete a list entry by making the prev/next entries point to each other.
+ *
+ * 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)
+{
+	next->prev = prev;
+	prev->next = next;
+}
+
+/**
+ * ntfs_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.
+ */
+static __inline__ void ntfs_list_del(struct ntfs_list_head *entry)
+{
+	__ntfs_list_del(entry->prev, entry->next);
+}
+
+/**
+ * ntfs_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)
+{
+	__ntfs_list_del(entry->prev, entry->next);
+	NTFS_INIT_LIST_HEAD(entry);
+}
+
+/**
+ * ntfs_list_empty - tests whether a list is empty
+ * @head:	the list to test.
+ */
+static __inline__ int ntfs_list_empty(struct ntfs_list_head *head)
+{
+	return head->next == head;
+}
+
+/**
+ * ntfs_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)
+{
+	struct ntfs_list_head *first = list->next;
+
+	if (first != list) {
+		struct ntfs_list_head *last = list->prev;
+		struct ntfs_list_head *at = head->next;
+
+		first->prev = head;
+		head->next = first;
+
+		last->next = at;
+		at->prev = last;
+	}
+}
+
+/**
+ * ntfs_list_entry - get the struct for this entry
+ * @ptr:	the &struct ntfs_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) \
+	((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.
+ * @head:	the head for your list.
+ */
+#define ntfs_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
+ * @head:	the head for your list.
+ */
+#define ntfs_list_for_each_safe(pos, n, head) \
+	for (pos = (head)->next, n = pos->next; pos != (head); \
+		pos = n, n = pos->next)
+
+#endif /* defined _NTFS_LIST_H */
+
diff --git a/ntfsprogs/mkntfs.8 b/ntfsprogs/mkntfs.8
new file mode 100755
index 0000000000000000000000000000000000000000..12005fcb6af310c10a6931fad127da4d0c45a564
--- /dev/null
+++ b/ntfsprogs/mkntfs.8
@@ -0,0 +1,290 @@
+.\" Copyright (c) 2001\-2006 Anton Altaparmakov.
+.\" Copyright (c) 2005 Richard Russon.
+.\" Copyright (c) 2005\-2006 Szabolcs Szakacsits.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH MKNTFS 8 "January 2006" "ntfs-3g 2015.3.14"
+.SH NAME
+mkntfs \- create an NTFS file system
+.SH SYNOPSIS
+.B mkntfs
+[\fIoptions\fR] \fIdevice \fR[\fInumber\-of\-sectors\fR]
+.PP
+.B mkntfs
+[
+.B \-C
+]
+[
+.B \-c
+.I cluster\-size
+]
+[
+.B \-F
+]
+[
+.B \-f
+]
+[
+.B \-H
+.I heads
+]
+[
+.B \-h
+]
+[
+.B \-I
+]
+[
+.B \-L
+.I volume\-label
+]
+[
+.B \-l
+]
+[
+.B \-n
+]
+[
+.B \-p
+.I part\-start\-sect
+]
+[
+.B \-Q
+]
+[
+.B \-q
+]
+[
+.B \-S
+.I sectors\-per\-track
+]
+[
+.B \-s
+.I sector\-size
+]
+[
+.B \-T
+]
+[
+.B \-U
+]
+[
+.B \-V
+]
+[
+.B \-v
+]
+[
+.B \-z
+.I mft\-zone\-multiplier
+]
+[
+.B \-\-debug
+]
+.I device
+[
+.I number\-of\-sectors
+]
+.SH DESCRIPTION
+.B mkntfs
+is used to create an NTFS file system on a device (usually a disk partition)
+or file.
+.I device
+is the special file corresponding to the device (e.g
+.IR /dev/hdXX ).
+.I number\-of\-sectors
+is the number of sectors on the device. If omitted,
+.B mkntfs
+automagically figures the file system size.
+.SH OPTIONS
+Below is a summary of all the options that
+.B mkntfs
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.SS Basic options
+.TP
+\fB\-f\fR, \fB\-\-fast\fR, \fB\-Q\fR, \fB\-\-quick\fR
+Perform quick (fast) format. This will skip both zeroing of the volume and bad
+sector checking.
+.TP
+\fB\-L\fR, \fB\-\-label\fR STRING
+Set the volume label for the filesystem.
+.TP
+\fB\-C\fR, \fB\-\-enable\-compression\fR
+Enable compression on the volume.
+.TP
+\fB\-n\fR, \fB\-\-no\-action\fR
+Causes
+.B mkntfs
+to not actually create a filesystem, but display what it would do if it were
+to create a filesystem. All steps of the format are carried out except the
+actual writing to the device.
+.SS Advanced options
+.TP
+\fB\-c\fR, \fB\-\-cluster\-size\fR BYTES
+Specify the size of clusters in bytes. Valid cluster size values are powers of
+two, with at least 256, and at most 65536 bytes per cluster. If omitted,
+.B mkntfs
+uses 4096 bytes as the default cluster size.
+.sp
+Note that the default cluster size is set to be at least equal to the sector
+size as a cluster cannot be smaller than a sector. Also, note that values
+greater than 4096 have the side effect that compression is disabled on the
+volume (due to limitations in the NTFS compression algorithm currently in use
+by Windows).
+.TP
+\fB\-s\fR, \fB\-\-sector\-size\fR BYTES
+Specify the size of sectors in bytes. Valid sector size values are 256, 512,
+1024, 2048 and 4096 bytes per sector. If omitted,
+.B mkntfs
+attempts to determine the
+.I sector\-size
+automatically and if that fails a default of 512 bytes per sector is used.
+.TP
+\fB\-p\fR, \fB\-\-partition\-start\fR SECTOR
+Specify the partition start sector. The maximum is 4294967295 (2^32\-1). If
+omitted,
+.B mkntfs
+attempts to determine
+.I part\-start\-sect
+automatically and if that fails a default of 0 is used. Note that
+.I part\-start\-sect
+is required for Windows to be able to boot from the created volume.
+.TP
+\fB\-H\fR, \fB\-\-heads\fR NUM
+Specify the number of heads. The maximum is 65535 (0xffff). If omitted,
+.B mkntfs
+attempts to determine the number of
+.I heads
+automatically and if that fails a default of 0 is used. Note that
+.I heads
+is required for Windows to be able to boot from the created volume.
+.TP
+\fB\-S\fR, \fB\-\-sectors\-per\-track\fR NUM
+Specify the number of sectors per track. The maximum is 65535 (0xffff). If
+omitted,
+.B mkntfs
+attempts to determine the number of
+.I sectors\-per\-track
+automatically and if that fails a default of 0 is used. Note that
+.I sectors\-per\-track
+is required for Windows to be able to boot from the created volume.
+.TP
+\fB\-z\fR, \fB\-\-mft\-zone\-multiplier\fR NUM
+Set the MFT zone multiplier, which determines the size of the MFT zone to use
+on the volume. The MFT zone is the area at the beginning of the volume reserved
+for the master file table (MFT), which stores the on disk inodes (MFT records).
+It is noteworthy that small files are stored entirely within the inode;
+thus, if you expect to use the volume for storing large numbers of very small
+files, it is useful to set the zone multiplier to a higher value. Note, that
+the MFT zone is resized on the fly as required during operation of the NTFS
+driver but choosing a good value will reduce fragmentation. Valid values
+are 1, 2, 3 and 4. The values have the following meaning:
+.TS
+box;
+lB lB
+lB lB
+c l.
+MFT zone	MFT zone size
+multiplier	(% of volume size)
+1	12.5% (default)
+2	25.0%
+3	37.5%
+4	50.0%
+.TE
+.sp
+.TP
+\fB\-T\fR, \fB\-\-zero\-time\fR
+Fake the time to be 00:00:00 UTC, Jan 1, 1970 instead of the current system
+time.  This is only really useful for debugging purposes.
+.TP
+\fB\-U\fR, \fB\-\-with\-uuid\fR
+Generate a random volume UUID.
+.TP
+\fB\-I\fR, \fB\-\-no\-indexing\fR
+Disable content indexing on the volume. (This is only meaningful on
+Windows 2000 and later. Windows NT 4.0 and earlier ignore this as they do
+not implement content indexing at all.)
+.TP
+\fB\-F\fR, \fB\-\-force\fR
+Force
+.B mkntfs
+to run, even if the specified
+.I device
+is not a block special device, or appears to be mounted.
+.SS Output options
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Quiet execution; only errors are written to stderr, no output to stdout
+occurs at all. Useful if
+.B mkntfs
+is run in a script.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Verbose execution.
+.TP
+\fB\-\-debug\fR
+Really verbose execution; includes the verbose output from the
+.B \-v
+option as well as additional output useful for debugging
+.B mkntfs.
+.SS Help options
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Print the version number of
+.B mkntfs
+and exit.
+.TP
+\fB\-l\fR, \fB\-\-license\fR
+Print the licensing information of
+.B mkntfs
+and exit.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.SH KNOWN ISSUES
+When applying chkdsk to a file system, it sometimes throws a warning
+"Correcting errors in the uppercase file." The uppercase file is created
+while formatting and it defines the mapping of lower case  characters to
+upper case ones, as needed to sort file names in directories. The warning
+means that the uppercase file defined on the file system is not the same as
+the one used by the Windows OS on which chkdsk is running, and this may
+happen because newer versions of Windows take into account new characters
+defined by the Unicode consortium.
+.P
+Currently, mkntfs creates the uppercase table so that no warning is thrown
+by Windows Vista, Windows 7 or Windows 8. A warning may be thrown by
+other Windows versions, or if chkdsk is applied in succession on different
+Windows versions.
+.SH BUGS
+If you find a bug please send an email describing the problem to the
+development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+.B mkntfs
+was written by Anton Altaparmakov, Richard Russon, Erik Sornes and Szabolcs Szakacsits.
+It was ported to ntfs-3g by Erik Larsson and Jean-Pierre Andre.
+.SH AVAILABILITY
+.B mkntfs
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR badblocks (8),
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/mkntfs.8.in b/ntfsprogs/mkntfs.8.in
new file mode 100755
index 0000000000000000000000000000000000000000..ce687f7dc6f2c779a26be9e7322f881ae407ab00
--- /dev/null
+++ b/ntfsprogs/mkntfs.8.in
@@ -0,0 +1,290 @@
+.\" Copyright (c) 2001\-2006 Anton Altaparmakov.
+.\" Copyright (c) 2005 Richard Russon.
+.\" Copyright (c) 2005\-2006 Szabolcs Szakacsits.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH MKNTFS 8 "January 2006" "ntfs-3g @VERSION@"
+.SH NAME
+mkntfs \- create an NTFS file system
+.SH SYNOPSIS
+.B mkntfs
+[\fIoptions\fR] \fIdevice \fR[\fInumber\-of\-sectors\fR]
+.PP
+.B mkntfs
+[
+.B \-C
+]
+[
+.B \-c
+.I cluster\-size
+]
+[
+.B \-F
+]
+[
+.B \-f
+]
+[
+.B \-H
+.I heads
+]
+[
+.B \-h
+]
+[
+.B \-I
+]
+[
+.B \-L
+.I volume\-label
+]
+[
+.B \-l
+]
+[
+.B \-n
+]
+[
+.B \-p
+.I part\-start\-sect
+]
+[
+.B \-Q
+]
+[
+.B \-q
+]
+[
+.B \-S
+.I sectors\-per\-track
+]
+[
+.B \-s
+.I sector\-size
+]
+[
+.B \-T
+]
+[
+.B \-U
+]
+[
+.B \-V
+]
+[
+.B \-v
+]
+[
+.B \-z
+.I mft\-zone\-multiplier
+]
+[
+.B \-\-debug
+]
+.I device
+[
+.I number\-of\-sectors
+]
+.SH DESCRIPTION
+.B mkntfs
+is used to create an NTFS file system on a device (usually a disk partition)
+or file.
+.I device
+is the special file corresponding to the device (e.g
+.IR /dev/hdXX ).
+.I number\-of\-sectors
+is the number of sectors on the device. If omitted,
+.B mkntfs
+automagically figures the file system size.
+.SH OPTIONS
+Below is a summary of all the options that
+.B mkntfs
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.SS Basic options
+.TP
+\fB\-f\fR, \fB\-\-fast\fR, \fB\-Q\fR, \fB\-\-quick\fR
+Perform quick (fast) format. This will skip both zeroing of the volume and bad
+sector checking.
+.TP
+\fB\-L\fR, \fB\-\-label\fR STRING
+Set the volume label for the filesystem.
+.TP
+\fB\-C\fR, \fB\-\-enable\-compression\fR
+Enable compression on the volume.
+.TP
+\fB\-n\fR, \fB\-\-no\-action\fR
+Causes
+.B mkntfs
+to not actually create a filesystem, but display what it would do if it were
+to create a filesystem. All steps of the format are carried out except the
+actual writing to the device.
+.SS Advanced options
+.TP
+\fB\-c\fR, \fB\-\-cluster\-size\fR BYTES
+Specify the size of clusters in bytes. Valid cluster size values are powers of
+two, with at least 256, and at most 65536 bytes per cluster. If omitted,
+.B mkntfs
+uses 4096 bytes as the default cluster size.
+.sp
+Note that the default cluster size is set to be at least equal to the sector
+size as a cluster cannot be smaller than a sector. Also, note that values
+greater than 4096 have the side effect that compression is disabled on the
+volume (due to limitations in the NTFS compression algorithm currently in use
+by Windows).
+.TP
+\fB\-s\fR, \fB\-\-sector\-size\fR BYTES
+Specify the size of sectors in bytes. Valid sector size values are 256, 512,
+1024, 2048 and 4096 bytes per sector. If omitted,
+.B mkntfs
+attempts to determine the
+.I sector\-size
+automatically and if that fails a default of 512 bytes per sector is used.
+.TP
+\fB\-p\fR, \fB\-\-partition\-start\fR SECTOR
+Specify the partition start sector. The maximum is 4294967295 (2^32\-1). If
+omitted,
+.B mkntfs
+attempts to determine
+.I part\-start\-sect
+automatically and if that fails a default of 0 is used. Note that
+.I part\-start\-sect
+is required for Windows to be able to boot from the created volume.
+.TP
+\fB\-H\fR, \fB\-\-heads\fR NUM
+Specify the number of heads. The maximum is 65535 (0xffff). If omitted,
+.B mkntfs
+attempts to determine the number of
+.I heads
+automatically and if that fails a default of 0 is used. Note that
+.I heads
+is required for Windows to be able to boot from the created volume.
+.TP
+\fB\-S\fR, \fB\-\-sectors\-per\-track\fR NUM
+Specify the number of sectors per track. The maximum is 65535 (0xffff). If
+omitted,
+.B mkntfs
+attempts to determine the number of
+.I sectors\-per\-track
+automatically and if that fails a default of 0 is used. Note that
+.I sectors\-per\-track
+is required for Windows to be able to boot from the created volume.
+.TP
+\fB\-z\fR, \fB\-\-mft\-zone\-multiplier\fR NUM
+Set the MFT zone multiplier, which determines the size of the MFT zone to use
+on the volume. The MFT zone is the area at the beginning of the volume reserved
+for the master file table (MFT), which stores the on disk inodes (MFT records).
+It is noteworthy that small files are stored entirely within the inode;
+thus, if you expect to use the volume for storing large numbers of very small
+files, it is useful to set the zone multiplier to a higher value. Note, that
+the MFT zone is resized on the fly as required during operation of the NTFS
+driver but choosing a good value will reduce fragmentation. Valid values
+are 1, 2, 3 and 4. The values have the following meaning:
+.TS
+box;
+lB lB
+lB lB
+c l.
+MFT zone	MFT zone size
+multiplier	(% of volume size)
+1	12.5% (default)
+2	25.0%
+3	37.5%
+4	50.0%
+.TE
+.sp
+.TP
+\fB\-T\fR, \fB\-\-zero\-time\fR
+Fake the time to be 00:00:00 UTC, Jan 1, 1970 instead of the current system
+time.  This is only really useful for debugging purposes.
+.TP
+\fB\-U\fR, \fB\-\-with\-uuid\fR
+Generate a random volume UUID.
+.TP
+\fB\-I\fR, \fB\-\-no\-indexing\fR
+Disable content indexing on the volume. (This is only meaningful on
+Windows 2000 and later. Windows NT 4.0 and earlier ignore this as they do
+not implement content indexing at all.)
+.TP
+\fB\-F\fR, \fB\-\-force\fR
+Force
+.B mkntfs
+to run, even if the specified
+.I device
+is not a block special device, or appears to be mounted.
+.SS Output options
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Quiet execution; only errors are written to stderr, no output to stdout
+occurs at all. Useful if
+.B mkntfs
+is run in a script.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Verbose execution.
+.TP
+\fB\-\-debug\fR
+Really verbose execution; includes the verbose output from the
+.B \-v
+option as well as additional output useful for debugging
+.B mkntfs.
+.SS Help options
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Print the version number of
+.B mkntfs
+and exit.
+.TP
+\fB\-l\fR, \fB\-\-license\fR
+Print the licensing information of
+.B mkntfs
+and exit.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.SH KNOWN ISSUES
+When applying chkdsk to a file system, it sometimes throws a warning
+"Correcting errors in the uppercase file." The uppercase file is created
+while formatting and it defines the mapping of lower case  characters to
+upper case ones, as needed to sort file names in directories. The warning
+means that the uppercase file defined on the file system is not the same as
+the one used by the Windows OS on which chkdsk is running, and this may
+happen because newer versions of Windows take into account new characters
+defined by the Unicode consortium.
+.P
+Currently, mkntfs creates the uppercase table so that no warning is thrown
+by Windows Vista, Windows 7 or Windows 8. A warning may be thrown by
+other Windows versions, or if chkdsk is applied in succession on different
+Windows versions.
+.SH BUGS
+If you find a bug please send an email describing the problem to the
+development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+.B mkntfs
+was written by Anton Altaparmakov, Richard Russon, Erik Sornes and Szabolcs Szakacsits.
+It was ported to ntfs-3g by Erik Larsson and Jean-Pierre Andre.
+.SH AVAILABILITY
+.B mkntfs
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR badblocks (8),
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/mkntfs.c b/ntfsprogs/mkntfs.c
new file mode 100755
index 0000000000000000000000000000000000000000..a7b1fd235fe9d89f8676fa05b88e256009da0650
--- /dev/null
+++ b/ntfsprogs/mkntfs.c
@@ -0,0 +1,5180 @@
+/**
+ * mkntfs - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2000-2011 Anton Altaparmakov
+ * Copyright (c) 2001-2005 Richard Russon
+ * Copyright (c) 2002-2006 Szabolcs Szakacsits
+ * Copyright (c) 2005      Erik Sornes
+ * Copyright (c) 2007      Yura Pakhuchiy
+ * Copyright (c) 2010-2014 Jean-Pierre Andre
+ *
+ * This utility will create an NTFS 1.2 or 3.1 volume on a user
+ * specified (block) device.
+ *
+ * Some things (option handling and determination of mount status) have been
+ * adapted from e2fsprogs-1.19 and lib/ext2fs/ismounted.c and misc/mke2fs.c in
+ * particular.
+ *
+ * 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 Linux-NTFS source
+ * 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_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifdef HAVE_LIBGEN_H
+#include <libgen.h>
+#endif
+#ifdef ENABLE_UUID
+#include <uuid/uuid.h>
+#endif
+
+
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+	extern char *optarg;
+	extern int optind;
+#endif
+
+#ifdef HAVE_LINUX_MAJOR_H
+#	include <linux/major.h>
+#	ifndef MAJOR
+#		define MAJOR(dev)	((dev) >> 8)
+#		define MINOR(dev)	((dev) & 0xff)
+#	endif
+#	ifndef IDE_DISK_MAJOR
+#		ifndef IDE0_MAJOR
+#			define IDE0_MAJOR	3
+#			define IDE1_MAJOR	22
+#			define IDE2_MAJOR	33
+#			define IDE3_MAJOR	34
+#			define IDE4_MAJOR	56
+#			define IDE5_MAJOR	57
+#			define IDE6_MAJOR	88
+#			define IDE7_MAJOR	89
+#			define IDE8_MAJOR	90
+#			define IDE9_MAJOR	91
+#		endif
+#		define IDE_DISK_MAJOR(M) \
+				((M) == IDE0_MAJOR || (M) == IDE1_MAJOR || \
+				(M) == IDE2_MAJOR || (M) == IDE3_MAJOR || \
+				(M) == IDE4_MAJOR || (M) == IDE5_MAJOR || \
+				(M) == IDE6_MAJOR || (M) == IDE7_MAJOR || \
+				(M) == IDE8_MAJOR || (M) == IDE9_MAJOR)
+#	endif
+#	ifndef SCSI_DISK_MAJOR
+#		ifndef SCSI_DISK0_MAJOR
+#			define SCSI_DISK0_MAJOR	8
+#			define SCSI_DISK1_MAJOR	65
+#			define SCSI_DISK7_MAJOR	71
+#		endif
+#		define SCSI_DISK_MAJOR(M) \
+				((M) == SCSI_DISK0_MAJOR || \
+				((M) >= SCSI_DISK1_MAJOR && \
+				(M) <= SCSI_DISK7_MAJOR))
+#	endif
+#endif
+
+#include "security.h"
+#include "types.h"
+#include "attrib.h"
+#include "bitmap.h"
+#include "bootsect.h"
+#include "device.h"
+#include "dir.h"
+#include "mft.h"
+#include "mst.h"
+#include "runlist.h"
+#include "utils.h"
+#include "ntfstime.h"
+#include "sd.h"
+#include "boot.h"
+#include "attrdef.h"
+/* #include "version.h" */
+#include "logging.h"
+#include "support.h"
+#include "unistr.h"
+#include "misc.h"
+
+#if defined(__sun) && defined (__SVR4)
+#undef basename
+#define basename(name) name
+#endif
+
+typedef enum { WRITE_STANDARD, WRITE_BITMAP, WRITE_LOGFILE } WRITE_TYPE;
+
+#ifdef NO_NTFS_DEVICE_DEFAULT_IO_OPS
+#error "No default device io operations!  Cannot build mkntfs.  \
+You need to run ./configure without the --disable-default-device-io-ops \
+switch if you want to be able to build the NTFS utilities."
+#endif
+
+/* Page size on ia32. Can change to 8192 on Alpha. */
+#define NTFS_PAGE_SIZE	4096
+
+static char EXEC_NAME[] = "mkntfs";
+
+struct BITMAP_ALLOCATION {
+	struct BITMAP_ALLOCATION *next;
+	LCN	lcn;		/* first allocated cluster */
+	s64	length;		/* count of consecutive clusters */
+} ;
+
+		/* Upcase $Info, used since Windows 8 */
+struct UPCASEINFO {
+	le32	len;
+	le32	filler;
+	le64	crc;
+	le32	osmajor;
+	le32	osminor;
+	le32	build;
+	le16	packmajor;
+	le16	packminor;
+} ;
+
+/**
+ * global variables
+ */
+static u8		  *g_buf		  = NULL;
+static int		   g_mft_bitmap_byte_size = 0;
+static u8		  *g_mft_bitmap		  = NULL;
+static int		   g_lcn_bitmap_byte_size = 0;
+static int		   g_dynamic_buf_size	  = 0;
+static u8		  *g_dynamic_buf	  = NULL;
+static struct UPCASEINFO  *g_upcaseinfo		  = NULL;
+static runlist		  *g_rl_mft		  = NULL;
+static runlist		  *g_rl_mft_bmp		  = NULL;
+static runlist		  *g_rl_mftmirr		  = NULL;
+static runlist		  *g_rl_logfile		  = NULL;
+static runlist		  *g_rl_boot		  = NULL;
+static runlist		  *g_rl_bad		  = NULL;
+static INDEX_ALLOCATION  *g_index_block	  = NULL;
+static ntfs_volume	  *g_vol		  = NULL;
+static int		   g_mft_size		  = 0;
+static long long	   g_mft_lcn		  = 0;		/* lcn of $MFT, $DATA attribute */
+static long long	   g_mftmirr_lcn	  = 0;		/* lcn of $MFTMirr, $DATA */
+static long long	   g_logfile_lcn	  = 0;		/* lcn of $LogFile, $DATA */
+static int		   g_logfile_size	  = 0;		/* in bytes, determined from volume_size */
+static long long	   g_mft_zone_end	  = 0;		/* Determined from volume_size and mft_zone_multiplier, in clusters */
+static long long	   g_num_bad_blocks	  = 0;		/* Number of bad clusters */
+static long long	  *g_bad_blocks		  = NULL;	/* Array of bad clusters */
+
+static struct BITMAP_ALLOCATION *g_allocation	  = NULL;	/* Head of cluster allocations */
+
+/**
+ * struct mkntfs_options
+ */
+static struct mkntfs_options {
+	char *dev_name;			/* Name of the device, or file, to use */
+	BOOL enable_compression;	/* -C, enables compression of all files on the volume by default. */
+	BOOL quick_format;		/* -f or -Q, fast format, don't zero the volume first. */
+	BOOL force;			/* -F, force fs creation. */
+	long heads;			/* -H, number of heads on device */
+	BOOL disable_indexing;		/* -I, disables indexing of file contents on the volume by default. */
+	BOOL no_action;			/* -n, do not write to device, only display what would be done. */
+	long long part_start_sect;	/* -p, start sector of partition on parent device */
+	long sector_size;		/* -s, in bytes, power of 2, default is 512 bytes. */
+	long sectors_per_track;		/* -S, number of sectors per track on device */
+	BOOL use_epoch_time;		/* -T, fake the time to be 00:00:00 UTC, Jan 1, 1970. */
+	long mft_zone_multiplier;	/* -z, value from 1 to 4. Default is 1. */
+	long long num_sectors;		/* size of device in sectors */
+	long cluster_size;		/* -c, format with this cluster-size */
+	BOOL with_uuid;			/* -U, request setting an uuid */
+	char *label;			/* -L, volume label */
+} opts;
+
+
+/**
+ * mkntfs_license
+ */
+static void mkntfs_license(void)
+{
+	ntfs_log_info("%s", ntfs_gpl);
+}
+
+/**
+ * mkntfs_usage
+ */
+static void mkntfs_usage(void)
+{
+	ntfs_log_info("\nUsage: %s [options] device [number-of-sectors]\n"
+"\n"
+"Basic options:\n"
+"    -f, --fast                      Perform a quick format\n"
+"    -Q, --quick                     Perform a quick format\n"
+"    -L, --label STRING              Set the volume label\n"
+"    -C, --enable-compression        Enable compression on the volume\n"
+"    -I, --no-indexing               Disable indexing on the volume\n"
+"    -n, --no-action                 Do not write to disk\n"
+"\n"
+"Advanced options:\n"
+"    -c, --cluster-size BYTES        Specify the cluster size for the volume\n"
+"    -s, --sector-size BYTES         Specify the sector size for the device\n"
+"    -p, --partition-start SECTOR    Specify the partition start sector\n"
+"    -H, --heads NUM                 Specify the number of heads\n"
+"    -S, --sectors-per-track NUM     Specify the number of sectors per track\n"
+"    -z, --mft-zone-multiplier NUM   Set the MFT zone multiplier\n"
+"    -T, --zero-time                 Fake the time to be 00:00 UTC, Jan 1, 1970\n"
+"    -F, --force                     Force execution despite errors\n"
+"\n"
+"Output options:\n"
+"    -q, --quiet                     Quiet execution\n"
+"    -v, --verbose                   Verbose execution\n"
+"        --debug                     Very verbose execution\n"
+"\n"
+"Help options:\n"
+"    -V, --version                   Display version\n"
+"    -l, --license                   Display licensing information\n"
+"    -h, --help                      Display this help\n"
+"\n", basename(EXEC_NAME));
+	ntfs_log_info("%s%s\n", ntfs_bugs, ntfs_home);
+}
+
+/**
+ * mkntfs_version
+ */
+static void mkntfs_version(void)
+{
+	ntfs_log_info("\n%s v%s (libntfs-3g)\n\n", EXEC_NAME, VERSION);
+	ntfs_log_info("Create an NTFS volume on a user specified (block) "
+			"device.\n\n");
+	ntfs_log_info("Copyright (c) 2000-2007 Anton Altaparmakov\n");
+	ntfs_log_info("Copyright (c) 2001-2005 Richard Russon\n");
+	ntfs_log_info("Copyright (c) 2002-2006 Szabolcs Szakacsits\n");
+	ntfs_log_info("Copyright (c) 2005      Erik Sornes\n");
+	ntfs_log_info("Copyright (c) 2007      Yura Pakhuchiy\n");
+	ntfs_log_info("Copyright (c) 2010-2014 Jean-Pierre Andre\n");
+	ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
+}
+
+/*
+ *  crc64, adapted from http://rpm5.org/docs/api/digest_8c-source.html
+ * ECMA-182 polynomial, see
+ *     http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-182.pdf
+ */
+		/* make sure the needed types are defined */
+#undef byte
+#undef uint32_t
+#undef uint64_t
+#define byte u8
+#define uint32_t u32
+#define uint64_t u64
+static uint64_t crc64(uint64_t crc, const byte * data, size_t size)
+	/*@*/
+{
+	static uint64_t polynomial = 0x9a6c9329ac4bc9b5ULL;
+	static uint64_t xorout = 0xffffffffffffffffULL;
+	static uint64_t table[256];
+
+	crc ^= xorout;
+
+	if (data == NULL) {
+	/* generate the table of CRC remainders for all possible bytes */
+		uint64_t c;
+		uint32_t i, j;
+		for (i = 0;  i < 256;  i++) {
+			c = i;
+			for (j = 0;  j < 8;  j++) {
+				if (c & 1)
+					c = polynomial ^ (c >> 1);
+				else
+					c = (c >> 1);
+			}
+			table[i] = c;
+		}
+	} else
+		while (size) {
+			crc = table[(crc ^ *data) & 0xff] ^ (crc >> 8);
+			size--;
+			data++;
+		}
+
+	crc ^= xorout;
+
+	return crc;
+}
+
+/*
+ *		Mark a run of clusters as allocated
+ *
+ *	Returns FALSE if unsuccessful
+ */
+
+static BOOL bitmap_allocate(LCN lcn, s64 length)
+{
+	BOOL done;
+	struct BITMAP_ALLOCATION *p;
+	struct BITMAP_ALLOCATION *q;
+	struct BITMAP_ALLOCATION *newall;
+
+	done = TRUE;
+	if (length) {
+		p = g_allocation;
+		q = (struct BITMAP_ALLOCATION*)NULL;
+		/* locate the first run which starts beyond the requested lcn */
+		while (p && (p->lcn <= lcn)) {
+			q = p;
+			p = p->next;
+		}
+		/* make sure the requested lcns were not allocated */
+		if ((q && ((q->lcn + q->length) > lcn))
+		   || (p && ((lcn + length) > p->lcn))) {
+			ntfs_log_error("Bitmap allocation error\n");
+			done = FALSE;
+		}
+		if (q && ((q->lcn + q->length) == lcn)) {
+			/* extend current run, no overlapping possible */
+			q->length += length;
+		} else {
+			newall = (struct BITMAP_ALLOCATION*)
+				    ntfs_malloc(sizeof(struct BITMAP_ALLOCATION));
+			if (newall) {
+				newall->lcn = lcn;
+				newall->length = length;
+				newall->next = p;
+				if (q) q->next = newall;
+				else g_allocation = newall;
+			} else {
+				done = FALSE;
+				ntfs_log_perror("Not enough memory");
+			}
+		}
+	}
+	return (done);
+}
+
+/*
+ *		Mark a run of cluster as not allocated
+ *
+ *	Returns FALSE if unsuccessful
+ *		(freeing free clusters is not considered as an error)
+ */
+
+static BOOL bitmap_deallocate(LCN lcn, s64 length)
+{
+	BOOL done;
+	struct BITMAP_ALLOCATION *p;
+	struct BITMAP_ALLOCATION *q;
+	LCN first, last;
+	s64 begin_length, end_length;
+
+	done = TRUE;
+	if (length) {
+		p = g_allocation;
+		q = (struct BITMAP_ALLOCATION*)NULL;
+			/* locate a run which has a common portion */
+		while (p) {
+			first = (p->lcn > lcn ? p->lcn : lcn);
+			last = ((p->lcn + p->length) < (lcn + length)
+				? p->lcn + p->length : lcn + length);
+			if (first < last) {
+					/* get the parts which must be kept */
+				begin_length = first - p->lcn;
+				end_length = p->lcn + p->length - last;
+					/* delete the entry */
+				if (q)
+					q->next = p->next;
+				else
+					g_allocation = p->next;
+				free(p);
+				/* reallocate the beginning and the end */
+				if (begin_length
+				    && !bitmap_allocate(first - begin_length,
+							begin_length))
+					done = FALSE;
+				if (end_length
+				    && !bitmap_allocate(last, end_length))
+					done = FALSE;
+					/* restart a full search */
+				p = g_allocation;
+				q = (struct BITMAP_ALLOCATION*)NULL;
+			} else {
+				q = p;
+				p = p->next;
+			}
+		}
+	}
+	return (done);
+}
+
+/*
+ *		Get the allocation status of a single cluster
+ *	and mark as allocated
+ *
+ *	Returns 1 if the cluster was previously allocated
+ */
+
+static int bitmap_get_and_set(LCN lcn, unsigned long length)
+{
+	struct BITMAP_ALLOCATION *p;
+	struct BITMAP_ALLOCATION *q;
+	int bit;
+
+	if (length == 1) {
+		p = g_allocation;
+		q = (struct BITMAP_ALLOCATION*)NULL;
+		/* locate the first run which starts beyond the requested lcn */
+		while (p && (p->lcn <= lcn)) {
+			q = p;
+			p = p->next;
+		}
+		if (q && (q->lcn <= lcn) && ((q->lcn + q->length) > lcn))
+			bit = 1; /* was allocated */
+		else {
+			bitmap_allocate(lcn, length);
+			bit = 0;
+		}
+	} else {
+		ntfs_log_error("Can only allocate a single cluster at a time\n");
+		bit = 0;
+	}
+	return (bit);
+}
+
+/*
+ *		Build a section of the bitmap according to allocation
+ */
+
+static void bitmap_build(u8 *buf, LCN lcn, s64 length)
+{
+	struct BITMAP_ALLOCATION *p;
+	LCN first, last;
+	int j; /* byte number */
+	int bn; /* bit number */
+
+	for (j=0; (8*j)<length; j++)
+		buf[j] = 0;
+	for (p=g_allocation; p; p=p->next) {
+		first = (p->lcn > lcn ? p->lcn : lcn);
+		last = ((p->lcn + p->length) < (lcn + length)
+			? p->lcn + p->length : lcn + length);
+		if (first < last) {
+			bn = first - lcn;
+				/* initial partial byte, if any */
+			while ((bn < (last - lcn)) && (bn & 7)) {
+				buf[bn >> 3] |= 1 << (bn & 7);
+				bn++;
+			}
+				/* full bytes */
+			while (bn < (last - lcn - 7)) {
+				buf[bn >> 3] = 255;
+				bn += 8;
+			}
+				/* final partial byte, if any */
+			while (bn < (last - lcn)) {
+				buf[bn >> 3] |= 1 << (bn & 7);
+				bn++;
+			}
+		}
+	}
+}
+
+/**
+ * mkntfs_parse_long
+ */
+static BOOL mkntfs_parse_long(const char *string, const char *name, long *num)
+{
+	char *end = NULL;
+	long tmp;
+
+	if (!string || !name || !num)
+		return FALSE;
+
+	if (*num >= 0) {
+		ntfs_log_error("You may only specify the %s once.\n", name);
+		return FALSE;
+	}
+
+	tmp = strtol(string, &end, 0);
+	if (end && *end) {
+		ntfs_log_error("Cannot understand the %s '%s'.\n", name, string);
+		return FALSE;
+	} else {
+		*num = tmp;
+		return TRUE;
+	}
+}
+
+/**
+ * mkntfs_parse_llong
+ */
+static BOOL mkntfs_parse_llong(const char *string, const char *name,
+		long long *num)
+{
+	char *end = NULL;
+	long long tmp;
+
+	if (!string || !name || !num)
+		return FALSE;
+
+	if (*num >= 0) {
+		ntfs_log_error("You may only specify the %s once.\n", name);
+		return FALSE;
+	}
+
+	tmp = strtoll(string, &end, 0);
+	if (end && *end) {
+		ntfs_log_error("Cannot understand the %s '%s'.\n", name,
+				string);
+		return FALSE;
+	} else {
+		*num = tmp;
+		return TRUE;
+	}
+}
+
+/**
+ * mkntfs_init_options
+ */
+static void mkntfs_init_options(struct mkntfs_options *opts2)
+{
+	if (!opts2)
+		return;
+
+	memset(opts2, 0, sizeof(*opts2));
+
+	/* Mark all the numeric options as "unset". */
+	opts2->cluster_size		= -1;
+	opts2->heads			= -1;
+	opts2->mft_zone_multiplier	= -1;
+	opts2->num_sectors		= -1;
+	opts2->part_start_sect		= -1;
+	opts2->sector_size		= -1;
+	opts2->sectors_per_track	= -1;
+}
+
+/**
+ * mkntfs_parse_options
+ */
+static int mkntfs_parse_options(int argc, char *argv[], struct mkntfs_options *opts2)
+{
+	static const char *sopt = "-c:CfFhH:IlL:np:qQs:S:TUvVz:";
+	static const struct option lopt[] = {
+		{ "cluster-size",	required_argument,	NULL, 'c' },
+		{ "debug",		no_argument,		NULL, 'Z' },
+		{ "enable-compression",	no_argument,		NULL, 'C' },
+		{ "fast",		no_argument,		NULL, 'f' },
+		{ "force",		no_argument,		NULL, 'F' },
+		{ "heads",		required_argument,	NULL, 'H' },
+		{ "help",		no_argument,		NULL, 'h' },
+		{ "label",		required_argument,	NULL, 'L' },
+		{ "license",		no_argument,		NULL, 'l' },
+		{ "mft-zone-multiplier",required_argument,	NULL, 'z' },
+		{ "no-action",		no_argument,		NULL, 'n' },
+		{ "no-indexing",	no_argument,		NULL, 'I' },
+		{ "partition-start",	required_argument,	NULL, 'p' },
+		{ "quick",		no_argument,		NULL, 'Q' },
+		{ "quiet",		no_argument,		NULL, 'q' },
+		{ "sector-size",	required_argument,	NULL, 's' },
+		{ "sectors-per-track",	required_argument,	NULL, 'S' },
+		{ "with-uuid",		no_argument,		NULL, 'U' },
+		{ "verbose",		no_argument,		NULL, 'v' },
+		{ "version",		no_argument,		NULL, 'V' },
+		{ "zero-time",		no_argument,		NULL, 'T' },
+		{ NULL, 0, NULL, 0 }
+	};
+
+	int c = -1;
+	int lic = 0;
+	int help = 0;
+	int err = 0;
+	int ver = 0;
+
+	if (!argv || !opts2) {
+		ntfs_log_error("Internal error: invalid parameters to "
+				"mkntfs_options.\n");
+		return FALSE;
+	}
+
+	opterr = 0; /* We'll handle the errors, thank you. */
+
+	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
+		switch (c) {
+		case 1:		/* A device, or a number of sectors */
+			if (!opts2->dev_name)
+				opts2->dev_name = argv[optind - 1];
+			else if (!mkntfs_parse_llong(optarg,
+					"number of sectors",
+					&opts2->num_sectors))
+				err++;
+			break;
+		case 'C':
+			opts2->enable_compression = TRUE;
+			break;
+		case 'c':
+			if (!mkntfs_parse_long(optarg, "cluster size",
+					&opts2->cluster_size))
+				err++;
+			break;
+		case 'F':
+			opts2->force = TRUE;
+			break;
+		case 'f':	/* fast */
+		case 'Q':	/* quick */
+			opts2->quick_format = TRUE;
+			break;
+		case 'H':
+			if (!mkntfs_parse_long(optarg, "heads", &opts2->heads))
+				err++;
+			break;
+		case 'h':
+			help++;	/* display help */
+			break;
+		case 'I':
+			opts2->disable_indexing = TRUE;
+			break;
+		case 'L':
+			if (!opts2->label) {
+				opts2->label = argv[optind-1];
+			} else {
+				ntfs_log_error("You may only specify the label "
+						"once.\n");
+				err++;
+			}
+			break;
+		case 'l':
+			lic++;	/* display the license */
+			break;
+		case 'n':
+			opts2->no_action = TRUE;
+			break;
+		case 'p':
+			if (!mkntfs_parse_llong(optarg, "partition start",
+						&opts2->part_start_sect))
+				err++;
+			break;
+		case 'q':
+			ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET |
+					NTFS_LOG_LEVEL_VERBOSE |
+					NTFS_LOG_LEVEL_PROGRESS);
+			break;
+		case 's':
+			if (!mkntfs_parse_long(optarg, "sector size",
+						&opts2->sector_size))
+				err++;
+			break;
+		case 'S':
+			if (!mkntfs_parse_long(optarg, "sectors per track",
+						&opts2->sectors_per_track))
+				err++;
+			break;
+		case 'T':
+			opts2->use_epoch_time = TRUE;
+			break;
+		case 'U':
+			opts2->with_uuid = TRUE;
+			break;
+		case 'v':
+			ntfs_log_set_levels(NTFS_LOG_LEVEL_QUIET |
+					NTFS_LOG_LEVEL_VERBOSE |
+					NTFS_LOG_LEVEL_PROGRESS);
+			break;
+		case 'V':
+			ver++;	/* display version info */
+			break;
+		case 'Z':	/* debug - turn on everything */
+			ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG |
+					NTFS_LOG_LEVEL_TRACE |
+					NTFS_LOG_LEVEL_VERBOSE |
+					NTFS_LOG_LEVEL_QUIET);
+			break;
+		case 'z':
+			if (!mkntfs_parse_long(optarg, "mft zone multiplier",
+						&opts2->mft_zone_multiplier))
+				err++;
+			break;
+		default:
+			if (ntfs_log_parse_option (argv[optind-1]))
+				break;
+			if (((optopt == 'c') || (optopt == 'H') ||
+			     (optopt == 'L') || (optopt == 'p') ||
+			     (optopt == 's') || (optopt == 'S') ||
+			     (optopt == 'N') || (optopt == 'z')) &&
+			     (!optarg)) {
+				ntfs_log_error("Option '%s' requires an "
+						"argument.\n", argv[optind-1]);
+			} else if (optopt != '?') {
+				ntfs_log_error("Unknown option '%s'.\n",
+						argv[optind - 1]);
+			}
+			err++;
+			break;
+		}
+	}
+
+	if (!err && !help && !ver && !lic) {
+		if (opts2->dev_name == NULL) {
+			if (argc > 1)
+				ntfs_log_error("You must specify a device.\n");
+			err++;
+		}
+	}
+
+	if (ver)
+		mkntfs_version();
+	if (lic)
+		mkntfs_license();
+	if (err || help)
+		mkntfs_usage();
+
+		/* tri-state 0 : done, 1 : error, -1 : proceed */
+	return (err ? 1 : (help || ver || lic ? 0 : -1));
+}
+
+
+/**
+ * mkntfs_time
+ */
+static ntfs_time mkntfs_time(void)
+{
+	struct timespec ts;
+
+	ts.tv_sec = 0;
+	ts.tv_nsec = 0;
+	if (!opts.use_epoch_time)
+		ts.tv_sec = time(NULL);
+	return timespec2ntfs(ts);
+}
+
+/**
+ * append_to_bad_blocks
+ */
+static BOOL append_to_bad_blocks(unsigned long long block)
+{
+	long long *new_buf;
+
+	if (!(g_num_bad_blocks & 15)) {
+		new_buf = realloc(g_bad_blocks, (g_num_bad_blocks + 16) *
+							sizeof(long long));
+		if (!new_buf) {
+			ntfs_log_perror("Reallocating memory for bad blocks "
+				"list failed");
+			return FALSE;
+		}
+		g_bad_blocks = new_buf;
+	}
+	g_bad_blocks[g_num_bad_blocks++] = block;
+	return TRUE;
+}
+
+/**
+ * mkntfs_write
+ */
+static long long mkntfs_write(struct ntfs_device *dev,
+		const void *b, long long count)
+{
+	long long bytes_written, total;
+	int retry;
+
+	if (opts.no_action)
+		return count;
+	total = 0LL;
+	retry = 0;
+	do {
+		bytes_written = dev->d_ops->write(dev, b, count);
+		if (bytes_written == -1LL) {
+			retry = errno;
+			ntfs_log_perror("Error writing to %s", dev->d_name);
+			errno = retry;
+			return bytes_written;
+		} else if (!bytes_written) {
+			retry++;
+		} else {
+			count -= bytes_written;
+			total += bytes_written;
+		}
+	} while (count && retry < 3);
+	if (count)
+		ntfs_log_error("Failed to complete writing to %s after three retries."
+			"\n", dev->d_name);
+	return total;
+}
+
+/**
+ *		Build and write a part of the global bitmap
+ *	without overflowing from the allocated buffer
+ *
+ * mkntfs_bitmap_write
+ */
+static s64 mkntfs_bitmap_write(struct ntfs_device *dev,
+			s64 offset, s64 length)
+{
+	s64 partial_length;
+	s64 written;
+
+	partial_length = length;
+	if (partial_length > g_dynamic_buf_size)
+		partial_length = g_dynamic_buf_size;
+		/* create a partial bitmap section, and write it */
+	bitmap_build(g_dynamic_buf,offset << 3,partial_length << 3);
+	written = dev->d_ops->write(dev, g_dynamic_buf, partial_length);
+	return (written);
+}
+
+/**
+ *		Build and write a part of the log file
+ *	without overflowing from the allocated buffer
+ *
+ * mkntfs_logfile_write
+ */
+static s64 mkntfs_logfile_write(struct ntfs_device *dev,
+			s64 offset __attribute__((unused)), s64 length)
+{
+	s64 partial_length;
+	s64 written;
+
+	partial_length = length;
+	if (partial_length > g_dynamic_buf_size)
+		partial_length = g_dynamic_buf_size;
+		/* create a partial bad cluster section, and write it */
+	memset(g_dynamic_buf, -1, partial_length);
+	written = dev->d_ops->write(dev, g_dynamic_buf, partial_length);
+	return (written);
+}
+
+/**
+ * ntfs_rlwrite - Write to disk the clusters contained in the runlist @rl
+ * taking the data from @val.  Take @val_len bytes from @val and pad the
+ * rest with zeroes.
+ *
+ * If the @rl specifies a completely sparse file, @val is allowed to be NULL.
+ *
+ * @inited_size if not NULL points to an output variable which will contain
+ * the actual number of bytes written to disk. I.e. this will not include
+ * sparse bytes for example.
+ *
+ * Return the number of bytes written (minus padding) or -1 on error. Errno
+ * will be set to the error code.
+ */
+static s64 ntfs_rlwrite(struct ntfs_device *dev, const runlist *rl,
+		const u8 *val, const s64 val_len, s64 *inited_size,
+		WRITE_TYPE write_type)
+{
+	s64 bytes_written, total, length, delta;
+	int retry, i;
+
+	if (inited_size)
+		*inited_size = 0LL;
+	if (opts.no_action)
+		return val_len;
+	total = 0LL;
+	delta = 0LL;
+	for (i = 0; rl[i].length; i++) {
+		length = rl[i].length * g_vol->cluster_size;
+		/* Don't write sparse runs. */
+		if (rl[i].lcn == -1) {
+			total += length;
+			if (!val)
+				continue;
+			/* TODO: Check that *val is really zero at pos and len. */
+			continue;
+		}
+		/*
+		 * Break up the write into the real data write and then a write
+		 * of zeroes between the end of the real data and the end of
+		 * the (last) run.
+		 */
+		if (total + length > val_len) {
+			delta = length;
+			length = val_len - total;
+			delta -= length;
+		}
+		if (dev->d_ops->seek(dev, rl[i].lcn * g_vol->cluster_size,
+				SEEK_SET) == (off_t)-1)
+			return -1LL;
+		retry = 0;
+		do {
+			/* use specific functions if buffer is not prefilled */
+			switch (write_type) {
+			case WRITE_BITMAP :
+				bytes_written = mkntfs_bitmap_write(dev,
+					total, length);
+				break;
+			case WRITE_LOGFILE :
+				bytes_written = mkntfs_logfile_write(dev,
+					total, length);
+				break;
+			default :
+				bytes_written = dev->d_ops->write(dev,
+					val + total, length);
+				break;
+			}
+			if (bytes_written == -1LL) {
+				retry = errno;
+				ntfs_log_perror("Error writing to %s",
+					dev->d_name);
+				errno = retry;
+				return bytes_written;
+			}
+			if (bytes_written) {
+				length -= bytes_written;
+				total += bytes_written;
+				if (inited_size)
+					*inited_size += bytes_written;
+			} else {
+				retry++;
+			}
+		} while (length && retry < 3);
+		if (length) {
+			ntfs_log_error("Failed to complete writing to %s after three "
+					"retries.\n", dev->d_name);
+			return total;
+		}
+	}
+	if (delta) {
+		int eo;
+		char *b = ntfs_calloc(delta);
+		if (!b)
+			return -1;
+		bytes_written = mkntfs_write(dev, b, delta);
+		eo = errno;
+		free(b);
+		errno = eo;
+		if (bytes_written == -1LL)
+			return bytes_written;
+	}
+	return total;
+}
+
+/**
+ * make_room_for_attribute - make room for an attribute inside an mft record
+ * @m:		mft record
+ * @pos:	position at which to make space
+ * @size:	byte size to make available at this position
+ *
+ * @pos points to the attribute in front of which we want to make space.
+ *
+ * Return 0 on success or -errno on error. Possible error codes are:
+ *
+ *	-ENOSPC		There is not enough space available to complete
+ *			operation. The caller has to make space before calling
+ *			this.
+ *	-EINVAL		Can only occur if mkntfs was compiled with -DDEBUG. Means
+ *			the input parameters were faulty.
+ */
+static int make_room_for_attribute(MFT_RECORD *m, char *pos, const u32 size)
+{
+	u32 biu;
+
+	if (!size)
+		return 0;
+#ifdef DEBUG
+	/*
+	 * Rigorous consistency checks. Always return -EINVAL even if more
+	 * appropriate codes exist for simplicity of parsing the return value.
+	 */
+	if (size != ((size + 7) & ~7)) {
+		ntfs_log_error("make_room_for_attribute() received non 8-byte aligned "
+				"size.\n");
+		return -EINVAL;
+	}
+	if (!m || !pos)
+		return -EINVAL;
+	if (pos < (char*)m || pos + size < (char*)m ||
+			pos > (char*)m + le32_to_cpu(m->bytes_allocated) ||
+			pos + size > (char*)m + le32_to_cpu(m->bytes_allocated))
+		return -EINVAL;
+	/* The -8 is for the attribute terminator. */
+	if (pos - (char*)m > (int)le32_to_cpu(m->bytes_in_use) - 8)
+		return -EINVAL;
+#endif
+	biu = le32_to_cpu(m->bytes_in_use);
+	/* Do we have enough space? */
+	if (biu + size > le32_to_cpu(m->bytes_allocated))
+		return -ENOSPC;
+	/* Move everything after pos to pos + size. */
+	memmove(pos + size, pos, biu - (pos - (char*)m));
+	/* Update mft record. */
+	m->bytes_in_use = cpu_to_le32(biu + size);
+	return 0;
+}
+
+/**
+ * deallocate_scattered_clusters
+ */
+static void deallocate_scattered_clusters(const runlist *rl)
+{
+	int i;
+
+	if (!rl)
+		return;
+	/* Iterate over all runs in the runlist @rl. */
+	for (i = 0; rl[i].length; i++) {
+		/* Skip sparse runs. */
+		if (rl[i].lcn == -1LL)
+			continue;
+		/* Deallocate the current run. */
+		bitmap_deallocate(rl[i].lcn, rl[i].length);
+	}
+}
+
+/**
+ * allocate_scattered_clusters
+ * @clusters: Amount of clusters to allocate.
+ *
+ * Allocate @clusters and create a runlist of the allocated clusters.
+ *
+ * Return the allocated runlist. Caller has to free the runlist when finished
+ * with it.
+ *
+ * On error return NULL and errno is set to the error code.
+ *
+ * TODO: We should be returning the size as well, but for mkntfs this is not
+ * necessary.
+ */
+static runlist * allocate_scattered_clusters(s64 clusters)
+{
+	runlist *rl = NULL, *rlt;
+	VCN vcn = 0LL;
+	LCN lcn, end, prev_lcn = 0LL;
+	int rlpos = 0;
+	int rlsize = 0;
+	s64 prev_run_len = 0LL;
+	char bit;
+
+	end = g_vol->nr_clusters;
+	/* Loop until all clusters are allocated. */
+	while (clusters) {
+		/* Loop in current zone until we run out of free clusters. */
+		for (lcn = g_mft_zone_end; lcn < end; lcn++) {
+			bit = bitmap_get_and_set(lcn,1);
+			if (bit)
+				continue;
+			/*
+			 * Reallocate memory if necessary. Make sure we have
+			 * enough for the terminator entry as well.
+			 */
+			if ((rlpos + 2) * (int)sizeof(runlist) >= rlsize) {
+				rlsize += 4096; /* PAGE_SIZE */
+				rlt = realloc(rl, rlsize);
+				if (!rlt)
+					goto err_end;
+				rl = rlt;
+			}
+			/* Coalesce with previous run if adjacent LCNs. */
+			if (prev_lcn == lcn - prev_run_len) {
+				rl[rlpos - 1].length = ++prev_run_len;
+				vcn++;
+			} else {
+				rl[rlpos].vcn = vcn++;
+				rl[rlpos].lcn = lcn;
+				prev_lcn = lcn;
+				rl[rlpos].length = 1LL;
+				prev_run_len = 1LL;
+				rlpos++;
+			}
+			/* Done? */
+			if (!--clusters) {
+				/* Add terminator element and return. */
+				rl[rlpos].vcn = vcn;
+				rl[rlpos].lcn = 0LL;
+				rl[rlpos].length = 0LL;
+				return rl;
+			}
+
+		}
+		/* Switch to next zone, decreasing mft zone by factor 2. */
+		end = g_mft_zone_end;
+		g_mft_zone_end >>= 1;
+		/* Have we run out of space on the volume? */
+		if (g_mft_zone_end <= 0)
+			goto err_end;
+	}
+	return rl;
+err_end:
+	if (rl) {
+		/* Add terminator element. */
+		rl[rlpos].vcn = vcn;
+		rl[rlpos].lcn = -1LL;
+		rl[rlpos].length = 0LL;
+		/* Deallocate all allocated clusters. */
+		deallocate_scattered_clusters(rl);
+		/* Free the runlist. */
+		free(rl);
+	}
+	return NULL;
+}
+
+/**
+ * ntfs_attr_find - find (next) attribute in mft record
+ * @type:	attribute type to find
+ * @name:	attribute name to find (optional, i.e. NULL means don't care)
+ * @name_len:	attribute name length (only needed if @name present)
+ * @ic:		IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present)
+ * @val:	attribute value to find (optional, resident attributes only)
+ * @val_len:	attribute value length
+ * @ctx:	search context with mft record and attribute to search from
+ *
+ * You shouldn't need to call this function directly. Use lookup_attr() instead.
+ *
+ * ntfs_attr_find() takes a search context @ctx as parameter and searches the
+ * mft record specified by @ctx->mrec, beginning at @ctx->attr, for an
+ * attribute of @type, optionally @name and @val. If found, ntfs_attr_find()
+ * returns 0 and @ctx->attr will point to the found attribute.
+ *
+ * If not found, ntfs_attr_find() returns -1, with errno set to ENOENT and
+ * @ctx->attr will point to the attribute before which the attribute being
+ * searched for would need to be inserted if such an action were to be desired.
+ *
+ * On actual error, ntfs_attr_find() returns -1 with errno set to the error
+ * code but not to ENOENT.  In this case @ctx->attr is undefined and in
+ * particular do not rely on it not changing.
+ *
+ * If @ctx->is_first is TRUE, the search begins with @ctx->attr itself. If it
+ * is FALSE, the search begins after @ctx->attr.
+ *
+ * If @type is AT_UNUSED, return the first found attribute, i.e. one can
+ * enumerate all attributes by setting @type to AT_UNUSED and then calling
+ * ntfs_attr_find() repeatedly until it returns -1 with errno set to ENOENT to
+ * indicate that there are no more entries. During the enumeration, each
+ * successful call of ntfs_attr_find() will return the next attribute in the
+ * mft record @ctx->mrec.
+ *
+ * If @type is AT_END, seek to the end and return -1 with errno set to ENOENT.
+ * AT_END is not a valid attribute, its length is zero for example, thus it is
+ * safer to return error instead of success in this case. This also allows us
+ * to interoperate cleanly with ntfs_external_attr_find().
+ *
+ * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present
+ * but not AT_UNNAMED search for a named attribute matching @name. Otherwise,
+ * match both named and unnamed attributes.
+ *
+ * If @ic is IGNORE_CASE, the @name comparison is not case sensitive and
+ * @ctx->ntfs_ino must be set to the ntfs inode to which the mft record
+ * @ctx->mrec belongs. This is so we can get at the ntfs volume and hence at
+ * the upcase table. If @ic is CASE_SENSITIVE, the comparison is case
+ * sensitive. When @name is present, @name_len is the @name length in Unicode
+ * characters.
+ *
+ * If @name is not present (NULL), we assume that the unnamed attribute is
+ * being searched for.
+ *
+ * Finally, the resident attribute value @val is looked for, if present.
+ * If @val is not present (NULL), @val_len is ignored.
+ *
+ * ntfs_attr_find() only searches the specified mft record and it ignores the
+ * presence of an attribute list attribute (unless it is the one being searched
+ * for, obviously). If you need to take attribute lists into consideration, use
+ * ntfs_attr_lookup() instead (see below). This also means that you cannot use
+ * ntfs_attr_find() to search for extent records of non-resident attributes, as
+ * extents with lowest_vcn != 0 are usually described by the attribute list
+ * attribute only. - Note that it is possible that the first extent is only in
+ * the attribute list while the last extent is in the base mft record, so don't
+ * rely on being able to find the first extent in the base mft record.
+ *
+ * Warning: Never use @val when looking for attribute types which can be
+ *	    non-resident as this most likely will result in a crash!
+ */
+static int mkntfs_attr_find(const ATTR_TYPES type, const ntfschar *name,
+		const u32 name_len, const IGNORE_CASE_BOOL ic,
+		const u8 *val, const u32 val_len, ntfs_attr_search_ctx *ctx)
+{
+	ATTR_RECORD *a;
+	ntfschar *upcase = g_vol->upcase;
+	u32 upcase_len = g_vol->upcase_len;
+
+	/*
+	 * Iterate over attributes in mft record starting at @ctx->attr, or the
+	 * attribute following that, if @ctx->is_first is TRUE.
+	 */
+	if (ctx->is_first) {
+		a = ctx->attr;
+		ctx->is_first = FALSE;
+	} else {
+		a = (ATTR_RECORD*)((char*)ctx->attr +
+				le32_to_cpu(ctx->attr->length));
+	}
+	for (;;	a = (ATTR_RECORD*)((char*)a + le32_to_cpu(a->length))) {
+		if (p2n(a) < p2n(ctx->mrec) || (char*)a > (char*)ctx->mrec +
+				le32_to_cpu(ctx->mrec->bytes_allocated))
+			break;
+		ctx->attr = a;
+		if (((type != AT_UNUSED) && (le32_to_cpu(a->type) >
+				le32_to_cpu(type))) ||
+				(a->type == AT_END)) {
+			errno = ENOENT;
+			return -1;
+		}
+		if (!a->length)
+			break;
+		/* If this is an enumeration return this attribute. */
+		if (type == AT_UNUSED)
+			return 0;
+		if (a->type != type)
+			continue;
+		/*
+		 * If @name is AT_UNNAMED we want an unnamed attribute.
+		 * If @name is present, compare the two names.
+		 * Otherwise, match any attribute.
+		 */
+		if (name == AT_UNNAMED) {
+			/* The search failed if the found attribute is named. */
+			if (a->name_length) {
+				errno = ENOENT;
+				return -1;
+			}
+		} else if (name && !ntfs_names_are_equal(name, name_len,
+				(ntfschar*)((char*)a + le16_to_cpu(a->name_offset)),
+				a->name_length, ic, upcase, upcase_len)) {
+			int rc;
+
+			rc = ntfs_names_full_collate(name, name_len,
+					(ntfschar*)((char*)a +
+					le16_to_cpu(a->name_offset)),
+					a->name_length, IGNORE_CASE,
+					upcase, upcase_len);
+			/*
+			 * If @name collates before a->name, there is no
+			 * matching attribute.
+			 */
+			if (rc == -1) {
+				errno = ENOENT;
+				return -1;
+			}
+			/* If the strings are not equal, continue search. */
+			if (rc)
+				continue;
+			rc = ntfs_names_full_collate(name, name_len,
+					(ntfschar*)((char*)a +
+					le16_to_cpu(a->name_offset)),
+					a->name_length, CASE_SENSITIVE,
+					upcase, upcase_len);
+			if (rc == -1) {
+				errno = ENOENT;
+				return -1;
+			}
+			if (rc)
+				continue;
+		}
+		/*
+		 * The names match or @name not present and attribute is
+		 * unnamed. If no @val specified, we have found the attribute
+		 * and are done.
+		 */
+		if (!val) {
+			return 0;
+		/* @val is present; compare values. */
+		} else {
+			int rc;
+
+			rc = memcmp(val, (char*)a +le16_to_cpu(a->value_offset),
+					min(val_len,
+					le32_to_cpu(a->value_length)));
+			/*
+			 * If @val collates before the current attribute's
+			 * value, there is no matching attribute.
+			 */
+			if (!rc) {
+				u32 avl;
+				avl = le32_to_cpu(a->value_length);
+				if (val_len == avl)
+					return 0;
+				if (val_len < avl) {
+					errno = ENOENT;
+					return -1;
+				}
+			} else if (rc < 0) {
+				errno = ENOENT;
+				return -1;
+			}
+		}
+	}
+	ntfs_log_trace("File is corrupt. Run chkdsk.\n");
+	errno = EIO;
+	return -1;
+}
+
+/**
+ * ntfs_attr_lookup - find an attribute in an ntfs inode
+ * @type:	attribute type to find
+ * @name:	attribute name to find (optional, i.e. NULL means don't care)
+ * @name_len:	attribute name length (only needed if @name present)
+ * @ic:		IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present)
+ * @lowest_vcn:	lowest vcn to find (optional, non-resident attributes only)
+ * @val:	attribute value to find (optional, resident attributes only)
+ * @val_len:	attribute value length
+ * @ctx:	search context with mft record and attribute to search from
+ *
+ * Find an attribute in an ntfs inode. On first search @ctx->ntfs_ino must
+ * be the base mft record and @ctx must have been obtained from a call to
+ * ntfs_attr_get_search_ctx().
+ *
+ * This function transparently handles attribute lists and @ctx is used to
+ * continue searches where they were left off at.
+ *
+ * If @type is AT_UNUSED, return the first found attribute, i.e. one can
+ * enumerate all attributes by setting @type to AT_UNUSED and then calling
+ * ntfs_attr_lookup() repeatedly until it returns -1 with errno set to ENOENT
+ * to indicate that there are no more entries. During the enumeration, each
+ * successful call of ntfs_attr_lookup() will return the next attribute, with
+ * the current attribute being described by the search context @ctx.
+ *
+ * If @type is AT_END, seek to the end of the base mft record ignoring the
+ * attribute list completely and return -1 with errno set to ENOENT.  AT_END is
+ * not a valid attribute, its length is zero for example, thus it is safer to
+ * return error instead of success in this case.  It should never be needed to
+ * do this, but we implement the functionality because it allows for simpler
+ * code inside ntfs_external_attr_find().
+ *
+ * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present
+ * but not AT_UNNAMED search for a named attribute matching @name. Otherwise,
+ * match both named and unnamed attributes.
+ *
+ * After finishing with the attribute/mft record you need to call
+ * ntfs_attr_put_search_ctx() to cleanup the search context (unmapping any
+ * mapped extent inodes, etc).
+ *
+ * Return 0 if the search was successful and -1 if not, with errno set to the
+ * error code.
+ *
+ * On success, @ctx->attr is the found attribute, it is in mft record
+ * @ctx->mrec, and @ctx->al_entry is the attribute list entry for this
+ * attribute with @ctx->base_* being the base mft record to which @ctx->attr
+ * belongs.  If no attribute list attribute is present @ctx->al_entry and
+ * @ctx->base_* are NULL.
+ *
+ * On error ENOENT, i.e. attribute not found, @ctx->attr is set to the
+ * attribute which collates just after the attribute being searched for in the
+ * base ntfs inode, i.e. if one wants to add the attribute to the mft record
+ * this is the correct place to insert it into, and if there is not enough
+ * space, the attribute should be placed in an extent mft record.
+ * @ctx->al_entry points to the position within @ctx->base_ntfs_ino->attr_list
+ * at which the new attribute's attribute list entry should be inserted.  The
+ * other @ctx fields, base_ntfs_ino, base_mrec, and base_attr are set to NULL.
+ * The only exception to this is when @type is AT_END, in which case
+ * @ctx->al_entry is set to NULL also (see above).
+ *
+ * The following error codes are defined:
+ *	ENOENT	Attribute not found, not an error as such.
+ *	EINVAL	Invalid arguments.
+ *	EIO	I/O error or corrupt data structures found.
+ *	ENOMEM	Not enough memory to allocate necessary buffers.
+ */
+static int mkntfs_attr_lookup(const ATTR_TYPES type, const ntfschar *name,
+		const u32 name_len, const IGNORE_CASE_BOOL ic,
+		const VCN lowest_vcn __attribute__((unused)), const u8 *val,
+		const u32 val_len, ntfs_attr_search_ctx *ctx)
+{
+	ntfs_inode *base_ni;
+
+	if (!ctx || !ctx->mrec || !ctx->attr) {
+		errno = EINVAL;
+		return -1;
+	}
+	if (ctx->base_ntfs_ino)
+		base_ni = ctx->base_ntfs_ino;
+	else
+		base_ni = ctx->ntfs_ino;
+	if (!base_ni || !NInoAttrList(base_ni) || type == AT_ATTRIBUTE_LIST)
+		return mkntfs_attr_find(type, name, name_len, ic, val, val_len,
+				ctx);
+	errno = EOPNOTSUPP;
+	return -1;
+}
+
+/**
+ * insert_positioned_attr_in_mft_record
+ *
+ * Create a non-resident attribute with a predefined on disk location
+ * specified by the runlist @rl. The clusters specified by @rl are assumed to
+ * be allocated already.
+ *
+ * Return 0 on success and -errno on error.
+ */
+static int insert_positioned_attr_in_mft_record(MFT_RECORD *m,
+		const ATTR_TYPES type, const char *name, u32 name_len,
+		const IGNORE_CASE_BOOL ic, const ATTR_FLAGS flags,
+		const runlist *rl, const u8 *val, const s64 val_len)
+{
+	ntfs_attr_search_ctx *ctx;
+	ATTR_RECORD *a;
+	u16 hdr_size;
+	int asize, mpa_size, err, i;
+	s64 bw = 0, inited_size;
+	VCN highest_vcn;
+	ntfschar *uname = NULL;
+	int uname_len = 0;
+	/*
+	if (base record)
+		attr_lookup();
+	else
+	*/
+
+	uname = ntfs_str2ucs(name, &uname_len);
+	if (!uname)
+		return -errno;
+
+	/* Check if the attribute is already there. */
+	ctx = ntfs_attr_get_search_ctx(NULL, m);
+	if (!ctx) {
+		ntfs_log_error("Failed to allocate attribute search context.\n");
+		err = -ENOMEM;
+		goto err_out;
+	}
+	if (ic == IGNORE_CASE) {
+		ntfs_log_error("FIXME: Hit unimplemented code path #1.\n");
+		err = -EOPNOTSUPP;
+		goto err_out;
+	}
+	if (!mkntfs_attr_lookup(type, uname, uname_len, ic, 0, NULL, 0, ctx)) {
+		err = -EEXIST;
+		goto err_out;
+	}
+	if (errno != ENOENT) {
+		ntfs_log_error("Corrupt inode.\n");
+		err = -errno;
+		goto err_out;
+	}
+	a = ctx->attr;
+	if (flags & ATTR_COMPRESSION_MASK) {
+		ntfs_log_error("Compressed attributes not supported yet.\n");
+		/* FIXME: Compress attribute into a temporary buffer, set */
+		/* val accordingly and save the compressed size. */
+		err = -EOPNOTSUPP;
+		goto err_out;
+	}
+	if (flags & (ATTR_IS_ENCRYPTED | ATTR_IS_SPARSE)) {
+		ntfs_log_error("Encrypted/sparse attributes not supported.\n");
+		err = -EOPNOTSUPP;
+		goto err_out;
+	}
+	if (flags & ATTR_COMPRESSION_MASK) {
+		hdr_size = 72;
+		/* FIXME: This compression stuff is all wrong. Never mind for */
+		/* now. (AIA) */
+		if (val_len)
+			mpa_size = 0; /* get_size_for_compressed_mapping_pairs(rl); */
+		else
+			mpa_size = 0;
+	} else {
+		hdr_size = 64;
+		if (val_len) {
+			mpa_size = ntfs_get_size_for_mapping_pairs(g_vol, rl, 0, INT_MAX);
+			if (mpa_size < 0) {
+				err = -errno;
+				ntfs_log_error("Failed to get size for mapping "
+						"pairs.\n");
+				goto err_out;
+			}
+		} else {
+			mpa_size = 0;
+		}
+	}
+	/* Mapping pairs array and next attribute must be 8-byte aligned. */
+	asize = (((int)hdr_size + ((name_len + 7) & ~7) + mpa_size) + 7) & ~7;
+	/* Get the highest vcn. */
+	for (i = 0, highest_vcn = 0LL; rl[i].length; i++)
+		highest_vcn += rl[i].length;
+	/* Does the value fit inside the allocated size? */
+	if (highest_vcn * g_vol->cluster_size < val_len) {
+		ntfs_log_error("BUG: Allocated size is smaller than data size!\n");
+		err = -EINVAL;
+		goto err_out;
+	}
+	err = make_room_for_attribute(m, (char*)a, asize);
+	if (err == -ENOSPC) {
+		/*
+		 * FIXME: Make space! (AIA)
+		 * can we make it non-resident? if yes, do that.
+		 *	does it fit now? yes -> do it.
+		 * m's $DATA or $BITMAP+$INDEX_ALLOCATION resident?
+		 * yes -> make non-resident
+		 *	does it fit now? yes -> do it.
+		 * make all attributes non-resident
+		 *	does it fit now? yes -> do it.
+		 * m is a base record? yes -> allocate extension record
+		 *	does the new attribute fit in there? yes -> do it.
+		 * split up runlist into extents and place each in an extension
+		 * record.
+		 * FIXME: the check for needing extension records should be
+		 * earlier on as it is very quick: asize > m->bytes_allocated?
+		 */
+		err = -EOPNOTSUPP;
+		goto err_out;
+#ifdef DEBUG
+	} else if (err == -EINVAL) {
+		ntfs_log_error("BUG(): in insert_positioned_attribute_in_mft_"
+				"record(): make_room_for_attribute() returned "
+				"error: EINVAL!\n");
+		goto err_out;
+#endif
+	}
+	a->type = type;
+	a->length = cpu_to_le32(asize);
+	a->non_resident = 1;
+	a->name_length = name_len;
+	a->name_offset = cpu_to_le16(hdr_size);
+	a->flags = flags;
+	a->instance = m->next_attr_instance;
+	m->next_attr_instance = cpu_to_le16((le16_to_cpu(m->next_attr_instance)
+			+ 1) & 0xffff);
+	a->lowest_vcn = cpu_to_le64(0);
+	a->highest_vcn = cpu_to_sle64(highest_vcn - 1LL);
+	a->mapping_pairs_offset = cpu_to_le16(hdr_size + ((name_len + 7) & ~7));
+	memset(a->reserved1, 0, sizeof(a->reserved1));
+	/* FIXME: Allocated size depends on compression. */
+	a->allocated_size = cpu_to_sle64(highest_vcn * g_vol->cluster_size);
+	a->data_size = cpu_to_sle64(val_len);
+	if (name_len)
+		memcpy((char*)a + hdr_size, uname, name_len << 1);
+	if (flags & ATTR_COMPRESSION_MASK) {
+		if (flags & ATTR_COMPRESSION_MASK & ~ATTR_IS_COMPRESSED) {
+			ntfs_log_error("Unknown compression format. Reverting "
+					"to standard compression.\n");
+			a->flags &= ~ATTR_COMPRESSION_MASK;
+			a->flags |= ATTR_IS_COMPRESSED;
+		}
+		a->compression_unit = 4;
+		inited_size = val_len;
+		/* FIXME: Set the compressed size. */
+		a->compressed_size = cpu_to_le64(0);
+		/* FIXME: Write out the compressed data. */
+		/* FIXME: err = build_mapping_pairs_compressed(); */
+		err = -EOPNOTSUPP;
+	} else {
+		a->compression_unit = 0;
+		if ((type == AT_DATA)
+		    && (m->mft_record_number
+				 == const_cpu_to_le32(FILE_LogFile)))
+			bw = ntfs_rlwrite(g_vol->dev, rl, val, val_len,
+					&inited_size, WRITE_LOGFILE);
+		else
+			bw = ntfs_rlwrite(g_vol->dev, rl, val, val_len,
+					&inited_size, WRITE_STANDARD);
+		if (bw != val_len) {
+			ntfs_log_error("Error writing non-resident attribute "
+					"value.\n");
+			return -errno;
+		}
+		err = ntfs_mapping_pairs_build(g_vol, (u8*)a + hdr_size +
+				((name_len + 7) & ~7), mpa_size, rl, 0, NULL);
+	}
+	a->initialized_size = cpu_to_sle64(inited_size);
+	if (err < 0 || bw != val_len) {
+		/* FIXME: Handle error. */
+		/* deallocate clusters */
+		/* remove attribute */
+		if (err >= 0)
+			err = -EIO;
+		ntfs_log_error("insert_positioned_attr_in_mft_record failed "
+				"with error %i.\n", err < 0 ? err : (int)bw);
+	}
+err_out:
+	if (ctx)
+		ntfs_attr_put_search_ctx(ctx);
+	ntfs_ucsfree(uname);
+	return err;
+}
+
+/**
+ * insert_non_resident_attr_in_mft_record
+ *
+ * Return 0 on success and -errno on error.
+ */
+static int insert_non_resident_attr_in_mft_record(MFT_RECORD *m,
+		const ATTR_TYPES type, const char *name, u32 name_len,
+		const IGNORE_CASE_BOOL ic, const ATTR_FLAGS flags,
+		const u8 *val, const s64 val_len,
+		WRITE_TYPE write_type)
+{
+	ntfs_attr_search_ctx *ctx;
+	ATTR_RECORD *a;
+	u16 hdr_size;
+	int asize, mpa_size, err, i;
+	runlist *rl = NULL;
+	s64 bw = 0;
+	ntfschar *uname = NULL;
+	int uname_len = 0;
+	/*
+	if (base record)
+		attr_lookup();
+	else
+	*/
+
+	uname = ntfs_str2ucs(name, &uname_len);
+	if (!uname)
+		return -errno;
+
+	/* Check if the attribute is already there. */
+	ctx = ntfs_attr_get_search_ctx(NULL, m);
+	if (!ctx) {
+		ntfs_log_error("Failed to allocate attribute search context.\n");
+		err = -ENOMEM;
+		goto err_out;
+	}
+	if (ic == IGNORE_CASE) {
+		ntfs_log_error("FIXME: Hit unimplemented code path #2.\n");
+		err = -EOPNOTSUPP;
+		goto err_out;
+	}
+	if (!mkntfs_attr_lookup(type, uname, uname_len, ic, 0, NULL, 0, ctx)) {
+		err = -EEXIST;
+		goto err_out;
+	}
+	if (errno != ENOENT) {
+		ntfs_log_error("Corrupt inode.\n");
+		err = -errno;
+		goto err_out;
+	}
+	a = ctx->attr;
+	if (flags & ATTR_COMPRESSION_MASK) {
+		ntfs_log_error("Compressed attributes not supported yet.\n");
+		/* FIXME: Compress attribute into a temporary buffer, set */
+		/* val accordingly and save the compressed size. */
+		err = -EOPNOTSUPP;
+		goto err_out;
+	}
+	if (flags & (ATTR_IS_ENCRYPTED | ATTR_IS_SPARSE)) {
+		ntfs_log_error("Encrypted/sparse attributes not supported.\n");
+		err = -EOPNOTSUPP;
+		goto err_out;
+	}
+	if (val_len) {
+		rl = allocate_scattered_clusters((val_len +
+				g_vol->cluster_size - 1) / g_vol->cluster_size);
+		if (!rl) {
+			err = -errno;
+			ntfs_log_perror("Failed to allocate scattered clusters");
+			goto err_out;
+		}
+	} else {
+		rl = NULL;
+	}
+	if (flags & ATTR_COMPRESSION_MASK) {
+		hdr_size = 72;
+		/* FIXME: This compression stuff is all wrong. Never mind for */
+		/* now. (AIA) */
+		if (val_len)
+			mpa_size = 0; /* get_size_for_compressed_mapping_pairs(rl); */
+		else
+			mpa_size = 0;
+	} else {
+		hdr_size = 64;
+		if (val_len) {
+			mpa_size = ntfs_get_size_for_mapping_pairs(g_vol, rl, 0, INT_MAX);
+			if (mpa_size < 0) {
+				err = -errno;
+				ntfs_log_error("Failed to get size for mapping "
+						"pairs.\n");
+				goto err_out;
+			}
+		} else {
+			mpa_size = 0;
+		}
+	}
+	/* Mapping pairs array and next attribute must be 8-byte aligned. */
+	asize = (((int)hdr_size + ((name_len + 7) & ~7) + mpa_size) + 7) & ~7;
+	err = make_room_for_attribute(m, (char*)a, asize);
+	if (err == -ENOSPC) {
+		/*
+		 * FIXME: Make space! (AIA)
+		 * can we make it non-resident? if yes, do that.
+		 *	does it fit now? yes -> do it.
+		 * m's $DATA or $BITMAP+$INDEX_ALLOCATION resident?
+		 * yes -> make non-resident
+		 *	does it fit now? yes -> do it.
+		 * make all attributes non-resident
+		 *	does it fit now? yes -> do it.
+		 * m is a base record? yes -> allocate extension record
+		 *	does the new attribute fit in there? yes -> do it.
+		 * split up runlist into extents and place each in an extension
+		 * record.
+		 * FIXME: the check for needing extension records should be
+		 * earlier on as it is very quick: asize > m->bytes_allocated?
+		 */
+		err = -EOPNOTSUPP;
+		goto err_out;
+#ifdef DEBUG
+	} else if (err == -EINVAL) {
+		ntfs_log_error("BUG(): in insert_non_resident_attribute_in_"
+				"mft_record(): make_room_for_attribute() "
+				"returned error: EINVAL!\n");
+		goto err_out;
+#endif
+	}
+	a->type = type;
+	a->length = cpu_to_le32(asize);
+	a->non_resident = 1;
+	a->name_length = name_len;
+	a->name_offset = cpu_to_le16(hdr_size);
+	a->flags = flags;
+	a->instance = m->next_attr_instance;
+	m->next_attr_instance = cpu_to_le16((le16_to_cpu(m->next_attr_instance)
+			+ 1) & 0xffff);
+	a->lowest_vcn = cpu_to_le64(0);
+	for (i = 0; rl[i].length; i++)
+		;
+	a->highest_vcn = cpu_to_sle64(rl[i].vcn - 1);
+	a->mapping_pairs_offset = cpu_to_le16(hdr_size + ((name_len + 7) & ~7));
+	memset(a->reserved1, 0, sizeof(a->reserved1));
+	/* FIXME: Allocated size depends on compression. */
+	a->allocated_size = cpu_to_sle64((val_len + (g_vol->cluster_size - 1)) &
+			~(g_vol->cluster_size - 1));
+	a->data_size = cpu_to_sle64(val_len);
+	a->initialized_size = cpu_to_sle64(val_len);
+	if (name_len)
+		memcpy((char*)a + hdr_size, uname, name_len << 1);
+	if (flags & ATTR_COMPRESSION_MASK) {
+		if (flags & ATTR_COMPRESSION_MASK & ~ATTR_IS_COMPRESSED) {
+			ntfs_log_error("Unknown compression format. Reverting "
+					"to standard compression.\n");
+			a->flags &= ~ATTR_COMPRESSION_MASK;
+			a->flags |= ATTR_IS_COMPRESSED;
+		}
+		a->compression_unit = 4;
+		/* FIXME: Set the compressed size. */
+		a->compressed_size = cpu_to_le64(0);
+		/* FIXME: Write out the compressed data. */
+		/* FIXME: err = build_mapping_pairs_compressed(); */
+		err = -EOPNOTSUPP;
+	} else {
+		a->compression_unit = 0;
+		bw = ntfs_rlwrite(g_vol->dev, rl, val, val_len, NULL,
+					write_type);
+		if (bw != val_len) {
+			ntfs_log_error("Error writing non-resident attribute "
+					"value.\n");
+			return -errno;
+		}
+		err = ntfs_mapping_pairs_build(g_vol, (u8*)a + hdr_size +
+				((name_len + 7) & ~7), mpa_size, rl, 0, NULL);
+	}
+	if (err < 0 || bw != val_len) {
+		/* FIXME: Handle error. */
+		/* deallocate clusters */
+		/* remove attribute */
+		if (err >= 0)
+			err = -EIO;
+		ntfs_log_error("insert_non_resident_attr_in_mft_record failed with "
+			"error %lld.\n", (long long) (err < 0 ? err : bw));
+	}
+err_out:
+	if (ctx)
+		ntfs_attr_put_search_ctx(ctx);
+	ntfs_ucsfree(uname);
+	free(rl);
+	return err;
+}
+
+/**
+ * insert_resident_attr_in_mft_record
+ *
+ * Return 0 on success and -errno on error.
+ */
+static int insert_resident_attr_in_mft_record(MFT_RECORD *m,
+		const ATTR_TYPES type, const char *name, u32 name_len,
+		const IGNORE_CASE_BOOL ic, const ATTR_FLAGS flags,
+		const RESIDENT_ATTR_FLAGS res_flags,
+		const u8 *val, const u32 val_len)
+{
+	ntfs_attr_search_ctx *ctx;
+	ATTR_RECORD *a;
+	int asize, err;
+	ntfschar *uname = NULL;
+	int uname_len = 0;
+	/*
+	if (base record)
+		mkntfs_attr_lookup();
+	else
+	*/
+
+	uname = ntfs_str2ucs(name, &uname_len);
+	if (!uname)
+		return -errno;
+
+	/* Check if the attribute is already there. */
+	ctx = ntfs_attr_get_search_ctx(NULL, m);
+	if (!ctx) {
+		ntfs_log_error("Failed to allocate attribute search context.\n");
+		err = -ENOMEM;
+		goto err_out;
+	}
+	if (ic == IGNORE_CASE) {
+		ntfs_log_error("FIXME: Hit unimplemented code path #3.\n");
+		err = -EOPNOTSUPP;
+		goto err_out;
+	}
+	if (!mkntfs_attr_lookup(type, uname, uname_len, ic, 0, val, val_len,
+			ctx)) {
+		err = -EEXIST;
+		goto err_out;
+	}
+	if (errno != ENOENT) {
+		ntfs_log_error("Corrupt inode.\n");
+		err = -errno;
+		goto err_out;
+	}
+	a = ctx->attr;
+	/* sizeof(resident attribute record header) == 24 */
+	asize = ((24 + ((name_len*2 + 7) & ~7) + val_len) + 7) & ~7;
+	err = make_room_for_attribute(m, (char*)a, asize);
+	if (err == -ENOSPC) {
+		/*
+		 * FIXME: Make space! (AIA)
+		 * can we make it non-resident? if yes, do that.
+		 *	does it fit now? yes -> do it.
+		 * m's $DATA or $BITMAP+$INDEX_ALLOCATION resident?
+		 * yes -> make non-resident
+		 *	does it fit now? yes -> do it.
+		 * make all attributes non-resident
+		 *	does it fit now? yes -> do it.
+		 * m is a base record? yes -> allocate extension record
+		 *	does the new attribute fit in there? yes -> do it.
+		 * split up runlist into extents and place each in an extension
+		 * record.
+		 * FIXME: the check for needing extension records should be
+		 * earlier on as it is very quick: asize > m->bytes_allocated?
+		 */
+		err = -EOPNOTSUPP;
+		goto err_out;
+	}
+#ifdef DEBUG
+	if (err == -EINVAL) {
+		ntfs_log_error("BUG(): in insert_resident_attribute_in_mft_"
+				"record(): make_room_for_attribute() returned "
+				"error: EINVAL!\n");
+		goto err_out;
+	}
+#endif
+	a->type = type;
+	a->length = cpu_to_le32(asize);
+	a->non_resident = 0;
+	a->name_length = name_len;
+	if (type == AT_OBJECT_ID)
+		a->name_offset = const_cpu_to_le16(0);
+	else
+		a->name_offset = const_cpu_to_le16(24);
+	a->flags = flags;
+	a->instance = m->next_attr_instance;
+	m->next_attr_instance = cpu_to_le16((le16_to_cpu(m->next_attr_instance)
+			+ 1) & 0xffff);
+	a->value_length = cpu_to_le32(val_len);
+	a->value_offset = cpu_to_le16(24 + ((name_len*2 + 7) & ~7));
+	a->resident_flags = res_flags;
+	a->reservedR = 0;
+	if (name_len)
+		memcpy((char*)a + 24, uname, name_len << 1);
+	if (val_len)
+		memcpy((char*)a + le16_to_cpu(a->value_offset), val, val_len);
+err_out:
+	if (ctx)
+		ntfs_attr_put_search_ctx(ctx);
+	ntfs_ucsfree(uname);
+	return err;
+}
+
+
+/**
+ * add_attr_std_info
+ *
+ * Return 0 on success or -errno on error.
+ */
+static int add_attr_std_info(MFT_RECORD *m, const FILE_ATTR_FLAGS flags,
+		le32 security_id)
+{
+	STANDARD_INFORMATION si;
+	int err, sd_size;
+
+	sd_size = 48;
+
+	si.creation_time = mkntfs_time();
+	si.last_data_change_time = si.creation_time;
+	si.last_mft_change_time = si.creation_time;
+	si.last_access_time = si.creation_time;
+	si.file_attributes = flags; /* already LE */
+	si.maximum_versions = cpu_to_le32(0);
+	si.version_number = cpu_to_le32(0);
+	si.class_id = cpu_to_le32(0);
+	si.security_id = security_id;
+	if (si.security_id != const_cpu_to_le32(0))
+		sd_size = 72;
+	/* FIXME: $Quota support... */
+	si.owner_id = cpu_to_le32(0);
+	si.quota_charged = cpu_to_le64(0ULL);
+	/* FIXME: $UsnJrnl support... Not needed on fresh w2k3-volume */
+	si.usn = cpu_to_le64(0ULL);
+	/* NTFS 1.2: size of si = 48, NTFS 3.[01]: size of si = 72 */
+	err = insert_resident_attr_in_mft_record(m, AT_STANDARD_INFORMATION,
+			NULL, 0, CASE_SENSITIVE, const_cpu_to_le16(0),
+			0, (u8*)&si, sd_size);
+	if (err < 0)
+		ntfs_log_perror("add_attr_std_info failed");
+	return err;
+}
+
+/*
+ *		Tell whether the unnamed data is non resident
+ */
+
+static BOOL non_resident_unnamed_data(MFT_RECORD *m)
+{
+	ATTR_RECORD *a;
+	ntfs_attr_search_ctx *ctx;
+	BOOL nonres;
+
+	ctx = ntfs_attr_get_search_ctx(NULL, m);
+	if (ctx && !mkntfs_attr_find(AT_DATA,
+				(const ntfschar*)NULL, 0, CASE_SENSITIVE,
+				(u8*)NULL, 0, ctx)) {
+		a = ctx->attr;
+		nonres = a->non_resident != 0;
+	} else {
+		ntfs_log_error("BUG: Unnamed data not found\n");
+		nonres = TRUE;
+	}
+	if (ctx)
+		ntfs_attr_put_search_ctx(ctx);
+	return (nonres);
+}
+
+/*
+ *		Get the time stored in the standard information attribute
+ */
+
+static ntfs_time stdinfo_time(MFT_RECORD *m)
+{
+	STANDARD_INFORMATION *si;
+	ntfs_attr_search_ctx *ctx;
+	ntfs_time info_time;
+
+	ctx = ntfs_attr_get_search_ctx(NULL, m);
+	if (ctx && !mkntfs_attr_find(AT_STANDARD_INFORMATION,
+				(const ntfschar*)NULL, 0, CASE_SENSITIVE,
+				(u8*)NULL, 0, ctx)) {
+		si = (STANDARD_INFORMATION*)((char*)ctx->attr +
+				le16_to_cpu(ctx->attr->value_offset));
+		info_time = si->creation_time;
+	} else {
+		ntfs_log_error("BUG: Standard information not found\n");
+		info_time = mkntfs_time();
+	}
+	if (ctx)
+		ntfs_attr_put_search_ctx(ctx);
+	return (info_time);
+}
+
+/**
+ * add_attr_file_name
+ *
+ * Return 0 on success or -errno on error.
+ */
+static int add_attr_file_name(MFT_RECORD *m, const leMFT_REF parent_dir,
+		const s64 allocated_size, const s64 data_size,
+		const FILE_ATTR_FLAGS flags, const u16 packed_ea_size,
+		const u32 reparse_point_tag, const char *file_name,
+		const FILE_NAME_TYPE_FLAGS file_name_type)
+{
+	ntfs_attr_search_ctx *ctx;
+	STANDARD_INFORMATION *si;
+	FILE_NAME_ATTR *fn;
+	int i, fn_size;
+	ntfschar *uname;
+
+	/* Check if the attribute is already there. */
+	ctx = ntfs_attr_get_search_ctx(NULL, m);
+	if (!ctx) {
+		ntfs_log_error("Failed to get attribute search context.\n");
+		return -ENOMEM;
+	}
+	if (mkntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED, 0,
+				CASE_SENSITIVE, 0, NULL, 0, ctx)) {
+		int eo = errno;
+		ntfs_log_error("BUG: Standard information attribute not "
+				"present in file record.\n");
+		ntfs_attr_put_search_ctx(ctx);
+		return -eo;
+	}
+	si = (STANDARD_INFORMATION*)((char*)ctx->attr +
+			le16_to_cpu(ctx->attr->value_offset));
+	i = (strlen(file_name) + 1) * sizeof(ntfschar);
+	fn_size = sizeof(FILE_NAME_ATTR) + i;
+	fn = ntfs_malloc(fn_size);
+	if (!fn) {
+		ntfs_attr_put_search_ctx(ctx);
+		return -errno;
+	}
+	fn->parent_directory = parent_dir;
+
+	fn->creation_time = si->creation_time;
+	fn->last_data_change_time = si->last_data_change_time;
+	fn->last_mft_change_time = si->last_mft_change_time;
+	fn->last_access_time = si->last_access_time;
+	ntfs_attr_put_search_ctx(ctx);
+
+	fn->allocated_size = cpu_to_sle64(allocated_size);
+	fn->data_size = cpu_to_sle64(data_size);
+	fn->file_attributes = flags;
+	/* These are in a union so can't have both. */
+	if (packed_ea_size && reparse_point_tag) {
+		free(fn);
+		return -EINVAL;
+	}
+	if (packed_ea_size) {
+		fn->packed_ea_size = cpu_to_le16(packed_ea_size);
+		fn->reserved = cpu_to_le16(0);
+	} else {
+		fn->reparse_point_tag = cpu_to_le32(reparse_point_tag);
+	}
+	fn->file_name_type = file_name_type;
+	uname = fn->file_name;
+	i = ntfs_mbstoucs_libntfscompat(file_name, &uname, i);
+	if (i < 1) {
+		free(fn);
+		return -EINVAL;
+	}
+	if (i > 0xff) {
+		free(fn);
+		return -ENAMETOOLONG;
+	}
+	/* No terminating null in file names. */
+	fn->file_name_length = i;
+	fn_size = sizeof(FILE_NAME_ATTR) + i * sizeof(ntfschar);
+	i = insert_resident_attr_in_mft_record(m, AT_FILE_NAME, NULL, 0,
+			CASE_SENSITIVE, const_cpu_to_le16(0),
+			RESIDENT_ATTR_IS_INDEXED, (u8*)fn, fn_size);
+	free(fn);
+	if (i < 0)
+		ntfs_log_error("add_attr_file_name failed: %s\n", strerror(-i));
+	return i;
+}
+
+/**
+ * add_attr_object_id -
+ *
+ * Note we insert only a basic object id which only has the GUID and none of
+ * the extended fields.  This is because we currently only use this function
+ * when creating the object id for the volume.
+ *
+ * Return 0 on success or -errno on error.
+ */
+static int add_attr_object_id(MFT_RECORD *m, const GUID *object_id)
+{
+	OBJECT_ID_ATTR oi;
+	int err;
+
+	oi = (OBJECT_ID_ATTR) {
+		.object_id = *object_id,
+	};
+	err = insert_resident_attr_in_mft_record(m, AT_OBJECT_ID, NULL,
+			0, CASE_SENSITIVE, const_cpu_to_le16(0),
+			0, (u8*)&oi, sizeof(oi.object_id));
+	if (err < 0)
+		ntfs_log_error("add_attr_vol_info failed: %s\n", strerror(-err));
+	return err;
+}
+
+/**
+ * add_attr_sd
+ *
+ * Create the security descriptor attribute adding the security descriptor @sd
+ * of length @sd_len to the mft record @m.
+ *
+ * Return 0 on success or -errno on error.
+ */
+static int add_attr_sd(MFT_RECORD *m, const u8 *sd, const s64 sd_len)
+{
+	int err;
+
+	/* Does it fit? NO: create non-resident. YES: create resident. */
+	if (le32_to_cpu(m->bytes_in_use) + 24 + sd_len >
+						le32_to_cpu(m->bytes_allocated))
+		err = insert_non_resident_attr_in_mft_record(m,
+				AT_SECURITY_DESCRIPTOR, NULL, 0,
+				CASE_SENSITIVE, const_cpu_to_le16(0), sd,
+				sd_len, WRITE_STANDARD);
+	else
+		err = insert_resident_attr_in_mft_record(m,
+				AT_SECURITY_DESCRIPTOR, NULL, 0,
+				CASE_SENSITIVE, const_cpu_to_le16(0), 0, sd,
+				sd_len);
+	if (err < 0)
+		ntfs_log_error("add_attr_sd failed: %s\n", strerror(-err));
+	return err;
+}
+
+/**
+ * add_attr_data
+ *
+ * Return 0 on success or -errno on error.
+ */
+static int add_attr_data(MFT_RECORD *m, const char *name, const u32 name_len,
+		const IGNORE_CASE_BOOL ic, const ATTR_FLAGS flags,
+		const u8 *val, const s64 val_len)
+{
+	int err;
+
+	/*
+	 * Does it fit? NO: create non-resident. YES: create resident.
+	 *
+	 * FIXME: Introduced arbitrary limit of mft record allocated size - 512.
+	 * This is to get around the problem that if $Bitmap/$DATA becomes too
+	 * big, but is just small enough to be resident, we would make it
+	 * resident, and later run out of space when creating the other
+	 * attributes and this would cause us to abort as making resident
+	 * attributes non-resident is not supported yet.
+	 * The proper fix is to support making resident attribute non-resident.
+	 */
+	if (le32_to_cpu(m->bytes_in_use) + 24 + val_len >
+			min(le32_to_cpu(m->bytes_allocated),
+			le32_to_cpu(m->bytes_allocated) - 512))
+		err = insert_non_resident_attr_in_mft_record(m, AT_DATA, name,
+				name_len, ic, flags, val, val_len,
+				WRITE_STANDARD);
+	else
+		err = insert_resident_attr_in_mft_record(m, AT_DATA, name,
+				name_len, ic, flags, 0, val, val_len);
+
+	if (err < 0)
+		ntfs_log_error("add_attr_data failed: %s\n", strerror(-err));
+	return err;
+}
+
+/**
+ * add_attr_data_positioned
+ *
+ * Create a non-resident data attribute with a predefined on disk location
+ * specified by the runlist @rl. The clusters specified by @rl are assumed to
+ * be allocated already.
+ *
+ * Return 0 on success or -errno on error.
+ */
+static int add_attr_data_positioned(MFT_RECORD *m, const char *name,
+		const u32 name_len, const IGNORE_CASE_BOOL ic,
+		const ATTR_FLAGS flags, const runlist *rl,
+		const u8 *val, const s64 val_len)
+{
+	int err;
+
+	err = insert_positioned_attr_in_mft_record(m, AT_DATA, name, name_len,
+			ic, flags, rl, val, val_len);
+	if (err < 0)
+		ntfs_log_error("add_attr_data_positioned failed: %s\n",
+				strerror(-err));
+	return err;
+}
+
+/**
+ * add_attr_vol_name
+ *
+ * Create volume name attribute specifying the volume name @vol_name as a null
+ * terminated char string of length @vol_name_len (number of characters not
+ * including the terminating null), which is converted internally to a little
+ * endian ntfschar string. The name is at least 1 character long (though
+ * Windows accepts zero characters), and at most 128 characters long (not
+ * counting the terminating null).
+ *
+ * Return 0 on success or -errno on error.
+ */
+static int add_attr_vol_name(MFT_RECORD *m, const char *vol_name,
+		const int vol_name_len __attribute__((unused)))
+{
+	ntfschar *uname = NULL;
+	int uname_len = 0;
+	int i;
+
+	if (vol_name) {
+		uname_len = ntfs_mbstoucs(vol_name, &uname);
+		if (uname_len < 0)
+			return -errno;
+		if (uname_len > 128) {
+			free(uname);
+			return -ENAMETOOLONG;
+		}
+	}
+	i = insert_resident_attr_in_mft_record(m, AT_VOLUME_NAME, NULL, 0,
+			CASE_SENSITIVE, const_cpu_to_le16(0),
+			0, (u8*)uname, uname_len*sizeof(ntfschar));
+	free(uname);
+	if (i < 0)
+		ntfs_log_error("add_attr_vol_name failed: %s\n", strerror(-i));
+	return i;
+}
+
+/**
+ * add_attr_vol_info
+ *
+ * Return 0 on success or -errno on error.
+ */
+static int add_attr_vol_info(MFT_RECORD *m, const VOLUME_FLAGS flags,
+		const u8 major_ver, const u8 minor_ver)
+{
+	VOLUME_INFORMATION vi;
+	int err;
+
+	memset(&vi, 0, sizeof(vi));
+	vi.major_ver = major_ver;
+	vi.minor_ver = minor_ver;
+	vi.flags = flags & VOLUME_FLAGS_MASK;
+	err = insert_resident_attr_in_mft_record(m, AT_VOLUME_INFORMATION, NULL,
+			0, CASE_SENSITIVE, const_cpu_to_le16(0),
+			0, (u8*)&vi, sizeof(vi));
+	if (err < 0)
+		ntfs_log_error("add_attr_vol_info failed: %s\n", strerror(-err));
+	return err;
+}
+
+/**
+ * add_attr_index_root
+ *
+ * Return 0 on success or -errno on error.
+ */
+static int add_attr_index_root(MFT_RECORD *m, const char *name,
+		const u32 name_len, const IGNORE_CASE_BOOL ic,
+		const ATTR_TYPES indexed_attr_type,
+		const COLLATION_RULES collation_rule,
+		const u32 index_block_size)
+{
+	INDEX_ROOT *r;
+	INDEX_ENTRY_HEADER *e;
+	int err, val_len;
+
+	val_len = sizeof(INDEX_ROOT) + sizeof(INDEX_ENTRY_HEADER);
+	r = ntfs_malloc(val_len);
+	if (!r)
+		return -errno;
+	r->type = (indexed_attr_type == AT_FILE_NAME)
+				? AT_FILE_NAME : const_cpu_to_le32(0);
+	if (indexed_attr_type == AT_FILE_NAME &&
+			collation_rule != COLLATION_FILE_NAME) {
+		free(r);
+		ntfs_log_error("add_attr_index_root: indexed attribute is $FILE_NAME "
+			"but collation rule is not COLLATION_FILE_NAME.\n");
+		return -EINVAL;
+	}
+	r->collation_rule = collation_rule;
+	r->index_block_size = cpu_to_le32(index_block_size);
+	if (index_block_size >= g_vol->cluster_size) {
+		if (index_block_size % g_vol->cluster_size) {
+			ntfs_log_error("add_attr_index_root: index block size is not "
+					"a multiple of the cluster size.\n");
+			free(r);
+			return -EINVAL;
+		}
+		r->clusters_per_index_block = index_block_size /
+				g_vol->cluster_size;
+	} else { /* if (g_vol->cluster_size > index_block_size) */
+		if (index_block_size & (index_block_size - 1)) {
+			ntfs_log_error("add_attr_index_root: index block size is not "
+					"a power of 2.\n");
+			free(r);
+			return -EINVAL;
+		}
+		if (index_block_size < (u32)opts.sector_size) {
+			 ntfs_log_error("add_attr_index_root: index block size "
+					 "is smaller than the sector size.\n");
+			 free(r);
+			 return -EINVAL;
+		}
+		r->clusters_per_index_block = index_block_size
+				>> NTFS_BLOCK_SIZE_BITS;
+	}
+	memset(&r->reserved, 0, sizeof(r->reserved));
+	r->index.entries_offset = const_cpu_to_le32(sizeof(INDEX_HEADER));
+	r->index.index_length = const_cpu_to_le32(sizeof(INDEX_HEADER) +
+			sizeof(INDEX_ENTRY_HEADER));
+	r->index.allocated_size = r->index.index_length;
+	r->index.ih_flags = SMALL_INDEX;
+	memset(&r->index.reserved, 0, sizeof(r->index.reserved));
+	e = (INDEX_ENTRY_HEADER*)((u8*)&r->index +
+			le32_to_cpu(r->index.entries_offset));
+	/*
+	 * No matter whether this is a file index or a view as this is a
+	 * termination entry, hence no key value / data is associated with it
+	 * at all. Thus, we just need the union to be all zero.
+	 */
+	e->indexed_file = const_cpu_to_le64(0LL);
+	e->length = const_cpu_to_le16(sizeof(INDEX_ENTRY_HEADER));
+	e->key_length = const_cpu_to_le16(0);
+	e->flags = INDEX_ENTRY_END;
+	e->reserved = const_cpu_to_le16(0);
+	err = insert_resident_attr_in_mft_record(m, AT_INDEX_ROOT, name,
+				name_len, ic, const_cpu_to_le16(0), 0,
+				(u8*)r, val_len);
+	free(r);
+	if (err < 0)
+		ntfs_log_error("add_attr_index_root failed: %s\n", strerror(-err));
+	return err;
+}
+
+/**
+ * add_attr_index_alloc
+ *
+ * Return 0 on success or -errno on error.
+ */
+static int add_attr_index_alloc(MFT_RECORD *m, const char *name,
+		const u32 name_len, const IGNORE_CASE_BOOL ic,
+		const u8 *index_alloc_val, const u32 index_alloc_val_len)
+{
+	int err;
+
+	err = insert_non_resident_attr_in_mft_record(m, AT_INDEX_ALLOCATION,
+			name, name_len, ic, const_cpu_to_le16(0),
+			index_alloc_val, index_alloc_val_len, WRITE_STANDARD);
+	if (err < 0)
+		ntfs_log_error("add_attr_index_alloc failed: %s\n", strerror(-err));
+	return err;
+}
+
+/**
+ * add_attr_bitmap
+ *
+ * Return 0 on success or -errno on error.
+ */
+static int add_attr_bitmap(MFT_RECORD *m, const char *name, const u32 name_len,
+		const IGNORE_CASE_BOOL ic, const u8 *bitmap,
+		const u32 bitmap_len)
+{
+	int err;
+
+	/* Does it fit? NO: create non-resident. YES: create resident. */
+	if (le32_to_cpu(m->bytes_in_use) + 24 + bitmap_len >
+						le32_to_cpu(m->bytes_allocated))
+		err = insert_non_resident_attr_in_mft_record(m, AT_BITMAP, name,
+				name_len, ic, const_cpu_to_le16(0), bitmap,
+				bitmap_len, WRITE_STANDARD);
+	else
+		err = insert_resident_attr_in_mft_record(m, AT_BITMAP, name,
+				name_len, ic, const_cpu_to_le16(0), 0,
+				bitmap, bitmap_len);
+
+	if (err < 0)
+		ntfs_log_error("add_attr_bitmap failed: %s\n", strerror(-err));
+	return err;
+}
+
+/**
+ * add_attr_bitmap_positioned
+ *
+ * Create a non-resident bitmap attribute with a predefined on disk location
+ * specified by the runlist @rl. The clusters specified by @rl are assumed to
+ * be allocated already.
+ *
+ * Return 0 on success or -errno on error.
+ */
+static int add_attr_bitmap_positioned(MFT_RECORD *m, const char *name,
+		const u32 name_len, const IGNORE_CASE_BOOL ic,
+		const runlist *rl, const u8 *bitmap, const u32 bitmap_len)
+{
+	int err;
+
+	err = insert_positioned_attr_in_mft_record(m, AT_BITMAP, name, name_len,
+			ic, const_cpu_to_le16(0), rl, bitmap, bitmap_len);
+	if (err < 0)
+		ntfs_log_error("add_attr_bitmap_positioned failed: %s\n",
+				strerror(-err));
+	return err;
+}
+
+
+/**
+ * upgrade_to_large_index
+ *
+ * Create bitmap and index allocation attributes, modify index root
+ * attribute accordingly and move all of the index entries from the index root
+ * into the index allocation.
+ *
+ * Return 0 on success or -errno on error.
+ */
+static int upgrade_to_large_index(MFT_RECORD *m, const char *name,
+		u32 name_len, const IGNORE_CASE_BOOL ic,
+		INDEX_ALLOCATION **idx)
+{
+	ntfs_attr_search_ctx *ctx;
+	ATTR_RECORD *a;
+	INDEX_ROOT *r;
+	INDEX_ENTRY *re;
+	INDEX_ALLOCATION *ia_val = NULL;
+	ntfschar *uname = NULL;
+	int uname_len = 0;
+	u8 bmp[8];
+	char *re_start, *re_end;
+	int i, err, index_block_size;
+
+	uname = ntfs_str2ucs(name, &uname_len);
+	if (!uname)
+		return -errno;
+
+	/* Find the index root attribute. */
+	ctx = ntfs_attr_get_search_ctx(NULL, m);
+	if (!ctx) {
+		ntfs_log_error("Failed to allocate attribute search context.\n");
+		ntfs_ucsfree(uname);
+		return -ENOMEM;
+	}
+	if (ic == IGNORE_CASE) {
+		ntfs_log_error("FIXME: Hit unimplemented code path #4.\n");
+		err = -EOPNOTSUPP;
+		ntfs_ucsfree(uname);
+		goto err_out;
+	}
+	err = mkntfs_attr_lookup(AT_INDEX_ROOT, uname, uname_len, ic, 0, NULL, 0,
+			ctx);
+	ntfs_ucsfree(uname);
+	if (err) {
+		err = -ENOTDIR;
+		goto err_out;
+	}
+	a = ctx->attr;
+	if (a->non_resident || a->flags) {
+		err = -EINVAL;
+		goto err_out;
+	}
+	r = (INDEX_ROOT*)((char*)a + le16_to_cpu(a->value_offset));
+	re_end = (char*)r + le32_to_cpu(a->value_length);
+	re_start = (char*)&r->index + le32_to_cpu(r->index.entries_offset);
+	re = (INDEX_ENTRY*)re_start;
+	index_block_size = le32_to_cpu(r->index_block_size);
+	memset(bmp, 0, sizeof(bmp));
+	ntfs_bit_set(bmp, 0ULL, 1);
+	/* Bitmap has to be at least 8 bytes in size. */
+	err = add_attr_bitmap(m, name, name_len, ic, bmp, sizeof(bmp));
+	if (err)
+		goto err_out;
+	ia_val = ntfs_calloc(index_block_size);
+	if (!ia_val) {
+		err = -errno;
+		goto err_out;
+	}
+	/* Setup header. */
+	ia_val->magic = magic_INDX;
+	ia_val->usa_ofs = cpu_to_le16(sizeof(INDEX_ALLOCATION));
+	if (index_block_size >= NTFS_BLOCK_SIZE) {
+		ia_val->usa_count = cpu_to_le16(index_block_size /
+				NTFS_BLOCK_SIZE + 1);
+	} else {
+		ia_val->usa_count = cpu_to_le16(1);
+		ntfs_log_error("Sector size is bigger than index block size. "
+				"Setting usa_count to 1. If Windows chkdsk "
+				"reports this as corruption, please email %s "
+				"stating that you saw this message and that "
+				"the filesystem created was corrupt.  "
+				"Thank you.", NTFS_DEV_LIST);
+	}
+	/* Set USN to 1. */
+	*(le16*)((char*)ia_val + le16_to_cpu(ia_val->usa_ofs)) =
+			cpu_to_le16(1);
+	ia_val->lsn = cpu_to_le64(0);
+	ia_val->index_block_vcn = cpu_to_le64(0);
+	ia_val->index.ih_flags = LEAF_NODE;
+	/* Align to 8-byte boundary. */
+	ia_val->index.entries_offset = cpu_to_le32((sizeof(INDEX_HEADER) +
+			le16_to_cpu(ia_val->usa_count) * 2 + 7) & ~7);
+	ia_val->index.allocated_size = cpu_to_le32(index_block_size -
+			(sizeof(INDEX_ALLOCATION) - sizeof(INDEX_HEADER)));
+	/* Find the last entry in the index root and save it in re. */
+	while ((char*)re < re_end && !(re->ie_flags & INDEX_ENTRY_END)) {
+		/* Next entry in index root. */
+		re = (INDEX_ENTRY*)((char*)re + le16_to_cpu(re->length));
+	}
+	/* Copy all the entries including the termination entry. */
+	i = (char*)re - re_start + le16_to_cpu(re->length);
+	memcpy((char*)&ia_val->index +
+			le32_to_cpu(ia_val->index.entries_offset), re_start, i);
+	/* Finish setting up index allocation. */
+	ia_val->index.index_length = cpu_to_le32(i +
+			le32_to_cpu(ia_val->index.entries_offset));
+	/* Move the termination entry forward to the beginning if necessary. */
+	if ((char*)re > re_start) {
+		memmove(re_start, (char*)re, le16_to_cpu(re->length));
+		re = (INDEX_ENTRY*)re_start;
+	}
+	/* Now fixup empty index root with pointer to index allocation VCN 0. */
+	r->index.ih_flags = LARGE_INDEX;
+	re->ie_flags |= INDEX_ENTRY_NODE;
+	if (le16_to_cpu(re->length) < sizeof(INDEX_ENTRY_HEADER) + sizeof(VCN))
+		re->length = cpu_to_le16(le16_to_cpu(re->length) + sizeof(VCN));
+	r->index.index_length = cpu_to_le32(le32_to_cpu(r->index.entries_offset)
+			+ le16_to_cpu(re->length));
+	r->index.allocated_size = r->index.index_length;
+	/* Resize index root attribute. */
+	if (ntfs_resident_attr_value_resize(m, a, sizeof(INDEX_ROOT) -
+			sizeof(INDEX_HEADER) +
+			le32_to_cpu(r->index.allocated_size))) {
+		/* TODO: Remove the added bitmap! */
+		/* Revert index root from index allocation. */
+		err = -errno;
+		goto err_out;
+	}
+	/* Set VCN pointer to 0LL. */
+	*(leVCN*)((char*)re + cpu_to_le16(re->length) - sizeof(VCN)) =
+			cpu_to_le64(0);
+	err = ntfs_mst_pre_write_fixup((NTFS_RECORD*)ia_val, index_block_size);
+	if (err) {
+		err = -errno;
+		ntfs_log_error("ntfs_mst_pre_write_fixup() failed in "
+				"upgrade_to_large_index.\n");
+		goto err_out;
+	}
+	err = add_attr_index_alloc(m, name, name_len, ic, (u8*)ia_val,
+			index_block_size);
+	ntfs_mst_post_write_fixup((NTFS_RECORD*)ia_val);
+	if (err) {
+		/* TODO: Remove the added bitmap! */
+		/* Revert index root from index allocation. */
+		goto err_out;
+	}
+	*idx = ia_val;
+	ntfs_attr_put_search_ctx(ctx);
+	return 0;
+err_out:
+	ntfs_attr_put_search_ctx(ctx);
+	free(ia_val);
+	return err;
+}
+
+/**
+ * make_room_for_index_entry_in_index_block
+ *
+ * Create space of @size bytes at position @pos inside the index block @idx.
+ *
+ * Return 0 on success or -errno on error.
+ */
+static int make_room_for_index_entry_in_index_block(INDEX_BLOCK *idx,
+		INDEX_ENTRY *pos, u32 size)
+{
+	u32 biu;
+
+	if (!size)
+		return 0;
+#ifdef DEBUG
+	/*
+	 * Rigorous consistency checks. Always return -EINVAL even if more
+	 * appropriate codes exist for simplicity of parsing the return value.
+	 */
+	if (size != ((size + 7) & ~7)) {
+		ntfs_log_error("make_room_for_index_entry_in_index_block() received "
+				"non 8-byte aligned size.\n");
+		return -EINVAL;
+	}
+	if (!idx || !pos)
+		return -EINVAL;
+	if ((char*)pos < (char*)idx || (char*)pos + size < (char*)idx ||
+			(char*)pos > (char*)idx + sizeof(INDEX_BLOCK) -
+				sizeof(INDEX_HEADER) +
+				le32_to_cpu(idx->index.allocated_size) ||
+			(char*)pos + size > (char*)idx + sizeof(INDEX_BLOCK) -
+				sizeof(INDEX_HEADER) +
+				le32_to_cpu(idx->index.allocated_size))
+		return -EINVAL;
+	/* The - sizeof(INDEX_ENTRY_HEADER) is for the index terminator. */
+	if ((char*)pos - (char*)&idx->index >
+			(int)le32_to_cpu(idx->index.index_length)
+			- (int)sizeof(INDEX_ENTRY_HEADER))
+		return -EINVAL;
+#endif
+	biu = le32_to_cpu(idx->index.index_length);
+	/* Do we have enough space? */
+	if (biu + size > le32_to_cpu(idx->index.allocated_size))
+		return -ENOSPC;
+	/* Move everything after pos to pos + size. */
+	memmove((char*)pos + size, (char*)pos, biu - ((char*)pos -
+			(char*)&idx->index));
+	/* Update index block. */
+	idx->index.index_length = cpu_to_le32(biu + size);
+	return 0;
+}
+
+/**
+ * ntfs_index_keys_compare
+ *
+ * not all types of COLLATION_RULES supported yet...
+ * added as needed.. (remove this comment when all are added)
+ */
+static int ntfs_index_keys_compare(u8 *key1, u8 *key2, int key1_length,
+		int key2_length, COLLATION_RULES collation_rule)
+{
+	u32 u1, u2;
+	int i;
+
+	if (collation_rule == COLLATION_NTOFS_ULONG) {
+		/* i.e. $SII or $QUOTA-$Q */
+		u1 = le32_to_cpup((const le32*)key1);
+		u2 = le32_to_cpup((const le32*)key2);
+		if (u1 < u2)
+			return -1;
+		if (u1 > u2)
+			return 1;
+		/* u1 == u2 */
+		return 0;
+	}
+	if (collation_rule == COLLATION_NTOFS_ULONGS) {
+		/* i.e $OBJID-$O */
+		i = 0;
+		while (i < min(key1_length, key2_length)) {
+			u1 = le32_to_cpup((const le32*)(key1 + i));
+			u2 = le32_to_cpup((const le32*)(key2 + i));
+			if (u1 < u2)
+				return -1;
+			if (u1 > u2)
+				return 1;
+			/* u1 == u2 */
+			i += sizeof(u32);
+		}
+		if (key1_length < key2_length)
+			return -1;
+		if (key1_length > key2_length)
+			return 1;
+		return 0;
+	}
+	if (collation_rule == COLLATION_NTOFS_SECURITY_HASH) {
+		/* i.e. $SDH */
+		u1 = le32_to_cpu(((SDH_INDEX_KEY*)key1)->hash);
+		u2 = le32_to_cpu(((SDH_INDEX_KEY*)key2)->hash);
+		if (u1 < u2)
+			return -1;
+		if (u1 > u2)
+			return 1;
+		/* u1 == u2 */
+		u1 = le32_to_cpu(((SDH_INDEX_KEY*)key1)->security_id);
+		u2 = le32_to_cpu(((SDH_INDEX_KEY*)key2)->security_id);
+		if (u1 < u2)
+			return -1;
+		if (u1 > u2)
+			return 1;
+		return 0;
+	}
+	if (collation_rule == COLLATION_NTOFS_SID) {
+		/* i.e. $QUOTA-O */
+		i = memcmp(key1, key2, min(key1_length, key2_length));
+		if (!i) {
+			if (key1_length < key2_length)
+				return -1;
+			if (key1_length > key2_length)
+				return 1;
+		}
+		return i;
+	}
+	ntfs_log_critical("ntfs_index_keys_compare called without supported "
+			"collation rule.\n");
+	return 0;	/* Claim they're equal.  What else can we do? */
+}
+
+/**
+ * insert_index_entry_in_res_dir_index
+ *
+ * i.e. insert an index_entry in some named index_root
+ * simplified search method, works for mkntfs
+ */
+static int insert_index_entry_in_res_dir_index(INDEX_ENTRY *idx, u32 idx_size,
+		MFT_RECORD *m, ntfschar *name, u32 name_size, ATTR_TYPES type)
+{
+	ntfs_attr_search_ctx *ctx;
+	INDEX_HEADER *idx_header;
+	INDEX_ENTRY *idx_entry, *idx_end;
+	ATTR_RECORD *a;
+	COLLATION_RULES collation_rule;
+	int err, i;
+
+	err = 0;
+	/* does it fit ?*/
+	if (g_vol->mft_record_size > idx_size + le32_to_cpu(m->bytes_allocated))
+		return -ENOSPC;
+	/* find the INDEX_ROOT attribute:*/
+	ctx = ntfs_attr_get_search_ctx(NULL, m);
+	if (!ctx) {
+		ntfs_log_error("Failed to allocate attribute search "
+				"context.\n");
+		err = -ENOMEM;
+		goto err_out;
+	}
+	if (mkntfs_attr_lookup(AT_INDEX_ROOT, name, name_size,
+			CASE_SENSITIVE, 0, NULL, 0, ctx)) {
+		err = -EEXIST;
+		goto err_out;
+	}
+	/* found attribute */
+	a = (ATTR_RECORD*)ctx->attr;
+	collation_rule = ((INDEX_ROOT*)((u8*)a +
+			le16_to_cpu(a->value_offset)))->collation_rule;
+	idx_header = (INDEX_HEADER*)((u8*)a + le16_to_cpu(a->value_offset)
+			+ 0x10);
+	idx_entry = (INDEX_ENTRY*)((u8*)idx_header +
+			le32_to_cpu(idx_header->entries_offset));
+	idx_end = (INDEX_ENTRY*)((u8*)idx_entry +
+			le32_to_cpu(idx_header->index_length));
+	/*
+	 * Loop until we exceed valid memory (corruption case) or until we
+	 * reach the last entry.
+	 */
+	if (type == AT_FILE_NAME) {
+		while (((u8*)idx_entry < (u8*)idx_end) &&
+				!(idx_entry->ie_flags & INDEX_ENTRY_END)) {
+			/*
+			i = ntfs_file_values_compare(&idx->key.file_name,
+					&idx_entry->key.file_name, 1,
+					IGNORE_CASE, g_vol->upcase,
+					g_vol->upcase_len);
+			*/
+			i = ntfs_names_full_collate(idx->key.file_name.file_name, idx->key.file_name.file_name_length,
+					idx_entry->key.file_name.file_name, idx_entry->key.file_name.file_name_length,
+					IGNORE_CASE, g_vol->upcase,
+					g_vol->upcase_len);
+			/*
+			 * If @file_name collates before ie->key.file_name,
+			 * there is no matching index entry.
+			 */
+			if (i == -1)
+				break;
+			/* If file names are not equal, continue search. */
+			if (i)
+				goto do_next;
+			if (idx->key.file_name.file_name_type !=
+					FILE_NAME_POSIX ||
+					idx_entry->key.file_name.file_name_type
+					!= FILE_NAME_POSIX)
+				return -EEXIST;
+			/*
+			i = ntfs_file_values_compare(&idx->key.file_name,
+					&idx_entry->key.file_name, 1,
+					CASE_SENSITIVE, g_vol->upcase,
+					g_vol->upcase_len);
+			*/
+			i = ntfs_names_full_collate(idx->key.file_name.file_name, idx->key.file_name.file_name_length,
+					idx_entry->key.file_name.file_name, idx_entry->key.file_name.file_name_length,
+					CASE_SENSITIVE, g_vol->upcase,
+					g_vol->upcase_len);
+			if (!i)
+				return -EEXIST;
+			if (i == -1)
+				break;
+do_next:
+			idx_entry = (INDEX_ENTRY*)((u8*)idx_entry +
+					le16_to_cpu(idx_entry->length));
+		}
+	} else if (type == AT_UNUSED) {  /* case view */
+		while (((u8*)idx_entry < (u8*)idx_end) &&
+				!(idx_entry->ie_flags & INDEX_ENTRY_END)) {
+			i = ntfs_index_keys_compare((u8*)idx + 0x10,
+					(u8*)idx_entry + 0x10,
+					le16_to_cpu(idx->key_length),
+					le16_to_cpu(idx_entry->key_length),
+					collation_rule);
+			if (!i)
+				return -EEXIST;
+			if (i == -1)
+				break;
+			idx_entry = (INDEX_ENTRY*)((u8*)idx_entry +
+					le16_to_cpu(idx_entry->length));
+		}
+	} else
+		return -EINVAL;
+	memmove((u8*)idx_entry + idx_size, (u8*)idx_entry,
+			le32_to_cpu(m->bytes_in_use) -
+			((u8*)idx_entry - (u8*)m));
+	memcpy((u8*)idx_entry, (u8*)idx, idx_size);
+	/* Adjust various offsets, etc... */
+	m->bytes_in_use = cpu_to_le32(le32_to_cpu(m->bytes_in_use) + idx_size);
+	a->length = cpu_to_le32(le32_to_cpu(a->length) + idx_size);
+	a->value_length = cpu_to_le32(le32_to_cpu(a->value_length) + idx_size);
+	idx_header->index_length = cpu_to_le32(
+			le32_to_cpu(idx_header->index_length) + idx_size);
+	idx_header->allocated_size = cpu_to_le32(
+			le32_to_cpu(idx_header->allocated_size) + idx_size);
+err_out:
+	if (ctx)
+		ntfs_attr_put_search_ctx(ctx);
+	return err;
+}
+
+/**
+ * initialize_secure
+ *
+ * initializes $Secure's $SDH and $SII indexes from $SDS datastream
+ */
+static int initialize_secure(char *sds, u32 sds_size, MFT_RECORD *m)
+{
+	int err, sdh_size, sii_size;
+	SECURITY_DESCRIPTOR_HEADER *sds_header;
+	INDEX_ENTRY *idx_entry_sdh, *idx_entry_sii;
+	SDH_INDEX_DATA *sdh_data;
+	SII_INDEX_DATA *sii_data;
+
+	sds_header = (SECURITY_DESCRIPTOR_HEADER*)sds;
+	sdh_size  = sizeof(INDEX_ENTRY_HEADER);
+	sdh_size += sizeof(SDH_INDEX_KEY) + sizeof(SDH_INDEX_DATA);
+	sii_size  = sizeof(INDEX_ENTRY_HEADER);
+	sii_size += sizeof(SII_INDEX_KEY) + sizeof(SII_INDEX_DATA);
+	idx_entry_sdh = ntfs_calloc(sizeof(INDEX_ENTRY));
+	if (!idx_entry_sdh)
+		return -errno;
+	idx_entry_sii = ntfs_calloc(sizeof(INDEX_ENTRY));
+	if (!idx_entry_sii) {
+		free(idx_entry_sdh);
+		return -errno;
+	}
+	err = 0;
+
+	while ((char*)sds_header < (char*)sds + sds_size) {
+		if (!sds_header->length)
+			break;
+		/* SDH index entry */
+		idx_entry_sdh->data_offset = const_cpu_to_le16(0x18);
+		idx_entry_sdh->data_length = const_cpu_to_le16(0x14);
+		idx_entry_sdh->reservedV = const_cpu_to_le32(0x00);
+		idx_entry_sdh->length = const_cpu_to_le16(0x30);
+		idx_entry_sdh->key_length = const_cpu_to_le16(0x08);
+		idx_entry_sdh->ie_flags = const_cpu_to_le16(0x00);
+		idx_entry_sdh->reserved = const_cpu_to_le16(0x00);
+		idx_entry_sdh->key.sdh.hash = sds_header->hash;
+		idx_entry_sdh->key.sdh.security_id = sds_header->security_id;
+		sdh_data = (SDH_INDEX_DATA*)((u8*)idx_entry_sdh +
+				le16_to_cpu(idx_entry_sdh->data_offset));
+		sdh_data->hash = sds_header->hash;
+		sdh_data->security_id = sds_header->security_id;
+		sdh_data->offset = sds_header->offset;
+		sdh_data->length = sds_header->length;
+		sdh_data->reserved_II = const_cpu_to_le32(0x00490049);
+
+		/* SII index entry */
+		idx_entry_sii->data_offset = const_cpu_to_le16(0x14);
+		idx_entry_sii->data_length = const_cpu_to_le16(0x14);
+		idx_entry_sii->reservedV = const_cpu_to_le32(0x00);
+		idx_entry_sii->length = const_cpu_to_le16(0x28);
+		idx_entry_sii->key_length = const_cpu_to_le16(0x04);
+		idx_entry_sii->ie_flags = const_cpu_to_le16(0x00);
+		idx_entry_sii->reserved = const_cpu_to_le16(0x00);
+		idx_entry_sii->key.sii.security_id = sds_header->security_id;
+		sii_data = (SII_INDEX_DATA*)((u8*)idx_entry_sii +
+				le16_to_cpu(idx_entry_sii->data_offset));
+		sii_data->hash = sds_header->hash;
+		sii_data->security_id = sds_header->security_id;
+		sii_data->offset = sds_header->offset;
+		sii_data->length = sds_header->length;
+		if ((err = insert_index_entry_in_res_dir_index(idx_entry_sdh,
+				sdh_size, m, NTFS_INDEX_SDH, 4, AT_UNUSED)))
+			break;
+		if ((err = insert_index_entry_in_res_dir_index(idx_entry_sii,
+				sii_size, m, NTFS_INDEX_SII, 4, AT_UNUSED)))
+			break;
+		sds_header = (SECURITY_DESCRIPTOR_HEADER*)((u8*)sds_header +
+				((le32_to_cpu(sds_header->length) + 15) & ~15));
+	}
+	free(idx_entry_sdh);
+	free(idx_entry_sii);
+	return err;
+}
+
+/**
+ * initialize_quota
+ *
+ * initialize $Quota with the default quota index-entries.
+ */
+static int initialize_quota(MFT_RECORD *m)
+{
+	int o_size, q1_size, q2_size, err, i;
+	INDEX_ENTRY *idx_entry_o, *idx_entry_q1, *idx_entry_q2;
+	QUOTA_O_INDEX_DATA *idx_entry_o_data;
+	QUOTA_CONTROL_ENTRY *idx_entry_q1_data, *idx_entry_q2_data;
+
+	err = 0;
+	/* q index entry num 1 */
+	q1_size = 0x48;
+	idx_entry_q1 = ntfs_calloc(q1_size);
+	if (!idx_entry_q1)
+		return errno;
+	idx_entry_q1->data_offset = const_cpu_to_le16(0x14);
+	idx_entry_q1->data_length = const_cpu_to_le16(0x30);
+	idx_entry_q1->reservedV = const_cpu_to_le32(0x00);
+	idx_entry_q1->length = const_cpu_to_le16(0x48);
+	idx_entry_q1->key_length = const_cpu_to_le16(0x04);
+	idx_entry_q1->ie_flags = const_cpu_to_le16(0x00);
+	idx_entry_q1->reserved = const_cpu_to_le16(0x00);
+	idx_entry_q1->key.owner_id = const_cpu_to_le32(0x01);
+	idx_entry_q1_data = (QUOTA_CONTROL_ENTRY*)((char*)idx_entry_q1
+			+ le16_to_cpu(idx_entry_q1->data_offset));
+	idx_entry_q1_data->version = const_cpu_to_le32(0x02);
+	idx_entry_q1_data->flags = QUOTA_FLAG_DEFAULT_LIMITS;
+	idx_entry_q1_data->bytes_used = const_cpu_to_le64(0x00);
+	idx_entry_q1_data->change_time = mkntfs_time();
+	idx_entry_q1_data->threshold = cpu_to_sle64(-1);
+	idx_entry_q1_data->limit = cpu_to_sle64(-1);
+	idx_entry_q1_data->exceeded_time = const_cpu_to_le64(0);
+	err = insert_index_entry_in_res_dir_index(idx_entry_q1, q1_size, m,
+			NTFS_INDEX_Q, 2, AT_UNUSED);
+	free(idx_entry_q1);
+	if (err)
+		return err;
+	/* q index entry num 2 */
+	q2_size = 0x58;
+	idx_entry_q2 = ntfs_calloc(q2_size);
+	if (!idx_entry_q2)
+		return errno;
+	idx_entry_q2->data_offset = const_cpu_to_le16(0x14);
+	idx_entry_q2->data_length = const_cpu_to_le16(0x40);
+	idx_entry_q2->reservedV = const_cpu_to_le32(0x00);
+	idx_entry_q2->length = const_cpu_to_le16(0x58);
+	idx_entry_q2->key_length = const_cpu_to_le16(0x04);
+	idx_entry_q2->ie_flags = const_cpu_to_le16(0x00);
+	idx_entry_q2->reserved = const_cpu_to_le16(0x00);
+	idx_entry_q2->key.owner_id = QUOTA_FIRST_USER_ID;
+	idx_entry_q2_data = (QUOTA_CONTROL_ENTRY*)((char*)idx_entry_q2
+			+ le16_to_cpu(idx_entry_q2->data_offset));
+	idx_entry_q2_data->version = const_cpu_to_le32(0x02);
+	idx_entry_q2_data->flags = QUOTA_FLAG_DEFAULT_LIMITS;
+	idx_entry_q2_data->bytes_used = const_cpu_to_le64(0x00);
+	idx_entry_q2_data->change_time = mkntfs_time();
+	idx_entry_q2_data->threshold = cpu_to_sle64(-1);
+	idx_entry_q2_data->limit = cpu_to_sle64(-1);
+	idx_entry_q2_data->exceeded_time = const_cpu_to_le64(0);
+	idx_entry_q2_data->sid.revision = 1;
+	idx_entry_q2_data->sid.sub_authority_count = 2;
+	for (i = 0; i < 5; i++)
+		idx_entry_q2_data->sid.identifier_authority.value[i] = 0;
+	idx_entry_q2_data->sid.identifier_authority.value[5] = 0x05;
+	idx_entry_q2_data->sid.sub_authority[0] =
+			const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
+	idx_entry_q2_data->sid.sub_authority[1] =
+			const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
+	err = insert_index_entry_in_res_dir_index(idx_entry_q2, q2_size, m,
+			NTFS_INDEX_Q, 2, AT_UNUSED);
+	free(idx_entry_q2);
+	if (err)
+		return err;
+	o_size = 0x28;
+	idx_entry_o = ntfs_calloc(o_size);
+	if (!idx_entry_o)
+		return errno;
+	idx_entry_o->data_offset = const_cpu_to_le16(0x20);
+	idx_entry_o->data_length = const_cpu_to_le16(0x04);
+	idx_entry_o->reservedV = const_cpu_to_le32(0x00);
+	idx_entry_o->length = const_cpu_to_le16(0x28);
+	idx_entry_o->key_length = const_cpu_to_le16(0x10);
+	idx_entry_o->ie_flags = const_cpu_to_le16(0x00);
+	idx_entry_o->reserved = const_cpu_to_le16(0x00);
+	idx_entry_o->key.sid.revision = 0x01;
+	idx_entry_o->key.sid.sub_authority_count = 0x02;
+	for (i = 0; i < 5; i++)
+		idx_entry_o->key.sid.identifier_authority.value[i] = 0;
+	idx_entry_o->key.sid.identifier_authority.value[5] = 0x05;
+	idx_entry_o->key.sid.sub_authority[0] =
+			const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
+	idx_entry_o->key.sid.sub_authority[1] =
+			const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
+	idx_entry_o_data = (QUOTA_O_INDEX_DATA*)((char*)idx_entry_o
+			+ le16_to_cpu(idx_entry_o->data_offset));
+	idx_entry_o_data->owner_id  = QUOTA_FIRST_USER_ID;
+	/* 20 00 00 00 padding after here on ntfs 3.1. 3.0 is unchecked. */
+	idx_entry_o_data->unknown = const_cpu_to_le32(32);
+	err = insert_index_entry_in_res_dir_index(idx_entry_o, o_size, m,
+			NTFS_INDEX_O, 2, AT_UNUSED);
+	free(idx_entry_o);
+
+	return err;
+}
+
+/**
+ * insert_file_link_in_dir_index
+ *
+ * Insert the fully completed FILE_NAME_ATTR @file_name which is inside
+ * the file with mft reference @file_ref into the index (allocation) block
+ * @idx (which belongs to @file_ref's parent directory).
+ *
+ * Return 0 on success or -errno on error.
+ */
+static int insert_file_link_in_dir_index(INDEX_BLOCK *idx, leMFT_REF file_ref,
+		FILE_NAME_ATTR *file_name, u32 file_name_size)
+{
+	int err, i;
+	INDEX_ENTRY *ie;
+	char *index_end;
+
+	/*
+	 * Lookup dir entry @file_name in dir @idx to determine correct
+	 * insertion location. FIXME: Using a very oversimplified lookup
+	 * method which is sufficient for mkntfs but no good whatsoever in
+	 * real world scenario. (AIA)
+	 */
+
+	index_end = (char*)&idx->index + le32_to_cpu(idx->index.index_length);
+	ie = (INDEX_ENTRY*)((char*)&idx->index +
+			le32_to_cpu(idx->index.entries_offset));
+	/*
+	 * Loop until we exceed valid memory (corruption case) or until we
+	 * reach the last entry.
+	 */
+	while ((char*)ie < index_end && !(ie->ie_flags & INDEX_ENTRY_END)) {
+#if 0
+#ifdef DEBUG
+		ntfs_log_debug("file_name_attr1->file_name_length = %i\n",
+				file_name->file_name_length);
+		if (file_name->file_name_length) {
+			char *__buf = NULL;
+			i = ntfs_ucstombs((ntfschar*)&file_name->file_name,
+				file_name->file_name_length, &__buf, 0);
+			if (i < 0)
+				ntfs_log_debug("Name contains non-displayable "
+						"Unicode characters.\n");
+			ntfs_log_debug("file_name_attr1->file_name = %s\n",
+					__buf);
+			free(__buf);
+		}
+		ntfs_log_debug("file_name_attr2->file_name_length = %i\n",
+				ie->key.file_name.file_name_length);
+		if (ie->key.file_name.file_name_length) {
+			char *__buf = NULL;
+			i = ntfs_ucstombs(ie->key.file_name.file_name,
+				ie->key.file_name.file_name_length + 1, &__buf,
+				0);
+			if (i < 0)
+				ntfs_log_debug("Name contains non-displayable "
+						"Unicode characters.\n");
+			ntfs_log_debug("file_name_attr2->file_name = %s\n",
+					__buf);
+			free(__buf);
+		}
+#endif
+#endif
+		/*
+		i = ntfs_file_values_compare(file_name,
+				(FILE_NAME_ATTR*)&ie->key.file_name, 1,
+				IGNORE_CASE, g_vol->upcase, g_vol->upcase_len);
+		*/
+		i = ntfs_names_full_collate(file_name->file_name, file_name->file_name_length,
+				((FILE_NAME_ATTR*)&ie->key.file_name)->file_name, ((FILE_NAME_ATTR*)&ie->key.file_name)->file_name_length,
+				IGNORE_CASE, g_vol->upcase, g_vol->upcase_len);
+		/*
+		 * If @file_name collates before ie->key.file_name, there is no
+		 * matching index entry.
+		 */
+		if (i == -1)
+			break;
+		/* If file names are not equal, continue search. */
+		if (i)
+			goto do_next;
+		/* File names are equal when compared ignoring case. */
+		/*
+		 * If BOTH file names are in the POSIX namespace, do a case
+		 * sensitive comparison as well. Otherwise the names match so
+		 * we return -EEXIST. FIXME: There are problems with this in a
+		 * real world scenario, when one is POSIX and one isn't, but
+		 * fine for mkntfs where we don't use POSIX namespace at all
+		 * and hence this following code is luxury. (AIA)
+		 */
+		if (file_name->file_name_type != FILE_NAME_POSIX ||
+		    ie->key.file_name.file_name_type != FILE_NAME_POSIX)
+			return -EEXIST;
+		/*
+		i = ntfs_file_values_compare(file_name,
+				(FILE_NAME_ATTR*)&ie->key.file_name, 1,
+				CASE_SENSITIVE, g_vol->upcase,
+				g_vol->upcase_len);
+		*/
+		i = ntfs_names_full_collate(file_name->file_name, file_name->file_name_length,
+				((FILE_NAME_ATTR*)&ie->key.file_name)->file_name, ((FILE_NAME_ATTR*)&ie->key.file_name)->file_name_length,
+				CASE_SENSITIVE, g_vol->upcase, g_vol->upcase_len);
+		if (i == -1)
+			break;
+		/* Complete match. Bugger. Can't insert. */
+		if (!i)
+			return -EEXIST;
+do_next:
+#ifdef DEBUG
+		/* Next entry. */
+		if (!ie->length) {
+			ntfs_log_debug("BUG: ie->length is zero, breaking out "
+					"of loop.\n");
+			break;
+		}
+#endif
+		ie = (INDEX_ENTRY*)((char*)ie + le16_to_cpu(ie->length));
+	};
+	i = (sizeof(INDEX_ENTRY_HEADER) + file_name_size + 7) & ~7;
+	err = make_room_for_index_entry_in_index_block(idx, ie, i);
+	if (err) {
+		ntfs_log_error("make_room_for_index_entry_in_index_block "
+				"failed: %s\n", strerror(-err));
+		return err;
+	}
+	/* Create entry in place and copy file name attribute value. */
+	ie->indexed_file = file_ref;
+	ie->length = cpu_to_le16(i);
+	ie->key_length = cpu_to_le16(file_name_size);
+	ie->ie_flags = cpu_to_le16(0);
+	ie->reserved = cpu_to_le16(0);
+	memcpy((char*)&ie->key.file_name, (char*)file_name, file_name_size);
+	return 0;
+}
+
+/**
+ * create_hardlink_res
+ *
+ * Create a file_name_attribute in the mft record @m_file which points to the
+ * parent directory with mft reference @ref_parent.
+ *
+ * Then, insert an index entry with this file_name_attribute in the index
+ * root @idx of the index_root attribute of the parent directory.
+ *
+ * @ref_file is the mft reference of @m_file.
+ *
+ * Return 0 on success or -errno on error.
+ */
+static int create_hardlink_res(MFT_RECORD *m_parent, const leMFT_REF ref_parent,
+		MFT_RECORD *m_file, const leMFT_REF ref_file,
+		const s64 allocated_size, const s64 data_size,
+		const FILE_ATTR_FLAGS flags, const u16 packed_ea_size,
+		const u32 reparse_point_tag, const char *file_name,
+		const FILE_NAME_TYPE_FLAGS file_name_type)
+{
+	FILE_NAME_ATTR *fn;
+	int i, fn_size, idx_size;
+	INDEX_ENTRY *idx_entry_new;
+	ntfschar *uname;
+
+	/* Create the file_name attribute. */
+	i = (strlen(file_name) + 1) * sizeof(ntfschar);
+	fn_size = sizeof(FILE_NAME_ATTR) + i;
+	fn = ntfs_malloc(fn_size);
+	if (!fn)
+		return -errno;
+	fn->parent_directory = ref_parent;
+	fn->creation_time = stdinfo_time(m_file);
+	fn->last_data_change_time = fn->creation_time;
+	fn->last_mft_change_time = fn->creation_time;
+	fn->last_access_time = fn->creation_time;
+	fn->allocated_size = cpu_to_sle64(allocated_size);
+	fn->data_size = cpu_to_sle64(data_size);
+	fn->file_attributes = flags;
+	/* These are in a union so can't have both. */
+	if (packed_ea_size && reparse_point_tag) {
+		free(fn);
+		return -EINVAL;
+	}
+	if (packed_ea_size) {
+		free(fn);
+		return -EINVAL;
+	}
+	if (packed_ea_size) {
+		fn->packed_ea_size = cpu_to_le16(packed_ea_size);
+		fn->reserved = cpu_to_le16(0);
+	} else {
+		fn->reparse_point_tag = cpu_to_le32(reparse_point_tag);
+	}
+	fn->file_name_type = file_name_type;
+	uname = fn->file_name;
+	i = ntfs_mbstoucs_libntfscompat(file_name, &uname, i);
+	if (i < 1) {
+		free(fn);
+		return -EINVAL;
+	}
+	if (i > 0xff) {
+		free(fn);
+		return -ENAMETOOLONG;
+	}
+	/* No terminating null in file names. */
+	fn->file_name_length = i;
+	fn_size = sizeof(FILE_NAME_ATTR) + i * sizeof(ntfschar);
+	/* Increment the link count of @m_file. */
+	i = le16_to_cpu(m_file->link_count);
+	if (i == 0xffff) {
+		ntfs_log_error("Too many hardlinks present already.\n");
+		free(fn);
+		return -EINVAL;
+	}
+	m_file->link_count = cpu_to_le16(i + 1);
+	/* Add the file_name to @m_file. */
+	i = insert_resident_attr_in_mft_record(m_file, AT_FILE_NAME, NULL, 0,
+			CASE_SENSITIVE, const_cpu_to_le16(0),
+			RESIDENT_ATTR_IS_INDEXED, (u8*)fn, fn_size);
+	if (i < 0) {
+		ntfs_log_error("create_hardlink failed adding file name "
+				"attribute: %s\n", strerror(-i));
+		free(fn);
+		/* Undo link count increment. */
+		m_file->link_count = cpu_to_le16(
+				le16_to_cpu(m_file->link_count) - 1);
+		return i;
+	}
+	/* Insert the index entry for file_name in @idx. */
+	idx_size = (fn_size + 7)  & ~7;
+	idx_entry_new = ntfs_calloc(idx_size + 0x10);
+	if (!idx_entry_new)
+		return -errno;
+	idx_entry_new->indexed_file = ref_file;
+	idx_entry_new->length = cpu_to_le16(idx_size + 0x10);
+	idx_entry_new->key_length = cpu_to_le16(fn_size);
+	memcpy((u8*)idx_entry_new + 0x10, (u8*)fn, fn_size);
+	i = insert_index_entry_in_res_dir_index(idx_entry_new, idx_size + 0x10,
+			m_parent, NTFS_INDEX_I30, 4, AT_FILE_NAME);
+	if (i < 0) {
+		ntfs_log_error("create_hardlink failed inserting index entry: "
+				"%s\n", strerror(-i));
+		/* FIXME: Remove the file name attribute from @m_file. */
+		free(idx_entry_new);
+		free(fn);
+		/* Undo link count increment. */
+		m_file->link_count = cpu_to_le16(
+				le16_to_cpu(m_file->link_count) - 1);
+		return i;
+	}
+	free(idx_entry_new);
+	free(fn);
+	return 0;
+}
+
+/**
+ * create_hardlink
+ *
+ * Create a file_name_attribute in the mft record @m_file which points to the
+ * parent directory with mft reference @ref_parent.
+ *
+ * Then, insert an index entry with this file_name_attribute in the index
+ * block @idx of the index allocation attribute of the parent directory.
+ *
+ * @ref_file is the mft reference of @m_file.
+ *
+ * Return 0 on success or -errno on error.
+ */
+static int create_hardlink(INDEX_BLOCK *idx, const leMFT_REF ref_parent,
+		MFT_RECORD *m_file, const leMFT_REF ref_file,
+		const s64 allocated_size, const s64 data_size,
+		const FILE_ATTR_FLAGS flags, const u16 packed_ea_size,
+		const u32 reparse_point_tag, const char *file_name,
+		const FILE_NAME_TYPE_FLAGS file_name_type)
+{
+	FILE_NAME_ATTR *fn;
+	int i, fn_size;
+	ntfschar *uname;
+
+	/* Create the file_name attribute. */
+	i = (strlen(file_name) + 1) * sizeof(ntfschar);
+	fn_size = sizeof(FILE_NAME_ATTR) + i;
+	fn = ntfs_malloc(fn_size);
+	if (!fn)
+		return -errno;
+	fn->parent_directory = ref_parent;
+	fn->creation_time = stdinfo_time(m_file);
+	fn->last_data_change_time = fn->creation_time;
+	fn->last_mft_change_time = fn->creation_time;
+	fn->last_access_time = fn->creation_time;
+		/* allocated size depends on unnamed data being resident */
+	if (allocated_size && non_resident_unnamed_data(m_file))
+		fn->allocated_size = cpu_to_sle64(allocated_size);
+	else
+		fn->allocated_size = cpu_to_sle64((data_size + 7) & -8);
+	fn->data_size = cpu_to_sle64(data_size);
+	fn->file_attributes = flags;
+	/* These are in a union so can't have both. */
+	if (packed_ea_size && reparse_point_tag) {
+		free(fn);
+		return -EINVAL;
+	}
+	if (packed_ea_size) {
+		fn->packed_ea_size = cpu_to_le16(packed_ea_size);
+		fn->reserved = cpu_to_le16(0);
+	} else {
+		fn->reparse_point_tag = cpu_to_le32(reparse_point_tag);
+	}
+	fn->file_name_type = file_name_type;
+	uname = fn->file_name;
+	i = ntfs_mbstoucs_libntfscompat(file_name, &uname, i);
+	if (i < 1) {
+		free(fn);
+		return -EINVAL;
+	}
+	if (i > 0xff) {
+		free(fn);
+		return -ENAMETOOLONG;
+	}
+	/* No terminating null in file names. */
+	fn->file_name_length = i;
+	fn_size = sizeof(FILE_NAME_ATTR) + i * sizeof(ntfschar);
+	/* Increment the link count of @m_file. */
+	i = le16_to_cpu(m_file->link_count);
+	if (i == 0xffff) {
+		ntfs_log_error("Too many hardlinks present already.\n");
+		free(fn);
+		return -EINVAL;
+	}
+	m_file->link_count = cpu_to_le16(i + 1);
+	/* Add the file_name to @m_file. */
+	i = insert_resident_attr_in_mft_record(m_file, AT_FILE_NAME, NULL, 0,
+			CASE_SENSITIVE, cpu_to_le16(0),
+			RESIDENT_ATTR_IS_INDEXED, (u8*)fn, fn_size);
+	if (i < 0) {
+		ntfs_log_error("create_hardlink failed adding file name attribute: "
+				"%s\n", strerror(-i));
+		free(fn);
+		/* Undo link count increment. */
+		m_file->link_count = cpu_to_le16(
+				le16_to_cpu(m_file->link_count) - 1);
+		return i;
+	}
+	/* Insert the index entry for file_name in @idx. */
+	i = insert_file_link_in_dir_index(idx, ref_file, fn, fn_size);
+	if (i < 0) {
+		ntfs_log_error("create_hardlink failed inserting index entry: %s\n",
+				strerror(-i));
+		/* FIXME: Remove the file name attribute from @m_file. */
+		free(fn);
+		/* Undo link count increment. */
+		m_file->link_count = cpu_to_le16(
+				le16_to_cpu(m_file->link_count) - 1);
+		return i;
+	}
+	free(fn);
+	return 0;
+}
+
+/**
+ * index_obj_id_insert
+ *
+ * Insert an index entry with the key @guid and data pointing to the mft record
+ * @ref in the $O index root of the mft record @m (which must be the mft record
+ * for $ObjId).
+ *
+ * Return 0 on success or -errno on error.
+ */
+static int index_obj_id_insert(MFT_RECORD *m, const GUID *guid,
+		const leMFT_REF ref)
+{
+	INDEX_ENTRY *idx_entry_new;
+	int data_ofs, idx_size, err;
+	OBJ_ID_INDEX_DATA *oi;
+
+	/*
+	 * Insert the index entry for the object id in the index.
+	 *
+	 * First determine the size of the index entry to be inserted.  This
+	 * consists of the index entry header, followed by the index key, i.e.
+	 * the GUID, followed by the index data, i.e. OBJ_ID_INDEX_DATA.
+	 */
+	data_ofs = (sizeof(INDEX_ENTRY_HEADER) + sizeof(GUID) + 7) & ~7;
+	idx_size = (data_ofs + sizeof(OBJ_ID_INDEX_DATA) + 7) & ~7;
+	idx_entry_new = ntfs_calloc(idx_size);
+	if (!idx_entry_new)
+		return -errno;
+	idx_entry_new->data_offset = cpu_to_le16(data_ofs);
+	idx_entry_new->data_length = cpu_to_le16(sizeof(OBJ_ID_INDEX_DATA));
+	idx_entry_new->length = cpu_to_le16(idx_size);
+	idx_entry_new->key_length = cpu_to_le16(sizeof(GUID));
+	idx_entry_new->key.object_id = *guid;
+	oi = (OBJ_ID_INDEX_DATA*)((u8*)idx_entry_new + data_ofs);
+	oi->mft_reference = ref;
+	err = insert_index_entry_in_res_dir_index(idx_entry_new, idx_size, m,
+			NTFS_INDEX_O, 2, AT_UNUSED);
+	free(idx_entry_new);
+	if (err < 0) {
+		ntfs_log_error("index_obj_id_insert failed inserting index "
+				"entry: %s\n", strerror(-err));
+		return err;
+	}
+	return 0;
+}
+
+/**
+ * mkntfs_cleanup
+ */
+static void mkntfs_cleanup(void)
+{
+	struct BITMAP_ALLOCATION *p, *q;
+
+	/* Close the volume */
+	if (g_vol) {
+		if (g_vol->dev) {
+			if (NDevOpen(g_vol->dev) && g_vol->dev->d_ops->close(g_vol->dev))
+				ntfs_log_perror("Warning: Could not close %s", g_vol->dev->d_name);
+			ntfs_device_free(g_vol->dev);
+		}
+		free(g_vol->vol_name);
+		free(g_vol->attrdef);
+		free(g_vol->upcase);
+		free(g_vol);
+		g_vol = NULL;
+	}
+
+	/* Free any memory we've used */
+	free(g_bad_blocks);	g_bad_blocks	= NULL;
+	free(g_buf);		g_buf		= NULL;
+	free(g_index_block);	g_index_block	= NULL;
+	free(g_dynamic_buf);	g_dynamic_buf	= NULL;
+	free(g_mft_bitmap);	g_mft_bitmap	= NULL;
+	free(g_rl_bad);		g_rl_bad	= NULL;
+	free(g_rl_boot);	g_rl_boot	= NULL;
+	free(g_rl_logfile);	g_rl_logfile	= NULL;
+	free(g_rl_mft);		g_rl_mft	= NULL;
+	free(g_rl_mft_bmp);	g_rl_mft_bmp	= NULL;
+	free(g_rl_mftmirr);	g_rl_mftmirr	= NULL;
+
+	p = g_allocation;
+	while (p) {
+		q = p->next;
+		free(p);
+		p = q;
+	}
+}
+
+
+/**
+ * mkntfs_open_partition -
+ */
+static BOOL mkntfs_open_partition(ntfs_volume *vol)
+{
+	BOOL result = FALSE;
+	int i;
+	struct stat sbuf;
+	unsigned long mnt_flags;
+
+	/*
+	 * Allocate and initialize an ntfs device structure and attach it to
+	 * the volume.
+	 */
+	vol->dev = ntfs_device_alloc(opts.dev_name, 0, &ntfs_device_default_io_ops, NULL);
+	if (!vol->dev) {
+		ntfs_log_perror("Could not create device");
+		goto done;
+	}
+
+	/* Open the device for reading or reading and writing. */
+	if (opts.no_action) {
+		ntfs_log_quiet("Running in READ-ONLY mode!\n");
+		i = O_RDONLY;
+	} else {
+		i = O_RDWR;
+	}
+	if (vol->dev->d_ops->open(vol->dev, i)) {
+		if (errno == ENOENT)
+			ntfs_log_error("The device doesn't exist; did you specify it correctly?\n");
+		else
+			ntfs_log_perror("Could not open %s", vol->dev->d_name);
+		goto done;
+	}
+	/* Verify we are dealing with a block device. */
+	if (vol->dev->d_ops->stat(vol->dev, &sbuf)) {
+		ntfs_log_perror("Error getting information about %s", vol->dev->d_name);
+		goto done;
+	}
+
+	if (!S_ISBLK(sbuf.st_mode)) {
+		ntfs_log_error("%s is not a block device.\n", vol->dev->d_name);
+		if (!opts.force) {
+			ntfs_log_error("Refusing to make a filesystem here!\n");
+			goto done;
+		}
+		if (!opts.num_sectors) {
+			if (!sbuf.st_size && !sbuf.st_blocks) {
+				ntfs_log_error("You must specify the number of sectors.\n");
+				goto done;
+			}
+			if (opts.sector_size) {
+				if (sbuf.st_size)
+					opts.num_sectors = sbuf.st_size / opts.sector_size;
+				else
+					opts.num_sectors = ((s64)sbuf.st_blocks << 9) / opts.sector_size;
+			} else {
+				if (sbuf.st_size)
+					opts.num_sectors = sbuf.st_size / 512;
+				else
+					opts.num_sectors = sbuf.st_blocks;
+				opts.sector_size = 512;
+			}
+		}
+		ntfs_log_warning("mkntfs forced anyway.\n");
+#ifdef HAVE_LINUX_MAJOR_H
+	} else if ((IDE_DISK_MAJOR(MAJOR(sbuf.st_rdev)) &&
+			MINOR(sbuf.st_rdev) % 64 == 0) ||
+			(SCSI_DISK_MAJOR(MAJOR(sbuf.st_rdev)) &&
+			MINOR(sbuf.st_rdev) % 16 == 0)) {
+		ntfs_log_error("%s is entire device, not just one partition.\n", vol->dev->d_name);
+		if (!opts.force) {
+			ntfs_log_error("Refusing to make a filesystem here!\n");
+			goto done;
+		}
+		ntfs_log_warning("mkntfs forced anyway.\n");
+#endif
+	}
+	/* Make sure the file system is not mounted. */
+	if (ntfs_check_if_mounted(vol->dev->d_name, &mnt_flags)) {
+		ntfs_log_perror("Failed to determine whether %s is mounted", vol->dev->d_name);
+	} else if (mnt_flags & NTFS_MF_MOUNTED) {
+		ntfs_log_error("%s is mounted.\n", vol->dev->d_name);
+		if (!opts.force) {
+			ntfs_log_error("Refusing to make a filesystem here!\n");
+			goto done;
+		}
+		ntfs_log_warning("mkntfs forced anyway. Hope /etc/mtab is incorrect.\n");
+	}
+	result = TRUE;
+done:
+	return result;
+}
+
+/**
+ * mkntfs_get_page_size - detect the system's memory page size.
+ */
+static long mkntfs_get_page_size(void)
+{
+	long page_size;
+#ifdef _SC_PAGESIZE
+	page_size = sysconf(_SC_PAGESIZE);
+	if (page_size < 0)
+#endif
+	{
+		ntfs_log_warning("Failed to determine system page size.  "
+				"Assuming safe default of 4096 bytes.\n");
+		return 4096;
+	}
+	ntfs_log_debug("System page size is %li bytes.\n", page_size);
+	return page_size;
+}
+
+/**
+ * mkntfs_override_vol_params -
+ */
+static BOOL mkntfs_override_vol_params(ntfs_volume *vol)
+{
+	s64 volume_size;
+	long page_size;
+	int i;
+	BOOL winboot = TRUE;
+
+	/* If user didn't specify the sector size, determine it now. */
+	if (opts.sector_size < 0) {
+		opts.sector_size = ntfs_device_sector_size_get(vol->dev);
+		if (opts.sector_size < 0) {
+			ntfs_log_warning("The sector size was not specified "
+				"for %s and it could not be obtained "
+				"automatically.  It has been set to 512 "
+				"bytes.\n", vol->dev->d_name);
+			opts.sector_size = 512;
+		}
+	}
+	/* Validate sector size. */
+	if ((opts.sector_size - 1) & opts.sector_size) {
+		ntfs_log_error("The sector size is invalid.  It must be a "
+			"power of two, e.g. 512, 1024.\n");
+		return FALSE;
+	}
+	if (opts.sector_size < 256 || opts.sector_size > 4096) {
+		ntfs_log_error("The sector size is invalid.  The minimum size "
+			"is 256 bytes and the maximum is 4096 bytes.\n");
+		return FALSE;
+	}
+	ntfs_log_debug("sector size = %ld bytes\n", opts.sector_size);
+	/* Now set the device block size to the sector size. */
+	if (ntfs_device_block_size_set(vol->dev, opts.sector_size))
+		ntfs_log_debug("Failed to set the device block size to the "
+				"sector size.  This may cause problems when "
+				"creating the backup boot sector and also may "
+				"affect performance but should be harmless "
+				"otherwise.  Error: %s\n", strerror(errno));
+	/* If user didn't specify the number of sectors, determine it now. */
+	if (opts.num_sectors < 0) {
+		opts.num_sectors = ntfs_device_size_get(vol->dev,
+				opts.sector_size);
+		if (opts.num_sectors <= 0) {
+			ntfs_log_error("Couldn't determine the size of %s.  "
+				"Please specify the number of sectors "
+				"manually.\n", vol->dev->d_name);
+			return FALSE;
+		}
+	}
+	ntfs_log_debug("number of sectors = %lld (0x%llx)\n", opts.num_sectors,
+			opts.num_sectors);
+	/*
+	 * Reserve the last sector for the backup boot sector unless the
+	 * sector size is less than 512 bytes in which case reserve 512 bytes
+	 * worth of sectors.
+	 */
+	i = 1;
+	if (opts.sector_size < 512)
+		i = 512 / opts.sector_size;
+	opts.num_sectors -= i;
+	/* If user didn't specify the partition start sector, determine it. */
+	if (opts.part_start_sect < 0) {
+		opts.part_start_sect = ntfs_device_partition_start_sector_get(
+				vol->dev);
+		if (opts.part_start_sect < 0) {
+			ntfs_log_warning("The partition start sector was not "
+				"specified for %s and it could not be obtained "
+				"automatically.  It has been set to 0.\n",
+				vol->dev->d_name);
+			opts.part_start_sect = 0;
+			winboot = FALSE;
+		} else if (opts.part_start_sect >> 32) {
+			ntfs_log_warning("The partition start sector specified "
+				"for %s and the automatically determined value "
+				"is too large.  It has been set to 0.\n",
+				vol->dev->d_name);
+			opts.part_start_sect = 0;
+			winboot = FALSE;
+		}
+	} else if (opts.part_start_sect >> 32) {
+		ntfs_log_error("Invalid partition start sector.  Maximum is "
+			"4294967295 (2^32-1).\n");
+		return FALSE;
+	}
+	/* If user didn't specify the sectors per track, determine it now. */
+	if (opts.sectors_per_track < 0) {
+		opts.sectors_per_track = ntfs_device_sectors_per_track_get(
+				vol->dev);
+		if (opts.sectors_per_track < 0) {
+			ntfs_log_warning("The number of sectors per track was "
+				"not specified for %s and it could not be "
+				"obtained automatically.  It has been set to "
+				"0.\n", vol->dev->d_name);
+			opts.sectors_per_track = 0;
+			winboot = FALSE;
+		} else if (opts.sectors_per_track > 65535) {
+			ntfs_log_warning("The number of sectors per track was "
+				"not specified for %s and the automatically "
+				"determined value is too large.  It has been "
+				"set to 0.\n", vol->dev->d_name);
+			opts.sectors_per_track = 0;
+			winboot = FALSE;
+		}
+	} else if (opts.sectors_per_track > 65535) {
+		ntfs_log_error("Invalid number of sectors per track.  Maximum "
+			"is 65535.\n");
+		return FALSE;
+	}
+	/* If user didn't specify the number of heads, determine it now. */
+	if (opts.heads < 0) {
+		opts.heads = ntfs_device_heads_get(vol->dev);
+		if (opts.heads < 0) {
+			ntfs_log_warning("The number of heads was not "
+				"specified for %s and it could not be obtained "
+				"automatically.  It has been set to 0.\n",
+				vol->dev->d_name);
+			opts.heads = 0;
+			winboot = FALSE;
+		} else if (opts.heads > 65535) {
+			ntfs_log_warning("The number of heads was not "
+				"specified for %s and the automatically "
+				"determined value is too large.  It has been "
+				"set to 0.\n", vol->dev->d_name);
+			opts.heads = 0;
+			winboot = FALSE;
+		}
+	} else if (opts.heads > 65535) {
+		ntfs_log_error("Invalid number of heads.  Maximum is 65535.\n");
+		return FALSE;
+	}
+	volume_size = opts.num_sectors * opts.sector_size;
+	/* Validate volume size. */
+	if (volume_size < (1 << 20)) {			/* 1MiB */
+		ntfs_log_error("Device is too small (%llikiB).  Minimum NTFS "
+				"volume size is 1MiB.\n",
+				(long long)(volume_size / 1024));
+		return FALSE;
+	}
+	ntfs_log_debug("volume size = %llikiB\n", volume_size / 1024);
+	/* If user didn't specify the cluster size, determine it now. */
+	if (!vol->cluster_size) {
+		/*
+		 * Windows Vista always uses 4096 bytes as the default cluster
+		 * size regardless of the volume size so we do it, too.
+		 */
+		vol->cluster_size = 4096;
+		/* For small volumes on devices with large sector sizes. */
+		if (vol->cluster_size < (u32)opts.sector_size)
+			vol->cluster_size = opts.sector_size;
+		/*
+		 * For huge volumes, grow the cluster size until the number of
+		 * clusters fits into 32 bits or the cluster size exceeds the
+		 * maximum limit of 64kiB.
+		 */
+		while (volume_size >> (ffs(vol->cluster_size) - 1 + 32)) {
+			vol->cluster_size <<= 1;
+			if (vol->cluster_size > 65535) {
+				ntfs_log_error("Device is too large to hold an "
+						"NTFS volume (maximum size is "
+						"256TiB).\n");
+				return FALSE;
+			}
+		}
+		ntfs_log_quiet("Cluster size has been automatically set to %u "
+				"bytes.\n", (unsigned)vol->cluster_size);
+	}
+	/* Validate cluster size. */
+	if (vol->cluster_size & (vol->cluster_size - 1)) {
+		ntfs_log_error("The cluster size is invalid.  It must be a "
+				"power of two, e.g. 1024, 4096.\n");
+		return FALSE;
+	}
+	if (vol->cluster_size < (u32)opts.sector_size) {
+		ntfs_log_error("The cluster size is invalid.  It must be equal "
+				"to, or larger than, the sector size.\n");
+		return FALSE;
+	}
+	if (vol->cluster_size > 128 * (u32)opts.sector_size) {
+		ntfs_log_error("The cluster size is invalid.  It cannot be "
+				"more that 128 times the size of the sector "
+				"size.\n");
+		return FALSE;
+	}
+	if (vol->cluster_size > 65536) {
+		ntfs_log_error("The cluster size is invalid.  The maximum "
+			"cluster size is 65536 bytes (64kiB).\n");
+		return FALSE;
+	}
+	vol->cluster_size_bits = ffs(vol->cluster_size) - 1;
+	ntfs_log_debug("cluster size = %u bytes\n",
+			(unsigned int)vol->cluster_size);
+	if (vol->cluster_size > 4096) {
+		if (opts.enable_compression) {
+			if (!opts.force) {
+				ntfs_log_error("Windows cannot use compression "
+						"when the cluster size is "
+						"larger than 4096 bytes.\n");
+				return FALSE;
+			}
+			opts.enable_compression = 0;
+		}
+		ntfs_log_warning("Windows cannot use compression when the "
+				"cluster size is larger than 4096 bytes.  "
+				"Compression has been disabled for this "
+				"volume.\n");
+	}
+	vol->nr_clusters = volume_size / vol->cluster_size;
+	/*
+	 * Check the cluster_size and num_sectors for consistency with
+	 * sector_size and num_sectors. And check both of these for consistency
+	 * with volume_size.
+	 */
+	if ((vol->nr_clusters != ((opts.num_sectors * opts.sector_size) /
+			vol->cluster_size) ||
+			(volume_size / opts.sector_size) != opts.num_sectors ||
+			(volume_size / vol->cluster_size) !=
+			vol->nr_clusters)) {
+		/* XXX is this code reachable? */
+		ntfs_log_error("Illegal combination of volume/cluster/sector "
+				"size and/or cluster/sector number.\n");
+		return FALSE;
+	}
+	ntfs_log_debug("number of clusters = %llu (0x%llx)\n",
+			vol->nr_clusters, vol->nr_clusters);
+	/* Number of clusters must fit within 32 bits (Win2k limitation). */
+	if (vol->nr_clusters >> 32) {
+		if (vol->cluster_size >= 65536) {
+			ntfs_log_error("Device is too large to hold an NTFS "
+					"volume (maximum size is 256TiB).\n");
+			return FALSE;
+		}
+		ntfs_log_error("Number of clusters exceeds 32 bits.  Please "
+				"try again with a larger\ncluster size or "
+				"leave the cluster size unspecified and the "
+				"smallest possible cluster size for the size "
+				"of the device will be used.\n");
+		return FALSE;
+	}
+	page_size = mkntfs_get_page_size();
+	/*
+	 * Set the mft record size.  By default this is 1024 but it has to be
+	 * at least as big as a sector and not bigger than a page on the system
+	 * or the NTFS kernel driver will not be able to mount the volume.
+	 * TODO: The mft record size should be user specifiable just like the
+	 * "inode size" can be specified on other Linux/Unix file systems.
+	 */
+	vol->mft_record_size = 1024;
+	if (vol->mft_record_size < (u32)opts.sector_size)
+		vol->mft_record_size = opts.sector_size;
+	if (vol->mft_record_size > (unsigned long)page_size)
+		ntfs_log_warning("Mft record size (%u bytes) exceeds system "
+				"page size (%li bytes).  You will not be able "
+				"to mount this volume using the NTFS kernel "
+				"driver.\n", (unsigned)vol->mft_record_size,
+				page_size);
+	vol->mft_record_size_bits = ffs(vol->mft_record_size) - 1;
+	ntfs_log_debug("mft record size = %u bytes\n",
+			(unsigned)vol->mft_record_size);
+	/*
+	 * Set the index record size.  By default this is 4096 but it has to be
+	 * at least as big as a sector and not bigger than a page on the system
+	 * or the NTFS kernel driver will not be able to mount the volume.
+	 * FIXME: Should we make the index record size to be user specifiable?
+	 */
+	vol->indx_record_size = 4096;
+	if (vol->indx_record_size < (u32)opts.sector_size)
+		vol->indx_record_size = opts.sector_size;
+	if (vol->indx_record_size > (unsigned long)page_size)
+		ntfs_log_warning("Index record size (%u bytes) exceeds system "
+				"page size (%li bytes).  You will not be able "
+				"to mount this volume using the NTFS kernel "
+				"driver.\n", (unsigned)vol->indx_record_size,
+				page_size);
+	vol->indx_record_size_bits = ffs(vol->indx_record_size) - 1;
+	ntfs_log_debug("index record size = %u bytes\n",
+			(unsigned)vol->indx_record_size);
+	if (!winboot) {
+		ntfs_log_warning("To boot from a device, Windows needs the "
+				"'partition start sector', the 'sectors per "
+				"track' and the 'number of heads' to be "
+				"set.\n");
+		ntfs_log_warning("Windows will not be able to boot from this "
+				"device.\n");
+	}
+	return TRUE;
+}
+
+/**
+ * mkntfs_initialize_bitmaps -
+ */
+static BOOL mkntfs_initialize_bitmaps(void)
+{
+	u64 i;
+	int mft_bitmap_size;
+
+	/* Determine lcn bitmap byte size and allocate it. */
+	g_lcn_bitmap_byte_size = (g_vol->nr_clusters + 7) >> 3;
+	/* Needs to be multiple of 8 bytes. */
+	g_lcn_bitmap_byte_size = (g_lcn_bitmap_byte_size + 7) & ~7;
+	i = (g_lcn_bitmap_byte_size + g_vol->cluster_size - 1) &
+			~(g_vol->cluster_size - 1);
+	ntfs_log_debug("g_lcn_bitmap_byte_size = %i, allocated = %llu\n",
+			g_lcn_bitmap_byte_size, i);
+	g_dynamic_buf_size = mkntfs_get_page_size();
+	g_dynamic_buf = (u8*)ntfs_calloc(g_dynamic_buf_size);
+	if (!g_dynamic_buf)
+		return FALSE;
+	/*
+	 * $Bitmap can overlap the end of the volume. Any bits in this region
+	 * must be set. This region also encompasses the backup boot sector.
+	 */
+	if (!bitmap_allocate(g_vol->nr_clusters,
+		    ((s64)g_lcn_bitmap_byte_size << 3) - g_vol->nr_clusters))
+		return (FALSE);
+	/*
+	 * Mft size is 27 (NTFS 3.0+) mft records or one cluster, whichever is
+	 * bigger.
+	 */
+	g_mft_size = 27;
+	g_mft_size *= g_vol->mft_record_size;
+	if (g_mft_size < (s32)g_vol->cluster_size)
+		g_mft_size = g_vol->cluster_size;
+	ntfs_log_debug("MFT size = %i (0x%x) bytes\n", g_mft_size, g_mft_size);
+	/* Determine mft bitmap size and allocate it. */
+	mft_bitmap_size = g_mft_size / g_vol->mft_record_size;
+	/* Convert to bytes, at least one. */
+	g_mft_bitmap_byte_size = (mft_bitmap_size + 7) >> 3;
+	/* Mft bitmap is allocated in multiples of 8 bytes. */
+	g_mft_bitmap_byte_size = (g_mft_bitmap_byte_size + 7) & ~7;
+	ntfs_log_debug("mft_bitmap_size = %i, g_mft_bitmap_byte_size = %i\n",
+			mft_bitmap_size, g_mft_bitmap_byte_size);
+	g_mft_bitmap = ntfs_calloc(g_mft_bitmap_byte_size);
+	if (!g_mft_bitmap)
+		return FALSE;
+	/* Create runlist for mft bitmap. */
+	g_rl_mft_bmp = ntfs_malloc(2 * sizeof(runlist));
+	if (!g_rl_mft_bmp)
+		return FALSE;
+
+	g_rl_mft_bmp[0].vcn = 0LL;
+	/* Mft bitmap is right after $Boot's data. */
+	i = (8192 + g_vol->cluster_size - 1) / g_vol->cluster_size;
+	g_rl_mft_bmp[0].lcn = i;
+	/*
+	 * Size is always one cluster, even though valid data size and
+	 * initialized data size are only 8 bytes.
+	 */
+	g_rl_mft_bmp[1].vcn = 1LL;
+	g_rl_mft_bmp[0].length = 1LL;
+	g_rl_mft_bmp[1].lcn = -1LL;
+	g_rl_mft_bmp[1].length = 0LL;
+	/* Allocate cluster for mft bitmap. */
+	return (bitmap_allocate(i,1));
+}
+
+/**
+ * mkntfs_initialize_rl_mft -
+ */
+static BOOL mkntfs_initialize_rl_mft(void)
+{
+	int j;
+	BOOL done;
+
+	/* If user didn't specify the mft lcn, determine it now. */
+	if (!g_mft_lcn) {
+		/*
+		 * We start at the higher value out of 16kiB and just after the
+		 * mft bitmap.
+		 */
+		g_mft_lcn = g_rl_mft_bmp[0].lcn + g_rl_mft_bmp[0].length;
+		if (g_mft_lcn * g_vol->cluster_size < 16 * 1024)
+			g_mft_lcn = (16 * 1024 + g_vol->cluster_size - 1) /
+					g_vol->cluster_size;
+	}
+	ntfs_log_debug("$MFT logical cluster number = 0x%llx\n", g_mft_lcn);
+	/* Determine MFT zone size. */
+	g_mft_zone_end = g_vol->nr_clusters;
+	switch (opts.mft_zone_multiplier) {  /* % of volume size in clusters */
+	case 4:
+		g_mft_zone_end = g_mft_zone_end >> 1;	/* 50%   */
+		break;
+	case 3:
+		g_mft_zone_end = g_mft_zone_end * 3 >> 3;/* 37.5% */
+		break;
+	case 2:
+		g_mft_zone_end = g_mft_zone_end >> 2;	/* 25%   */
+		break;
+	case 1:
+	default:
+		g_mft_zone_end = g_mft_zone_end >> 3;	/* 12.5% */
+		break;
+	}
+	ntfs_log_debug("MFT zone size = %lldkiB\n", g_mft_zone_end <<
+			g_vol->cluster_size_bits >> 10 /* >> 10 == / 1024 */);
+	/*
+	 * The mft zone begins with the mft data attribute, not at the beginning
+	 * of the device.
+	 */
+	g_mft_zone_end += g_mft_lcn;
+	/* Create runlist for mft. */
+	g_rl_mft = ntfs_malloc(2 * sizeof(runlist));
+	if (!g_rl_mft)
+		return FALSE;
+
+	g_rl_mft[0].vcn = 0LL;
+	g_rl_mft[0].lcn = g_mft_lcn;
+	/* rounded up division by cluster size */
+	j = (g_mft_size + g_vol->cluster_size - 1) / g_vol->cluster_size;
+	g_rl_mft[1].vcn = j;
+	g_rl_mft[0].length = j;
+	g_rl_mft[1].lcn = -1LL;
+	g_rl_mft[1].length = 0LL;
+	/* Allocate clusters for mft. */
+	bitmap_allocate(g_mft_lcn,j);
+	/* Determine mftmirr_lcn (middle of volume). */
+	g_mftmirr_lcn = (opts.num_sectors * opts.sector_size >> 1)
+			/ g_vol->cluster_size;
+	ntfs_log_debug("$MFTMirr logical cluster number = 0x%llx\n",
+			g_mftmirr_lcn);
+	/* Create runlist for mft mirror. */
+	g_rl_mftmirr = ntfs_malloc(2 * sizeof(runlist));
+	if (!g_rl_mftmirr)
+		return FALSE;
+
+	g_rl_mftmirr[0].vcn = 0LL;
+	g_rl_mftmirr[0].lcn = g_mftmirr_lcn;
+	/*
+	 * The mft mirror is either 4kb (the first four records) or one cluster
+	 * in size, which ever is bigger. In either case, it contains a
+	 * byte-for-byte identical copy of the beginning of the mft (i.e. either
+	 * the first four records (4kb) or the first cluster worth of records,
+	 * whichever is bigger).
+	 */
+	j = (4 * g_vol->mft_record_size + g_vol->cluster_size - 1) / g_vol->cluster_size;
+	g_rl_mftmirr[1].vcn = j;
+	g_rl_mftmirr[0].length = j;
+	g_rl_mftmirr[1].lcn = -1LL;
+	g_rl_mftmirr[1].length = 0LL;
+	/* Allocate clusters for mft mirror. */
+	done = bitmap_allocate(g_mftmirr_lcn,j);
+	g_logfile_lcn = g_mftmirr_lcn + j;
+	ntfs_log_debug("$LogFile logical cluster number = 0x%llx\n",
+			g_logfile_lcn);
+	return (done);
+}
+
+/**
+ * mkntfs_initialize_rl_logfile -
+ */
+static BOOL mkntfs_initialize_rl_logfile(void)
+{
+	int j;
+	u64 volume_size;
+
+	/* Create runlist for log file. */
+	g_rl_logfile = ntfs_malloc(2 * sizeof(runlist));
+	if (!g_rl_logfile)
+		return FALSE;
+
+
+	volume_size = g_vol->nr_clusters << g_vol->cluster_size_bits;
+
+	g_rl_logfile[0].vcn = 0LL;
+	g_rl_logfile[0].lcn = g_logfile_lcn;
+	/*
+	 * Determine logfile_size from volume_size (rounded up to a cluster),
+	 * making sure it does not overflow the end of the volume.
+	 */
+	if (volume_size < 2048LL * 1024)		/* < 2MiB	*/
+		g_logfile_size = 256LL * 1024;		/*   -> 256kiB	*/
+	else if (volume_size < 4000000LL)		/* < 4MB	*/
+		g_logfile_size = 512LL * 1024;		/*   -> 512kiB	*/
+	else if (volume_size <= 200LL * 1024 * 1024)	/* < 200MiB	*/
+		g_logfile_size = 2048LL * 1024;		/*   -> 2MiB	*/
+	else	{
+		/*
+		 * FIXME: The $LogFile size is 64 MiB upwards from 12GiB but
+		 * the "200" divider below apparently approximates "100" or
+		 * some other value as the volume size decreases. For example:
+		 *      Volume size   LogFile size    Ratio
+		 *	  8799808        46048       191.100
+		 *	  8603248        45072       190.877
+		 *	  7341704        38768       189.375
+		 *	  6144828        32784       187.433
+		 *	  4192932        23024       182.111
+		 */
+		if (volume_size >= 12LL << 30)		/* > 12GiB	*/
+			g_logfile_size = 64 << 20;	/*   -> 64MiB	*/
+		else
+			g_logfile_size = (volume_size / 200) &
+					~(g_vol->cluster_size - 1);
+	}
+	j = g_logfile_size / g_vol->cluster_size;
+	while (g_rl_logfile[0].lcn + j >= g_vol->nr_clusters) {
+		/*
+		 * $Logfile would overflow volume. Need to make it smaller than
+		 * the standard size. It's ok as we are creating a non-standard
+		 * volume anyway if it is that small.
+		 */
+		g_logfile_size >>= 1;
+		j = g_logfile_size / g_vol->cluster_size;
+	}
+	g_logfile_size = (g_logfile_size + g_vol->cluster_size - 1) &
+			~(g_vol->cluster_size - 1);
+	ntfs_log_debug("$LogFile (journal) size = %ikiB\n",
+			g_logfile_size / 1024);
+	/*
+	 * FIXME: The 256kiB limit is arbitrary. Should find out what the real
+	 * minimum requirement for Windows is so it doesn't blue screen.
+	 */
+	if (g_logfile_size < 256 << 10) {
+		ntfs_log_error("$LogFile would be created with invalid size. "
+				"This is not allowed as it would cause Windows "
+				"to blue screen and during boot.\n");
+		return FALSE;
+	}
+	g_rl_logfile[1].vcn = j;
+	g_rl_logfile[0].length = j;
+	g_rl_logfile[1].lcn = -1LL;
+	g_rl_logfile[1].length = 0LL;
+	/* Allocate clusters for log file. */
+	return (bitmap_allocate(g_logfile_lcn,j));
+}
+
+/**
+ * mkntfs_initialize_rl_boot -
+ */
+static BOOL mkntfs_initialize_rl_boot(void)
+{
+	int j;
+	/* Create runlist for $Boot. */
+	g_rl_boot = ntfs_malloc(2 * sizeof(runlist));
+	if (!g_rl_boot)
+		return FALSE;
+
+	g_rl_boot[0].vcn = 0LL;
+	g_rl_boot[0].lcn = 0LL;
+	/*
+	 * $Boot is always 8192 (0x2000) bytes or 1 cluster, whichever is
+	 * bigger.
+	 */
+	j = (8192 + g_vol->cluster_size - 1) / g_vol->cluster_size;
+	g_rl_boot[1].vcn = j;
+	g_rl_boot[0].length = j;
+	g_rl_boot[1].lcn = -1LL;
+	g_rl_boot[1].length = 0LL;
+	/* Allocate clusters for $Boot. */
+	return (bitmap_allocate(0,j));
+}
+
+/**
+ * mkntfs_initialize_rl_bad -
+ */
+static BOOL mkntfs_initialize_rl_bad(void)
+{
+	/* Create runlist for $BadClus, $DATA named stream $Bad. */
+	g_rl_bad = ntfs_malloc(2 * sizeof(runlist));
+	if (!g_rl_bad)
+		return FALSE;
+
+	g_rl_bad[0].vcn = 0LL;
+	g_rl_bad[0].lcn = -1LL;
+	/*
+	 * $BadClus named stream $Bad contains the whole volume as a single
+	 * sparse runlist entry.
+	 */
+	g_rl_bad[1].vcn = g_vol->nr_clusters;
+	g_rl_bad[0].length = g_vol->nr_clusters;
+	g_rl_bad[1].lcn = -1LL;
+	g_rl_bad[1].length = 0LL;
+
+	/* TODO: Mark bad blocks as such. */
+	return TRUE;
+}
+
+/**
+ * mkntfs_fill_device_with_zeroes -
+ */
+static BOOL mkntfs_fill_device_with_zeroes(void)
+{
+	/*
+	 * If not quick format, fill the device with 0s.
+	 * FIXME: Except bad blocks! (AIA)
+	 */
+	int i;
+	ssize_t bw;
+	unsigned long long position;
+	float progress_inc = (float)g_vol->nr_clusters / 100;
+	u64 volume_size;
+
+	volume_size = g_vol->nr_clusters << g_vol->cluster_size_bits;
+
+	ntfs_log_progress("Initializing device with zeroes:   0%%");
+	for (position = 0; position < (unsigned long long)g_vol->nr_clusters;
+			position++) {
+		if (!(position % (int)(progress_inc+1))) {
+			ntfs_log_progress("\b\b\b\b%3.0f%%", position /
+					progress_inc);
+		}
+		bw = mkntfs_write(g_vol->dev, g_buf, g_vol->cluster_size);
+		if (bw != (ssize_t)g_vol->cluster_size) {
+			if (bw != -1 || errno != EIO) {
+				ntfs_log_error("This should not happen.\n");
+				return FALSE;
+			}
+			if (!position) {
+				ntfs_log_error("Error: Cluster zero is bad. "
+					"Cannot create NTFS file "
+					"system.\n");
+				return FALSE;
+			}
+			/* Add the baddie to our bad blocks list. */
+			if (!append_to_bad_blocks(position))
+				return FALSE;
+			ntfs_log_quiet("\nFound bad cluster (%lld). Adding to "
+				"list of bad blocks.\nInitializing "
+				"device with zeroes: %3.0f%%", position,
+				position / progress_inc);
+			/* Seek to next cluster. */
+			g_vol->dev->d_ops->seek(g_vol->dev,
+					((off_t)position + 1) *
+					g_vol->cluster_size, SEEK_SET);
+		}
+	}
+	ntfs_log_progress("\b\b\b\b100%%");
+	position = (volume_size & (g_vol->cluster_size - 1)) /
+			opts.sector_size;
+	for (i = 0; (unsigned long)i < position; i++) {
+		bw = mkntfs_write(g_vol->dev, g_buf, opts.sector_size);
+		if (bw != opts.sector_size) {
+			if (bw != -1 || errno != EIO) {
+				ntfs_log_error("This should not happen.\n");
+				return FALSE;
+			} else if (i + 1ull == position) {
+				ntfs_log_error("Error: Bad cluster found in "
+					"location reserved for system "
+					"file $Boot.\n");
+				return FALSE;
+			}
+			/* Seek to next sector. */
+			g_vol->dev->d_ops->seek(g_vol->dev,
+					opts.sector_size, SEEK_CUR);
+		}
+	}
+	ntfs_log_progress(" - Done.\n");
+	return TRUE;
+}
+
+/**
+ * mkntfs_sync_index_record
+ *
+ * (ERSO) made a function out of this, but the reason for doing that
+ * disappeared during coding....
+ */
+static BOOL mkntfs_sync_index_record(INDEX_ALLOCATION* idx, MFT_RECORD* m,
+		ntfschar* name, u32 name_len)
+{
+	int i, err;
+	ntfs_attr_search_ctx *ctx;
+	ATTR_RECORD *a;
+	long long lw;
+	runlist	*rl_index = NULL;
+
+	i = 5 * sizeof(ntfschar);
+	ctx = ntfs_attr_get_search_ctx(NULL, m);
+	if (!ctx) {
+		ntfs_log_perror("Failed to allocate attribute search context");
+		return FALSE;
+	}
+	/* FIXME: This should be IGNORE_CASE! */
+	if (mkntfs_attr_lookup(AT_INDEX_ALLOCATION, name, name_len,
+			CASE_SENSITIVE, 0, NULL, 0, ctx)) {
+		ntfs_attr_put_search_ctx(ctx);
+		ntfs_log_error("BUG: $INDEX_ALLOCATION attribute not found.\n");
+		return FALSE;
+	}
+	a = ctx->attr;
+	rl_index = ntfs_mapping_pairs_decompress(g_vol, a, NULL);
+	if (!rl_index) {
+		ntfs_attr_put_search_ctx(ctx);
+		ntfs_log_error("Failed to decompress runlist of $INDEX_ALLOCATION "
+				"attribute.\n");
+		return FALSE;
+	}
+	if (sle64_to_cpu(a->initialized_size) < i) {
+		ntfs_attr_put_search_ctx(ctx);
+		free(rl_index);
+		ntfs_log_error("BUG: $INDEX_ALLOCATION attribute too short.\n");
+		return FALSE;
+	}
+	ntfs_attr_put_search_ctx(ctx);
+	i = sizeof(INDEX_BLOCK) - sizeof(INDEX_HEADER) +
+			le32_to_cpu(idx->index.allocated_size);
+	err = ntfs_mst_pre_write_fixup((NTFS_RECORD*)idx, i);
+	if (err) {
+		free(rl_index);
+		ntfs_log_error("ntfs_mst_pre_write_fixup() failed while "
+			"syncing index block.\n");
+		return FALSE;
+	}
+	lw = ntfs_rlwrite(g_vol->dev, rl_index, (u8*)idx, i, NULL,
+				WRITE_STANDARD);
+	free(rl_index);
+	if (lw != i) {
+		ntfs_log_error("Error writing $INDEX_ALLOCATION.\n");
+		return FALSE;
+	}
+	/* No more changes to @idx below here so no need for fixup: */
+	/* ntfs_mst_post_write_fixup((NTFS_RECORD*)idx); */
+	return TRUE;
+}
+
+/**
+ * create_file_volume -
+ */
+static BOOL create_file_volume(MFT_RECORD *m, leMFT_REF root_ref,
+		VOLUME_FLAGS fl, const GUID *volume_guid)
+{
+	int i, err;
+	u8 *sd;
+
+	ntfs_log_verbose("Creating $Volume (mft record 3)\n");
+	m = (MFT_RECORD*)(g_buf + 3 * g_vol->mft_record_size);
+	err = create_hardlink(g_index_block, root_ref, m,
+			MK_LE_MREF(FILE_Volume, FILE_Volume), 0LL, 0LL,
+			FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0,
+			"$Volume", FILE_NAME_WIN32_AND_DOS);
+	if (!err) {
+		init_system_file_sd(FILE_Volume, &sd, &i);
+		err = add_attr_sd(m, sd, i);
+	}
+	if (!err)
+		err = add_attr_data(m, NULL, 0, CASE_SENSITIVE,
+				const_cpu_to_le16(0), NULL, 0);
+	if (!err)
+		err = add_attr_vol_name(m, g_vol->vol_name, g_vol->vol_name ?
+				strlen(g_vol->vol_name) : 0);
+	if (!err) {
+		if (fl & VOLUME_IS_DIRTY)
+			ntfs_log_quiet("Setting the volume dirty so check "
+					"disk runs on next reboot into "
+					"Windows.\n");
+		err = add_attr_vol_info(m, fl, g_vol->major_ver,
+				g_vol->minor_ver);
+	}
+	if (!err && opts.with_uuid)
+		err = add_attr_object_id(m, volume_guid);
+	if (err < 0) {
+		ntfs_log_error("Couldn't create $Volume: %s\n",
+				strerror(-err));
+		return FALSE;
+	}
+	return TRUE;
+}
+
+/**
+ * create_backup_boot_sector
+ *
+ * Return 0 on success or -1 if it couldn't be created.
+ */
+static int create_backup_boot_sector(u8 *buff)
+{
+	const char *s;
+	ssize_t bw;
+	int size, e;
+
+	ntfs_log_verbose("Creating backup boot sector.\n");
+	/*
+	 * Write the first max(512, opts.sector_size) bytes from buf to the
+	 * last sector, but limit that to 8192 bytes of written data since that
+	 * is how big $Boot is (and how big our buffer is)..
+	 */
+	size = 512;
+	if (size < opts.sector_size)
+		size = opts.sector_size;
+	if (g_vol->dev->d_ops->seek(g_vol->dev, (opts.num_sectors + 1) *
+			opts.sector_size - size, SEEK_SET) == (off_t)-1) {
+		ntfs_log_perror("Seek failed");
+		goto bb_err;
+	}
+	if (size > 8192)
+		size = 8192;
+	bw = mkntfs_write(g_vol->dev, buff, size);
+	if (bw == size)
+		return 0;
+	e = errno;
+	if (bw == -1LL)
+		s = strerror(e);
+	else
+		s = "unknown error";
+	/* At least some 2.4 kernels return EIO instead of ENOSPC. */
+	if (bw != -1LL || (bw == -1LL && e != ENOSPC && e != EIO)) {
+		ntfs_log_critical("Couldn't write backup boot sector: %s\n", s);
+		return -1;
+	}
+bb_err:
+	ntfs_log_error("Couldn't write backup boot sector. This is due to a "
+			"limitation in the\nLinux kernel. This is not a major "
+			"problem as Windows check disk will create the\n"
+			"backup boot sector when it is run on your next boot "
+			"into Windows.\n");
+	return -1;
+}
+
+/**
+ * mkntfs_create_root_structures -
+ */
+static BOOL mkntfs_create_root_structures(void)
+{
+	NTFS_BOOT_SECTOR *bs;
+	MFT_RECORD *m;
+	leMFT_REF root_ref;
+	leMFT_REF extend_ref;
+	int i;
+	int j;
+	int err;
+	u8 *sd;
+	FILE_ATTR_FLAGS extend_flags;
+	VOLUME_FLAGS volume_flags = const_cpu_to_le16(0);
+	int nr_sysfiles;
+	int buf_sds_first_size;
+	char *buf_sds;
+	GUID vol_guid;
+
+	ntfs_log_quiet("Creating NTFS volume structures.\n");
+	nr_sysfiles = 27;
+	/*
+	 * Setup an empty mft record.  Note, we can just give 0 as the mft
+	 * reference as we are creating an NTFS 1.2 volume for which the mft
+	 * reference is ignored by ntfs_mft_record_layout().
+	 *
+	 * Copy the mft record onto all 16 records in the buffer and setup the
+	 * sequence numbers of each system file to equal the mft record number
+	 * of that file (only for $MFT is the sequence number 1 rather than 0).
+	 */
+	for (i = 0; i < nr_sysfiles; i++) {
+		if (ntfs_mft_record_layout(g_vol, 0, m = (MFT_RECORD *)(g_buf +
+				i * g_vol->mft_record_size))) {
+			ntfs_log_error("Failed to layout system mft records."
+					"\n");
+			return FALSE;
+		}
+		if (i == 0 || i > 23)
+			m->sequence_number = cpu_to_le16(1);
+		else
+			m->sequence_number = cpu_to_le16(i);
+	}
+	/*
+	 * If only one cluster contains all system files then
+	 * fill the rest of it with empty, formatted records.
+	 */
+	if (nr_sysfiles * (s32)g_vol->mft_record_size < g_mft_size) {
+		for (i = nr_sysfiles;
+		      i * (s32)g_vol->mft_record_size < g_mft_size; i++) {
+			m = (MFT_RECORD *)(g_buf + i * g_vol->mft_record_size);
+			if (ntfs_mft_record_layout(g_vol, 0, m)) {
+				ntfs_log_error("Failed to layout mft record."
+						"\n");
+				return FALSE;
+			}
+			m->flags = cpu_to_le16(0);
+			m->sequence_number = cpu_to_le16(i);
+		}
+	}
+	/*
+	 * Create the 16 system files, adding the system information attribute
+	 * to each as well as marking them in use in the mft bitmap.
+	 */
+	for (i = 0; i < nr_sysfiles; i++) {
+		le32 file_attrs;
+
+		m = (MFT_RECORD*)(g_buf + i * g_vol->mft_record_size);
+		if (i < 16 || i > 23) {
+			m->mft_record_number = cpu_to_le32(i);
+			m->flags |= MFT_RECORD_IN_USE;
+			ntfs_bit_set(g_mft_bitmap, 0LL + i, 1);
+		}
+		file_attrs = FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM;
+		if (i == FILE_root) {
+			file_attrs |= FILE_ATTR_ARCHIVE;
+			if (opts.disable_indexing)
+				file_attrs |= FILE_ATTR_NOT_CONTENT_INDEXED;
+			if (opts.enable_compression)
+				file_attrs |= FILE_ATTR_COMPRESSED;
+		}
+		/* setting specific security_id flag and */
+		/* file permissions for ntfs 3.x */
+		if (i == 0 || i == 1 || i == 2 || i == 6 || i == 8 ||
+				i == 10) {
+			add_attr_std_info(m, file_attrs,
+				cpu_to_le32(0x0100));
+		} else if (i == 9) {
+			file_attrs |= FILE_ATTR_VIEW_INDEX_PRESENT;
+			add_attr_std_info(m, file_attrs,
+				cpu_to_le32(0x0101));
+		} else if (i == 11) {
+			add_attr_std_info(m, file_attrs,
+				cpu_to_le32(0x0101));
+		} else if (i == 24 || i == 25 || i == 26) {
+			file_attrs |= FILE_ATTR_ARCHIVE;
+			file_attrs |= FILE_ATTR_VIEW_INDEX_PRESENT;
+			add_attr_std_info(m, file_attrs,
+				cpu_to_le32(0x0101));
+		} else {
+			add_attr_std_info(m, file_attrs,
+				cpu_to_le32(0x00));
+		}
+	}
+	/* The root directory mft reference. */
+	root_ref = MK_LE_MREF(FILE_root, FILE_root);
+	extend_ref = MK_LE_MREF(11,11);
+	ntfs_log_verbose("Creating root directory (mft record 5)\n");
+	m = (MFT_RECORD*)(g_buf + 5 * g_vol->mft_record_size);
+	m->flags |= MFT_RECORD_IS_DIRECTORY;
+	m->link_count = cpu_to_le16(le16_to_cpu(m->link_count) + 1);
+	err = add_attr_file_name(m, root_ref, 0LL, 0LL,
+			FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM |
+			FILE_ATTR_I30_INDEX_PRESENT, 0, 0, ".",
+			FILE_NAME_WIN32_AND_DOS);
+	if (!err) {
+		init_root_sd(&sd, &i);
+		err = add_attr_sd(m, sd, i);
+	}
+	/* FIXME: This should be IGNORE_CASE */
+	if (!err)
+		err = add_attr_index_root(m, "$I30", 4, CASE_SENSITIVE,
+				AT_FILE_NAME, COLLATION_FILE_NAME,
+				g_vol->indx_record_size);
+	/* FIXME: This should be IGNORE_CASE */
+	if (!err)
+		err = upgrade_to_large_index(m, "$I30", 4, CASE_SENSITIVE,
+				&g_index_block);
+	if (!err) {
+		ntfs_attr_search_ctx *ctx;
+		ATTR_RECORD *a;
+		ctx = ntfs_attr_get_search_ctx(NULL, m);
+		if (!ctx) {
+			ntfs_log_perror("Failed to allocate attribute search "
+					"context");
+			return FALSE;
+		}
+		/* There is exactly one file name so this is ok. */
+		if (mkntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0,
+				CASE_SENSITIVE, 0, NULL, 0, ctx)) {
+			ntfs_attr_put_search_ctx(ctx);
+			ntfs_log_error("BUG: $FILE_NAME attribute not found."
+					"\n");
+			return FALSE;
+		}
+		a = ctx->attr;
+		err = insert_file_link_in_dir_index(g_index_block, root_ref,
+				(FILE_NAME_ATTR*)((char*)a +
+				le16_to_cpu(a->value_offset)),
+				le32_to_cpu(a->value_length));
+		ntfs_attr_put_search_ctx(ctx);
+	}
+	if (err) {
+		ntfs_log_error("Couldn't create root directory: %s\n",
+			strerror(-err));
+		return FALSE;
+	}
+	/* Add all other attributes, on a per-file basis for clarity. */
+	ntfs_log_verbose("Creating $MFT (mft record 0)\n");
+	m = (MFT_RECORD*)g_buf;
+	err = add_attr_data_positioned(m, NULL, 0, CASE_SENSITIVE,
+			const_cpu_to_le16(0), g_rl_mft, g_buf, g_mft_size);
+	if (!err)
+		err = create_hardlink(g_index_block, root_ref, m,
+				MK_LE_MREF(FILE_MFT, 1),
+				((g_mft_size - 1)
+					| (g_vol->cluster_size - 1)) + 1,
+				g_mft_size, FILE_ATTR_HIDDEN |
+				FILE_ATTR_SYSTEM, 0, 0, "$MFT",
+				FILE_NAME_WIN32_AND_DOS);
+	/* mft_bitmap is not modified in mkntfs; no need to sync it later. */
+	if (!err)
+		err = add_attr_bitmap_positioned(m, NULL, 0, CASE_SENSITIVE,
+				g_rl_mft_bmp,
+				g_mft_bitmap, g_mft_bitmap_byte_size);
+	if (err < 0) {
+		ntfs_log_error("Couldn't create $MFT: %s\n", strerror(-err));
+		return FALSE;
+	}
+	ntfs_log_verbose("Creating $MFTMirr (mft record 1)\n");
+	m = (MFT_RECORD*)(g_buf + 1 * g_vol->mft_record_size);
+	err = add_attr_data_positioned(m, NULL, 0, CASE_SENSITIVE,
+			const_cpu_to_le16(0), g_rl_mftmirr, g_buf,
+			g_rl_mftmirr[0].length * g_vol->cluster_size);
+	if (!err)
+		err = create_hardlink(g_index_block, root_ref, m,
+				MK_LE_MREF(FILE_MFTMirr, FILE_MFTMirr),
+				g_rl_mftmirr[0].length * g_vol->cluster_size,
+				g_rl_mftmirr[0].length * g_vol->cluster_size,
+				FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0,
+				"$MFTMirr", FILE_NAME_WIN32_AND_DOS);
+	if (err < 0) {
+		ntfs_log_error("Couldn't create $MFTMirr: %s\n",
+				strerror(-err));
+		return FALSE;
+	}
+	ntfs_log_verbose("Creating $LogFile (mft record 2)\n");
+	m = (MFT_RECORD*)(g_buf + 2 * g_vol->mft_record_size);
+	err = add_attr_data_positioned(m, NULL, 0, CASE_SENSITIVE,
+			const_cpu_to_le16(0), g_rl_logfile,
+			(const u8*)NULL, g_logfile_size);
+	if (!err)
+		err = create_hardlink(g_index_block, root_ref, m,
+				MK_LE_MREF(FILE_LogFile, FILE_LogFile),
+				g_logfile_size, g_logfile_size,
+				FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0,
+				"$LogFile", FILE_NAME_WIN32_AND_DOS);
+	if (err < 0) {
+		ntfs_log_error("Couldn't create $LogFile: %s\n",
+				strerror(-err));
+		return FALSE;
+	}
+	ntfs_log_verbose("Creating $AttrDef (mft record 4)\n");
+	m = (MFT_RECORD*)(g_buf + 4 * g_vol->mft_record_size);
+	err = add_attr_data(m, NULL, 0, CASE_SENSITIVE, const_cpu_to_le16(0),
+			(u8*)g_vol->attrdef, g_vol->attrdef_len);
+	if (!err)
+		err = create_hardlink(g_index_block, root_ref, m,
+				MK_LE_MREF(FILE_AttrDef, FILE_AttrDef),
+				(g_vol->attrdef_len + g_vol->cluster_size - 1) &
+				~(g_vol->cluster_size - 1), g_vol->attrdef_len,
+				FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0,
+				"$AttrDef", FILE_NAME_WIN32_AND_DOS);
+	if (!err) {
+		init_system_file_sd(FILE_AttrDef, &sd, &i);
+		err = add_attr_sd(m, sd, i);
+	}
+	if (err < 0) {
+		ntfs_log_error("Couldn't create $AttrDef: %s\n",
+				strerror(-err));
+		return FALSE;
+	}
+	ntfs_log_verbose("Creating $Bitmap (mft record 6)\n");
+	m = (MFT_RECORD*)(g_buf + 6 * g_vol->mft_record_size);
+	/* the data attribute of $Bitmap must be non-resident or otherwise */
+	/* windows 2003 will regard the volume as corrupt (ERSO) */
+	if (!err)
+		err = insert_non_resident_attr_in_mft_record(m,
+			AT_DATA,  NULL, 0, CASE_SENSITIVE,
+			const_cpu_to_le16(0), (const u8*)NULL,
+			g_lcn_bitmap_byte_size, WRITE_BITMAP);
+
+
+	if (!err)
+		err = create_hardlink(g_index_block, root_ref, m,
+				MK_LE_MREF(FILE_Bitmap, FILE_Bitmap),
+				(g_lcn_bitmap_byte_size + g_vol->cluster_size -
+				1) & ~(g_vol->cluster_size - 1),
+				g_lcn_bitmap_byte_size,
+				FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0,
+				"$Bitmap", FILE_NAME_WIN32_AND_DOS);
+	if (err < 0) {
+		ntfs_log_error("Couldn't create $Bitmap: %s\n", strerror(-err));
+		return FALSE;
+	}
+	ntfs_log_verbose("Creating $Boot (mft record 7)\n");
+	m = (MFT_RECORD*)(g_buf + 7 * g_vol->mft_record_size);
+	bs = ntfs_calloc(8192);
+	if (!bs)
+		return FALSE;
+	memcpy(bs, boot_array, sizeof(boot_array));
+	/*
+	 * Create the boot sector in bs. Note, that bs is already zeroed
+	 * in the boot sector section and that it has the NTFS OEM id/magic
+	 * already inserted, so no need to worry about these things.
+	 */
+	bs->bpb.bytes_per_sector = cpu_to_le16(opts.sector_size);
+	bs->bpb.sectors_per_cluster = (u8)(g_vol->cluster_size /
+			opts.sector_size);
+	bs->bpb.media_type = 0xf8; /* hard disk */
+	bs->bpb.sectors_per_track = cpu_to_le16(opts.sectors_per_track);
+	ntfs_log_debug("sectors per track = %ld (0x%lx)\n",
+			opts.sectors_per_track, opts.sectors_per_track);
+	bs->bpb.heads = cpu_to_le16(opts.heads);
+	ntfs_log_debug("heads = %ld (0x%lx)\n", opts.heads, opts.heads);
+	bs->bpb.hidden_sectors = cpu_to_le32(opts.part_start_sect);
+	ntfs_log_debug("hidden sectors = %llu (0x%llx)\n", opts.part_start_sect,
+			opts.part_start_sect);
+	bs->physical_drive = 0x80;  	    /* boot from hard disk */
+	bs->extended_boot_signature = 0x80; /* everybody sets this, so we do */
+	bs->number_of_sectors = cpu_to_sle64(opts.num_sectors);
+	bs->mft_lcn = cpu_to_sle64(g_mft_lcn);
+	bs->mftmirr_lcn = cpu_to_sle64(g_mftmirr_lcn);
+	if (g_vol->mft_record_size >= g_vol->cluster_size) {
+		bs->clusters_per_mft_record = g_vol->mft_record_size /
+			g_vol->cluster_size;
+	} else {
+		bs->clusters_per_mft_record = -(ffs(g_vol->mft_record_size) -
+				1);
+		if ((u32)(1 << -bs->clusters_per_mft_record) !=
+				g_vol->mft_record_size) {
+			free(bs);
+			ntfs_log_error("BUG: calculated clusters_per_mft_record"
+					" is wrong (= 0x%x)\n",
+					bs->clusters_per_mft_record);
+			return FALSE;
+		}
+	}
+	ntfs_log_debug("clusters per mft record = %i (0x%x)\n",
+			bs->clusters_per_mft_record,
+			bs->clusters_per_mft_record);
+	if (g_vol->indx_record_size >= g_vol->cluster_size) {
+		bs->clusters_per_index_record = g_vol->indx_record_size /
+			g_vol->cluster_size;
+	} else {
+		bs->clusters_per_index_record = -g_vol->indx_record_size_bits;
+		if ((1 << -bs->clusters_per_index_record) !=
+				(s32)g_vol->indx_record_size) {
+			free(bs);
+			ntfs_log_error("BUG: calculated "
+					"clusters_per_index_record is wrong "
+					"(= 0x%x)\n",
+					bs->clusters_per_index_record);
+			return FALSE;
+		}
+	}
+	ntfs_log_debug("clusters per index block = %i (0x%x)\n",
+			bs->clusters_per_index_record,
+			bs->clusters_per_index_record);
+	/* Generate a 64-bit random number for the serial number. */
+	bs->volume_serial_number = cpu_to_le64(((u64)random() << 32) |
+			((u64)random() & 0xffffffff));
+	/*
+	 * Leave zero for now as NT4 leaves it zero, too. If want it later, see
+	 * ../libntfs/bootsect.c for how to calculate it.
+	 */
+	bs->checksum = cpu_to_le32(0);
+	/* Make sure the bootsector is ok. */
+	if (!ntfs_boot_sector_is_ntfs(bs)) {
+		free(bs);
+		ntfs_log_error("FATAL: Generated boot sector is invalid!\n");
+		return FALSE;
+	}
+	err = add_attr_data_positioned(m, NULL, 0, CASE_SENSITIVE,
+			const_cpu_to_le16(0), g_rl_boot, (u8*)bs, 8192);
+	if (!err)
+		err = create_hardlink(g_index_block, root_ref, m,
+				MK_LE_MREF(FILE_Boot, FILE_Boot),
+				(8192 + g_vol->cluster_size - 1) &
+				~(g_vol->cluster_size - 1), 8192,
+				FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0,
+				"$Boot", FILE_NAME_WIN32_AND_DOS);
+	if (!err) {
+		init_system_file_sd(FILE_Boot, &sd, &i);
+		err = add_attr_sd(m, sd, i);
+	}
+	if (err < 0) {
+		free(bs);
+		ntfs_log_error("Couldn't create $Boot: %s\n", strerror(-err));
+		return FALSE;
+	}
+	if (create_backup_boot_sector((u8*)bs)) {
+		/*
+		 * Pre-2.6 kernels couldn't access the last sector if it was
+		 * odd and we failed to set the device block size to the sector
+		 * size, hence we schedule chkdsk to create it.
+		 */
+		volume_flags |= VOLUME_IS_DIRTY;
+	}
+	free(bs);
+	/*
+	 * We cheat a little here and if the user has requested all times to be
+	 * set to zero then we set the GUID to zero as well.  This options is
+	 * only used for development purposes so that should be fine.
+	 */
+	if (!opts.use_epoch_time) {
+		/* Generate a GUID for the volume. */
+#ifdef ENABLE_UUID
+		uuid_generate((void*)&vol_guid);
+#else
+		ntfs_generate_guid(&vol_guid);
+#endif
+	} else
+		memset(&vol_guid, 0, sizeof(vol_guid));
+	if (!create_file_volume(m, root_ref, volume_flags, &vol_guid))
+		return FALSE;
+	ntfs_log_verbose("Creating $BadClus (mft record 8)\n");
+	m = (MFT_RECORD*)(g_buf + 8 * g_vol->mft_record_size);
+	/* FIXME: This should be IGNORE_CASE */
+	/* Create a sparse named stream of size equal to the volume size. */
+	err = add_attr_data_positioned(m, "$Bad", 4, CASE_SENSITIVE,
+			const_cpu_to_le16(0), g_rl_bad, NULL,
+			g_vol->nr_clusters * g_vol->cluster_size);
+	if (!err) {
+		err = add_attr_data(m, NULL, 0, CASE_SENSITIVE,
+				const_cpu_to_le16(0), NULL, 0);
+	}
+	if (!err) {
+		err = create_hardlink(g_index_block, root_ref, m,
+				MK_LE_MREF(FILE_BadClus, FILE_BadClus),
+				0LL, 0LL, FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM,
+				0, 0, "$BadClus", FILE_NAME_WIN32_AND_DOS);
+	}
+	if (err < 0) {
+		ntfs_log_error("Couldn't create $BadClus: %s\n",
+				strerror(-err));
+		return FALSE;
+	}
+	/* create $Secure (NTFS 3.0+) */
+	ntfs_log_verbose("Creating $Secure (mft record 9)\n");
+	m = (MFT_RECORD*)(g_buf + 9 * g_vol->mft_record_size);
+	m->flags |= MFT_RECORD_IS_VIEW_INDEX;
+	if (!err)
+		err = create_hardlink(g_index_block, root_ref, m,
+				MK_LE_MREF(9, 9), 0LL, 0LL,
+				FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM |
+				FILE_ATTR_VIEW_INDEX_PRESENT, 0, 0,
+				"$Secure", FILE_NAME_WIN32_AND_DOS);
+	buf_sds = NULL;
+	buf_sds_first_size = 0;
+	if (!err) {
+		int buf_sds_size;
+
+		buf_sds_first_size = 0xfc;
+		buf_sds_size = 0x40000 + buf_sds_first_size;
+		buf_sds = ntfs_calloc(buf_sds_size);
+		if (!buf_sds)
+			return FALSE;
+		init_secure_sds(buf_sds);
+		memcpy(buf_sds + 0x40000, buf_sds, buf_sds_first_size);
+		err = add_attr_data(m, "$SDS", 4, CASE_SENSITIVE,
+				const_cpu_to_le16(0), (u8*)buf_sds,
+				buf_sds_size);
+	}
+	/* FIXME: This should be IGNORE_CASE */
+	if (!err)
+		err = add_attr_index_root(m, "$SDH", 4, CASE_SENSITIVE,
+			AT_UNUSED, COLLATION_NTOFS_SECURITY_HASH,
+			g_vol->indx_record_size);
+	/* FIXME: This should be IGNORE_CASE */
+	if (!err)
+		err = add_attr_index_root(m, "$SII", 4, CASE_SENSITIVE,
+			AT_UNUSED, COLLATION_NTOFS_ULONG,
+			g_vol->indx_record_size);
+	if (!err)
+		err = initialize_secure(buf_sds, buf_sds_first_size, m);
+	free(buf_sds);
+	if (err < 0) {
+		ntfs_log_error("Couldn't create $Secure: %s\n",
+			strerror(-err));
+		return FALSE;
+	}
+	ntfs_log_verbose("Creating $UpCase (mft record 0xa)\n");
+	m = (MFT_RECORD*)(g_buf + 0xa * g_vol->mft_record_size);
+	err = add_attr_data(m, NULL, 0, CASE_SENSITIVE, const_cpu_to_le16(0),
+			(u8*)g_vol->upcase, g_vol->upcase_len << 1);
+	/*
+	 * The $Info only exists since Windows 8, but it apparently
+	 * does not disturb chkdsk from earlier versions.
+	 */
+	if (!err)
+		err = add_attr_data(m, "$Info", 5, CASE_SENSITIVE,
+			const_cpu_to_le16(0),
+			(u8*)g_upcaseinfo, sizeof(struct UPCASEINFO));
+	if (!err)
+		err = create_hardlink(g_index_block, root_ref, m,
+				MK_LE_MREF(FILE_UpCase, FILE_UpCase),
+				((g_vol->upcase_len << 1) +
+				g_vol->cluster_size - 1) &
+				~(g_vol->cluster_size - 1),
+				g_vol->upcase_len << 1,
+				FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0,
+				"$UpCase", FILE_NAME_WIN32_AND_DOS);
+	if (err < 0) {
+		ntfs_log_error("Couldn't create $UpCase: %s\n", strerror(-err));
+		return FALSE;
+	}
+	ntfs_log_verbose("Creating $Extend (mft record 11)\n");
+	/*
+	 * $Extend index must be resident.  Otherwise, w2k3 will regard the
+	 * volume as corrupt. (ERSO)
+	 */
+	m = (MFT_RECORD*)(g_buf + 11 * g_vol->mft_record_size);
+	m->flags |= MFT_RECORD_IS_DIRECTORY;
+	if (!err)
+		err = create_hardlink(g_index_block, root_ref, m,
+				MK_LE_MREF(11, 11), 0LL, 0LL,
+				FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM |
+				FILE_ATTR_I30_INDEX_PRESENT, 0, 0,
+				"$Extend", FILE_NAME_WIN32_AND_DOS);
+	/* FIXME: This should be IGNORE_CASE */
+	if (!err)
+		err = add_attr_index_root(m, "$I30", 4, CASE_SENSITIVE,
+			AT_FILE_NAME, COLLATION_FILE_NAME,
+			g_vol->indx_record_size);
+	if (err < 0) {
+		ntfs_log_error("Couldn't create $Extend: %s\n",
+			strerror(-err));
+		return FALSE;
+	}
+	/* NTFS reserved system files (mft records 0xc-0xf) */
+	for (i = 0xc; i < 0x10; i++) {
+		ntfs_log_verbose("Creating system file (mft record 0x%x)\n", i);
+		m = (MFT_RECORD*)(g_buf + i * g_vol->mft_record_size);
+		err = add_attr_data(m, NULL, 0, CASE_SENSITIVE,
+				const_cpu_to_le16(0), NULL, 0);
+		if (!err) {
+			init_system_file_sd(i, &sd, &j);
+			err = add_attr_sd(m, sd, j);
+		}
+		if (err < 0) {
+			ntfs_log_error("Couldn't create system file %i (0x%x): "
+					"%s\n", i, i, strerror(-err));
+			return FALSE;
+		}
+	}
+	/* create systemfiles for ntfs volumes (3.1) */
+	/* starting with file 24 (ignoring file 16-23) */
+	extend_flags = FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM |
+		FILE_ATTR_ARCHIVE | FILE_ATTR_VIEW_INDEX_PRESENT;
+	ntfs_log_verbose("Creating $Quota (mft record 24)\n");
+	m = (MFT_RECORD*)(g_buf + 24 * g_vol->mft_record_size);
+	m->flags |= MFT_RECORD_IS_4;
+	m->flags |= MFT_RECORD_IS_VIEW_INDEX;
+	if (!err)
+		err = create_hardlink_res((MFT_RECORD*)(g_buf +
+			11 * g_vol->mft_record_size), extend_ref, m,
+			MK_LE_MREF(24, 1), 0LL, 0LL, extend_flags,
+			0, 0, "$Quota", FILE_NAME_WIN32_AND_DOS);
+	/* FIXME: This should be IGNORE_CASE */
+	if (!err)
+		err = add_attr_index_root(m, "$Q", 2, CASE_SENSITIVE, AT_UNUSED,
+			COLLATION_NTOFS_ULONG, g_vol->indx_record_size);
+	/* FIXME: This should be IGNORE_CASE */
+	if (!err)
+		err = add_attr_index_root(m, "$O", 2, CASE_SENSITIVE, AT_UNUSED,
+			COLLATION_NTOFS_SID, g_vol->indx_record_size);
+	if (!err)
+		err = initialize_quota(m);
+	if (err < 0) {
+		ntfs_log_error("Couldn't create $Quota: %s\n", strerror(-err));
+		return FALSE;
+	}
+	ntfs_log_verbose("Creating $ObjId (mft record 25)\n");
+	m = (MFT_RECORD*)(g_buf + 25 * g_vol->mft_record_size);
+	m->flags |= MFT_RECORD_IS_4;
+	m->flags |= MFT_RECORD_IS_VIEW_INDEX;
+	if (!err)
+		err = create_hardlink_res((MFT_RECORD*)(g_buf +
+				11 * g_vol->mft_record_size), extend_ref,
+				m, MK_LE_MREF(25, 1), 0LL, 0LL,
+				extend_flags, 0, 0, "$ObjId",
+				FILE_NAME_WIN32_AND_DOS);
+
+	/* FIXME: This should be IGNORE_CASE */
+	if (!err)
+		err = add_attr_index_root(m, "$O", 2, CASE_SENSITIVE, AT_UNUSED,
+			COLLATION_NTOFS_ULONGS,
+			g_vol->indx_record_size);
+	if (!err && opts.with_uuid)
+		err = index_obj_id_insert(m, &vol_guid,
+				MK_LE_MREF(FILE_Volume, FILE_Volume));
+	if (err < 0) {
+		ntfs_log_error("Couldn't create $ObjId: %s\n",
+				strerror(-err));
+		return FALSE;
+	}
+	ntfs_log_verbose("Creating $Reparse (mft record 26)\n");
+	m = (MFT_RECORD*)(g_buf + 26 * g_vol->mft_record_size);
+	m->flags |= MFT_RECORD_IS_4;
+	m->flags |= MFT_RECORD_IS_VIEW_INDEX;
+	if (!err)
+		err = create_hardlink_res((MFT_RECORD*)(g_buf +
+				11 * g_vol->mft_record_size),
+				extend_ref, m, MK_LE_MREF(26, 1),
+				0LL, 0LL, extend_flags, 0, 0,
+				"$Reparse", FILE_NAME_WIN32_AND_DOS);
+	/* FIXME: This should be IGNORE_CASE */
+	if (!err)
+		err = add_attr_index_root(m, "$R", 2, CASE_SENSITIVE, AT_UNUSED,
+			COLLATION_NTOFS_ULONGS, g_vol->indx_record_size);
+	if (err < 0) {
+		ntfs_log_error("Couldn't create $Reparse: %s\n",
+			strerror(-err));
+		return FALSE;
+	}
+	return TRUE;
+}
+
+/**
+ * mkntfs_redirect
+ */
+static int mkntfs_redirect(struct mkntfs_options *opts2)
+{
+	u64 upcase_crc;
+	int result = 1;
+	ntfs_attr_search_ctx *ctx = NULL;
+	long long lw, pos;
+	ATTR_RECORD *a;
+	MFT_RECORD *m;
+	int i, err;
+
+	if (!opts2) {
+		ntfs_log_error("Internal error: invalid parameters to mkntfs_options.\n");
+		goto done;
+	}
+	/* Initialize the random number generator with the current time. */
+	srandom(le64_to_cpu(mkntfs_time())/10000000);
+	/* Allocate and initialize ntfs_volume structure g_vol. */
+	g_vol = ntfs_volume_alloc();
+	if (!g_vol) {
+		ntfs_log_perror("Could not create volume");
+		goto done;
+	}
+	/* Create NTFS 3.1 (Windows XP/Vista) volumes. */
+	g_vol->major_ver = 3;
+	g_vol->minor_ver = 1;
+	/* Transfer some options to the volume. */
+	if (opts.label) {
+		g_vol->vol_name = strdup(opts.label);
+		if (!g_vol->vol_name) {
+			ntfs_log_perror("Could not copy volume name");
+			goto done;
+		}
+	}
+	if (opts.cluster_size >= 0)
+		g_vol->cluster_size = opts.cluster_size;
+	/* Length is in unicode characters. */
+	g_vol->upcase_len = ntfs_upcase_build_default(&g_vol->upcase);
+	/* Since Windows 8, there is a $Info stream in $UpCase */
+	g_upcaseinfo =
+		(struct UPCASEINFO*)ntfs_malloc(sizeof(struct UPCASEINFO));
+	if (!g_vol->upcase_len || !g_upcaseinfo)
+		goto done;
+	/* If the CRC is correct, chkdsk does not warn about obsolete table */
+	crc64(0,(byte*)NULL,0); /* initialize the crc computation */
+	upcase_crc = crc64(0,(byte*)g_vol->upcase,
+			g_vol->upcase_len * sizeof(ntfschar));
+	/* keep the version fields as zero */
+	memset(g_upcaseinfo, 0, sizeof(struct UPCASEINFO));
+	g_upcaseinfo->len = cpu_to_le32(sizeof(struct UPCASEINFO));
+	g_upcaseinfo->crc = cpu_to_le64(upcase_crc);
+	g_vol->attrdef = ntfs_malloc(sizeof(attrdef_ntfs3x_array));
+	if (!g_vol->attrdef) {
+		ntfs_log_perror("Could not create attrdef structure");
+		goto done;
+	}
+	memcpy(g_vol->attrdef, attrdef_ntfs3x_array,
+			sizeof(attrdef_ntfs3x_array));
+	g_vol->attrdef_len = sizeof(attrdef_ntfs3x_array);
+	/* Open the partition. */
+	if (!mkntfs_open_partition(g_vol))
+		goto done;
+	/*
+	 * Decide on the sector size, cluster size, mft record and index record
+	 * sizes as well as the number of sectors/tracks/heads/size, etc.
+	 */
+	if (!mkntfs_override_vol_params(g_vol))
+		goto done;
+	/* Initialize $Bitmap and $MFT/$BITMAP related stuff. */
+	if (!mkntfs_initialize_bitmaps())
+		goto done;
+	/* Initialize MFT & set g_logfile_lcn. */
+	if (!mkntfs_initialize_rl_mft())
+		goto done;
+	/* Initialize $LogFile. */
+	if (!mkntfs_initialize_rl_logfile())
+		goto done;
+	/* Initialize $Boot. */
+	if (!mkntfs_initialize_rl_boot())
+		goto done;
+	/* Allocate a buffer large enough to hold the mft. */
+	g_buf = ntfs_calloc(g_mft_size);
+	if (!g_buf)
+		goto done;
+	/* Create runlist for $BadClus, $DATA named stream $Bad. */
+	if (!mkntfs_initialize_rl_bad())
+		goto done;
+	/* If not quick format, fill the device with 0s. */
+	if (!opts.quick_format) {
+		if (!mkntfs_fill_device_with_zeroes())
+			goto done;
+	}
+	/* Create NTFS volume structures. */
+	if (!mkntfs_create_root_structures())
+		goto done;
+	/*
+	 * - Do not step onto bad blocks!!!
+	 * - If any bad blocks were specified or found, modify $BadClus,
+	 *   allocating the bad clusters in $Bitmap.
+	 * - C&w bootsector backup bootsector (backup in last sector of the
+	 *   partition).
+	 * - If NTFS 3.0+, c&w $Secure file and $Extend directory with the
+	 *   corresponding special files in it, i.e. $ObjId, $Quota, $Reparse,
+	 *   and $UsnJrnl. And others? Or not all necessary?
+	 * - RE: Populate $root with the system files (and $Extend directory if
+	 *   applicable). Possibly should move this as far to the top as
+	 *   possible and update during each subsequent c&w of each system file.
+	 */
+	ntfs_log_verbose("Syncing root directory index record.\n");
+	if (!mkntfs_sync_index_record(g_index_block, (MFT_RECORD*)(g_buf + 5 *
+			g_vol->mft_record_size), NTFS_INDEX_I30, 4))
+		goto done;
+
+	ntfs_log_verbose("Syncing $Bitmap.\n");
+	m = (MFT_RECORD*)(g_buf + 6 * g_vol->mft_record_size);
+
+	ctx = ntfs_attr_get_search_ctx(NULL, m);
+	if (!ctx) {
+		ntfs_log_perror("Could not create an attribute search context");
+		goto done;
+	}
+
+	if (mkntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, CASE_SENSITIVE,
+				0, NULL, 0, ctx)) {
+		ntfs_log_error("BUG: $DATA attribute not found.\n");
+		goto done;
+	}
+
+	a = ctx->attr;
+	if (a->non_resident) {
+		runlist *rl = ntfs_mapping_pairs_decompress(g_vol, a, NULL);
+		if (!rl) {
+			ntfs_log_error("ntfs_mapping_pairs_decompress() failed\n");
+			goto done;
+		}
+		lw = ntfs_rlwrite(g_vol->dev, rl, (const u8*)NULL,
+			 g_lcn_bitmap_byte_size, NULL, WRITE_BITMAP);
+		err = errno;
+		free(rl);
+		if (lw != g_lcn_bitmap_byte_size) {
+			ntfs_log_error("ntfs_rlwrite: %s\n", lw == -1 ?
+				       strerror(err) : "unknown error");
+			goto done;
+		}
+	} else {
+		/* Error : the bitmap must be created non resident */
+		ntfs_log_error("Error : the global bitmap is resident\n");
+		goto done;
+	}
+
+	/*
+	 * No need to sync $MFT/$BITMAP as that has never been modified since
+	 * its creation.
+	 */
+	ntfs_log_verbose("Syncing $MFT.\n");
+	pos = g_mft_lcn * g_vol->cluster_size;
+	lw = 1;
+	for (i = 0; i < g_mft_size / (s32)g_vol->mft_record_size; i++) {
+		if (!opts.no_action)
+			lw = ntfs_mst_pwrite(g_vol->dev, pos, 1, g_vol->mft_record_size, g_buf + i * g_vol->mft_record_size);
+		if (lw != 1) {
+			ntfs_log_error("ntfs_mst_pwrite: %s\n", lw == -1 ?
+				       strerror(errno) : "unknown error");
+			goto done;
+		}
+		pos += g_vol->mft_record_size;
+	}
+	ntfs_log_verbose("Updating $MFTMirr.\n");
+	pos = g_mftmirr_lcn * g_vol->cluster_size;
+	lw = 1;
+	for (i = 0; i < g_rl_mftmirr[0].length * g_vol->cluster_size / g_vol->mft_record_size; i++) {
+		m = (MFT_RECORD*)(g_buf + i * g_vol->mft_record_size);
+		/*
+		 * Decrement the usn by one, so it becomes the same as the one
+		 * in $MFT once it is mst protected. - This is as we need the
+		 * $MFTMirr to have the exact same byte by byte content as
+		 * $MFT, rather than just equivalent meaning content.
+		 */
+		if (ntfs_mft_usn_dec(m)) {
+			ntfs_log_error("ntfs_mft_usn_dec");
+			goto done;
+		}
+		if (!opts.no_action)
+			lw = ntfs_mst_pwrite(g_vol->dev, pos, 1, g_vol->mft_record_size, g_buf + i * g_vol->mft_record_size);
+		if (lw != 1) {
+			ntfs_log_error("ntfs_mst_pwrite: %s\n", lw == -1 ?
+				       strerror(errno) : "unknown error");
+			goto done;
+		}
+		pos += g_vol->mft_record_size;
+	}
+	ntfs_log_verbose("Syncing device.\n");
+	if (g_vol->dev->d_ops->sync(g_vol->dev)) {
+		ntfs_log_error("Syncing device. FAILED");
+		goto done;
+	}
+	ntfs_log_quiet("mkntfs completed successfully. Have a nice day.\n");
+	result = 0;
+done:
+	ntfs_attr_put_search_ctx(ctx);
+	mkntfs_cleanup();	/* Device is unlocked and closed here */
+	return result;
+}
+
+
+/**
+ * main - Begin here
+ *
+ * Start from here.
+ *
+ * Return:  0  Success, the program worked
+ *	    1  Error, something went wrong
+ */
+int main(int argc, char *argv[])
+{
+	int result = 1;
+
+	ntfs_log_set_handler(ntfs_log_handler_outerr);
+	utils_set_locale();
+
+	mkntfs_init_options(&opts);			/* Set up the options */
+
+			/* Read the command line options */
+	result = mkntfs_parse_options(argc, argv, &opts);
+
+	if (result < 0)
+		result = mkntfs_redirect(&opts);
+
+	return result;
+}
diff --git a/ntfsprogs/ntfscat.8 b/ntfsprogs/ntfscat.8
new file mode 100755
index 0000000000000000000000000000000000000000..3ca182363fd92dca87dd7f7b9c761ba8f6040b78
--- /dev/null
+++ b/ntfsprogs/ntfscat.8
@@ -0,0 +1,136 @@
+.\" Copyright (c) 2003\-2005 Richard Russon.
+.\" Copyright (c) 2007 Yura Pakhuchiy.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSCAT 8 "September 2007" "ntfs-3g 2015.3.14"
+.SH NAME
+ntfscat \- print NTFS files and streams on the standard output
+.SH SYNOPSIS
+[\fIoptions\fR] \fIdevice \fR[\fIfile\fR]
+.SH DESCRIPTION
+.B ntfscat
+will read a file or stream from an NTFS volume and display the contents
+on the standard output.
+.PP
+The case of the filename passed to
+.B ntfscat
+is ignored.
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfscat
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-a\fR, \fB\-\-attribute\fR TYPE
+Display the contents of a particular attribute type.  By default, the unnamed
+$DATA attribute will be shown.  The attribute can be specified by a number
+in decimal or hexadecimal, or by name.
+.TS
+box;
+lB lB lB
+l l l.
+Hex	Decimal	Name
+0x10	16	"$STANDARD_INFORMATION"
+0x20	32	"$ATTRIBUTE_LIST"
+0x30	48	"$FILE_NAME"
+0x40	64	"$OBJECT_ID"
+0x50	80	"$SECURITY_DESCRIPTOR"
+0x60	96	"$VOLUME_NAME"
+0x70	112	"$VOLUME_INFORMATION"
+0x80	128	"$DATA"
+0x90	144	"$INDEX_ROOT"
+0xA0	160	"$INDEX_ALLOCATION"
+0xB0	176	"$BITMAP"
+0xC0	192	"$REPARSE_POINT"
+0xD0	208	"$EA_INFORMATION"
+0xE0	224	"$EA"
+0xF0	240	"$PROPERTY_SET"
+0x100	256	"$LOGGED_UTILITY_STREAM"
+.TE
+.sp
+.sp
+.B Notes
+The attribute names may be given without the leading $ symbol.
+.br
+If you use the $ symbol, you must quote the name to prevent the shell
+interpreting the name.
+.TP
+\fB\-n\fR, \fB\-\-attribute\-name\fR NAME
+Display this named attribute, stream.
+.TP
+\fB\-i\fR, \fB\-\-inode\fR NUM
+Specify a file by its inode number instead of its name.
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+This will override some sensible defaults, such as not using a mounted volume.
+Use this option with caution.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Suppress some debug/warning/error messages.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Show the version number, copyright and license
+.BR ntfscat .
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Display more debug/warning/error messages.
+.SH EXAMPLES
+Display the contents of a file in the root of an NTFS volume.
+.RS
+.sp
+.B ntfscat /dev/hda1 boot.ini
+.sp
+.RE
+Display the contents of a file in a subdirectory of an NTFS volume.
+.RS
+.sp
+.B ntfscat /dev/hda1 /winnt/system32/drivers/etc/hosts
+.sp
+.RE
+Display the contents of the $INDEX_ROOT attribute of the root directory (inode
+5).
+.RS
+.sp
+.B ntfscat /dev/hda1 \-a INDEX_ROOT \-i 5 | hexdump \-C
+.sp
+.RE
+.SH BUGS
+There are no known problems with
+.BR ntfscat .
+If you find a bug please send an email describing the problem to the
+development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+.B ntfscat
+was written by Richard Russon, Anton Altaparmakov and Szabolcs Szakacsits.
+It was ported to ntfs-3g by Erik Larsson.
+.SH AVAILABILITY
+.B ntfscat
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+Read \fBlibntfs\fR(8) for details how to access encrypted files.
+.sp
+.BR libntfs (8),
+.BR ntfsls (8),
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/ntfscat.8.in b/ntfsprogs/ntfscat.8.in
new file mode 100755
index 0000000000000000000000000000000000000000..478d9b4b233983296463a8ad395135ea79e6fd92
--- /dev/null
+++ b/ntfsprogs/ntfscat.8.in
@@ -0,0 +1,136 @@
+.\" Copyright (c) 2003\-2005 Richard Russon.
+.\" Copyright (c) 2007 Yura Pakhuchiy.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSCAT 8 "September 2007" "ntfs-3g @VERSION@"
+.SH NAME
+ntfscat \- print NTFS files and streams on the standard output
+.SH SYNOPSIS
+[\fIoptions\fR] \fIdevice \fR[\fIfile\fR]
+.SH DESCRIPTION
+.B ntfscat
+will read a file or stream from an NTFS volume and display the contents
+on the standard output.
+.PP
+The case of the filename passed to
+.B ntfscat
+is ignored.
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfscat
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-a\fR, \fB\-\-attribute\fR TYPE
+Display the contents of a particular attribute type.  By default, the unnamed
+$DATA attribute will be shown.  The attribute can be specified by a number
+in decimal or hexadecimal, or by name.
+.TS
+box;
+lB lB lB
+l l l.
+Hex	Decimal	Name
+0x10	16	"$STANDARD_INFORMATION"
+0x20	32	"$ATTRIBUTE_LIST"
+0x30	48	"$FILE_NAME"
+0x40	64	"$OBJECT_ID"
+0x50	80	"$SECURITY_DESCRIPTOR"
+0x60	96	"$VOLUME_NAME"
+0x70	112	"$VOLUME_INFORMATION"
+0x80	128	"$DATA"
+0x90	144	"$INDEX_ROOT"
+0xA0	160	"$INDEX_ALLOCATION"
+0xB0	176	"$BITMAP"
+0xC0	192	"$REPARSE_POINT"
+0xD0	208	"$EA_INFORMATION"
+0xE0	224	"$EA"
+0xF0	240	"$PROPERTY_SET"
+0x100	256	"$LOGGED_UTILITY_STREAM"
+.TE
+.sp
+.sp
+.B Notes
+The attribute names may be given without the leading $ symbol.
+.br
+If you use the $ symbol, you must quote the name to prevent the shell
+interpreting the name.
+.TP
+\fB\-n\fR, \fB\-\-attribute\-name\fR NAME
+Display this named attribute, stream.
+.TP
+\fB\-i\fR, \fB\-\-inode\fR NUM
+Specify a file by its inode number instead of its name.
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+This will override some sensible defaults, such as not using a mounted volume.
+Use this option with caution.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Suppress some debug/warning/error messages.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Show the version number, copyright and license
+.BR ntfscat .
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Display more debug/warning/error messages.
+.SH EXAMPLES
+Display the contents of a file in the root of an NTFS volume.
+.RS
+.sp
+.B ntfscat /dev/hda1 boot.ini
+.sp
+.RE
+Display the contents of a file in a subdirectory of an NTFS volume.
+.RS
+.sp
+.B ntfscat /dev/hda1 /winnt/system32/drivers/etc/hosts
+.sp
+.RE
+Display the contents of the $INDEX_ROOT attribute of the root directory (inode
+5).
+.RS
+.sp
+.B ntfscat /dev/hda1 \-a INDEX_ROOT \-i 5 | hexdump \-C
+.sp
+.RE
+.SH BUGS
+There are no known problems with
+.BR ntfscat .
+If you find a bug please send an email describing the problem to the
+development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+.B ntfscat
+was written by Richard Russon, Anton Altaparmakov and Szabolcs Szakacsits.
+It was ported to ntfs-3g by Erik Larsson.
+.SH AVAILABILITY
+.B ntfscat
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+Read \fBlibntfs\fR(8) for details how to access encrypted files.
+.sp
+.BR libntfs (8),
+.BR ntfsls (8),
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/ntfscat.c b/ntfsprogs/ntfscat.c
new file mode 100755
index 0000000000000000000000000000000000000000..2ae1f9cdc0f5a5bf047dee54c1ae739a38fa6110
--- /dev/null
+++ b/ntfsprogs/ntfscat.c
@@ -0,0 +1,444 @@
+/**
+ * ntfscat - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2003-2005 Richard Russon
+ * Copyright (c) 2003-2005 Anton Altaparmakov
+ * Copyright (c) 2003-2005 Szabolcs Szakacsits
+ * Copyright (c) 2007      Yura Pakhuchiy
+ *
+ * This utility will concatenate files and print on the standard output.
+ *
+ * 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 Linux-NTFS
+ * 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_GETOPT_H
+#include <getopt.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include "types.h"
+#include "attrib.h"
+#include "utils.h"
+#include "volume.h"
+#include "debug.h"
+#include "dir.h"
+#include "ntfscat.h"
+/* #include "version.h" */
+#include "utils.h"
+
+static const char *EXEC_NAME = "ntfscat";
+static struct options opts;
+
+/**
+ * version - Print version information about the program
+ *
+ * Print a copyright statement and a brief description of the program.
+ *
+ * Return:  none
+ */
+static void version(void)
+{
+	ntfs_log_info("\n%s v%s (libntfs-3g) - Concatenate files and print "
+			"on the standard output.\n\n", EXEC_NAME, VERSION);
+	ntfs_log_info("Copyright (c) 2003-2005 Richard Russon\n");
+	ntfs_log_info("Copyright (c) 2003-2005 Anton Altaparmakov\n");
+	ntfs_log_info("Copyright (c) 2003-2005 Szabolcs Szakacsits\n");
+	ntfs_log_info("Copyright (c) 2007      Yura Pakhuchiy\n");
+	ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
+}
+
+/**
+ * usage - Print a list of the parameters to the program
+ *
+ * Print a list of the parameters and options for the program.
+ *
+ * Return:  none
+ */
+static void usage(void)
+{
+	ntfs_log_info("\nUsage: %s [options] device [file]\n\n"
+		"    -a, --attribute TYPE       Display this attribute type\n"
+		"    -n, --attribute-name NAME  Display this attribute name\n"
+		"    -i, --inode NUM            Display this inode\n\n"
+		"    -f, --force                Use less caution\n"
+		"    -h, --help                 Print this help\n"
+		"    -q, --quiet                Less output\n"
+		"    -V, --version              Version information\n"
+		"    -v, --verbose              More output\n\n",
+// Does not work for compressed files at present so leave undocumented...
+//		"    -r  --raw                  Display the raw data (e.g. for compressed or encrypted file)",
+		EXEC_NAME);
+	ntfs_log_info("%s%s\n", ntfs_bugs, ntfs_home);
+}
+
+/**
+ * parse_attribute - Read an attribute name, or number
+ * @value:   String to be parsed
+ * @attr:    Resulting attribute id (on success)
+ *
+ * Read a string representing an attribute.  It may be a decimal, octal or
+ * hexadecimal number, or the attribute name in full.  The leading $ sign is
+ * optional.
+ *
+ * Return:  1  Success, a valid attribute name or number
+ *	    0  Error, not an attribute name or number
+ */
+static int parse_attribute(const char *value, ATTR_TYPES *attr)
+{
+	static const char *attr_name[] = {
+		"$STANDARD_INFORMATION",
+		"$ATTRIBUTE_LIST",
+		"$FILE_NAME",
+		"$OBJECT_ID",
+		"$SECURITY_DESCRIPTOR",
+		"$VOLUME_NAME",
+		"$VOLUME_INFORMATION",
+		"$DATA",
+		"$INDEX_ROOT",
+		"$INDEX_ALLOCATION",
+		"$BITMAP",
+		"$REPARSE_POINT",
+		"$EA_INFORMATION",
+		"$EA",
+		"$PROPERTY_SET",
+		"$LOGGED_UTILITY_STREAM",
+		NULL
+	};
+
+	int i;
+	long num;
+
+	for (i = 0; attr_name[i]; i++) {
+		if ((strcmp(value, attr_name[i]) == 0) ||
+		    (strcmp(value, attr_name[i] + 1) == 0)) {
+			*attr = (ATTR_TYPES)cpu_to_le32((i + 1) * 16);
+			return 1;
+		}
+	}
+
+	num = strtol(value, NULL, 0);
+	if ((num > 0) && (num < 257)) {
+		*attr = (ATTR_TYPES)cpu_to_le32(num);
+		return 1;
+	}
+
+	return 0;
+}
+
+/**
+ * parse_options - Read and validate the programs command line
+ *
+ * Read the command line, verify the syntax and parse the options.
+ * This function is very long, but quite simple.
+ *
+ * Return:  1 Success
+ *	    0 Error, one or more problems
+ */
+static int parse_options(int argc, char **argv)
+{
+	static const char *sopt = "-a:fh?i:n:qVvr";
+	static const struct option lopt[] = {
+		{ "attribute",      required_argument,	NULL, 'a' },
+		{ "attribute-name", required_argument,	NULL, 'n' },
+		{ "force",	    no_argument,	NULL, 'f' },
+		{ "help",	    no_argument,	NULL, 'h' },
+		{ "inode",	    required_argument,	NULL, 'i' },
+		{ "quiet",	    no_argument,	NULL, 'q' },
+		{ "version",	    no_argument,	NULL, 'V' },
+		{ "verbose",	    no_argument,	NULL, 'v' },
+		{ "raw",	    no_argument,	NULL, 'r' },
+		{ NULL,		    0,			NULL, 0   }
+	};
+
+	int c = -1;
+	int err  = 0;
+	int ver  = 0;
+	int help = 0;
+	int levels = 0;
+	ATTR_TYPES attr = AT_UNUSED;
+
+	opterr = 0; /* We'll handle the errors, thank you. */
+
+	opts.inode = -1;
+	opts.attr = cpu_to_le32(-1);
+	opts.attr_name = NULL;
+	opts.attr_name_len = 0;
+
+	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
+		switch (c) {
+		case 1:	/* A non-option argument */
+			if (!opts.device) {
+				opts.device = argv[optind - 1];
+			} else if (!opts.file) {
+				opts.file = argv[optind - 1];
+			} else {
+				ntfs_log_error("You must specify exactly one "
+						"file.\n");
+				err++;
+			}
+			break;
+		case 'a':
+			if (opts.attr != cpu_to_le32(-1)) {
+				ntfs_log_error("You must specify exactly one "
+						"attribute.\n");
+			} else if (parse_attribute(optarg, &attr) > 0) {
+				opts.attr = attr;
+				break;
+			} else {
+				ntfs_log_error("Couldn't parse attribute.\n");
+			}
+			err++;
+			break;
+		case 'f':
+			opts.force++;
+			break;
+		case 'h':
+			help++;
+			break;
+		case 'i':
+			if (opts.inode != -1)
+				ntfs_log_error("You must specify exactly one inode.\n");
+			else if (utils_parse_size(optarg, &opts.inode, FALSE))
+				break;
+			else
+				ntfs_log_error("Couldn't parse inode number.\n");
+			err++;
+			break;
+
+		case 'n':
+			opts.attr_name_len = ntfs_mbstoucs(optarg,
+							   &opts.attr_name);
+			if (opts.attr_name_len < 0) {
+				ntfs_log_perror("Invalid attribute name '%s'",
+						optarg);
+				usage();
+			}
+
+		case 'q':
+			opts.quiet++;
+			ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
+			break;
+		case 'V':
+			ver++;
+			break;
+		case 'v':
+			opts.verbose++;
+			ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
+			break;
+		case 'r':
+			opts.raw = TRUE;
+			break;
+		case '?':
+			if (strncmp (argv[optind-1], "--log-", 6) == 0) {
+				if (!ntfs_log_parse_option (argv[optind-1]))
+					err++;
+				break;
+			}
+			/* fall through */
+		default:
+			ntfs_log_error("Unknown option '%s'.\n", argv[optind-1]);
+			err++;
+			break;
+		}
+	}
+
+	/* Make sure we're in sync with the log levels */
+	levels = ntfs_log_get_levels();
+	if (levels & NTFS_LOG_LEVEL_VERBOSE)
+		opts.verbose++;
+	if (!(levels & NTFS_LOG_LEVEL_QUIET))
+		opts.quiet++;
+
+	if (help || ver) {
+		opts.quiet = 0;
+	} else {
+		if (opts.device == NULL) {
+			ntfs_log_error("You must specify a device.\n");
+			err++;
+
+		} else if (opts.file == NULL && opts.inode == -1) {
+			ntfs_log_error("You must specify a file or inode "
+				 "with the -i option.\n");
+			err++;
+
+		} else if (opts.file != NULL && opts.inode != -1) {
+			ntfs_log_error("You can't specify both a file and inode.\n");
+			err++;
+		}
+
+		if (opts.quiet && opts.verbose) {
+			ntfs_log_error("You may not use --quiet and --verbose at the "
+					"same time.\n");
+			err++;
+		}
+	}
+
+	if (ver)
+		version();
+	if (help || err)
+		usage();
+
+		/* tri-state 0 : done, 1 : error, -1 : proceed */
+	return (err ? 1 : (help || ver ? 0 : -1));
+}
+
+/**
+ * index_get_size - Find the INDX block size from the index root
+ * @inode:  Inode of the directory to be checked
+ *
+ * Find the size of a directory's INDX block from the INDEX_ROOT attribute.
+ *
+ * Return:  n  Success, the INDX blocks are n bytes in size
+ *	    0  Error, not a directory
+ */
+static int index_get_size(ntfs_inode *inode)
+{
+	ATTR_RECORD *attr90;
+	INDEX_ROOT *iroot;
+
+	attr90 = find_first_attribute(AT_INDEX_ROOT, inode->mrec);
+	if (!attr90)
+		return 0;	// not a directory
+
+	iroot = (INDEX_ROOT*)((u8*)attr90 + le16_to_cpu(attr90->value_offset));
+	return le32_to_cpu(iroot->index_block_size);
+}
+
+/**
+ * cat
+ */
+static int cat(ntfs_volume *vol, ntfs_inode *inode, ATTR_TYPES type,
+		ntfschar *name, int namelen)
+{
+	const int bufsize = 4096;
+	char *buffer;
+	ntfs_attr *attr;
+	s64 bytes_read, written;
+	s64 offset;
+	u32 block_size;
+
+	buffer = malloc(bufsize);
+	if (!buffer)
+		return 1;
+
+	attr = ntfs_attr_open(inode, type, name, namelen);
+	if (!attr) {
+		ntfs_log_error("Cannot find attribute type 0x%x.\n",
+				le32_to_cpu(type));
+		free(buffer);
+		return 1;
+	}
+
+	if ((inode->mft_no < 2) && (attr->type == AT_DATA))
+		block_size = vol->mft_record_size;
+	else if (attr->type == AT_INDEX_ALLOCATION)
+		block_size = index_get_size(inode);
+	else
+		block_size = 0;
+
+	offset = 0;
+	for (;;) {
+		if (!opts.raw && block_size > 0) {
+			// These types have fixup
+			bytes_read = ntfs_attr_mst_pread(attr, offset, 1, block_size, buffer);
+			if (bytes_read > 0)
+				bytes_read *= block_size;
+		} else {
+			bytes_read = ntfs_attr_pread(attr, offset, bufsize, buffer);
+		}
+		//ntfs_log_info("read %lld bytes\n", bytes_read);
+		if (bytes_read == -1) {
+			ntfs_log_perror("ERROR: Couldn't read file");
+			break;
+		}
+		if (!bytes_read)
+			break;
+
+		written = fwrite(buffer, 1, bytes_read, stdout);
+		if (written != bytes_read) {
+			ntfs_log_perror("ERROR: Couldn't output all data!");
+			break;
+		}
+		offset += bytes_read;
+	}
+
+	ntfs_attr_close(attr);
+	free(buffer);
+	return 0;
+}
+
+/**
+ * main - Begin here
+ *
+ * Start from here.
+ *
+ * Return:  0  Success, the program worked
+ *	    1  Error, something went wrong
+ */
+int main(int argc, char *argv[])
+{
+	ntfs_volume *vol;
+	ntfs_inode *inode;
+	ATTR_TYPES attr;
+	int res;
+	int result = 1;
+
+	ntfs_log_set_handler(ntfs_log_handler_stderr);
+
+	res = parse_options(argc, argv);
+	if (res >= 0)
+		return (res);
+
+	utils_set_locale();
+
+	vol = utils_mount_volume(opts.device, NTFS_MNT_RDONLY |
+			(opts.force ? NTFS_MNT_RECOVER : 0));
+	if (!vol) {
+		ntfs_log_perror("ERROR: couldn't mount volume");
+		return 1;
+	}
+
+	if (opts.inode != -1)
+		inode = ntfs_inode_open(vol, opts.inode);
+	else
+		inode = ntfs_pathname_to_inode(vol, NULL, opts.file);
+
+	if (!inode) {
+		ntfs_log_perror("ERROR: Couldn't open inode");
+		return 1;
+	}
+
+	attr = AT_DATA;
+	if (opts.attr != cpu_to_le32(-1))
+		attr = opts.attr;
+
+	result = cat(vol, inode, attr, opts.attr_name, opts.attr_name_len);
+
+	ntfs_inode_close(inode);
+	ntfs_umount(vol, FALSE);
+
+	return result;
+}
diff --git a/ntfsprogs/ntfscat.h b/ntfsprogs/ntfscat.h
new file mode 100755
index 0000000000000000000000000000000000000000..cf474b4889dd3908858dee99aa49c5369fb98d2c
--- /dev/null
+++ b/ntfsprogs/ntfscat.h
@@ -0,0 +1,46 @@
+/*
+ * ntfscat - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2003 Richard Russon
+ * Copyright (c) 2003 Anton Altaparmakov
+ *
+ * This utility will concatenate files and print on the standard output.
+ *
+ * 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 Linux-NTFS
+ * 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 _NTFSCAT_H_
+#define _NTFSCAT_H_
+
+#include "types.h"
+#include "layout.h"
+
+struct options {
+	char		*device;	/* Device/File to work with */
+	char		*file;		/* File to display */
+	s64		 inode;		/* Inode to work with */
+	ATTR_TYPES	 attr;		/* Attribute type to display */
+	ntfschar	*attr_name;	/* Attribute name to display */
+	int		 attr_name_len;	/* Attribute name length */
+	int		 force;		/* Override common sense */
+	int		 quiet;		/* Less output */
+	int		 verbose;	/* Extra output */
+	BOOL		 raw;		/* Raw data output */
+};
+
+#endif /* _NTFSCAT_H_ */
+
+
diff --git a/ntfsprogs/ntfsck.c b/ntfsprogs/ntfsck.c
new file mode 100755
index 0000000000000000000000000000000000000000..278160190dc3345e8058467fccc59e0ddef14511
--- /dev/null
+++ b/ntfsprogs/ntfsck.c
@@ -0,0 +1,883 @@
+/**
+ * ntfsck - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2006 Yuval Fledel
+ *
+ * This utility will check and fix errors on an NTFS volume.
+ *
+ * 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 Linux-NTFS
+ * 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_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#include <layout.h>
+#include <bitmap.h>
+#include <endians.h>
+#include <bootsect.h>
+#include <misc.h>
+
+#include "cluster.h"
+#include "utils.h"
+
+#define RETURN_FS_ERRORS_CORRECTED (1)
+#define RETURN_SYSTEM_NEEDS_REBOOT (2)
+#define RETURN_FS_ERRORS_LEFT_UNCORRECTED (4)
+#define RETURN_OPERATIONAL_ERROR (8)
+#define RETURN_USAGE_OR_SYNTAX_ERROR (16)
+#define RETURN_CANCELLED_BY_USER (32)
+/* Where did 64 go? */
+#define RETURN_SHARED_LIBRARY_ERROR (128)
+
+/* todo: command line: (everything is optional)
+ *  fsck-frontend options:
+ *	-C [fd]	: display progress bar (send it to the file descriptor if specified)
+ *	-T	: don't show the title on startup
+ *  fsck-checker options:
+ *	-a	: auto-repair. no questions. (optional: if marked clean and -f not specified, just check if mounable)
+ *	-p	: auto-repair safe. no questions (optional: same)
+ *	-n	: only check. no repair.
+ *	-r	: interactively repair.
+ *	-y	: always yes.
+ *	-v	: verbose.
+ *	-V	: version.
+ *  taken from fsck.ext2
+ *	-b sb	: use the superblock from sb. For corrupted volumes. (do we want separete boot/mft options?)
+ *	-c	: use badblocks(8) to find bad blocks (R/O mode) and add the findings to $Bad.
+ *	-C fd	: write competion info to fd. If 0, print a completion bar.
+ *	-d	: debugging output.
+ *	-D	: rebalance indices.
+ *	-f	: force checking even if marked clean.
+ *	-F	: flush buffers before beginning. (for time-benchmarking)
+ *	-k	: When used with -c, don't erase previous $Bad items.
+ *	-n	: Open fs as readonly. assume always no. (why is it needed if -r is not specified?)
+ *	-t	: Print time statistics.
+ *  taken from fsck.reiserfs
+ *	--rebuild-sb	: try to find $MFT start and rebuild the boot sector.
+ *	--rebuild-tree	: scan for items and rebuild the indices that point to them (0x30, $SDS, etc.)
+ *	--clean-reserved: zero rezerved fields. (use with care!)
+ *	--adjust-size -z: insert a sparse hole if the data_size is larger than the size marked in the runlist.
+ *	--logfile file	: report corruptions (unlike other errors) to a file instead of stderr.
+ *	--nolog		: don't report corruptions at all.
+ *	--quiet -q	: no progress bar.
+ *  taken from fsck.msdos
+ *	-w	: flush after every write.
+ *	- do n passes. (only 2 in fsck.msdos. second should not report errors. Bonus: stop when error list does not change)
+ *  taken from fsck.jfs
+ *	--omit-journal-reply: self-descriptive (why would someone do that?)
+ *	--replay-journal-only: self-descriptive. don't check otherwise.
+ *  taken from fsck.xfs
+ *	-s	: only serious errors should be reported.
+ *	-i ino	: verbose behaviour only for inode ino.
+ *	-b bno	: verbose behaviour only for cluster bno.
+ *	-L	: zero log.
+ *  inspired by others
+ *	- don't do cluster accounting.
+ *	- don't do mft record accounting.
+ *	- don't do file names accounting.
+ *	- don't do security_id accounting.
+ *	- don't check acl inheritance problems.
+ *	- undelete unused mft records. (bonus: different options for 100% salvagable and less)
+ *	- error-level-report n: only report errors above this error level
+ *	- error-level-repair n: only repair errors below this error level
+ *	- don't fail on ntfsclone metadata pruning.
+ *  signals:
+ *	SIGUSR1	: start displaying progress bar
+ *	SIGUSR2	: stop displaying progress bar.
+ */
+
+/* Assuming NO_NTFS_DEVICE_DEFAULT_IO_OPS is not set */
+
+static int errors = 0;
+static int unsupported = 0;
+
+static short bytes_per_sector, sectors_per_cluster;
+//static s64 mft_offset, mftmirr_offset;
+static s64 current_mft_record;
+
+/**
+ * This is just a preliminary volume.
+ * Filled while checking the boot sector and used in the preliminary MFT check.
+ */
+//static ntfs_volume vol;
+
+static runlist_element *mft_rl, *mft_bitmap_rl;
+
+#define check_failed(FORMAT, ARGS...) \
+	do { \
+		errors++; \
+		ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__, \
+				NTFS_LOG_LEVEL_ERROR,NULL,FORMAT,##ARGS); \
+	} while (0);
+
+/**
+ * 0 success.
+ * 1 fail.
+ */
+static int assert_u32_equal(u32 val, u32 ok, const char *name)
+{
+	if (val!=ok) {
+		check_failed("Assertion failed for '%lld:%s'. should be 0x%x, "
+			"was 0x%x.\n", (long long)current_mft_record, name,
+			(int)ok, (int)val);
+		//errors++;
+		return 1;
+	}
+	return 0;
+}
+
+static int assert_u32_noteq(u32 val, u32 wrong, const char *name)
+{
+	if (val==wrong) {
+		check_failed("Assertion failed for '%lld:%s'. should not be "
+			"0x%x.\n", (long long)current_mft_record, name,
+			(int)wrong);
+		return 1;
+	}
+	return 0;
+}
+
+static int assert_u32_lesseq(u32 val1, u32 val2, const char *name)
+{
+	if (val1 > val2) {
+		check_failed("Assertion failed for '%s'. 0x%x > 0x%x\n",
+			name, (int)val1, (int)val2);
+		//errors++;
+		return 1;
+	}
+	return 0;
+}
+
+static int assert_u32_less(u32 val1, u32 val2, const char *name)
+{
+	if (val1 >= val2) {
+		check_failed("Assertion failed for '%s'. 0x%x >= 0x%x\n",
+			name, (int)val1, (int)val2);
+		//errors++;
+		return 1;
+	}
+	return 0;
+}
+
+/**
+ * Return: 0 ok, 1 error.
+ *
+ * todo: may we use ntfs_boot_sector_is_ntfs() instead?
+ *	It already does the checks but will not be able to fix anything.
+ */
+static BOOL verify_boot_sector(struct ntfs_device *dev, ntfs_volume *rawvol)
+{
+	u8 buf[512];
+	NTFS_BOOT_SECTOR *ntfs_boot = (NTFS_BOOT_SECTOR *)&buf;
+	//u32 bytes_per_cluster;
+
+	current_mft_record = 9;
+
+	if (ntfs_pread(dev, 0, sizeof(buf), buf) != sizeof(buf)) {
+		check_failed("Failed to read boot sector.\n");
+		return 1;
+	}
+
+	if ((buf[0]!=0xeb) ||
+			((buf[1]!=0x52) && (buf[1]!=0x5b)) ||
+			(buf[2]!=0x90)) {
+		check_failed("Boot sector: Bad jump.\n");
+	}
+	if (ntfs_boot->oem_id != magicNTFS) {
+		check_failed("Boot sector: Bad NTFS magic.\n");
+	}
+	bytes_per_sector = le16_to_cpu(ntfs_boot->bpb.bytes_per_sector);
+	if (!bytes_per_sector) {
+		check_failed("Boot sector: Bytes per sector is 0.\n");
+	}
+	if (bytes_per_sector%512) {
+		check_failed("Boot sector: Bytes per sector is not a multiple"
+					" of 512.\n");
+	}
+	sectors_per_cluster = ntfs_boot->bpb.sectors_per_cluster;
+
+	// todo: if partition, query bios and match heads/tracks? */
+
+	// Initialize some values into rawvol. We will need those later.
+	rawvol->dev = dev;
+	ntfs_boot_sector_parse(rawvol, (NTFS_BOOT_SECTOR *)buf);
+
+	return 0;
+}
+
+/**
+ * Load the runlist of the <attr_type> attribute.
+ *
+ * Return NULL if an error.
+ * The caller is responsible on freeing the allocated memory if the result is not NULL.
+ *
+ * Set size_of_file_record to some reasonable size when in doubt (the Windows default is 1024.)
+ *
+ * attr_type must be little endian.
+ *
+ * This function has code duplication with check_file_record() and
+ * check_attr_record() but its goal is to be less strict. Thus the
+ * duplicated checks are the minimal required for not crashing.
+ *
+ * Assumes dev is open.
+ */
+static runlist *load_runlist(ntfs_volume *rawvol, s64 offset_to_file_record, u32 attr_type, u32 size_of_file_record)
+{
+	u8 *buf;
+	u16 attrs_offset;
+	u32 length;
+	ATTR_RECORD *attr_rec;
+	
+	if (size_of_file_record<22) // offset to attrs_offset
+		return NULL;
+
+	buf = (u8*)ntfs_malloc(size_of_file_record);
+	if (!buf)
+		return NULL;
+
+	if (ntfs_pread(rawvol->dev, offset_to_file_record, size_of_file_record, buf) !=
+			size_of_file_record) {
+		check_failed("Failed to read file record at offset %lld (0x%llx).\n",
+					(long long)offset_to_file_record,
+					(long long)offset_to_file_record);
+		return NULL;
+	}
+
+	attrs_offset = le16_to_cpu(((MFT_RECORD*)buf)->attrs_offset);
+	// first attribute must be after the header.
+	if (attrs_offset<42) {
+		check_failed("First attribute must be after the header (%u).\n", (int)attrs_offset);
+	}
+	attr_rec = (ATTR_RECORD *)(buf + attrs_offset);
+	//printf("uv1.\n");
+
+	while ((u8*)attr_rec<=buf+size_of_file_record-4) {
+
+		//printf("Attr type: 0x%x.\n", attr_rec->type);
+		// Check attribute record. (Only what is in the buffer)
+		if (attr_rec->type==AT_END) {
+			check_failed("Attribute 0x%x not found in file record at offset %lld (0x%llx).\n", (int)le32_to_cpu(attr_rec->type),
+					(long long)offset_to_file_record,
+					(long long)offset_to_file_record);
+			return NULL;
+		}
+		if ((u8*)attr_rec>buf+size_of_file_record-8) {
+			// not AT_END yet no room for the length field.
+			check_failed("Attribute 0x%x is not AT_END, yet no "
+					"room for the length field.\n",
+					(int)le32_to_cpu(attr_rec->type));
+			return NULL;
+		}
+
+		length = le32_to_cpu(attr_rec->length);
+
+		// Check that this attribute does not overflow the mft_record
+		if ((u8*)attr_rec+length >= buf+size_of_file_record) {
+			check_failed("Attribute (0x%x) is larger than FILE record at offset %lld (0x%llx).\n",
+					(int)le32_to_cpu(attr_rec->type),
+					(long long)offset_to_file_record,
+					(long long)offset_to_file_record);
+			return NULL;
+		}
+		// todo: what ATTRIBUTE_LIST (0x20)?
+
+		if (attr_rec->type==attr_type) {
+			// Eurika!
+
+			// ntfs_mapping_pairs_decompress only use two values from vol. Just fake it.
+			// todo: it will also use vol->major_ver if defined(DEBUG). But only for printing purposes.
+
+			// Assume ntfs_boot_sector_parse() was called.
+			return ntfs_mapping_pairs_decompress(rawvol, attr_rec, NULL);
+		}
+
+		attr_rec = (ATTR_RECORD*)((u8*)attr_rec+length);
+	}
+	// If we got here, there was an overflow.
+	check_failed("file record corrupted at offset %lld (0x%llx).\n",
+			(long long)offset_to_file_record,
+			(long long)offset_to_file_record);
+	return NULL;
+}
+
+/**
+ * Return: >=0 last VCN
+ *	   LCN_EINVAL error.
+ */
+static VCN get_last_vcn(runlist *rl)
+{
+	VCN res;
+
+	if (!rl)
+		return LCN_EINVAL;
+
+	res = LCN_EINVAL;
+	while (rl->length) {
+		ntfs_log_verbose("vcn: %lld, length: %lld.\n",
+				(long long)rl->vcn, (long long)rl->length);
+		if (rl->vcn<0)
+			res = rl->vcn;
+		else
+			res = rl->vcn + rl->length;
+		rl++;
+	}
+
+	return res;
+}
+
+static u32 mft_bitmap_records;
+static u8 *mft_bitmap_buf;
+
+/**
+ * Assumes mft_bitmap_rl is initialized.
+ * return: 0 ok.
+ *	   RETURN_OPERATIONAL_ERROR on error.
+ */
+static int mft_bitmap_load(ntfs_volume *rawvol)
+{
+	VCN vcn;
+	u32 mft_bitmap_length;
+
+	vcn = get_last_vcn(mft_bitmap_rl);
+	if (vcn<=LCN_EINVAL) {
+		mft_bitmap_buf = NULL;
+		/* This case should not happen, not even with on-disk errors */
+		goto error;
+	}
+
+	mft_bitmap_length = vcn * rawvol->cluster_size;
+	mft_bitmap_records = 8 * mft_bitmap_length * rawvol->cluster_size /
+		rawvol->mft_record_size;
+
+	//printf("sizes: %d, %d.\n", mft_bitmap_length, mft_bitmap_records);
+
+	mft_bitmap_buf = (u8*)ntfs_malloc(mft_bitmap_length);
+	if (!mft_bitmap_buf)
+		goto error;
+	if (ntfs_rl_pread(rawvol, mft_bitmap_rl, 0, mft_bitmap_length,
+			mft_bitmap_buf)!=mft_bitmap_length)
+		goto error;
+	return 0;
+error:
+	mft_bitmap_records = 0;
+	ntfs_log_error("Could not load $MFT/Bitmap.\n");
+	return RETURN_OPERATIONAL_ERROR;
+}
+
+/**
+ * -1 Error.
+ *  0 Unused record
+ *  1 Used record
+ *
+ * Assumes mft_bitmap_rl was initialized.
+ */
+static int mft_bitmap_get_bit(s64 mft_no)
+{
+	if (mft_no>=mft_bitmap_records)
+		return -1;
+	return ntfs_bit_get(mft_bitmap_buf, mft_no);
+}
+
+/**
+ * @attr_rec: The attribute record to check
+ * @mft_rec: The parent FILE record.
+ * @buflen: The size of the FILE record.
+ *
+ * Return:
+ *  NULL: Fatal error occured. Not sure where is the next record.
+ *  otherwise: pointer to the next attribute record.
+ *
+ * The function only check fields that are inside this attr record.
+ *
+ * Assumes mft_rec is current_mft_record.
+ */
+static ATTR_REC *check_attr_record(ATTR_REC *attr_rec, MFT_RECORD *mft_rec,
+			u16 buflen)
+{
+	u16 name_offset;
+	u16 attrs_offset = le16_to_cpu(mft_rec->attrs_offset);
+	u32 attr_type = le32_to_cpu(attr_rec->type);
+	u32 length = le32_to_cpu(attr_rec->length);
+
+	// Check that this attribute does not overflow the mft_record
+	if ((u8*)attr_rec+length >= ((u8*)mft_rec)+buflen) {
+		check_failed("Attribute (0x%x) is larger than FILE record (%lld).\n",
+				(int)attr_type, (long long)current_mft_record);
+		return NULL;
+	}
+
+	// Attr type must be a multiple of 0x10 and 0x10<=x<=0x100.
+	if ((attr_type & ~0x0F0) && (attr_type != 0x100)) {
+		check_failed("Unknown attribute type 0x%x.\n",
+			(int)attr_type);
+		goto check_attr_record_next_attr;
+	}
+
+	if (length<24) {
+		check_failed("Attribute %lld:0x%x Length too short (%u).\n",
+			(long long)current_mft_record, (int)attr_type,
+			(int)length);
+		goto check_attr_record_next_attr;
+	}
+
+	// If this is the first attribute:
+	// todo: instance number must be smaller than next_instance.
+	if ((u8*)attr_rec == ((u8*)mft_rec) + attrs_offset) {
+		if (!mft_rec->base_mft_record)
+			assert_u32_equal(attr_type, 0x10,
+				"First attribute type");
+		// The following not always holds.
+		// attr 0x10 becomes instance 1 and attr 0x40 becomes 0.
+		//assert_u32_equal(attr_rec->instance, 0,
+		//	"First attribute instance number");
+	} else {
+		assert_u32_noteq(attr_type, 0x10,
+			"Not-first attribute type");
+		// The following not always holds.
+		//assert_u32_noteq(attr_rec->instance, 0,
+		//	"Not-first attribute instance number");
+	}
+	//if (current_mft_record==938 || current_mft_record==1683 || current_mft_record==3152 || current_mft_record==22410)
+	//printf("Attribute %lld:0x%x instance: %u isbase:%d.\n",
+	//		current_mft_record, (int)attr_type, (int)le16_to_cpu(attr_rec->instance), (int)mft_rec->base_mft_record);
+	// todo: instance is unique.
+
+	// Check flags.
+	if (attr_rec->flags & ~(const_cpu_to_le16(0xc0ff))) {
+		check_failed("Attribute %lld:0x%x Unknown flags (0x%x).\n",
+			(long long)current_mft_record, (int)attr_type,
+			(int)le16_to_cpu(attr_rec->flags));
+	}
+
+	if (attr_rec->non_resident>1) {
+		check_failed("Attribute %lld:0x%x Unknown non-resident "
+			"flag (0x%x).\n", (long long)current_mft_record,
+			(int)attr_type, (int)attr_rec->non_resident);
+		goto check_attr_record_next_attr;
+	}
+
+	name_offset = le16_to_cpu(attr_rec->name_offset);
+	/*
+	 * todo: name must be legal unicode.
+	 * Not really, information below in urls is about filenames, but I
+	 * believe it also applies to attribute names.  (Yura)
+	 *  http://blogs.msdn.com/michkap/archive/2006/09/24/769540.aspx
+	 *  http://blogs.msdn.com/michkap/archive/2006/09/10/748699.aspx
+	 */
+
+	if (attr_rec->non_resident) {
+		// Non-Resident
+
+		// Make sure all the fields exist.
+		if (length<64) {
+			check_failed("Non-resident attribute %lld:0x%x too short (%u).\n",
+				(long long)current_mft_record, (int)attr_type,
+				(int)length);
+			goto check_attr_record_next_attr;
+		}
+		if (attr_rec->compression_unit && (length<72)) {
+			check_failed("Compressed attribute %lld:0x%x too short (%u).\n",
+				(long long)current_mft_record, (int)attr_type,
+				(int)length);
+			goto check_attr_record_next_attr;
+		}
+
+		// todo: name comes before mapping pairs, and after the header.
+		// todo: length==mapping_pairs_offset+length of compressed mapping pairs.
+		// todo: mapping_pairs_offset is 8-byte aligned.
+
+		// todo: lowest vcn <= highest_vcn
+		// todo: if base record -> lowest vcn==0
+		// todo: lowest_vcn!=0 -> attribute list is used.
+		// todo: lowest_vcn & highest_vcn are in the drive (0<=x<total clusters)
+		// todo: mapping pairs agree with highest_vcn.
+		// todo: compression unit == 0 or 4.
+		// todo: reserved1 == 0.
+		// todo: if not compressed nor sparse, initialized_size <= allocated_size and data_size <= allocated_size.
+		// todo: if compressed or sparse, allocated_size <= initialized_size and allocated_size <= data_size
+		// todo: if mft_no!=0 and not compressed/sparse, data_size==initialized_size.
+		// todo: if mft_no!=0 and compressed/sparse, allocated_size==initialized_size.
+		// todo: what about compressed_size if compressed?
+		// todo: attribute must not be 0x10, 0x30, 0x40, 0x60, 0x70, 0x90, 0xd0 (not sure about 0xb0, 0xe0, 0xf0)
+	} else {
+		u16 value_offset = le16_to_cpu(attr_rec->value_offset);
+		u32 value_length = le32_to_cpu(attr_rec->value_length);
+		// Resident
+		if (attr_rec->name_length) {
+			if (name_offset < 24)
+				check_failed("Resident attribute with "
+					"name intersecting header.\n");
+			if (value_offset < name_offset +
+					attr_rec->name_length)
+				check_failed("Named resident attribute "
+					"with value before name.\n");
+		}
+		// if resident, length==value_length+value_offset
+		//assert_u32_equal(le32_to_cpu(attr_rec->value_length)+
+		//	value_offset, length,
+		//	"length==value_length+value_offset");
+		// if resident, length==value_length+value_offset
+		if (value_length+value_offset > length) {
+			check_failed("value_length(%d)+value_offset(%d)>length(%d) for attribute 0x%x.\n", (int)value_length, (int)value_offset, (int)length, (int)attr_type);
+			return NULL;
+		}
+
+		// Check resident_flags.
+		if (attr_rec->resident_flags>0x01) {
+			check_failed("Unknown resident flags (0x%x) for attribute 0x%x.\n", (int)attr_rec->resident_flags, (int)attr_type);
+		} else if (attr_rec->resident_flags && (attr_type!=0x30)) {
+			check_failed("Resident flags mark attribute 0x%x as indexed.\n", (int)attr_type);
+		}
+
+		// reservedR is 0.
+		assert_u32_equal(attr_rec->reservedR, 0, "Resident Reserved");
+
+		// todo: attribute must not be 0xa0 (not sure about 0xb0, 0xe0, 0xf0)
+		// todo: check content well-formness per attr_type.
+	}
+	return 0;
+check_attr_record_next_attr:
+	return (ATTR_REC *)(((u8 *)attr_rec) + length);
+}
+
+/**
+ * All checks that can be satisfied only by data from the buffer.
+ * No other [MFT records/metadata files] are required.
+ *
+ * The buffer is changed by removing the Update Sequence.
+ *
+ * Return:
+ *	0	Everything's cool.
+ *	else	Consider this record as damaged.
+ */
+static BOOL check_file_record(u8 *buffer, u16 buflen)
+{
+	u16 usa_count, usa_ofs, attrs_offset, usa;
+	u32 bytes_in_use, bytes_allocated, i;
+	MFT_RECORD *mft_rec = (MFT_RECORD *)buffer;
+	ATTR_REC *attr_rec;
+
+	// check record magic
+	assert_u32_equal(mft_rec->magic, magic_FILE, "FILE record magic");
+	// todo: records 16-23 must be filled in order.
+	// todo: what to do with magic_BAAD?
+
+	// check usa_count+offset to update seq <= attrs_offset <
+	//	bytes_in_use <= bytes_allocated <= buflen.
+	usa_ofs = le16_to_cpu(mft_rec->usa_ofs);
+	usa_count = le16_to_cpu(mft_rec->usa_count);
+	attrs_offset = le16_to_cpu(mft_rec->attrs_offset);
+	bytes_in_use = le32_to_cpu(mft_rec->bytes_in_use);
+	bytes_allocated = le32_to_cpu(mft_rec->bytes_allocated);
+	if (assert_u32_lesseq(usa_ofs+usa_count, attrs_offset,
+				"usa_ofs+usa_count <= attrs_offset") ||
+			assert_u32_less(attrs_offset, bytes_in_use,
+				"attrs_offset < bytes_in_use") ||
+			assert_u32_lesseq(bytes_in_use, bytes_allocated,
+				"bytes_in_use <= bytes_allocated") ||
+			assert_u32_lesseq(bytes_allocated, buflen,
+				"bytes_allocated <= max_record_size")) {
+		return 1;
+	}
+
+
+	// We should know all the flags.
+	if (mft_rec->flags>0xf) {
+		check_failed("Unknown MFT record flags (0x%x).\n",
+			(unsigned int)mft_rec->flags);
+	}
+	// todo: flag in_use must be on.
+
+	// Remove update seq & check it.
+	usa = *(u16*)(buffer+usa_ofs); // The value that should be at the end of every sector.
+	assert_u32_equal(usa_count-1, buflen/NTFS_BLOCK_SIZE, "USA length");
+	for (i=1;i<usa_count;i++) {
+		u16 *fixup = (u16*)(buffer+NTFS_BLOCK_SIZE*i-2); // the value at the end of the sector.
+		u16 saved_val = *(u16*)(buffer+usa_ofs+2*i); // the actual data value that was saved in the us array.
+
+		assert_u32_equal(*fixup, usa, "fixup");
+		*fixup = saved_val; // remove it.
+	}
+
+	attr_rec = (ATTR_REC *)(buffer + attrs_offset);
+	while ((u8*)attr_rec<=buffer+buflen-4) {
+
+		// Check attribute record. (Only what is in the buffer)
+		if (attr_rec->type==AT_END) {
+			// Done.
+			return 0;
+		}
+		if ((u8*)attr_rec>buffer+buflen-8) {
+			// not AT_END yet no room for the length field.
+			check_failed("Attribute 0x%x is not AT_END, yet no "
+					"room for the length field.\n",
+					(int)le32_to_cpu(attr_rec->type));
+			return 1;
+		}
+
+		attr_rec = check_attr_record(attr_rec, mft_rec, buflen);
+		if (!attr_rec)
+			return 1;
+	}
+	// If we got here, there was an overflow.
+	return 1;
+	
+	// todo: an attribute should be at the offset to first attribute, and the offset should be inside the buffer. It should have the value of "next attribute id".
+	// todo: if base record, it should start with attribute 0x10.
+
+	// Highlevel check of attributes.
+	//  todo: Attributes are well-formed.
+	//  todo: Room for next attribute in the end of the previous record.
+
+	return FALSE;
+}
+
+static void replay_log(ntfs_volume *vol __attribute__((unused)))
+{
+	// At this time, only check that the log is fully replayed.
+	ntfs_log_warning("Unsupported: replay_log()\n");
+	// todo: if logfile is clean, return success.
+	unsupported++;
+}
+
+static void verify_mft_record(ntfs_volume *vol, s64 mft_num)
+{
+	u8 *buffer;
+	int is_used;
+
+	current_mft_record = mft_num;
+
+	is_used = mft_bitmap_get_bit(mft_num);
+	if (is_used<0) {
+		ntfs_log_error("Error getting bit value for record %lld.\n",
+			(long long)mft_num);
+	} else if (!is_used) {
+		ntfs_log_verbose("Record %lld unused. Skipping.\n",
+				(long long)mft_num);
+		return;
+	}
+
+	buffer = ntfs_malloc(vol->mft_record_size);
+	if (!buffer)
+		goto verify_mft_record_error;
+
+	ntfs_log_verbose("MFT record %lld\n", (long long)mft_num);
+	if (ntfs_attr_pread(vol->mft_na, mft_num*vol->mft_record_size, vol->mft_record_size, buffer) < 0) {
+		ntfs_log_perror("Couldn't read $MFT record %lld", (long long)mft_num);
+		goto verify_mft_record_error;
+	}
+	
+	check_file_record(buffer, vol->mft_record_size);
+	// todo: if offset to first attribute >= 0x30, number of mft record should match.
+	// todo: Match the "record is used" with the mft bitmap.
+	// todo: if this is not base, check that the parent is a base, and is in use, and pointing to this record.
+
+	// todo: if base record: for each extent record:
+	//   todo: verify_file_record
+	//   todo: hard link count should be the number of 0x30 attributes.
+	//   todo: Order of attributes.
+	//   todo: make sure compression_unit is the same.
+
+	return;
+verify_mft_record_error:
+
+	if (buffer)
+		free(buffer);
+	errors++;
+}
+
+/**
+ * This function serves as bootstraping for the more comprehensive checks.
+ * It will load the MFT runlist and MFT/Bitmap runlist.
+ * It should not depend on other checks or we may have a circular dependancy.
+ * Also, this loadng must be forgiving, unlike the comprehensive checks.
+ */
+static int verify_mft_preliminary(ntfs_volume *rawvol)
+{
+	current_mft_record = 0;
+	s64 mft_offset, mftmirr_offset;
+	int res;
+
+	ntfs_log_trace("Entering verify_mft_preliminary().\n");
+	// todo: get size_of_file_record from boot sector
+	// Load the first segment of the $MFT/DATA runlist.
+	mft_offset = rawvol->mft_lcn * rawvol->cluster_size;
+	mftmirr_offset = rawvol->mftmirr_lcn * rawvol->cluster_size;
+	mft_rl = load_runlist(rawvol, mft_offset, AT_DATA, 1024);
+	if (!mft_rl) {
+		check_failed("Loading $MFT runlist failed. Trying $MFTMirr.\n");
+		mft_rl = load_runlist(rawvol, mftmirr_offset, AT_DATA, 1024);
+	}
+	if (!mft_rl) {
+		check_failed("Loading $MFTMirr runlist failed too. Aborting.\n");
+		return RETURN_FS_ERRORS_LEFT_UNCORRECTED | RETURN_OPERATIONAL_ERROR;
+	}
+	// TODO: else { recover $MFT } // Use $MFTMirr to recover $MFT.
+	// todo: support loading the next runlist extents when ATTRIBUTE_LIST is used on $MFT.
+	// If attribute list: Gradually load mft runlist. (parse runlist from first file record, check all referenced file records, continue with the next file record). If no attribute list, just load it.
+
+	// Load the runlist of $MFT/Bitmap.
+	// todo: what about ATTRIBUTE_LIST? Can we reuse code?
+	mft_bitmap_rl = load_runlist(rawvol, mft_offset, AT_BITMAP, 1024);
+	if (!mft_bitmap_rl) {
+		check_failed("Loading $MFT/Bitmap runlist failed. Trying $MFTMirr.\n");
+		mft_bitmap_rl = load_runlist(rawvol, mftmirr_offset, AT_BITMAP, 1024);
+	}
+	if (!mft_bitmap_rl) {
+		check_failed("Loading $MFTMirr/Bitmap runlist failed too. Aborting.\n");
+		return RETURN_FS_ERRORS_LEFT_UNCORRECTED;
+		// todo: rebuild the bitmap by using the "in_use" file record flag or by filling it with 1's.
+	}
+
+	/* Load $MFT/Bitmap */
+	if ((res = mft_bitmap_load(rawvol)))
+		return res;
+	return -1; /* FIXME: Just added to fix compiler warning without
+			thinking about what should be here.  (Yura) */
+}
+
+static void check_volume(ntfs_volume *vol)
+{
+	s64 mft_num, nr_mft_records;
+
+	ntfs_log_warning("Unsupported: check_volume()\n");
+	unsupported++;
+
+	// For each mft record, verify that it contains a valid file record.
+	nr_mft_records = vol->mft_na->initialized_size >>
+			vol->mft_record_size_bits;
+	ntfs_log_info("Checking %lld MFT records.\n", (long long)nr_mft_records);
+
+	for (mft_num=0; mft_num < nr_mft_records; mft_num++) {
+	 	verify_mft_record(vol, mft_num);
+	}
+
+	// todo: Check metadata files.
+
+	// todo: Second pass on mft records. Now check the contents as well.
+	// todo: When going through runlists, build a bitmap.
+
+	// todo: cluster accounting.
+	return;
+}
+
+static int reset_dirty(ntfs_volume *vol)
+{
+	u16 flags;
+
+	if (!(vol->flags | VOLUME_IS_DIRTY))
+		return 0;
+
+	ntfs_log_verbose("Resetting dirty flag.\n");
+
+	flags = vol->flags & ~VOLUME_IS_DIRTY;
+
+	if (ntfs_volume_write_flags(vol, flags)) {
+		ntfs_log_error("Error setting volume flags.\n");
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * main - Does just what C99 claim it does.
+ *
+ * For more details on arguments and results, check the man page.
+ */
+int main(int argc, char **argv)
+{
+	struct ntfs_device *dev;
+	ntfs_volume rawvol;
+	ntfs_volume *vol;
+	const char *name;
+	int ret;
+
+	if (argc != 2)
+		return RETURN_USAGE_OR_SYNTAX_ERROR;
+	name = argv[1];
+
+	ntfs_log_set_handler(ntfs_log_handler_outerr);
+	//ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG | NTFS_LOG_LEVEL_TRACE | NTFS_LOG_LEVEL_QUIET | NTFS_LOG_LEVEL_INFO | NTFS_LOG_LEVEL_VERBOSE | NTFS_LOG_LEVEL_PROGRESS);
+
+	/* Allocate an ntfs_device structure. */
+	dev = ntfs_device_alloc(name, 0, &ntfs_device_default_io_ops, NULL);
+	if (!dev)
+		return RETURN_OPERATIONAL_ERROR;
+	if (dev->d_ops->open(dev, O_RDONLY)) { //O_RDWR/O_RDONLY?
+		ntfs_log_perror("Error opening partition device");
+		ntfs_device_free(dev);
+		return RETURN_OPERATIONAL_ERROR;
+	}
+
+	if ((ret = verify_boot_sector(dev,&rawvol))) {
+		dev->d_ops->close(dev);
+		return ret;
+	}
+	ntfs_log_verbose("Boot sector verification complete. Proceeding to $MFT");
+
+	verify_mft_preliminary(&rawvol);
+
+	/* ntfs_device_mount() expects the device to be closed. */
+	if (dev->d_ops->close(dev))
+		ntfs_log_perror("Failed to close the device.");
+
+	// at this point we know that the volume is valid enough for mounting.
+
+	/* Call ntfs_device_mount() to do the actual mount. */
+	vol = ntfs_device_mount(dev, NTFS_MNT_RDONLY);
+	if (!vol) {
+		ntfs_device_free(dev);
+		return 2;
+	}
+
+	replay_log(vol);
+
+	if (vol->flags & VOLUME_IS_DIRTY)
+		ntfs_log_warning("Volume is dirty.\n");
+
+	check_volume(vol);
+
+	if (errors)
+		ntfs_log_info("Errors found.\n");
+	if (unsupported)
+		ntfs_log_info("Unsupported cases found.\n");
+
+	if (!errors && !unsupported) {
+		reset_dirty(vol);
+	}
+
+	ntfs_umount(vol, FALSE);
+
+	if (errors)
+		return 2;
+	if (unsupported)
+		return 1;
+	return 0;
+}
+
diff --git a/ntfsprogs/ntfsclone.8 b/ntfsprogs/ntfsclone.8
new file mode 100755
index 0000000000000000000000000000000000000000..9b5c6a3ff448cf734d6fd60d40107f250faf0a5f
--- /dev/null
+++ b/ntfsprogs/ntfsclone.8
@@ -0,0 +1,392 @@
+.\" Copyright (c) 2003\-2005 Richard Russon.
+.\" Copyright (c) 2003\-2006 Szabolcs Szakacsits.
+.\" Copyright (c) 2004 Per Olofsson.
+.\" Copyright (c) 2010\-2013 Jean-Pierre Andre.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSCLONE 8 "February 2013" "ntfs-3g 2015.3.14"
+.SH NAME
+ntfsclone \- Efficiently clone, image, restore or rescue an NTFS
+.SH SYNOPSIS
+.B ntfsclone
+[\fIOPTIONS\fR]
+.I SOURCE
+.br
+.B ntfsclone \-\-save\-image
+[\fIOPTIONS\fR]
+.I SOURCE
+.br
+.B ntfsclone \-\-restore\-image
+[\fIOPTIONS\fR]
+.I SOURCE
+.br
+.B ntfsclone \-\-metadata
+[\fIOPTIONS\fR]
+.I SOURCE
+.SH DESCRIPTION
+.B ntfsclone
+will efficiently clone (copy, save, backup, restore) or rescue an NTFS
+filesystem to a sparse file, image, device (partition) or standard output.
+It works at disk sector level and
+copies only the used data. Unused disk space becomes zero (cloning to
+sparse file), encoded with control codes (saving in special image format),
+left unchanged (cloning to a disk/partition) or
+filled with zeros (cloning to standard output).
+
+.B ntfsclone
+can be useful to make backups, an exact snapshot of an NTFS filesystem
+and restore it later on, or for developers to test NTFS read/write
+functionality, troubleshoot/investigate users' issues using the clone
+without the risk of destroying the original filesystem.
+
+The clone, if not using the special image format, is an exact copy of the
+original NTFS filesystem from sector to sector thus it can be also mounted
+just like the original NTFS filesystem.
+For example if you clone to a file and the kernel has loopback device and
+NTFS support then the file can be mounted as
+.RS
+.sp
+.B   mount \-t ntfs \-o loop ntfsclone.img /mnt/ntfsclone
+.sp
+.RE
+.SS Windows Cloning
+If you want to copy, move or restore a system or boot partition to another 
+computer, or to a different disk or partition (e.g. hda1\->hda2, hda1\->hdb1
+or to a different disk sector offset) then you will need to take extra care.
+
+Usually, Windows will not be able to boot, unless you copy, move or restore 
+NTFS to the same partition which starts at the same sector on the same type 
+of disk having the same BIOS legacy cylinder setting as the original 
+partition and disk had.
+
+The ntfsclone utility guarantees to make an exact copy of NTFS but it 
+won't deal with booting issues. This is by design: ntfsclone is a 
+filesystem, not system utility. Its aim is only NTFS cloning, not Windows 
+cloning. Hereby ntfsclone can be used as a very fast and reliable 
+build block for Windows cloning but itself it's not enough.
+.SS Sparse Files
+A file is sparse if it has unallocated blocks (holes). The reported size of
+such files are always higher than the disk space consumed by them.  The
+.BR du
+command can tell the real disk space used by a sparse file.
+The holes are always read as zeros. All major Linux filesystem like,
+ext2, ext3, reiserfs, Reiser4, JFS and XFS, supports
+sparse files but for example the ISO 9600 CD\-ROM filesystem doesn't.
+.SS Handling Large Sparse Files
+As of today Linux provides inadequate support for managing (tar,
+cp, gzip, gunzip, bzip2, bunzip2, cat, etc) large sparse files.
+The only main Linux filesystem
+having support for efficient sparse file handling is XFS by the
+XFS_IOC_GETBMAPX
+.BR ioctl (2) .
+However none of the common utilities supports it.
+This means when you tar, cp, gzip, bzip2, etc a large sparse file
+they will always read the entire file, even if you use the "sparse support"
+options.
+
+.BR bzip2 (1)
+compresses large sparse files much better than
+.BR gzip (1)
+but it does so
+also much slower. Moreover neither of them handles large sparse
+files efficiently during uncompression from disk space usage point
+of view.
+
+At present the most efficient way, both speed and space\-wise, to
+compress and uncompress large sparse files by common tools
+would be using
+.BR tar (1)
+with the options
+.B \-S
+(handle sparse files "efficiently") and
+.B \-j
+(filter the archive through bzip2). Although
+.BR tar
+still reads and analyses the entire file, it doesn't pass on the
+large data blocks having only zeros to filters and it also avoids
+writing large amount of zeros to the disk needlessly. But since
+.BR tar
+can't create an archive from the standard input, you can't do this
+in\-place by just reading
+.BR ntfsclone
+standard output. Even more sadly, using the \-S option results 
+serious data loss since the end of 2004 and the GNU
+.BR tar
+maintainers didn't release fixed versions until the present day.
+.SS The Special Image Format
+It's also possible, actually it's recommended, to save an NTFS filesystem
+to a special image format.
+Instead of representing unallocated blocks as holes, they are
+encoded using control codes. Thus, the image saves space without
+requiring sparse file support. The image format is ideal for streaming
+filesystem images over the network and similar, and can be used as a
+replacement for Ghost or Partition Image if it is combined with other
+tools. The downside is that you can't mount the image directly, you
+need to restore it first.
+
+To save an image using the special image format, use the
+.B \-s
+or the
+.B \-\-save\-image
+option. To restore an image, use the
+.B \-r
+or the
+.B \-\-restore\-image
+option. Note that you can restore images from standard input by
+using '\-' as the
+.I SOURCE
+file.
+.SS Metadata\-only Cloning
+One of the features of
+.BR ntfsclone
+is that, it can also save only the NTFS metadata using the option
+.B \-m
+or
+.B \-\-metadata
+and the clone still will be
+mountable. In this case all non\-metadata file content will be lost and
+reading them back will result always zeros.
+
+The metadata\-only image can be compressed very
+well, usually to not more than 1\-8 MB thus it's easy to transfer
+for investigation, troubleshooting.
+
+In this mode of ntfsclone,
+.B NONE
+of the user's data is saved, including the resident user's data
+embedded into metadata. All is filled with zeros.
+Moreover all the file timestamps, deleted and unused spaces inside
+the metadata are filled with zeros. Thus this mode is inappropriate
+for example for forensic analyses.
+This mode may be combined with \fB\-\-save\-image\fP to create a
+special image format file instead of a sparse file.
+
+Please note, filenames are not wiped out. They might contain
+sensitive information, so think twice before sending such an
+image to anybody.
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfsclone
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.B \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.B "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-o\fR, \fB\-\-output\fR FILE
+Clone NTFS to the non\-existent
+.IR FILE .
+If
+.I FILE
+is '\-' then clone to the
+standard output.
+.TP
+\fB\-O\fR, \fB\-\-overwrite\fR FILE
+Clone NTFS to
+.IR FILE ,
+overwriting if exists.
+.TP
+\fB\-s\fR, \fB\-\-save\-image\fR
+Save to the special image format. This is the most efficient way space and
+speed\-wise if imaging is done to the standard output, e.g. for image
+compression, encryption or streaming through a network.
+.TP
+\fB\-r\fR, \fB\-\-restore\-image\fR
+Restore from the special image format specified by
+.I SOURCE
+argument. If the
+.I SOURCE
+is '\-' then the image is read from the standard input.
+.TP
+\fB\-n\fR, \fB\-\-no\-action\fR
+Test the consistency of a saved image by simulating its restoring without
+writing anything. The NTFS data contained in the image is not tested.
+The option \fB\-\-restore\-image\fR must also be present, and the options
+\fB\-\-output\fR and \fB\-\-overwrite\fR must be omitted.
+.TP
+\fB\-\-rescue\fR
+Ignore disk read errors so disks having bad sectors, e.g. dying disks, can be
+rescued the most efficiently way, with minimal stress on them. Ntfsclone works
+at the lowest, sector level in this mode too thus more data can be rescued.
+The contents of the unreadable sectors are filled by character '?' and the
+beginning of such sectors are marked by "BadSectoR\\0".
+.TP
+\fB\-m\fR, \fB\-\-metadata\fR
+Clone
+.B ONLY METADATA
+(for NTFS experts). Only cloning to a (sparse) file is allowed, unless used
+the option \fB\-\-save\-image\fP is also used.
+You can't metadata\-only clone to a device.
+.TP
+\fB\-\-ignore\-fs\-check\fR
+Ignore the result of the filesystem consistency check. This option is allowed
+to be used only with the
+.B \-\-metadata
+option, for the safety of user's data. The clusters which cause the
+inconsistency are saved too.
+.TP
+\fB\-t\fR, \fB\-\-preserve\-timestamps\fR
+Do not wipe the timestamps, to be used only with the
+.B \-\-metadata
+option.
+
+
+.TP
+\fB\-\-new\-serial\fR, or
+.TP
+\fB\-\-new\-half\-serial\fR
+Set a new random serial number to the clone. The serial number is a 64
+bit number used to identify the device during the mounting process, so
+it has to be changed to enable the original file system
+and the clone to be mounted at the same time on the same computer.
+
+The option \fB\-\-new\-half\-serial\fP only changes the upper part of the
+serial number, keeping the lower part which is used by Windows unchanged.
+
+The options \fB\-\-new\-serial\fP and \fB\-\-new\-half\-serial\fP can
+only be used when cloning a file system of restoring from an image.
+
+The serial number is not the volume UUID used by Windows
+to locate files which have been moved to another volume.
+
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+Forces ntfsclone to proceed if the filesystem is marked
+"dirty" for consistency check.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Do not display any progress-bars during operation.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.SH EXIT CODES
+The exit code is 0 on success, non\-zero otherwise.
+.SH EXAMPLES
+Clone NTFS on /dev/hda1 to /dev/hdc1:
+.RS
+.sp
+.B ntfsclone \-\-overwrite /dev/hdc1 /dev/hda1
+.sp
+.RE
+Save an NTFS to a file in the special image format:
+.RS
+.sp
+.B ntfsclone \-\-save\-image \-\-output backup.img /dev/hda1
+.sp
+.RE
+Restore an NTFS from a special image file to its original partition:
+.RS
+.sp
+.B ntfsclone \-\-restore\-image \-\-overwrite /dev/hda1 backup.img
+.sp
+.RE
+Save an NTFS into a compressed image file:
+.RS
+.sp
+.B ntfsclone \-\-save\-image \-o \- /dev/hda1 | gzip \-c > backup.img.gz
+.sp
+.RE
+Restore an NTFS volume from a compressed image file:
+.RS
+.sp
+.B gunzip \-c backup.img.gz | \\\\
+.br
+.B ntfsclone \-\-restore\-image \-\-overwrite /dev/hda1 \-
+.sp
+.RE
+Backup an NTFS volume to a remote host, using ssh. Please note, that 
+ssh may ask for a password!
+.RS
+.sp
+.B ntfsclone \-\-save\-image \-\-output \- /dev/hda1 | \\\\
+.br
+.B gzip \-c | ssh host 'cat > backup.img.gz'
+.sp
+.RE
+Restore an NTFS volume from a remote host via ssh. Please note, that 
+ssh may ask for a password!
+.RS
+.sp
+.B ssh host 'cat backup.img.gz' | gunzip \-c | \\\\
+.br
+.B ntfsclone \-\-restore\-image \-\-overwrite /dev/hda1 \-
+.sp
+.RE
+Stream an image file from a web server and restore it to a partition:
+.RS
+.sp
+.B wget \-qO \- http://server/backup.img | \\\\
+.br
+.B ntfsclone \-\-restore\-image \-\-overwrite /dev/hda1 \-
+.sp
+.RE
+Clone an NTFS volume to a non\-existent file:
+.RS
+.sp
+.B ntfsclone \-\-output ntfs\-clone.img /dev/hda1
+.sp
+.RE
+Pack NTFS metadata for NTFS experts. Please note that bzip2 runs
+very long but results usually at least 10 times smaller archives 
+than gzip on a sparse file.
+.RS
+.sp
+.B ntfsclone \-\-metadata \-\-output ntfsmeta.img /dev/hda1
+.br
+.B bzip2 ntfsmeta.img
+.sp
+Or, outputting to a compressed image :
+.br
+.B ntfsclone \-mst \-\-output - /dev/hda1 | bzip2 > ntfsmeta.bz2
+.sp
+.RE
+Unpacking NTFS metadata into a sparse file:
+.RS
+.sp
+.B bunzip2 \-c ntfsmeta.img.bz2 | \\\\
+.br
+.B cp \-\-sparse=always /proc/self/fd/0 ntfsmeta.img
+.sp
+.RE
+.SH KNOWN ISSUES
+There are no known problems with
+.BR ntfsclone .
+If you think you have found a problem then please send an email describing it
+to the development team:
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.sp
+Sometimes it might appear ntfsclone froze if the clone is on ReiserFS
+and even CTRL\-C won't stop it. This is not a bug in ntfsclone, however
+it's due to ReiserFS being extremely inefficient creating large
+sparse files and not handling signals during this operation. This
+ReiserFS problem was improved in kernel 2.4.22.
+XFS, JFS and ext3 don't have this problem.
+.hy
+.SH AUTHORS
+.B ntfsclone
+was written by Szabolcs Szakacsits with contributions from Per Olofsson 
+(special image format support) and Anton Altaparmakov.
+It was ported to ntfs-3g by Erik Larsson and Jean-Pierre Andre.
+.SH AVAILABILITY
+.B ntfsclone
+is part of the
+.B ntfs-3g
+package and is available at:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR ntfsresize (8)
+.BR ntfsprogs (8)
+.BR xfs_copy (8)
+.BR debugreiserfs (8)
+.BR e2image (8)
diff --git a/ntfsprogs/ntfsclone.8.in b/ntfsprogs/ntfsclone.8.in
new file mode 100755
index 0000000000000000000000000000000000000000..d156634cd6897e9f05782dea7698dd165438e6e0
--- /dev/null
+++ b/ntfsprogs/ntfsclone.8.in
@@ -0,0 +1,392 @@
+.\" Copyright (c) 2003\-2005 Richard Russon.
+.\" Copyright (c) 2003\-2006 Szabolcs Szakacsits.
+.\" Copyright (c) 2004 Per Olofsson.
+.\" Copyright (c) 2010\-2013 Jean-Pierre Andre.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSCLONE 8 "February 2013" "ntfs-3g @VERSION@"
+.SH NAME
+ntfsclone \- Efficiently clone, image, restore or rescue an NTFS
+.SH SYNOPSIS
+.B ntfsclone
+[\fIOPTIONS\fR]
+.I SOURCE
+.br
+.B ntfsclone \-\-save\-image
+[\fIOPTIONS\fR]
+.I SOURCE
+.br
+.B ntfsclone \-\-restore\-image
+[\fIOPTIONS\fR]
+.I SOURCE
+.br
+.B ntfsclone \-\-metadata
+[\fIOPTIONS\fR]
+.I SOURCE
+.SH DESCRIPTION
+.B ntfsclone
+will efficiently clone (copy, save, backup, restore) or rescue an NTFS
+filesystem to a sparse file, image, device (partition) or standard output.
+It works at disk sector level and
+copies only the used data. Unused disk space becomes zero (cloning to
+sparse file), encoded with control codes (saving in special image format),
+left unchanged (cloning to a disk/partition) or
+filled with zeros (cloning to standard output).
+
+.B ntfsclone
+can be useful to make backups, an exact snapshot of an NTFS filesystem
+and restore it later on, or for developers to test NTFS read/write
+functionality, troubleshoot/investigate users' issues using the clone
+without the risk of destroying the original filesystem.
+
+The clone, if not using the special image format, is an exact copy of the
+original NTFS filesystem from sector to sector thus it can be also mounted
+just like the original NTFS filesystem.
+For example if you clone to a file and the kernel has loopback device and
+NTFS support then the file can be mounted as
+.RS
+.sp
+.B   mount \-t ntfs \-o loop ntfsclone.img /mnt/ntfsclone
+.sp
+.RE
+.SS Windows Cloning
+If you want to copy, move or restore a system or boot partition to another 
+computer, or to a different disk or partition (e.g. hda1\->hda2, hda1\->hdb1
+or to a different disk sector offset) then you will need to take extra care.
+
+Usually, Windows will not be able to boot, unless you copy, move or restore 
+NTFS to the same partition which starts at the same sector on the same type 
+of disk having the same BIOS legacy cylinder setting as the original 
+partition and disk had.
+
+The ntfsclone utility guarantees to make an exact copy of NTFS but it 
+won't deal with booting issues. This is by design: ntfsclone is a 
+filesystem, not system utility. Its aim is only NTFS cloning, not Windows 
+cloning. Hereby ntfsclone can be used as a very fast and reliable 
+build block for Windows cloning but itself it's not enough.
+.SS Sparse Files
+A file is sparse if it has unallocated blocks (holes). The reported size of
+such files are always higher than the disk space consumed by them.  The
+.BR du
+command can tell the real disk space used by a sparse file.
+The holes are always read as zeros. All major Linux filesystem like,
+ext2, ext3, reiserfs, Reiser4, JFS and XFS, supports
+sparse files but for example the ISO 9600 CD\-ROM filesystem doesn't.
+.SS Handling Large Sparse Files
+As of today Linux provides inadequate support for managing (tar,
+cp, gzip, gunzip, bzip2, bunzip2, cat, etc) large sparse files.
+The only main Linux filesystem
+having support for efficient sparse file handling is XFS by the
+XFS_IOC_GETBMAPX
+.BR ioctl (2) .
+However none of the common utilities supports it.
+This means when you tar, cp, gzip, bzip2, etc a large sparse file
+they will always read the entire file, even if you use the "sparse support"
+options.
+
+.BR bzip2 (1)
+compresses large sparse files much better than
+.BR gzip (1)
+but it does so
+also much slower. Moreover neither of them handles large sparse
+files efficiently during uncompression from disk space usage point
+of view.
+
+At present the most efficient way, both speed and space\-wise, to
+compress and uncompress large sparse files by common tools
+would be using
+.BR tar (1)
+with the options
+.B \-S
+(handle sparse files "efficiently") and
+.B \-j
+(filter the archive through bzip2). Although
+.BR tar
+still reads and analyses the entire file, it doesn't pass on the
+large data blocks having only zeros to filters and it also avoids
+writing large amount of zeros to the disk needlessly. But since
+.BR tar
+can't create an archive from the standard input, you can't do this
+in\-place by just reading
+.BR ntfsclone
+standard output. Even more sadly, using the \-S option results 
+serious data loss since the end of 2004 and the GNU
+.BR tar
+maintainers didn't release fixed versions until the present day.
+.SS The Special Image Format
+It's also possible, actually it's recommended, to save an NTFS filesystem
+to a special image format.
+Instead of representing unallocated blocks as holes, they are
+encoded using control codes. Thus, the image saves space without
+requiring sparse file support. The image format is ideal for streaming
+filesystem images over the network and similar, and can be used as a
+replacement for Ghost or Partition Image if it is combined with other
+tools. The downside is that you can't mount the image directly, you
+need to restore it first.
+
+To save an image using the special image format, use the
+.B \-s
+or the
+.B \-\-save\-image
+option. To restore an image, use the
+.B \-r
+or the
+.B \-\-restore\-image
+option. Note that you can restore images from standard input by
+using '\-' as the
+.I SOURCE
+file.
+.SS Metadata\-only Cloning
+One of the features of
+.BR ntfsclone
+is that, it can also save only the NTFS metadata using the option
+.B \-m
+or
+.B \-\-metadata
+and the clone still will be
+mountable. In this case all non\-metadata file content will be lost and
+reading them back will result always zeros.
+
+The metadata\-only image can be compressed very
+well, usually to not more than 1\-8 MB thus it's easy to transfer
+for investigation, troubleshooting.
+
+In this mode of ntfsclone,
+.B NONE
+of the user's data is saved, including the resident user's data
+embedded into metadata. All is filled with zeros.
+Moreover all the file timestamps, deleted and unused spaces inside
+the metadata are filled with zeros. Thus this mode is inappropriate
+for example for forensic analyses.
+This mode may be combined with \fB\-\-save\-image\fP to create a
+special image format file instead of a sparse file.
+
+Please note, filenames are not wiped out. They might contain
+sensitive information, so think twice before sending such an
+image to anybody.
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfsclone
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.B \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.B "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-o\fR, \fB\-\-output\fR FILE
+Clone NTFS to the non\-existent
+.IR FILE .
+If
+.I FILE
+is '\-' then clone to the
+standard output.
+.TP
+\fB\-O\fR, \fB\-\-overwrite\fR FILE
+Clone NTFS to
+.IR FILE ,
+overwriting if exists.
+.TP
+\fB\-s\fR, \fB\-\-save\-image\fR
+Save to the special image format. This is the most efficient way space and
+speed\-wise if imaging is done to the standard output, e.g. for image
+compression, encryption or streaming through a network.
+.TP
+\fB\-r\fR, \fB\-\-restore\-image\fR
+Restore from the special image format specified by
+.I SOURCE
+argument. If the
+.I SOURCE
+is '\-' then the image is read from the standard input.
+.TP
+\fB\-n\fR, \fB\-\-no\-action\fR
+Test the consistency of a saved image by simulating its restoring without
+writing anything. The NTFS data contained in the image is not tested.
+The option \fB\-\-restore\-image\fR must also be present, and the options
+\fB\-\-output\fR and \fB\-\-overwrite\fR must be omitted.
+.TP
+\fB\-\-rescue\fR
+Ignore disk read errors so disks having bad sectors, e.g. dying disks, can be
+rescued the most efficiently way, with minimal stress on them. Ntfsclone works
+at the lowest, sector level in this mode too thus more data can be rescued.
+The contents of the unreadable sectors are filled by character '?' and the
+beginning of such sectors are marked by "BadSectoR\\0".
+.TP
+\fB\-m\fR, \fB\-\-metadata\fR
+Clone
+.B ONLY METADATA
+(for NTFS experts). Only cloning to a (sparse) file is allowed, unless used
+the option \fB\-\-save\-image\fP is also used.
+You can't metadata\-only clone to a device.
+.TP
+\fB\-\-ignore\-fs\-check\fR
+Ignore the result of the filesystem consistency check. This option is allowed
+to be used only with the
+.B \-\-metadata
+option, for the safety of user's data. The clusters which cause the
+inconsistency are saved too.
+.TP
+\fB\-t\fR, \fB\-\-preserve\-timestamps\fR
+Do not wipe the timestamps, to be used only with the
+.B \-\-metadata
+option.
+
+
+.TP
+\fB\-\-new\-serial\fR, or
+.TP
+\fB\-\-new\-half\-serial\fR
+Set a new random serial number to the clone. The serial number is a 64
+bit number used to identify the device during the mounting process, so
+it has to be changed to enable the original file system
+and the clone to be mounted at the same time on the same computer.
+
+The option \fB\-\-new\-half\-serial\fP only changes the upper part of the
+serial number, keeping the lower part which is used by Windows unchanged.
+
+The options \fB\-\-new\-serial\fP and \fB\-\-new\-half\-serial\fP can
+only be used when cloning a file system of restoring from an image.
+
+The serial number is not the volume UUID used by Windows
+to locate files which have been moved to another volume.
+
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+Forces ntfsclone to proceed if the filesystem is marked
+"dirty" for consistency check.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Do not display any progress-bars during operation.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.SH EXIT CODES
+The exit code is 0 on success, non\-zero otherwise.
+.SH EXAMPLES
+Clone NTFS on /dev/hda1 to /dev/hdc1:
+.RS
+.sp
+.B ntfsclone \-\-overwrite /dev/hdc1 /dev/hda1
+.sp
+.RE
+Save an NTFS to a file in the special image format:
+.RS
+.sp
+.B ntfsclone \-\-save\-image \-\-output backup.img /dev/hda1
+.sp
+.RE
+Restore an NTFS from a special image file to its original partition:
+.RS
+.sp
+.B ntfsclone \-\-restore\-image \-\-overwrite /dev/hda1 backup.img
+.sp
+.RE
+Save an NTFS into a compressed image file:
+.RS
+.sp
+.B ntfsclone \-\-save\-image \-o \- /dev/hda1 | gzip \-c > backup.img.gz
+.sp
+.RE
+Restore an NTFS volume from a compressed image file:
+.RS
+.sp
+.B gunzip \-c backup.img.gz | \\\\
+.br
+.B ntfsclone \-\-restore\-image \-\-overwrite /dev/hda1 \-
+.sp
+.RE
+Backup an NTFS volume to a remote host, using ssh. Please note, that 
+ssh may ask for a password!
+.RS
+.sp
+.B ntfsclone \-\-save\-image \-\-output \- /dev/hda1 | \\\\
+.br
+.B gzip \-c | ssh host 'cat > backup.img.gz'
+.sp
+.RE
+Restore an NTFS volume from a remote host via ssh. Please note, that 
+ssh may ask for a password!
+.RS
+.sp
+.B ssh host 'cat backup.img.gz' | gunzip \-c | \\\\
+.br
+.B ntfsclone \-\-restore\-image \-\-overwrite /dev/hda1 \-
+.sp
+.RE
+Stream an image file from a web server and restore it to a partition:
+.RS
+.sp
+.B wget \-qO \- http://server/backup.img | \\\\
+.br
+.B ntfsclone \-\-restore\-image \-\-overwrite /dev/hda1 \-
+.sp
+.RE
+Clone an NTFS volume to a non\-existent file:
+.RS
+.sp
+.B ntfsclone \-\-output ntfs\-clone.img /dev/hda1
+.sp
+.RE
+Pack NTFS metadata for NTFS experts. Please note that bzip2 runs
+very long but results usually at least 10 times smaller archives 
+than gzip on a sparse file.
+.RS
+.sp
+.B ntfsclone \-\-metadata \-\-output ntfsmeta.img /dev/hda1
+.br
+.B bzip2 ntfsmeta.img
+.sp
+Or, outputting to a compressed image :
+.br
+.B ntfsclone \-mst \-\-output - /dev/hda1 | bzip2 > ntfsmeta.bz2
+.sp
+.RE
+Unpacking NTFS metadata into a sparse file:
+.RS
+.sp
+.B bunzip2 \-c ntfsmeta.img.bz2 | \\\\
+.br
+.B cp \-\-sparse=always /proc/self/fd/0 ntfsmeta.img
+.sp
+.RE
+.SH KNOWN ISSUES
+There are no known problems with
+.BR ntfsclone .
+If you think you have found a problem then please send an email describing it
+to the development team:
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.sp
+Sometimes it might appear ntfsclone froze if the clone is on ReiserFS
+and even CTRL\-C won't stop it. This is not a bug in ntfsclone, however
+it's due to ReiserFS being extremely inefficient creating large
+sparse files and not handling signals during this operation. This
+ReiserFS problem was improved in kernel 2.4.22.
+XFS, JFS and ext3 don't have this problem.
+.hy
+.SH AUTHORS
+.B ntfsclone
+was written by Szabolcs Szakacsits with contributions from Per Olofsson 
+(special image format support) and Anton Altaparmakov.
+It was ported to ntfs-3g by Erik Larsson and Jean-Pierre Andre.
+.SH AVAILABILITY
+.B ntfsclone
+is part of the
+.B ntfs-3g
+package and is available at:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR ntfsresize (8)
+.BR ntfsprogs (8)
+.BR xfs_copy (8)
+.BR debugreiserfs (8)
+.BR e2image (8)
diff --git a/ntfsprogs/ntfsclone.c b/ntfsprogs/ntfsclone.c
new file mode 100755
index 0000000000000000000000000000000000000000..1504c252a46e91d6d56a56d87b6499e9eedc8754
--- /dev/null
+++ b/ntfsprogs/ntfsclone.c
@@ -0,0 +1,2746 @@
+/**
+ * ntfsclone - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2003-2006 Szabolcs Szakacsits
+ * Copyright (c) 2004-2006 Anton Altaparmakov
+ * Copyright (c) 2010-2014 Jean-Pierre Andre
+ * Special image format support copyright (c) 2004 Per Olofsson
+ *
+ * Clone NTFS data and/or metadata to a sparse file, image, device or stdout.
+ *
+ * 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.
+ */
+
+#include "config.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_VFS_H
+#include <sys/vfs.h>
+#endif
+#ifdef HAVE_SYS_STATVFS_H
+#include <sys/statvfs.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
+#endif
+
+/*
+ * FIXME: ntfsclone do bad things about endians handling. Fix it and remove
+ * this note and define.
+ */
+#define NTFS_DO_NOT_CHECK_ENDIANS
+
+#include "debug.h"
+#include "types.h"
+#include "support.h"
+#include "endians.h"
+#include "bootsect.h"
+#include "device.h"
+#include "attrib.h"
+#include "mst.h"
+#include "volume.h"
+#include "mft.h"
+#include "bitmap.h"
+#include "inode.h"
+#include "index.h"
+#include "dir.h"
+#include "runlist.h"
+#include "ntfstime.h"
+#include "utils.h"
+/* #include "version.h" */
+#include "misc.h"
+
+#if defined(linux) && defined(_IO) && !defined(BLKGETSIZE)
+#define BLKGETSIZE	_IO(0x12,96)  /* Get device size in 512-byte blocks. */
+#endif
+#if defined(linux) && defined(_IOR) && !defined(BLKGETSIZE64)
+#define BLKGETSIZE64	_IOR(0x12,114,size_t)	/* Get device size in bytes. */
+#endif
+
+#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
+
+#if defined(__sun) | defined(HAVE_WINDOWS_H)
+#define NO_STATFS 1	/* statfs(2) and f_type are not universal */
+#endif
+
+#ifdef HAVE_WINDOWS_H
+/*
+ *		Replacements for functions which do not exist on Windows
+ */
+int setmode(int, int); /* from msvcrt.dll */
+
+#define getpid() (0)
+#define srandom(seed) srand(seed)
+#define random() rand()
+#define fsync(fd) (0)
+#define ioctl(fd,code,buf) (-1)
+#define ftruncate(fd, size) ntfs_device_win32_ftruncate(dev_out, size)
+#define BINWMODE "wb"
+#else
+#define BINWMODE "w"
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+static const char *EXEC_NAME = "ntfsclone";
+
+static const char *bad_sectors_warning_msg =
+"*************************************************************************\n"
+"* WARNING: The disk has one or more bad sectors. This means that damage *\n"
+"* has occurred on the disk surface, possibly caused by deterioration of *\n"
+"* the physical media, manufacturing faults or other reasons. The        *\n"
+"* reliability of the disk may stay stable or degrade fast.              *\n"
+"* Use the --rescue option to efficiently save as much data as possible! *\n"
+"*************************************************************************\n";
+
+static const char *dirty_volume_msg =
+"Volume '%s' is scheduled for a check or it was shutdown \n"
+"uncleanly. Please boot Windows or use the --force option to progress.\n";
+
+static struct {
+	int verbose;
+	int quiet;
+	int debug;
+	int force;
+	int overwrite;
+	int std_out;
+	int blkdev_out;		/* output file is block device */
+	int metadata;		/* metadata only cloning */
+	int no_action;		/* do not really restore */
+	int ignore_fs_check;
+	int rescue;
+	int save_image;
+	int new_serial;
+	int metadata_image;
+	int preserve_timestamps;
+	int restore_image;
+	char *output;
+	char *volume;
+#ifndef NO_STATFS
+	struct statfs stfs;
+#endif
+} opt;
+
+struct bitmap {
+	s64 size;
+	u8 *bm;
+};
+
+struct progress_bar {
+	u64 start;
+	u64 stop;
+	int resolution;
+	float unit;
+};
+
+typedef struct {
+	ntfs_inode *ni;			/* inode being processed */
+	ntfs_attr_search_ctx *ctx;	/* inode attribute being processed */
+	s64 inuse;			/* number of clusters in use */
+	int more_use;			/* possibly allocated clusters */
+	LCN current_lcn;
+} ntfs_walk_clusters_ctx;
+
+typedef int (ntfs_walk_op)(ntfs_inode *ni, void *data);
+
+struct ntfs_walk_cluster {
+	ntfs_walk_op *inode_op;		/* not implemented yet */
+	ntfs_walk_clusters_ctx *image;
+};
+
+
+static ntfs_volume *vol = NULL;
+static struct bitmap lcn_bitmap;
+
+static int fd_in;
+static int fd_out;
+static FILE *stream_out = (FILE*)NULL;
+struct ntfs_device *dev_out = (struct ntfs_device*)NULL;
+static FILE *msg_out = NULL;
+
+static int wipe = 0;
+static unsigned int nr_used_mft_records   = 0;
+static unsigned int wiped_unused_mft_data = 0;
+static unsigned int wiped_unused_mft      = 0;
+static unsigned int wiped_resident_data   = 0;
+static unsigned int wiped_timestamp_data  = 0;
+
+static le64 volume_serial_number; /* new random serial number */
+static u64 full_device_size; /* full size, including the backup boot sector */
+
+static BOOL image_is_host_endian = FALSE;
+
+#define IMAGE_MAGIC "\0ntfsclone-image"
+#define IMAGE_MAGIC_SIZE 16
+#define IMAGE_OFFSET_OFFSET 46 /* must be the same for all versions ! */
+#define IMAGE_HDR_ALIGN 8 /* alignment wanted after header */
+
+/* This is the first endianness safe format version. */
+#define NTFSCLONE_IMG_VER_MAJOR_ENDIANNESS_SAFE	10
+#define NTFSCLONE_IMG_VER_MINOR_ENDIANNESS_SAFE	0
+
+/*
+ * Set the version to 10.0 to avoid colisions with old ntfsclone which
+ * stupidly used the volume version as the image version...  )-:  I hope NTFS
+ * never reaches version 10.0 and if it does one day I hope no-one is using
+ * such an old ntfsclone by then...
+ *
+ * NOTE: Only bump the minor version if the image format and header are still
+ * backwards compatible.  Otherwise always bump the major version.  If in
+ * doubt, bump the major version.
+ *
+ * Moved to 10.1 : Alternate boot sector now saved. Still compatible.
+ */
+#define NTFSCLONE_IMG_VER_MAJOR	10
+#define NTFSCLONE_IMG_VER_MINOR	1
+
+enum { CMD_GAP, CMD_NEXT } ;
+
+/* All values are in little endian. */
+static struct image_hdr {
+	char magic[IMAGE_MAGIC_SIZE];
+	u8 major_ver;
+	u8 minor_ver;
+	/* the following is aligned dangerously (too late...) */
+	le32 cluster_size;
+	le64 device_size;
+	sle64 nr_clusters;
+	le64 inuse;
+	le32 offset_to_image_data;	/* From start of image_hdr. */
+} __attribute__((__packed__)) image_hdr;
+
+static int compare_bitmaps(struct bitmap *a, BOOL copy);
+
+#define NTFSCLONE_IMG_HEADER_SIZE_OLD	\
+		(offsetof(struct image_hdr, offset_to_image_data))
+
+#define NTFS_MBYTE (1000 * 1000)
+
+#define ERR_PREFIX   "ERROR"
+#define PERR_PREFIX  ERR_PREFIX "(%d): "
+#define NERR_PREFIX  ERR_PREFIX ": "
+
+#define LAST_METADATA_INODE	11
+
+#define NTFS_MAX_CLUSTER_SIZE	65536
+#define NTFS_SECTOR_SIZE	  512
+
+#define rounded_up_division(a, b) (((a) + (b - 1)) / (b))
+
+#define read_all(f, p, n)  io_all((f), (p), (n), 0)
+#define write_all(f, p, n) io_all((f), (p), (n), 1)
+
+__attribute__((format(printf, 1, 2)))
+static void Printf(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	vfprintf(msg_out, fmt, ap);
+	va_end(ap);
+	fflush(msg_out);
+}
+
+__attribute__((format(printf, 1, 2)))
+static void perr_printf(const char *fmt, ...)
+{
+	va_list ap;
+	int eo = errno;
+
+	Printf(PERR_PREFIX, eo);
+	va_start(ap, fmt);
+	vfprintf(msg_out, fmt, ap);
+	va_end(ap);
+	Printf(": %s\n", strerror(eo));
+	fflush(msg_out);
+}
+
+__attribute__((format(printf, 1, 2)))
+static void err_printf(const char *fmt, ...)
+{
+	va_list ap;
+
+	Printf(NERR_PREFIX);
+	va_start(ap, fmt);
+	vfprintf(msg_out, fmt, ap);
+	va_end(ap);
+	fflush(msg_out);
+}
+
+__attribute__((noreturn))
+__attribute__((format(printf, 1, 2)))
+static void err_exit(const char *fmt, ...)
+{
+	va_list ap;
+
+	Printf(NERR_PREFIX);
+	va_start(ap, fmt);
+	vfprintf(msg_out, fmt, ap);
+	va_end(ap);
+	fflush(msg_out);
+	if (vol)
+		ntfs_umount(vol,FALSE);
+	exit(1);
+}
+
+__attribute__((noreturn))
+__attribute__((format(printf, 1, 2)))
+static void perr_exit(const char *fmt, ...)
+{
+	va_list ap;
+	int eo = errno;
+
+	Printf(PERR_PREFIX, eo);
+	va_start(ap, fmt);
+	vfprintf(msg_out, fmt, ap);
+	va_end(ap);
+	Printf(": %s\n", strerror(eo));
+	fflush(msg_out);
+	if (vol)
+		ntfs_umount(vol,FALSE);
+	exit(1);
+}
+
+
+__attribute__((noreturn))
+static void usage(int ret)
+{
+	fprintf(stderr, "\nUsage: %s [OPTIONS] SOURCE\n"
+		"    Efficiently clone NTFS to a sparse file, image, device or standard output.\n"
+		"\n"
+		"    -o, --output FILE      Clone NTFS to the non-existent FILE\n"
+		"    -O, --overwrite FILE   Clone NTFS to FILE, overwriting if exists\n"
+		"    -s, --save-image       Save to the special image format\n"
+		"    -r, --restore-image    Restore from the special image format\n"
+		"        --rescue           Continue after disk read errors\n"
+		"    -m, --metadata         Clone *only* metadata (for NTFS experts)\n"
+		"    -n, --no-action        Test restoring, without outputting anything\n"
+		"        --ignore-fs-check  Ignore the filesystem check result\n"
+		"        --new-serial       Set a new serial number\n"
+		"        --new-half-serial  Set a partial new serial number\n"
+		"    -t, --preserve-timestamps Do not clear the timestamps\n"
+		"    -q, --quiet            Do not display any progress bars\n"
+		"    -f, --force            Force to progress (DANGEROUS)\n"
+		"    -h, --help             Display this help\n"
+#ifdef DEBUG
+		"    -d, --debug            Show debug information\n"
+#endif
+		"    -V, --version           Display version information\n"
+		"\n"
+		"    If FILE is '-' then send the image to the standard output. If SOURCE is '-'\n"
+		"    and --restore-image is used then read the image from the standard input.\n"
+		"\n", EXEC_NAME);
+	fprintf(stderr, "%s%s", ntfs_bugs, ntfs_home);
+	exit(ret);
+}
+
+/**
+ * version
+ */
+__attribute__((noreturn))
+static void version(void)
+{
+	fprintf(stderr,
+		   "Efficiently clone, image, restore or rescue an NTFS Volume.\n\n"
+		   "Copyright (c) 2003-2006 Szabolcs Szakacsits\n"
+		   "Copyright (c) 2004-2006 Anton Altaparmakov\n"
+		   "Copyright (c) 2010-2014 Jean-Pierre Andre\n\n");
+	fprintf(stderr, "%s\n%s%s", ntfs_gpl, ntfs_bugs, ntfs_home);
+	exit(0);
+}
+
+static void parse_options(int argc, char **argv)
+{
+	static const char *sopt = "-dfhmno:O:qrstV";
+	static const struct option lopt[] = {
+#ifdef DEBUG
+		{ "debug",	      no_argument,	 NULL, 'd' },
+#endif
+		{ "quiet",	      no_argument,	 NULL, 'q' },
+		{ "force",	      no_argument,	 NULL, 'f' },
+		{ "help",	      no_argument,	 NULL, 'h' },
+		{ "metadata",	      no_argument,	 NULL, 'm' },
+		{ "no-action",	      no_argument,	 NULL, 'n' },
+		{ "output",	      required_argument, NULL, 'o' },
+		{ "overwrite",	      required_argument, NULL, 'O' },
+		{ "restore-image",    no_argument,	 NULL, 'r' },
+		{ "ignore-fs-check",  no_argument,	 NULL, 'C' },
+		{ "rescue",           no_argument,	 NULL, 'R' },
+		{ "new-serial",       no_argument,	 NULL, 'I' },
+		{ "new-half-serial",  no_argument,	 NULL, 'i' },
+		{ "save-image",	      no_argument,	 NULL, 's' },
+		{ "preserve-timestamps",   no_argument,  NULL, 't' },
+		{ "version",	      no_argument,	 NULL, 'V' },
+		{ NULL, 0, NULL, 0 }
+	};
+
+	int c;
+
+	memset(&opt, 0, sizeof(opt));
+
+	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
+		switch (c) {
+		case 1:	/* A non-option argument */
+			if (opt.volume)
+				usage(1);
+			opt.volume = argv[optind-1];
+			break;
+		case 'd':
+			opt.debug++;
+			break;
+		case 'q':
+			opt.quiet++;
+			break;
+		case 'f':
+			opt.force++;
+			break;
+		case 'h':
+			usage(0);
+		case '?':
+			usage(1);
+		case 'i':	/* not proposed as a short option */
+			opt.new_serial |= 1;
+			break;
+		case 'I':	/* not proposed as a short option */
+			opt.new_serial |= 2;
+			break;
+		case 'm':
+			opt.metadata++;
+			break;
+		case 'n':
+			opt.no_action++;
+			break;
+		case 'O':
+			opt.overwrite++;
+		case 'o':
+			if (opt.output)
+				usage(1);
+			opt.output = optarg;
+			break;
+		case 'r':
+			opt.restore_image++;
+			break;
+		case 'C':
+			opt.ignore_fs_check++;
+			break;
+		case 'R':
+			opt.rescue++;
+			break;
+		case 's':
+			opt.save_image++;
+			break;
+		case 't':
+			opt.preserve_timestamps++;
+			break;
+		case 'V':
+			version();
+			break;
+		default:
+			err_printf("Unknown option '%s'.\n", argv[optind-1]);
+			usage(1);
+		}
+	}
+
+	if (!opt.no_action && (opt.output == NULL)) {
+		err_printf("You must specify an output file.\n");
+		usage(1);
+	}
+
+	if (!opt.no_action && (strcmp(opt.output, "-") == 0))
+		opt.std_out++;
+
+	if (opt.volume == NULL) {
+		err_printf("You must specify a device file.\n");
+		usage(1);
+	}
+
+	if (!opt.restore_image && !strcmp(opt.volume, "-")) {
+		err_printf("Only special images can be read from standard input\n");
+		usage(1);
+	}
+
+	if (opt.metadata && opt.save_image) {
+		opt.metadata_image++;
+		opt.save_image = 0;
+	}
+
+	if (opt.metadata && opt.restore_image)
+		err_exit("Restoring only metadata from an image is not "
+			 "supported!\n");
+
+	if (opt.metadata && !opt.metadata_image && opt.std_out)
+		err_exit("Cloning only metadata to stdout isn't supported!\n");
+
+	if (opt.ignore_fs_check && !opt.metadata && !opt.rescue)
+		err_exit("Filesystem check can be ignored only for metadata "
+			 "cloning or rescue situations!\n");
+
+	if (opt.save_image && opt.restore_image)
+		err_exit("Saving and restoring an image at the same time "
+			 "is not supported!\n");
+
+	if (opt.no_action && !opt.restore_image)
+		err_exit("A restoring test requires the restore option!\n");
+
+	if (opt.no_action && opt.output)
+		err_exit("A restoring test requires not defining any output!\n");
+
+	if (!opt.no_action && !opt.std_out) {
+		struct stat st;
+#ifdef HAVE_WINDOWS_H
+		BOOL blkdev = opt.output[0] && (opt.output[1] == ':')
+					&& !opt.output[2];
+
+		if (!blkdev && (stat(opt.output, &st) == -1)) {
+#else
+		if (stat(opt.output, &st) == -1) {
+#endif
+			if (errno != ENOENT)
+				perr_exit("Couldn't access '%s'", opt.output);
+		} else {
+			if (!opt.overwrite)
+				err_exit("Output file '%s' already exists.\n"
+					 "Use option --overwrite if you want to"
+					 " replace its content.\n", opt.output);
+
+#ifdef HAVE_WINDOWS_H
+			if (blkdev) {
+#else
+			if (S_ISBLK(st.st_mode)) {
+#endif
+				opt.blkdev_out = 1;
+				if (opt.metadata && !opt.force)
+					err_exit("Cloning only metadata to a "
+					     "block device does not usually "
+					     "make sense, aborting...\n"
+					     "If you were instructed to do "
+					     "this by a developer and/or are "
+					     "sure that this is what you want "
+					     "to do, run this utility again "
+					     "but this time add the force "
+					     "option, i.e. add '--force' to "
+					     "the command line arguments.");
+			}
+		}
+	}
+
+	/*
+	 * Send messages, debug information and library messages to stdout,
+	 * but, if outputing to stdout send them to stderr
+	 */
+	if (opt.std_out) {
+		msg_out = stderr;
+		ntfs_log_set_handler(ntfs_log_handler_stderr);
+	} else {
+		msg_out = stdout;
+		ntfs_log_set_handler(ntfs_log_handler_outerr);
+	}
+}
+
+/*
+ * Initialize the random number generator with the current
+ * time, and generate a 64-bit random number for the serial
+ * number
+ */
+static void generate_serial_number(void) {
+	u64 sn;
+
+		/* different values for parallel processes */
+	srandom(time((time_t*)NULL) ^ (getpid() << 16));
+	sn = ((u64)random() << 32) | ((u64)random() & 0xffffffff);
+	volume_serial_number = cpu_to_le64(sn);
+}
+
+static void progress_init(struct progress_bar *p, u64 start, u64 stop, int res)
+{
+	p->start = start;
+	p->stop = stop;
+	p->unit = 100.0 / (stop - start);
+	p->resolution = res;
+}
+
+
+static void progress_update(struct progress_bar *p, u64 current)
+{
+	float percent = p->unit * current;
+
+	if (opt.quiet)
+		return;
+
+	if (current != p->stop) {
+		if ((current - p->start) % p->resolution)
+			return;
+		Printf("%6.2f percent completed\r", percent);
+	} else
+		Printf("100.00 percent completed\n");
+	fflush(msg_out);
+}
+
+static s64 is_critical_metadata(ntfs_walk_clusters_ctx *image, runlist *rl)
+{
+	s64 inode = image->ni->mft_no;
+
+	if (inode <= LAST_METADATA_INODE) {
+
+		/* Don't save bad sectors (both $Bad and unnamed are ignored */
+		if (inode == FILE_BadClus && image->ctx->attr->type == AT_DATA)
+			return 0;
+
+		if (inode != FILE_LogFile)
+			return rl->length;
+
+		if (image->ctx->attr->type == AT_DATA) {
+
+			/* Save at least the first 16 KiB of FILE_LogFile */
+			s64 s = (s64)16384 - rl->vcn * vol->cluster_size;
+			if (s > 0) {
+				s = rounded_up_division(s, vol->cluster_size);
+				if (rl->length < s)
+					s = rl->length;
+				return s;
+			}
+			return 0;
+		}
+	}
+
+	if (image->ctx->attr->type != AT_DATA)
+		return rl->length;
+
+	return 0;
+}
+
+static off_t tellin(int in)
+{
+	return (lseek(in, 0, SEEK_CUR));
+}
+
+static int io_all(void *fd, void *buf, int count, int do_write)
+{
+	int i;
+	struct ntfs_device *dev = fd;
+
+	while (count > 0) {
+		if (do_write) {
+			if (opt.no_action) {
+				i = count;
+			} else {
+				if (opt.save_image || opt.metadata_image)
+					i = fwrite(buf, 1, count, stream_out);
+#ifdef HAVE_WINDOWS_H
+				else if (dev_out)
+					i = dev_out->d_ops->write(dev_out,
+								buf, count);
+#endif
+				else
+					i = write(*(int *)fd, buf, count);
+			}
+		} else if (opt.restore_image)
+			i = read(*(int *)fd, buf, count);
+		else
+			i = dev->d_ops->read(dev, buf, count);
+		if (i < 0) {
+			if (errno != EAGAIN && errno != EINTR)
+				return -1;
+		} else if (i == 0 && !do_write && opt.restore_image) {
+			return -1;
+		} else {
+			count -= i;
+			buf = i + (char *) buf;
+		}
+	}
+	return 0;
+}
+
+
+static void rescue_sector(void *fd, u32 bytes_per_sector, off_t pos, void *buff)
+{
+	const char badsector_magic[] = "BadSectoR";
+	struct ntfs_device *dev = fd;
+
+	if (opt.restore_image) {
+		if (!opt.no_action
+		    && (lseek(*(int *)fd, pos, SEEK_SET) == (off_t)-1))
+			perr_exit("lseek");
+	} else {
+		if (vol->dev->d_ops->seek(dev, pos, SEEK_SET) == (off_t)-1)
+			perr_exit("seek input");
+	}
+
+	if (read_all(fd, buff, bytes_per_sector) == -1) {
+		Printf("WARNING: Can't read sector at %llu, lost data.\n",
+			(unsigned long long)pos);
+		memset(buff, '?', bytes_per_sector);
+		memmove(buff, badsector_magic, sizeof(badsector_magic));
+	}
+}
+
+/*
+ *		Read a cluster, try to rescue if cannot read
+ */
+
+static void read_rescue(void *fd, char *buff, u32 csize, u32 bytes_per_sector,
+				u64 rescue_lcn)
+{
+	off_t rescue_pos;
+
+	if (read_all(fd, buff, csize) == -1) {
+
+		if (errno != EIO)
+			perr_exit("read_all");
+		else if (opt.rescue){
+			u32 i;
+
+			rescue_pos = (off_t)(rescue_lcn * csize);
+			for (i = 0; i < csize; i += bytes_per_sector)
+				rescue_sector(fd, bytes_per_sector,
+						rescue_pos + i, buff + i);
+		} else {
+			Printf("%s", bad_sectors_warning_msg);
+			err_exit("Disk is faulty, can't make full backup!");
+		}
+	}
+}
+
+static void copy_cluster(int rescue, u64 rescue_lcn, u64 lcn)
+{
+	char buff[NTFS_MAX_CLUSTER_SIZE]; /* overflow checked at mount time */
+	/* vol is NULL if opt.restore_image is set */
+	s32 csize = le32_to_cpu(image_hdr.cluster_size);
+	BOOL backup_bootsector;
+	void *fd = (void *)&fd_in;
+	off_t rescue_pos;
+	NTFS_BOOT_SECTOR *bs;
+	le64 mask;
+	static u16 bytes_per_sector = NTFS_SECTOR_SIZE;
+
+	if (!opt.restore_image) {
+		csize = vol->cluster_size;
+		bytes_per_sector = vol->sector_size;
+		fd = vol->dev;
+	}
+
+	rescue_pos = (off_t)(rescue_lcn * csize);
+
+		/* possible partial cluster holding the backup boot sector */
+	backup_bootsector = (lcn + 1)*csize >= full_device_size;
+	if (backup_bootsector) {
+		csize = full_device_size - lcn*csize;
+		if (csize < 0) {
+			err_exit("Corrupted input, copy aborted");
+		}
+	}
+
+// need reading when not about to write ?
+	if (read_all(fd, buff, csize) == -1) {
+
+		if (errno != EIO) {
+			if (!errno && opt.restore_image)
+				err_exit("Short image file...\n");
+			else
+				perr_exit("read_all");
+		}
+		else if (rescue){
+			s32 i;
+			for (i = 0; i < csize; i += bytes_per_sector)
+				rescue_sector(fd, bytes_per_sector,
+						rescue_pos + i, buff + i);
+		} else {
+			Printf("%s", bad_sectors_warning_msg);
+			err_exit("Disk is faulty, can't make full backup!");
+		}
+	}
+
+		/* Set the new serial number if requested */
+	if (opt.new_serial
+	    && !opt.save_image
+	    && (!lcn || backup_bootsector)) {
+			/*
+			 * For updating the backup boot sector, we need to
+			 * know the sector size, but this is not recorded
+			 * in the image header, so we collect it on the fly
+			 * while reading the first boot sector.
+			 */
+		if (!lcn) {
+			bs = (NTFS_BOOT_SECTOR*)buff;
+			bytes_per_sector = le16_to_cpu(bs->bpb.bytes_per_sector);
+			if ((bytes_per_sector > csize)
+			    || (bytes_per_sector < NTFS_SECTOR_SIZE))
+				bytes_per_sector = NTFS_SECTOR_SIZE;
+		} else
+			bs = (NTFS_BOOT_SECTOR*)(buff
+						+ csize - bytes_per_sector);
+		if (opt.new_serial & 2)
+			bs->volume_serial_number = volume_serial_number;
+		else {
+			mask = const_cpu_to_le64(~0x0ffffffffULL);
+			bs->volume_serial_number
+			    = (volume_serial_number & mask)
+				| (bs->volume_serial_number & ~mask);
+		}
+			/* Show the new full serial after merging */
+		if (!lcn)
+			Printf("New serial number      : 0x%llx\n",
+				(long long)le64_to_cpu(
+						bs->volume_serial_number));
+	}
+
+	if (opt.save_image || (opt.metadata_image && wipe)) {
+		char cmd = CMD_NEXT;
+		if (write_all(&fd_out, &cmd, sizeof(cmd)) == -1)
+			perr_exit("write_all");
+	}
+
+	if ((!opt.metadata_image || wipe)
+	    && (write_all(&fd_out, buff, csize) == -1)) {
+#ifndef NO_STATFS
+		int err = errno;
+		perr_printf("Write failed");
+		if (err == EIO && opt.stfs.f_type == 0x517b)
+			Printf("Apparently you tried to clone to a remote "
+			       "Windows computer but they don't\nhave "
+			       "efficient sparse file handling by default. "
+			       "Please try a different method.\n");
+		exit(1);
+#else
+		perr_printf("Write failed");
+#endif
+	}
+}
+
+static s64 lseek_out(int fd, s64 pos, int mode)
+{
+	s64 ret;
+
+	if (dev_out)
+		ret = (dev_out->d_ops->seek)(dev_out, pos, mode);
+	else
+		ret = lseek(fd, pos, mode);
+	return (ret);
+}
+
+static void lseek_to_cluster(s64 lcn)
+{
+	off_t pos;
+
+	pos = (off_t)(lcn * vol->cluster_size);
+
+	if (vol->dev->d_ops->seek(vol->dev, pos, SEEK_SET) == (off_t)-1)
+		perr_exit("lseek input");
+
+	if (opt.std_out || opt.save_image || opt.metadata_image)
+		return;
+
+	if (lseek_out(fd_out, pos, SEEK_SET) == (off_t)-1)
+			perr_exit("lseek output");
+}
+
+static void gap_to_cluster(s64 gap)
+{
+	sle64 count;
+	char buf[1 + sizeof(count)];
+
+	if (gap) {
+		count = cpu_to_sle64(gap);
+		buf[0] = CMD_GAP;
+		memcpy(&buf[1], &count, sizeof(count));
+		if (write_all(&fd_out, buf, sizeof(buf)) == -1)
+			perr_exit("write_all");
+	}
+}
+
+static void image_skip_clusters(s64 count)
+{
+	if (opt.save_image && count > 0) {
+		s64 count_buf;
+		char buff[1 + sizeof(count)];
+
+		buff[0] = CMD_GAP;
+		count_buf = cpu_to_sle64(count);
+		memcpy(buff + 1, &count_buf, sizeof(count_buf));
+
+		if (write_all(&fd_out, buff, sizeof(buff)) == -1)
+			perr_exit("write_all");
+	}
+}
+
+static void write_image_hdr(void)
+{
+	char alignment[IMAGE_HDR_ALIGN];
+
+	if (opt.save_image || opt.metadata_image) {
+		int alignsize = le32_to_cpu(image_hdr.offset_to_image_data)
+				- sizeof(image_hdr);
+		memset(alignment,0,IMAGE_HDR_ALIGN);
+		if ((alignsize < 0)
+			|| write_all(&fd_out, &image_hdr, sizeof(image_hdr))
+			|| write_all(&fd_out, alignment, alignsize))
+			perr_exit("write_all");
+	}
+}
+
+static void clone_ntfs(u64 nr_clusters, int more_use)
+{
+	u64 cl, last_cl;  /* current and last used cluster */
+	void *buf;
+	u32 csize = vol->cluster_size;
+	u64 p_counter = 0;
+	char alignment[IMAGE_HDR_ALIGN];
+	struct progress_bar progress;
+
+	if (opt.save_image)
+		Printf("Saving NTFS to image ...\n");
+	else
+		Printf("Cloning NTFS ...\n");
+
+	if (opt.new_serial)
+		generate_serial_number();
+
+	buf = ntfs_calloc(csize);
+	if (!buf)
+		perr_exit("clone_ntfs");
+
+	progress_init(&progress, p_counter, nr_clusters, 100);
+
+	if (opt.save_image) {
+		int alignsize = le32_to_cpu(image_hdr.offset_to_image_data)
+				- sizeof(image_hdr);
+		memset(alignment,0,IMAGE_HDR_ALIGN);
+		if ((alignsize < 0)
+			|| write_all(&fd_out, &image_hdr, sizeof(image_hdr))
+			|| write_all(&fd_out, alignment, alignsize))
+			perr_exit("write_all");
+	}
+
+		/* save suspicious clusters if required */
+	if (more_use && opt.ignore_fs_check) {
+		compare_bitmaps(&lcn_bitmap, TRUE);
+	}
+		/* Examine up to the alternate boot sector */
+	for (last_cl = cl = 0; cl <= (u64)vol->nr_clusters; cl++) {
+
+		if (ntfs_bit_get(lcn_bitmap.bm, cl)) {
+			progress_update(&progress, ++p_counter);
+			lseek_to_cluster(cl);
+			image_skip_clusters(cl - last_cl - 1);
+
+			copy_cluster(opt.rescue, cl, cl);
+			last_cl = cl;
+			continue;
+		}
+
+		if (opt.std_out && !opt.save_image) {
+			progress_update(&progress, ++p_counter);
+			if (write_all(&fd_out, buf, csize) == -1)
+				perr_exit("write_all");
+		}
+	}
+	image_skip_clusters(cl - last_cl - 1);
+	free(buf);
+}
+
+static void write_empty_clusters(s32 csize, s64 count,
+				 struct progress_bar *progress, u64 *p_counter)
+{
+	s64 i;
+	char buff[NTFS_MAX_CLUSTER_SIZE];
+
+	memset(buff, 0, csize);
+
+	for (i = 0; i < count; i++) {
+		if (write_all(&fd_out, buff, csize) == -1)
+			perr_exit("write_all");
+		progress_update(progress, ++(*p_counter));
+	}
+}
+
+static void restore_image(void)
+{
+	s64 pos = 0, count;
+	s32 csize = le32_to_cpu(image_hdr.cluster_size);
+	char cmd;
+	u64 p_counter = 0;
+	struct progress_bar progress;
+
+	Printf("Restoring NTFS from image ...\n");
+
+	progress_init(&progress, p_counter, opt.std_out ?
+		      sle64_to_cpu(image_hdr.nr_clusters) + 1 :
+		      sle64_to_cpu(image_hdr.inuse) + 1,
+		      100);
+
+	if (opt.new_serial)
+		generate_serial_number();
+
+		/* Restore up to the alternate boot sector */
+	while (pos <= sle64_to_cpu(image_hdr.nr_clusters)) {
+		if (read_all(&fd_in, &cmd, sizeof(cmd)) == -1) {
+			if (pos == sle64_to_cpu(image_hdr.nr_clusters)) {
+				/* alternate boot sector no present in old images */
+				Printf("Warning : no alternate boot"
+						" sector in image\n");
+				break;
+			} else
+				perr_exit("read_all");
+		}
+
+		if (cmd == CMD_GAP) {
+			if (!image_is_host_endian) {
+				le64 lecount;
+
+				/* little endian image, on any computer */
+				if (read_all(&fd_in, &lecount,
+						sizeof(lecount)) == -1)
+					perr_exit("read_all");
+				count = sle64_to_cpu(lecount);
+			} else {
+				/* big endian image on big endian computer */
+				if (read_all(&fd_in, &count,
+						sizeof(count)) == -1)
+					perr_exit("read_all");
+			}
+			if (!count)
+				err_exit("Bad offset at input location 0x%llx\n",
+					(long long)tellin(fd_in) - 9);
+			if (opt.std_out) {
+				if ((!p_counter && count) || (count < 0))
+					err_exit("Cannot restore a metadata"
+						" image to stdout\n");
+				else
+					write_empty_clusters(csize, count,
+						     &progress, &p_counter);
+			} else {
+				if (((pos + count) < 0)
+				   || ((pos + count)
+					> sle64_to_cpu(image_hdr.nr_clusters)))
+					err_exit("restore_image: corrupt image "
+						"at input offset %lld\n",
+						(long long)tellin(fd_in) - 9);
+				else {
+					if (!opt.no_action
+					    && (lseek_out(fd_out, count * csize,
+							SEEK_CUR) == (off_t)-1))
+						perr_exit("restore_image: lseek");
+				}
+			}
+			pos += count;
+		} else if (cmd == CMD_NEXT) {
+			copy_cluster(0, 0, pos);
+			pos++;
+			progress_update(&progress, ++p_counter);
+		} else
+			err_exit("Invalid command code %d at input offset 0x%llx\n",
+					cmd, (long long)tellin(fd_in) - 1);
+	}
+}
+
+static void wipe_index_entry_timestams(INDEX_ENTRY *e)
+{
+	static const struct timespec zero_time = { .tv_sec = 0, .tv_nsec = 0 };
+	le64 timestamp = timespec2ntfs(zero_time);
+
+	/* FIXME: can fall into infinite loop if corrupted */
+	while (!(e->ie_flags & INDEX_ENTRY_END)) {
+
+		e->key.file_name.creation_time = timestamp;
+		e->key.file_name.last_data_change_time = timestamp;
+		e->key.file_name.last_mft_change_time = timestamp;
+		e->key.file_name.last_access_time = timestamp;
+
+		wiped_timestamp_data += 32;
+
+		e = (INDEX_ENTRY *)((u8 *)e + le16_to_cpu(e->length));
+	}
+}
+
+static void wipe_index_allocation_timestamps(ntfs_inode *ni, ATTR_RECORD *attr)
+{
+	INDEX_ALLOCATION *indexa, *tmp_indexa;
+	INDEX_ENTRY *entry;
+	INDEX_ROOT *indexr;
+	u8 *bitmap, *byte;
+	int bit;
+	ntfs_attr *na;
+	ntfschar *name;
+	u32 name_len;
+
+	indexr = ntfs_index_root_get(ni, attr);
+	if (!indexr) {
+		perr_printf("Failed to read $INDEX_ROOT attribute of inode "
+			    "%lld", (long long)ni->mft_no);
+		return;
+	}
+
+	if (indexr->type != AT_FILE_NAME)
+		goto out_indexr;
+
+	name = (ntfschar *)((u8 *)attr + le16_to_cpu(attr->name_offset));
+	name_len = attr->name_length;
+
+	byte = bitmap = ntfs_attr_readall(ni, AT_BITMAP, name, name_len,
+						NULL);
+	if (!byte) {
+		perr_printf("Failed to read $BITMAP attribute");
+		goto out_indexr;
+	}
+
+	na = ntfs_attr_open(ni, AT_INDEX_ALLOCATION, name, name_len);
+	if (!na) {
+		perr_printf("Failed to open $INDEX_ALLOCATION attribute");
+		goto out_bitmap;
+	}
+
+	if (!na->data_size)
+		goto out_na;
+
+	tmp_indexa = indexa = ntfs_malloc(na->data_size);
+	if (!tmp_indexa)
+		goto out_na;
+
+	if (ntfs_attr_pread(na, 0, na->data_size, indexa) != na->data_size) {
+		perr_printf("Failed to read $INDEX_ALLOCATION attribute");
+		goto out_indexa;
+	}
+
+	bit = 0;
+	while ((u8 *)tmp_indexa < (u8 *)indexa + na->data_size) {
+		if (*byte & (1 << bit)) {
+			if (ntfs_mst_post_read_fixup((NTFS_RECORD *)tmp_indexa,
+					le32_to_cpu(
+					indexr->index_block_size))) {
+				perr_printf("Damaged INDX record");
+				goto out_indexa;
+			}
+			entry = (INDEX_ENTRY *)((u8 *)tmp_indexa + le32_to_cpu(
+				tmp_indexa->index.entries_offset) + 0x18);
+
+			wipe_index_entry_timestams(entry);
+
+			if (ntfs_mft_usn_dec((MFT_RECORD *)tmp_indexa))
+				perr_exit("ntfs_mft_usn_dec");
+
+			if (ntfs_mst_pre_write_fixup((NTFS_RECORD *)tmp_indexa,
+					le32_to_cpu(
+					indexr->index_block_size))) {
+				perr_printf("INDX write fixup failed");
+				goto out_indexa;
+			}
+		}
+		tmp_indexa = (INDEX_ALLOCATION *)((u8 *)tmp_indexa +
+				le32_to_cpu(indexr->index_block_size));
+		bit++;
+		if (bit > 7) {
+			bit = 0;
+			byte++;
+		}
+	}
+	if (ntfs_rl_pwrite(vol, na->rl, 0, 0, na->data_size, indexa) != na->data_size)
+		perr_printf("ntfs_rl_pwrite failed for inode %lld",
+				(long long)ni->mft_no);
+out_indexa:
+	free(indexa);
+out_na:
+	ntfs_attr_close(na);
+out_bitmap:
+	free(bitmap);
+out_indexr:
+	free(indexr);
+}
+
+static void wipe_index_root_timestamps(ATTR_RECORD *attr, le64 timestamp)
+{
+	INDEX_ENTRY *entry;
+	INDEX_ROOT *iroot;
+
+	iroot = (INDEX_ROOT *)((u8 *)attr + le16_to_cpu(attr->value_offset));
+	entry = (INDEX_ENTRY *)((u8 *)iroot +
+			le32_to_cpu(iroot->index.entries_offset) + 0x10);
+
+	while (!(entry->ie_flags & INDEX_ENTRY_END)) {
+
+		if (iroot->type == AT_FILE_NAME) {
+
+			entry->key.file_name.creation_time = timestamp;
+			entry->key.file_name.last_access_time = timestamp;
+			entry->key.file_name.last_data_change_time = timestamp;
+			entry->key.file_name.last_mft_change_time = timestamp;
+
+			wiped_timestamp_data += 32;
+
+		} else if (ntfs_names_are_equal(NTFS_INDEX_Q,
+				sizeof(NTFS_INDEX_Q) / 2 - 1,
+				(ntfschar *)((char *)attr +
+					    le16_to_cpu(attr->name_offset)),
+				attr->name_length, CASE_SENSITIVE, NULL, 0)) {
+
+			QUOTA_CONTROL_ENTRY *quota_q;
+
+			quota_q = (QUOTA_CONTROL_ENTRY *)((u8 *)entry +
+					le16_to_cpu(entry->data_offset));
+			/*
+			 *  FIXME: no guarantee it's indeed /$Extend/$Quota:$Q.
+			 *  For now, as a minimal safeguard, we check only for
+			 *  quota version 2 ...
+			 */
+			if (le32_to_cpu(quota_q->version) == 2) {
+				quota_q->change_time = timestamp;
+				wiped_timestamp_data += 4;
+			}
+		}
+
+		entry = (INDEX_ENTRY*)((u8*)entry + le16_to_cpu(entry->length));
+	}
+}
+
+#define WIPE_TIMESTAMPS(atype, attr, timestamp)			\
+do {								\
+	atype *ats;						\
+	ats = (atype *)((char *)(attr) + le16_to_cpu((attr)->value_offset)); \
+								\
+	ats->creation_time = (timestamp);	       		\
+	ats->last_data_change_time = (timestamp);		\
+	ats->last_mft_change_time= (timestamp);			\
+	ats->last_access_time = (timestamp);			\
+								\
+	wiped_timestamp_data += 32;				\
+								\
+} while (0)
+
+static void wipe_timestamps(ntfs_walk_clusters_ctx *image)
+{
+	static const struct timespec zero_time = { .tv_sec = 0, .tv_nsec = 0 };
+	ATTR_RECORD *a = image->ctx->attr;
+	le64 timestamp = timespec2ntfs(zero_time);
+
+	if (a->type == AT_FILE_NAME)
+		WIPE_TIMESTAMPS(FILE_NAME_ATTR, a, timestamp);
+
+	else if (a->type == AT_STANDARD_INFORMATION)
+		WIPE_TIMESTAMPS(STANDARD_INFORMATION, a, timestamp);
+
+	else if (a->type == AT_INDEX_ROOT)
+		wipe_index_root_timestamps(a, timestamp);
+}
+
+static void wipe_resident_data(ntfs_walk_clusters_ctx *image)
+{
+	ATTR_RECORD *a;
+	u32 i;
+	int n = 0;
+	u8 *p;
+
+	a = image->ctx->attr;
+	p = (u8*)a + le16_to_cpu(a->value_offset);
+
+	if (image->ni->mft_no <= LAST_METADATA_INODE)
+		return;
+
+	if (a->type != AT_DATA)
+		return;
+
+	for (i = 0; i < le32_to_cpu(a->value_length); i++) {
+		if (p[i]) {
+			p[i] = 0;
+			n++;
+		}
+	}
+
+	wiped_resident_data += n;
+}
+
+static int wipe_data(char *p, int pos, int len)
+{
+	int wiped = 0;
+
+	for (p += pos; --len >= 0;) {
+		if (p[len]) {
+			p[len] = 0;
+			wiped++;
+		}
+	}
+
+	return wiped;
+}
+
+static void wipe_unused_mft_data(ntfs_inode *ni)
+{
+	int unused;
+	MFT_RECORD *m = ni->mrec;
+
+	/* FIXME: broken MFTMirr update was fixed in libntfs, check if OK now */
+	if (ni->mft_no <= LAST_METADATA_INODE)
+		return;
+
+	unused = le32_to_cpu(m->bytes_allocated) - le32_to_cpu(m->bytes_in_use);
+	wiped_unused_mft_data += wipe_data((char *)m,
+			le32_to_cpu(m->bytes_in_use), unused);
+}
+
+static void wipe_unused_mft(ntfs_inode *ni)
+{
+	int unused;
+	MFT_RECORD *m = ni->mrec;
+
+	/* FIXME: broken MFTMirr update was fixed in libntfs, check if OK now */
+	if (ni->mft_no <= LAST_METADATA_INODE)
+		return;
+
+	unused = le32_to_cpu(m->bytes_in_use) - sizeof(MFT_RECORD);
+	wiped_unused_mft += wipe_data((char *)m, sizeof(MFT_RECORD), unused);
+}
+
+static void clone_logfile_parts(ntfs_walk_clusters_ctx *image, runlist *rl)
+{
+	s64 offset = 0, lcn, vcn;
+
+	while (1) {
+
+		vcn = offset / image->ni->vol->cluster_size;
+		lcn = ntfs_rl_vcn_to_lcn(rl, vcn);
+		if (lcn < 0)
+			break;
+
+		lseek_to_cluster(lcn);
+
+		if ((lcn + 1) != image->current_lcn) {
+			/* do not duplicate a cluster */
+			if (opt.metadata_image && wipe)
+				gap_to_cluster(lcn - image->current_lcn);
+
+			copy_cluster(opt.rescue, lcn, lcn);
+		}
+		image->current_lcn = lcn + 1;
+		if (opt.metadata_image && !wipe)
+			image->inuse++;
+
+		if (offset == 0)
+			offset = NTFS_BLOCK_SIZE >> 1;
+		else
+			offset <<= 1;
+	}
+}
+
+/*
+ *		In-memory wiping of MFT record or MFTMirr record
+ *	(only for metadata images)
+ *
+ *	The resident data and (optionally) the timestamps are wiped.
+ */
+
+static void wipe_mft(char *mrec, u32 mrecsz, u64 mft_no)
+{
+	ntfs_walk_clusters_ctx image;
+	ntfs_attr_search_ctx *ctx;
+	ntfs_inode ni;
+
+	ni.mft_no = mft_no;
+	ni.mrec = (MFT_RECORD*)mrec;
+	ni.vol = vol; /* Hmm */
+	image.ni = &ni;
+	ntfs_mst_post_read_fixup_warn((NTFS_RECORD*)mrec,mrecsz,FALSE);
+	wipe_unused_mft_data(&ni);
+	if (!(((MFT_RECORD*)mrec)->flags & MFT_RECORD_IN_USE)) {
+		wipe_unused_mft(&ni);
+	} else {
+			/* ctx with no ntfs_inode prevents from searching external attrs */
+		if (!(ctx = ntfs_attr_get_search_ctx((ntfs_inode*)NULL, (MFT_RECORD*)mrec)))
+			perr_exit("ntfs_get_attr_search_ctx");
+
+		while (!ntfs_attr_lookup(AT_UNUSED, NULL, 0, CASE_SENSITIVE, 0,
+						NULL, 0, ctx)) {
+			if (ctx->attr->type == AT_END)
+				break;
+
+			image.ctx = ctx;
+			if (!ctx->attr->non_resident
+			    && (mft_no > LAST_METADATA_INODE))
+				wipe_resident_data(&image);
+			if (!opt.preserve_timestamps)
+				wipe_timestamps(&image);
+		}
+		ntfs_attr_put_search_ctx(ctx);
+	}
+	ntfs_mft_usn_dec((MFT_RECORD*)mrec);
+	ntfs_mst_pre_write_fixup((NTFS_RECORD*)mrec,mrecsz);
+}
+
+/*
+ *		In-memory wiping of a directory record (I30)
+ *	(only for metadata images)
+ *
+ *	The timestamps are (optionally) wiped
+ */
+
+static void wipe_indx(char *mrec, u32 mrecsz)
+{
+	INDEX_ENTRY *entry;
+	INDEX_ALLOCATION *indexa;
+
+	if (ntfs_mst_post_read_fixup((NTFS_RECORD *)mrec, mrecsz)) {
+		perr_printf("Damaged INDX record");
+		goto out_indexa;
+	}
+	indexa = (INDEX_ALLOCATION*)mrec;
+		/*
+		 * The index bitmap is not checked, obsoleted records are
+		 * wiped if they pass the safety checks
+		 */
+	if ((indexa->magic == magic_INDX)
+	    && (le32_to_cpu(indexa->index.entries_offset) >= sizeof(INDEX_HEADER))
+	    && (le32_to_cpu(indexa->index.allocated_size) <= mrecsz)) {
+		entry = (INDEX_ENTRY *)((u8 *)mrec + le32_to_cpu(
+				indexa->index.entries_offset) + 0x18);
+		wipe_index_entry_timestams(entry);
+	}
+
+	if (ntfs_mft_usn_dec((MFT_RECORD *)mrec))
+		perr_exit("ntfs_mft_usn_dec");
+
+	if (ntfs_mst_pre_write_fixup((NTFS_RECORD *)mrec, mrecsz)) {
+		perr_printf("INDX write fixup failed");
+		goto out_indexa;
+	}
+out_indexa : ;
+}
+
+/*
+ *		Output a set of related clusters (MFT record or index block)
+ */
+
+static void write_set(char *buff, u32 csize, s64 *current_lcn,
+			runlist_element *rl, u32 wi, u32 wj, u32 cnt)
+{
+	u32 k;
+	s64 target_lcn;
+	char cmd = CMD_NEXT;
+
+	for (k=0; k<cnt; k++) {
+		target_lcn = rl[wi].lcn + wj;
+		if (target_lcn != *current_lcn)
+			gap_to_cluster(target_lcn - *current_lcn);
+		if ((write_all(&fd_out, &cmd, sizeof(cmd)) == -1)
+		    || (write_all(&fd_out, &buff[k*csize], csize) == -1))
+			perr_exit("Failed to write_all");
+		*current_lcn = target_lcn + 1;
+			
+		if (++wj >= rl[wi].length) {
+			wj = 0;
+			wi++;
+		}
+	}
+}
+
+/*
+ *		Copy and wipe the full MFT or MFTMirr data.
+ *	(only for metadata images)
+ *
+ *	Data are read and written by full clusters, but the wiping is done
+ *	per MFT record.
+ */
+
+static void copy_wipe_mft(ntfs_walk_clusters_ctx *image, runlist *rl)
+{
+	char buff[NTFS_MAX_CLUSTER_SIZE]; /* overflow checked at mount time */
+	void *fd;
+	s64 mft_no;
+	u32 mft_record_size;
+	u32 csize;
+	u32 bytes_per_sector;
+	u32 records_per_set;
+	u32 clusters_per_set;
+	u32 wi,wj; /* indexes for reading */
+	u32 ri,rj; /* indexes for writing */
+	u32 k; /* lcn within run */
+	u32 r; /* mft_record within set */
+	s64 current_lcn;
+
+	current_lcn = image->current_lcn;
+	mft_record_size = image->ni->vol->mft_record_size;
+	csize = image->ni->vol->cluster_size;
+	bytes_per_sector = image->ni->vol->sector_size;
+	fd = image->ni->vol->dev;
+		/*
+		 * Depending on the sizes, there may be several records
+		 * per cluster, or several clusters per record.
+		 */
+	if (csize >= mft_record_size) {
+		records_per_set = csize/mft_record_size;
+		clusters_per_set = 1;
+	} else {
+		clusters_per_set = mft_record_size/csize;
+		records_per_set = 1;
+	}
+	mft_no = 0;
+	ri = rj = 0;
+	wi = wj = 0;
+	if (rl[ri].length)
+		lseek_to_cluster(rl[ri].lcn);
+	while (rl[ri].length) {
+		for (k=0; (k<clusters_per_set) && rl[ri].length; k++) {
+			read_rescue(fd, &buff[k*csize], csize, bytes_per_sector,
+							rl[ri].lcn + rj);
+			if (++rj >= rl[ri].length) {
+				rj = 0;
+				if (rl[++ri].length)
+					lseek_to_cluster(rl[ri].lcn);
+			}
+		}
+		if (k == clusters_per_set) {
+			for (r=0; r<records_per_set; r++) {
+				if (!strncmp(&buff[r*mft_record_size],"FILE",4))
+					wipe_mft(&buff[r*mft_record_size],
+						mft_record_size, mft_no);
+				mft_no++;
+			}
+			write_set(buff, csize, &current_lcn,
+					rl, wi, wj, clusters_per_set);
+			wj += clusters_per_set;
+			while (rl[wi].length && (wj >= rl[wi].length))
+				wj -= rl[wi++].length;
+		} else {
+			err_exit("Short last MFT record\n");
+		}
+	}
+	image->current_lcn = current_lcn;
+}
+
+/*
+ *		Copy and wipe the non-resident part of a directory index
+ *	(only for metadata images)
+ *
+ *	Data are read and written by full clusters, but the wiping is done
+ *	per index record.
+ */
+
+static void copy_wipe_i30(ntfs_walk_clusters_ctx *image, runlist *rl)
+{
+	char buff[NTFS_MAX_CLUSTER_SIZE]; /* overflow checked at mount time */
+	void *fd;
+	u32 indx_record_size;
+	u32 csize;
+	u32 bytes_per_sector;
+	u32 records_per_set;
+	u32 clusters_per_set;
+	u32 wi,wj; /* indexes for reading */
+	u32 ri,rj; /* indexes for writing */
+	u32 k; /* lcn within run */
+	u32 r; /* mft_record within set */
+	s64 current_lcn;
+
+	current_lcn = image->current_lcn;
+	csize = image->ni->vol->cluster_size;
+	bytes_per_sector = image->ni->vol->sector_size;
+	fd = image->ni->vol->dev;
+		/*
+		 * Depending on the sizes, there may be several records
+		 * per cluster, or several clusters per record.
+		 */
+	indx_record_size = image->ni->vol->indx_record_size;
+	if (csize >= indx_record_size) {
+		records_per_set = csize/indx_record_size;
+		clusters_per_set = 1;
+	} else {
+		clusters_per_set = indx_record_size/csize;
+		records_per_set = 1;
+	}
+	ri = rj = 0;
+	wi = wj = 0;
+	if (rl[ri].length)
+		lseek_to_cluster(rl[ri].lcn);
+	while (rl[ri].length) {
+		for (k=0; (k<clusters_per_set) && rl[ri].length; k++) {
+			read_rescue(fd, &buff[k*csize], csize, bytes_per_sector,
+							rl[ri].lcn + rj);
+			if (++rj >= rl[ri].length) {
+				rj = 0;
+				if (rl[++ri].length)
+					lseek_to_cluster(rl[ri].lcn);
+			}
+		}
+		if (k == clusters_per_set) {
+			/* wipe records_per_set records */
+			if (!opt.preserve_timestamps)
+				for (r=0; r<records_per_set; r++) {
+					if (!strncmp(&buff[r*indx_record_size],"INDX",4))
+						wipe_indx(&buff[r*indx_record_size],
+							indx_record_size);
+				}
+			write_set(buff, csize, &current_lcn,
+					rl, wi, wj, clusters_per_set);
+			wj += clusters_per_set;
+			while (rl[wi].length && (wj >= rl[wi].length))
+				wj -= rl[wi++].length;
+		} else {
+			err_exit("Short last directory index record\n");
+		}
+	}
+	image->current_lcn = current_lcn;
+}
+
+static void dump_clusters(ntfs_walk_clusters_ctx *image, runlist *rl)
+{
+	s64 i, len; /* number of clusters to copy */
+
+	if (opt.restore_image)
+		err_exit("Bug : invalid dump_clusters()\n");
+
+	if ((opt.std_out && !opt.metadata_image) || !opt.metadata)
+		return;
+	if (!(len = is_critical_metadata(image, rl)))
+		return;
+
+	lseek_to_cluster(rl->lcn);
+	if (opt.metadata_image ? wipe : !wipe) {
+		if (opt.metadata_image)
+			gap_to_cluster(rl->lcn - image->current_lcn);
+		/* FIXME: this could give pretty suboptimal performance */
+		for (i = 0; i < len; i++)
+			copy_cluster(opt.rescue, rl->lcn + i, rl->lcn + i);
+		if (opt.metadata_image)
+			image->current_lcn = rl->lcn + len;
+	}
+}
+
+static void walk_runs(struct ntfs_walk_cluster *walk)
+{
+	int i, j;
+	runlist *rl;
+	ATTR_RECORD *a;
+	ntfs_attr_search_ctx *ctx;
+	BOOL mft_data;
+	BOOL index_i30;
+
+	ctx = walk->image->ctx;
+	a = ctx->attr;
+
+	if (!a->non_resident) {
+		if (wipe) {
+			wipe_resident_data(walk->image);
+			if (!opt.preserve_timestamps)
+				wipe_timestamps(walk->image);
+		}
+		return;
+	}
+
+	if (wipe
+	    && !opt.preserve_timestamps
+	    && walk->image->ctx->attr->type == AT_INDEX_ALLOCATION)
+		wipe_index_allocation_timestamps(walk->image->ni, a);
+
+	if (!(rl = ntfs_mapping_pairs_decompress(vol, a, NULL)))
+		perr_exit("ntfs_decompress_mapping_pairs");
+
+		/* special wipings for MFT records and directory indexes */
+	mft_data = ((walk->image->ni->mft_no == FILE_MFT)
+			|| (walk->image->ni->mft_no == FILE_MFTMirr))
+		    && (a->type == AT_DATA);
+	index_i30 = (walk->image->ctx->attr->type == AT_INDEX_ALLOCATION)
+		    && (a->name_length == 4)
+		    && !memcmp((char*)a + le16_to_cpu(a->name_offset),
+					NTFS_INDEX_I30,8);
+
+	for (i = 0; rl[i].length; i++) {
+		s64 lcn = rl[i].lcn;
+		s64 lcn_length = rl[i].length;
+
+		if (lcn == LCN_HOLE || lcn == LCN_RL_NOT_MAPPED)
+			continue;
+
+		/* FIXME: ntfs_mapping_pairs_decompress should return error */
+		if (lcn < 0 || lcn_length < 0)
+			err_exit("Corrupt runlist in inode %lld attr %x LCN "
+				 "%llx length %llx\n",
+				(long long)ctx->ntfs_ino->mft_no,
+				(unsigned int)le32_to_cpu(a->type),
+				(long long)lcn, (long long)lcn_length);
+
+		if (opt.metadata_image ? wipe && !mft_data && !index_i30 : !wipe)
+			dump_clusters(walk->image, rl + i);
+
+		for (j = 0; j < lcn_length; j++) {
+			u64 k = (u64)lcn + j;
+			if (ntfs_bit_get_and_set(lcn_bitmap.bm, k, 1))
+				err_exit("Cluster %llu referenced twice!\n"
+					 "You didn't shutdown your Windows "
+					 "properly?\n", (unsigned long long)k);
+		}
+
+		if (!opt.metadata_image)
+			walk->image->inuse += lcn_length;
+			/*
+			 * For a metadata image, we have to compute the
+			 * number of metadata clusters for the percentages
+			 * to be displayed correctly while restoring.
+			 */
+		if (!wipe && opt.metadata_image) {
+			if ((walk->image->ni->mft_no == FILE_LogFile)
+			    && (walk->image->ctx->attr->type == AT_DATA)) {
+					/* 16 KiB of FILE_LogFile */
+				walk->image->inuse
+				   += is_critical_metadata(walk->image,rl);
+			} else {
+				if ((walk->image->ni->mft_no
+						<= LAST_METADATA_INODE)
+				   || (walk->image->ctx->attr->type != AT_DATA))
+					walk->image->inuse += lcn_length;
+			}
+		}
+	}
+	if (wipe && opt.metadata_image) {
+		ntfs_attr *na;
+		/*
+		 * Non-resident metadata has to be wiped globally,
+		 * because its logical blocks may be larger than
+		 * a cluster and split over two extents.
+		 */
+		if (mft_data && !a->lowest_vcn) {
+			na = ntfs_attr_open(walk->image->ni,
+					AT_DATA, NULL, 0);
+			if (na) {
+				na->rl = rl;
+				rl = (runlist_element*)NULL;
+				if (!ntfs_attr_map_whole_runlist(na)) {
+					copy_wipe_mft(walk->image,na->rl);
+				} else
+					perr_exit("Failed to map data of inode %lld",
+						(long long)walk->image->ni->mft_no);
+				ntfs_attr_close(na);
+			} else
+				perr_exit("Failed to open data of inode %lld",
+					(long long)walk->image->ni->mft_no);
+		}
+		if (index_i30 && !a->lowest_vcn) {
+			na = ntfs_attr_open(walk->image->ni,
+					AT_INDEX_ALLOCATION, NTFS_INDEX_I30, 4);
+			if (na) {
+				na->rl = rl;
+				rl = (runlist_element*)NULL;
+				if (!ntfs_attr_map_whole_runlist(na)) {
+					copy_wipe_i30(walk->image,na->rl);
+				} else
+					perr_exit("Failed to map index of inode %lld",
+						(long long)walk->image->ni->mft_no);
+				ntfs_attr_close(na);
+			} else
+				perr_exit("Failed to open index of inode %lld",
+					(long long)walk->image->ni->mft_no);
+		}
+	}
+	if (opt.metadata
+	    && (opt.metadata_image || !wipe)
+	    && (walk->image->ni->mft_no == FILE_LogFile)
+	    && (walk->image->ctx->attr->type == AT_DATA))
+		clone_logfile_parts(walk->image, rl);
+
+	free(rl);
+}
+
+
+static void walk_attributes(struct ntfs_walk_cluster *walk)
+{
+	ntfs_attr_search_ctx *ctx;
+
+	if (!(ctx = ntfs_attr_get_search_ctx(walk->image->ni, NULL)))
+		perr_exit("ntfs_get_attr_search_ctx");
+
+	while (!ntfs_attrs_walk(ctx)) {
+		if (ctx->attr->type == AT_END)
+			break;
+
+		walk->image->ctx = ctx;
+		walk_runs(walk);
+	}
+
+	ntfs_attr_put_search_ctx(ctx);
+}
+
+/*
+ *		Compare the actual bitmap to the list of clusters
+ *	allocated to identified files.
+ *
+ *	Clusters found in use, though not marked in the bitmap are copied
+ *	if the option --ignore-fs-checks is set.
+ */
+
+static int compare_bitmaps(struct bitmap *a, BOOL copy)
+{
+	s64 i, pos, count;
+	int mismatch = 0;
+	int more_use = 0;
+	s64 new_cl;
+	u8 bm[NTFS_BUF_SIZE];
+
+	Printf("Accounting clusters ...\n");
+
+	pos = 0;
+	new_cl = 0;
+	while (1) {
+		count = ntfs_attr_pread(vol->lcnbmp_na, pos, NTFS_BUF_SIZE, bm);
+		if (count == -1)
+			perr_exit("Couldn't get $Bitmap $DATA");
+
+		if (count == 0) {
+			/* the backup bootsector need not be accounted for */
+			if (((vol->nr_clusters + 7) >> 3) > pos)
+				err_exit("$Bitmap size is smaller than expected"
+					 " (%lld < %lld)\n",
+					(long long)pos, (long long)a->size);
+			break;
+		}
+
+		for (i = 0; i < count; i++, pos++) {
+			s64 cl;  /* current cluster */
+
+			if (a->size <= pos)
+				goto done;
+
+			if (a->bm[pos] == bm[i])
+				continue;
+
+			for (cl = pos * 8; cl < (pos + 1) * 8; cl++) {
+				char bit;
+
+				bit = ntfs_bit_get(a->bm, cl);
+				if (bit == ntfs_bit_get(bm, i * 8 + cl % 8))
+					continue;
+
+				if (!bit)
+					more_use++;
+				if (opt.ignore_fs_check && !bit && copy) {
+					lseek_to_cluster(cl);
+					if (opt.save_image
+					   || (opt.metadata
+						&& opt.metadata_image)) {
+						gap_to_cluster(cl - new_cl);
+						new_cl = cl + 1;
+					}
+					copy_cluster(opt.rescue, cl, cl);
+				}
+
+				if (++mismatch > 10)
+					continue;
+
+				Printf("Cluster accounting failed at %lld "
+				       "(0x%llx): %s cluster in $Bitmap\n",
+				       (long long)cl, (unsigned long long)cl,
+				       bit ? "missing" : "extra");
+			}
+		}
+	}
+done:
+	if (mismatch) {
+		Printf("Totally %d cluster accounting mismatches.\n", mismatch);
+		if (opt.ignore_fs_check) {
+			Printf("WARNING: The NTFS inconsistency was overruled "
+			       "by the --ignore-fs-check option.\n");
+			if (new_cl) {
+				gap_to_cluster(-new_cl);
+			}
+			return (more_use);
+		}
+		err_exit("Filesystem check failed! Windows wasn't shutdown "
+			 "properly or inconsistent\nfilesystem. Please run "
+			 "chkdsk /f on Windows then reboot it TWICE.\n");
+	}
+	return (more_use);
+}
+
+
+static void mft_record_write_with_same_usn(ntfs_volume *volume, ntfs_inode *ni)
+{
+	if (ntfs_mft_usn_dec(ni->mrec))
+		perr_exit("ntfs_mft_usn_dec");
+
+	if (ntfs_mft_record_write(volume, ni->mft_no, ni->mrec))
+		perr_exit("ntfs_mft_record_write");
+}
+
+static void mft_inode_write_with_same_usn(ntfs_volume *volume, ntfs_inode *ni)
+{
+	s32 i;
+
+	mft_record_write_with_same_usn(volume, ni);
+
+	if (ni->nr_extents <= 0)
+		return;
+
+	for (i = 0; i < ni->nr_extents; ++i) {
+		ntfs_inode *eni = ni->extent_nis[i];
+		mft_record_write_with_same_usn(volume, eni);
+	}
+}
+
+static int walk_clusters(ntfs_volume *volume, struct ntfs_walk_cluster *walk)
+{
+	s64 inode = 0;
+	s64 last_mft_rec;
+	u64 nr_clusters;
+	ntfs_inode *ni;
+	struct progress_bar progress;
+
+	if (opt.restore_image || (!opt.metadata && wipe))
+		err_exit("Bug : invalid walk_clusters()\n");
+	Printf("Scanning volume ...\n");
+
+	last_mft_rec = (volume->mft_na->initialized_size >>
+			volume->mft_record_size_bits) - 1;
+	walk->image->current_lcn = 0;
+	progress_init(&progress, inode, last_mft_rec, 100);
+
+	NVolSetNoFixupWarn(volume);
+	for (; inode <= last_mft_rec; inode++) {
+
+		int err, deleted_inode;
+		MFT_REF mref = (MFT_REF)inode;
+
+		progress_update(&progress, inode);
+
+		/* FIXME: Terrible kludge for libntfs not being able to return
+		   a deleted MFT record as inode */
+		ni = ntfs_calloc(sizeof(ntfs_inode));
+		if (!ni)
+			perr_exit("walk_clusters");
+
+		ni->vol = volume;
+
+		err = ntfs_file_record_read(volume, mref, &ni->mrec, NULL);
+		if (err == -1) {
+			free(ni);
+			continue;
+		}
+
+		deleted_inode = !(ni->mrec->flags & MFT_RECORD_IN_USE);
+
+		if (deleted_inode && !opt.metadata_image) {
+
+			ni->mft_no = MREF(mref);
+			if (wipe) {
+				wipe_unused_mft(ni);
+				wipe_unused_mft_data(ni);
+				mft_record_write_with_same_usn(volume, ni);
+			}
+		}
+
+		free(ni->mrec);
+		free(ni);
+
+		if (deleted_inode)
+			continue;
+
+		if ((ni = ntfs_inode_open(volume, mref)) == NULL) {
+			/* FIXME: continue only if it make sense, e.g.
+			   MFT record not in use based on $MFT bitmap */
+			if (errno == EIO || errno == ENOENT)
+				continue;
+			perr_exit("Reading inode %lld failed",
+				(long long)inode);
+		}
+
+		if (wipe)
+			nr_used_mft_records++;
+
+		if (ni->mrec->base_mft_record)
+			goto out;
+
+		walk->image->ni = ni;
+		walk_attributes(walk);
+out:
+		if (wipe && !opt.metadata_image) {
+			int i;
+
+			wipe_unused_mft_data(ni);
+			for (i = 0; i < ni->nr_extents; ++i) {
+				wipe_unused_mft_data(ni->extent_nis[i]);
+			}
+			mft_inode_write_with_same_usn(volume, ni);
+		}
+
+		if (ntfs_inode_close(ni))
+			perr_exit("ntfs_inode_close for inode %lld",
+				(long long)inode);
+	}
+	if (opt.metadata) {
+		if (opt.metadata_image && wipe && opt.ignore_fs_check) {
+			gap_to_cluster(-walk->image->current_lcn);
+			compare_bitmaps(&lcn_bitmap, TRUE);
+			walk->image->current_lcn = 0;
+		}
+		if (opt.metadata_image ? wipe : !wipe) {
+				/* also get the backup bootsector */
+			nr_clusters = vol->nr_clusters;
+			lseek_to_cluster(nr_clusters);
+			if (opt.metadata_image && wipe)
+				gap_to_cluster(nr_clusters
+					- walk->image->current_lcn);
+			copy_cluster(opt.rescue, nr_clusters, nr_clusters);
+			walk->image->current_lcn = nr_clusters;
+		}
+			/* Not counted, for compatibility with older versions */
+		if (!opt.metadata_image)
+			walk->image->inuse++;
+	}
+	return 0;
+}
+
+
+/*
+ * $Bitmap can overlap the end of the volume. Any bits in this region
+ * must be set. This region also encompasses the backup boot sector.
+ */
+static void bitmap_file_data_fixup(s64 cluster, struct bitmap *bm)
+{
+	for (; cluster < bm->size << 3; cluster++)
+		ntfs_bit_set(bm->bm, (u64)cluster, 1);
+}
+
+
+/*
+ * Allocate a block of memory with one bit for each cluster of the disk.
+ * All the bits are set to 0, except those representing the region beyond the
+ * end of the disk.
+ */
+static void setup_lcn_bitmap(void)
+{
+	/* Determine lcn bitmap byte size and allocate it. */
+	/* include the alternate boot sector in the bitmap count */
+	lcn_bitmap.size = rounded_up_division(vol->nr_clusters + 1, 8);
+
+	lcn_bitmap.bm = ntfs_calloc(lcn_bitmap.size);
+	if (!lcn_bitmap.bm)
+		perr_exit("Failed to allocate internal buffer");
+
+	bitmap_file_data_fixup(vol->nr_clusters, &lcn_bitmap);
+}
+
+
+static s64 volume_size(ntfs_volume *volume, s64 nr_clusters)
+{
+	return nr_clusters * volume->cluster_size;
+}
+
+
+static void print_volume_size(const char *str, s64 bytes)
+{
+	Printf("%s: %lld bytes (%lld MB)\n", str, (long long)bytes,
+			(long long)rounded_up_division(bytes, NTFS_MBYTE));
+}
+
+
+static void print_disk_usage(const char *spacer, u32 cluster_size,
+		s64 nr_clusters, s64 inuse)
+{
+	s64 total, used;
+
+	total = nr_clusters * cluster_size;
+	used = inuse * cluster_size;
+
+	Printf("Space in use       %s: %lld MB (%.1f%%)   ", spacer,
+			(long long)rounded_up_division(used, NTFS_MBYTE),
+			100.0 * ((float)used / total));
+
+	Printf("\n");
+}
+
+static void print_image_info(void)
+{
+	Printf("Ntfsclone image version: %d.%d\n",
+			image_hdr.major_ver, image_hdr.minor_ver);
+	Printf("Cluster size           : %u bytes\n",
+			(unsigned)le32_to_cpu(image_hdr.cluster_size));
+	print_volume_size("Image volume size      ",
+			sle64_to_cpu(image_hdr.nr_clusters) *
+			le32_to_cpu(image_hdr.cluster_size));
+	Printf("Image device size      : %lld bytes\n",
+			(long long)sle64_to_cpu(image_hdr.device_size));
+	print_disk_usage("    ", le32_to_cpu(image_hdr.cluster_size),
+			sle64_to_cpu(image_hdr.nr_clusters),
+			sle64_to_cpu(image_hdr.inuse));
+	Printf("Offset to image data   : %u (0x%x) bytes\n",
+			(unsigned)le32_to_cpu(image_hdr.offset_to_image_data),
+			(unsigned)le32_to_cpu(image_hdr.offset_to_image_data));
+}
+
+static void check_if_mounted(const char *device, unsigned long new_mntflag)
+{
+	unsigned long mntflag;
+
+	if (ntfs_check_if_mounted(device, &mntflag))
+		perr_exit("Failed to check '%s' mount state", device);
+
+	if (mntflag & NTFS_MF_MOUNTED) {
+		if (!(mntflag & NTFS_MF_READONLY))
+			err_exit("Device '%s' is mounted read-write. "
+				 "You must 'umount' it first.\n", device);
+		if (!new_mntflag)
+			err_exit("Device '%s' is mounted. "
+				 "You must 'umount' it first.\n", device);
+	}
+}
+
+/**
+ * mount_volume -
+ *
+ * First perform some checks to determine if the volume is already mounted, or
+ * is dirty (Windows wasn't shutdown properly).  If everything is OK, then mount
+ * the volume (load the metadata into memory).
+ */
+static void mount_volume(unsigned long new_mntflag)
+{
+	check_if_mounted(opt.volume, new_mntflag);
+
+	if (!(vol = ntfs_mount(opt.volume, new_mntflag))) {
+
+		int err = errno;
+
+		perr_printf("Opening '%s' as NTFS failed", opt.volume);
+		if (err == EINVAL) {
+			Printf("Apparently device '%s' doesn't have a "
+			       "valid NTFS. Maybe you selected\nthe whole "
+			       "disk instead of a partition (e.g. /dev/hda, "
+			       "not /dev/hda1)?\n", opt.volume);
+		}
+		/*
+		 * Retry with recovering the log file enabled.
+		 * Normally avoided in order to get the original log file
+		 * data, but needed when remounting the metadata of a
+		 * volume improperly unmounted from Windows.
+		 */
+		if (!(new_mntflag & (NTFS_MNT_RDONLY | NTFS_MNT_RECOVER))) {
+			Printf("Trying to recover...\n");
+			vol = ntfs_mount(opt.volume,
+					new_mntflag | NTFS_MNT_RECOVER);
+			Printf("... %s\n",(vol ? "Successful" : "Failed"));
+		}
+		if (!vol)
+			exit(1);
+	}
+
+	if (vol->flags & VOLUME_IS_DIRTY)
+		if (opt.force-- <= 0)
+			err_exit(dirty_volume_msg, opt.volume);
+
+	if (NTFS_MAX_CLUSTER_SIZE < vol->cluster_size)
+		err_exit("Cluster size %u is too large!\n",
+				(unsigned int)vol->cluster_size);
+
+	Printf("NTFS volume version: %d.%d\n", vol->major_ver, vol->minor_ver);
+	if (ntfs_version_is_supported(vol))
+		perr_exit("Unknown NTFS version");
+
+	Printf("Cluster size       : %u bytes\n",
+			(unsigned int)vol->cluster_size);
+	print_volume_size("Current volume size",
+			  volume_size(vol, vol->nr_clusters));
+}
+
+static struct ntfs_walk_cluster backup_clusters = { NULL, NULL };
+
+static int device_offset_valid(int fd, s64 ofs)
+{
+	char ch;
+
+	if (lseek(fd, ofs, SEEK_SET) >= 0 && read(fd, &ch, 1) == 1)
+		return 0;
+	return -1;
+}
+
+static s64 device_size_get(int fd)
+{
+	s64 high, low;
+#ifdef BLKGETSIZE64
+	{	u64 size;
+
+		if (ioctl(fd, BLKGETSIZE64, &size) >= 0) {
+			ntfs_log_debug("BLKGETSIZE64 nr bytes = %llu "
+				"(0x%llx).\n", (unsigned long long)size,
+				(unsigned long long)size);
+			return (s64)size;
+		}
+	}
+#endif
+#ifdef BLKGETSIZE
+	{	unsigned long size;
+
+		if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
+			ntfs_log_debug("BLKGETSIZE nr 512 byte blocks = %lu "
+				"(0x%lx).\n", size, size);
+			return (s64)size * 512;
+		}
+	}
+#endif
+#ifdef FDGETPRM
+	{       struct floppy_struct this_floppy;
+
+		if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) {
+			ntfs_log_debug("FDGETPRM nr 512 byte blocks = %lu "
+				"(0x%lx).\n", this_floppy.size,
+				this_floppy.size);
+			return (s64)this_floppy.size * 512;
+		}
+	}
+#endif
+	/*
+	 * We couldn't figure it out by using a specialized ioctl,
+	 * so do binary search to find the size of the device.
+	 */
+	low = 0LL;
+	for (high = 1024LL; !device_offset_valid(fd, high); high <<= 1)
+		low = high;
+	while (low < high - 1LL) {
+		const s64 mid = (low + high) / 2;
+
+		if (!device_offset_valid(fd, mid))
+			low = mid;
+		else
+			high = mid;
+	}
+	lseek(fd, 0LL, SEEK_SET);
+	return (low + 1LL);
+}
+
+static void fsync_clone(int fd)
+{
+	Printf("Syncing ...\n");
+	if (opt.save_image && stream_out && fflush(stream_out))
+		perr_exit("fflush");
+	if (fsync(fd) && errno != EINVAL)
+		perr_exit("fsync");
+}
+
+static void set_filesize(s64 filesize)
+{
+#ifndef NO_STATFS
+	long fs_type = 0; /* Unknown filesystem type */
+
+	if (fstatfs(fd_out, &opt.stfs) == -1)
+		Printf("WARNING: Couldn't get filesystem type: "
+		       "%s\n", strerror(errno));
+	else
+		fs_type = opt.stfs.f_type;
+
+	if (fs_type == 0x52654973)
+		Printf("WARNING: You're using ReiserFS, it has very poor "
+		       "performance creating\nlarge sparse files. The next "
+		       "operation might take a very long time!\n"
+		       "Creating sparse output file ...\n");
+	else if (fs_type == 0x517b)
+		Printf("WARNING: You're using SMBFS and if the remote share "
+		       "isn't Samba but a Windows\ncomputer then the clone "
+		       "operation will be very inefficient and may fail!\n");
+#endif
+
+	if (!opt.no_action && (ftruncate(fd_out, filesize) == -1)) {
+		int err = errno;
+		perr_printf("ftruncate failed for file '%s'", opt.output);
+#ifndef NO_STATFS
+		if (fs_type)
+			Printf("Destination filesystem type is 0x%lx.\n",
+			       (unsigned long)fs_type);
+#endif
+		if (err == E2BIG) {
+			Printf("Your system or the destination filesystem "
+			       "doesn't support large files.\n");
+#ifndef NO_STATFS
+			if (fs_type == 0x517b) {
+				Printf("SMBFS needs minimum Linux kernel "
+				       "version 2.4.25 and\n the 'lfs' option"
+				       "\nfor smbmount to have large "
+				       "file support.\n");
+			}
+#endif
+		} else if (err == EPERM) {
+			Printf("Apparently the destination filesystem doesn't "
+			       "support sparse files.\nYou can overcome this "
+			       "by using the more efficient --save-image "
+			       "option\nof ntfsclone. Use the --restore-image "
+			       "option to restore the image.\n");
+		}
+		exit(1);
+	}
+		/*
+		 * If truncate just created a sparse file, the ability
+		 * to generically store big files has been checked, but no
+		 * space has been reserved and available space has probably
+		 * not been checked. Better reset the file so that we write
+		 * sequentially to the end.
+		 */
+	if (!opt.no_action) {
+#ifdef HAVE_WINDOWS_H
+		if (ftruncate(fd_out, 0))
+			Printf("Failed to reset the output file.\n");
+#else
+		struct stat st;
+		int s;
+
+		s = fstat(fd_out, &st);
+		if (s || (!st.st_blocks && ftruncate(fd_out, 0)))
+			Printf("Failed to reset the output file.\n");
+#endif
+			/* Proceed even if ftruncate failed */
+	}
+}
+
+static s64 open_image(void)
+{
+	if (strcmp(opt.volume, "-") == 0) {
+		if ((fd_in = fileno(stdin)) == -1)
+			perr_exit("fileno for stdin failed");
+#ifdef HAVE_WINDOWS_H
+		if (setmode(fd_in,O_BINARY) == -1)
+			perr_exit("setting binary stdin failed");
+#endif
+	} else {
+		if ((fd_in = open(opt.volume, O_RDONLY | O_BINARY)) == -1)
+			perr_exit("failed to open image");
+	}
+	if (read_all(&fd_in, &image_hdr, NTFSCLONE_IMG_HEADER_SIZE_OLD) == -1)
+		perr_exit("read_all");
+	if (memcmp(image_hdr.magic, IMAGE_MAGIC, IMAGE_MAGIC_SIZE) != 0)
+		err_exit("Input file is not an image! (invalid magic)\n");
+	if (image_hdr.major_ver < NTFSCLONE_IMG_VER_MAJOR_ENDIANNESS_SAFE) {
+		image_hdr.major_ver = NTFSCLONE_IMG_VER_MAJOR;
+		image_hdr.minor_ver = NTFSCLONE_IMG_VER_MINOR;
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+		/*
+		 * old image read on a big endian computer,
+		 * assuming it was created big endian and read cpu-wise,
+		 * so we should translate to little endian
+		 */
+		Printf("Old image format detected.  If the image was created "
+				"on a little endian architecture it will not "
+				"work.  Use a more recent version of "
+				"ntfsclone to recreate the image.\n");
+		image_hdr.cluster_size = cpu_to_le32(image_hdr.cluster_size);
+		image_hdr.device_size = cpu_to_sle64(image_hdr.device_size);
+		image_hdr.nr_clusters = cpu_to_sle64(image_hdr.nr_clusters);
+		image_hdr.inuse = cpu_to_sle64(image_hdr.inuse);
+#endif
+		image_hdr.offset_to_image_data =
+				const_cpu_to_le32((sizeof(image_hdr)
+				    + IMAGE_HDR_ALIGN - 1) & -IMAGE_HDR_ALIGN);
+		image_is_host_endian = TRUE;
+	} else {
+			/* safe image : little endian data */
+		le32 offset_to_image_data;
+		int delta;
+
+		if (image_hdr.major_ver > NTFSCLONE_IMG_VER_MAJOR)
+			err_exit("Do not know how to handle image format "
+					"version %d.%d.  Please obtain a "
+					"newer version of ntfsclone.\n",
+					image_hdr.major_ver,
+					image_hdr.minor_ver);
+		/* Read the image header data offset. */
+		if (read_all(&fd_in, &offset_to_image_data,
+				sizeof(offset_to_image_data)) == -1)
+			perr_exit("read_all");
+			/* do not translate little endian data */
+		image_hdr.offset_to_image_data = offset_to_image_data;
+		/*
+		 * Read any fields from the header that we have not read yet so
+		 * that the input stream is positioned correctly.  This means
+		 * we can support future minor versions that just extend the
+		 * header in a backwards compatible way.
+		 */
+		delta = le32_to_cpu(offset_to_image_data)
+				- (NTFSCLONE_IMG_HEADER_SIZE_OLD +
+				sizeof(image_hdr.offset_to_image_data));
+		if (delta > 0) {
+			char *dummy_buf;
+
+			dummy_buf = malloc(delta);
+			if (!dummy_buf)
+				perr_exit("malloc dummy_buffer");
+			if (read_all(&fd_in, dummy_buf, delta) == -1)
+				perr_exit("read_all");
+			free(dummy_buf);
+		}
+	}
+	return sle64_to_cpu(image_hdr.device_size);
+}
+
+static s64 open_volume(void)
+{
+	s64 device_size;
+
+	mount_volume(NTFS_MNT_RDONLY);
+
+	device_size = ntfs_device_size_get(vol->dev, 1);
+	if (device_size <= 0)
+		err_exit("Couldn't get device size (%lld)!\n",
+			(long long)device_size);
+
+	print_volume_size("Current device size", device_size);
+
+	if (device_size < vol->nr_clusters * vol->cluster_size)
+		err_exit("Current NTFS volume size is bigger than the device "
+			 "size (%lld)!\nCorrupt partition table or incorrect "
+			 "device partitioning?\n", (long long)device_size);
+
+	return device_size;
+}
+
+static void initialise_image_hdr(s64 device_size, s64 inuse)
+{
+	memcpy(image_hdr.magic, IMAGE_MAGIC, IMAGE_MAGIC_SIZE);
+	image_hdr.major_ver = NTFSCLONE_IMG_VER_MAJOR;
+	image_hdr.minor_ver = NTFSCLONE_IMG_VER_MINOR;
+	image_hdr.cluster_size = cpu_to_le32(vol->cluster_size);
+	image_hdr.device_size = cpu_to_sle64(device_size);
+	image_hdr.nr_clusters = cpu_to_sle64(vol->nr_clusters);
+	image_hdr.inuse = cpu_to_sle64(inuse);
+	image_hdr.offset_to_image_data = cpu_to_le32((sizeof(image_hdr)
+			 + IMAGE_HDR_ALIGN - 1) & -IMAGE_HDR_ALIGN);
+}
+
+static void check_output_device(s64 input_size)
+{
+	if (opt.blkdev_out) {
+		s64 dest_size;
+
+		if (dev_out)
+			dest_size = ntfs_device_size_get(dev_out, 1);
+		else
+			dest_size = device_size_get(fd_out);
+		if (dest_size < input_size)
+			err_exit("Output device is too small (%lld) to fit the "
+				 "NTFS image (%lld).\n",
+				(long long)dest_size, (long long)input_size);
+
+		check_if_mounted(opt.output, 0);
+	} else
+		set_filesize(input_size);
+}
+
+static ntfs_attr_search_ctx *attr_get_search_ctx(ntfs_inode *ni)
+{
+	ntfs_attr_search_ctx *ret;
+
+	if ((ret = ntfs_attr_get_search_ctx(ni, NULL)) == NULL)
+		perr_printf("ntfs_attr_get_search_ctx");
+
+	return ret;
+}
+
+/**
+ * lookup_data_attr
+ *
+ * Find the $DATA attribute (with or without a name) for the given ntfs inode.
+ */
+static ntfs_attr_search_ctx *lookup_data_attr(ntfs_inode *ni, const char *aname)
+{
+	ntfs_attr_search_ctx *ctx;
+	ntfschar *ustr;
+	int len = 0;
+
+	if ((ctx = attr_get_search_ctx(ni)) == NULL)
+		return NULL;
+
+	if ((ustr = ntfs_str2ucs(aname, &len)) == NULL) {
+		perr_printf("Couldn't convert '%s' to Unicode", aname);
+		goto error_out;
+	}
+
+	if (ntfs_attr_lookup(AT_DATA, ustr, len, CASE_SENSITIVE,
+				0, NULL, 0, ctx)) {
+		perr_printf("ntfs_attr_lookup");
+		goto error_out;
+	}
+	ntfs_ucsfree(ustr);
+	return ctx;
+error_out:
+	ntfs_attr_put_search_ctx(ctx);
+	return NULL;
+}
+
+static void ignore_bad_clusters(ntfs_walk_clusters_ctx *image)
+{
+	ntfs_inode *ni;
+	ntfs_attr_search_ctx *ctx = NULL;
+	runlist *rl, *rl_bad;
+	s64 nr_bad_clusters = 0;
+
+	if (!(ni = ntfs_inode_open(vol, FILE_BadClus)))
+		perr_exit("ntfs_open_inode");
+
+	if ((ctx = lookup_data_attr(ni, "$Bad")) == NULL)
+		exit(1);
+
+	if (!(rl_bad = ntfs_mapping_pairs_decompress(vol, ctx->attr, NULL)))
+		perr_exit("ntfs_mapping_pairs_decompress");
+
+	for (rl = rl_bad; rl->length; rl++) {
+		s64 lcn = rl->lcn;
+
+		if (lcn == LCN_HOLE || lcn < 0)
+			continue;
+
+		for (; lcn < rl->lcn + rl->length; lcn++, nr_bad_clusters++) {
+			if (ntfs_bit_get_and_set(lcn_bitmap.bm, lcn, 0))
+				image->inuse--;
+		}
+	}
+	if (nr_bad_clusters)
+		Printf("WARNING: The disk has %lld or more bad sectors"
+		       " (hardware faults).\n", (long long)nr_bad_clusters);
+	free(rl_bad);
+
+	ntfs_attr_put_search_ctx(ctx);
+	if (ntfs_inode_close(ni))
+		perr_exit("ntfs_inode_close failed for $BadClus");
+}
+
+static void check_dest_free_space(u64 src_bytes)
+{
+#ifndef HAVE_WINDOWS_H
+	u64 dest_bytes;
+	struct statvfs stvfs;
+	struct stat st;
+
+	if (opt.metadata || opt.blkdev_out || opt.std_out)
+		return;
+	/*
+	 * TODO: save_image needs a bit more space than src_bytes
+	 * due to the free space encoding overhead.
+	 */
+	if (fstatvfs(fd_out, &stvfs) == -1) {
+		Printf("WARNING: Unknown free space on the destination: %s\n",
+		       strerror(errno));
+		return;
+	}
+	
+	/* If file is a FIFO then there is no point in checking the size. */
+	if (!fstat(fd_out, &st)) {
+		if (S_ISFIFO(st.st_mode))
+			return;
+	} else
+		Printf("WARNING: fstat failed: %s\n", strerror(errno));
+
+	dest_bytes = (u64)stvfs.f_frsize * stvfs.f_bfree;
+	if (!dest_bytes)
+		dest_bytes = (u64)stvfs.f_bsize * stvfs.f_bfree;
+
+	if (dest_bytes < src_bytes)
+		err_exit("Destination doesn't have enough free space: "
+			 "%llu MB < %llu MB\n",
+			 (unsigned long long)rounded_up_division(dest_bytes, NTFS_MBYTE),
+			 (unsigned long long)rounded_up_division(src_bytes,  NTFS_MBYTE));
+#endif
+}
+
+int main(int argc, char **argv)
+{
+	ntfs_walk_clusters_ctx image;
+	s64 device_size;        /* input device size in bytes */
+	s64 ntfs_size;
+	unsigned int wiped_total = 0;
+
+	/* make sure the layout of header is not affected by alignments */
+	if (offsetof(struct image_hdr, offset_to_image_data)
+			!= IMAGE_OFFSET_OFFSET) {
+		fprintf(stderr,"ntfsclone is not compiled properly. "
+				"Please fix\n");
+		exit(1);
+	}
+	/* print to stderr, stdout can be an NTFS image ... */
+	fprintf(stderr, "%s v%s (libntfs-3g)\n", EXEC_NAME, VERSION);
+	msg_out = stderr;
+
+	parse_options(argc, argv);
+
+	utils_set_locale();
+
+	if (opt.restore_image) {
+		device_size = open_image();
+		ntfs_size = sle64_to_cpu(image_hdr.nr_clusters) *
+				le32_to_cpu(image_hdr.cluster_size);
+	} else {
+		device_size = open_volume();
+		ntfs_size = vol->nr_clusters * vol->cluster_size;
+	}
+	// FIXME: This needs to be the cluster size...
+	ntfs_size += 512; /* add backup boot sector */
+	full_device_size = device_size;
+
+	if (opt.std_out) {
+		if ((fd_out = fileno(stdout)) == -1)
+			perr_exit("fileno for stdout failed");
+		stream_out = stdout;
+#ifdef HAVE_WINDOWS_H
+		if (setmode(fileno(stdout),O_BINARY) == -1)
+			perr_exit("setting binary stdout failed");
+#endif
+	} else {
+		/* device_size_get() might need to read() */
+		int flags = O_RDWR | O_BINARY;
+
+		fd_out = 0;
+		if (!opt.blkdev_out) {
+			flags |= O_CREAT | O_TRUNC;
+			if (!opt.overwrite)
+				flags |= O_EXCL;
+		}
+
+		if (opt.save_image || opt.metadata_image) {
+			stream_out = fopen(opt.output,BINWMODE);
+			if (!stream_out)
+				perr_exit("Opening file '%s' failed",
+						opt.output);
+			fd_out = fileno(stream_out);
+		} else {
+#ifdef HAVE_WINDOWS_H
+			if (!opt.no_action) {
+				dev_out = ntfs_device_alloc(opt.output, 0,
+					&ntfs_device_default_io_ops, NULL);
+				if (!dev_out
+				    || (dev_out->d_ops->open)(dev_out, flags))
+					perr_exit("Opening volume '%s' failed",
+							opt.output);
+			}
+#else
+			if (!opt.no_action
+			    && ((fd_out = open(opt.output, flags,
+						S_IRUSR | S_IWUSR)) == -1))
+				perr_exit("Opening file '%s' failed",
+						opt.output);
+#endif
+		}
+
+		if (!opt.save_image && !opt.metadata_image && !opt.no_action)
+			check_output_device(ntfs_size);
+	}
+
+	if (opt.restore_image) {
+		print_image_info();
+		restore_image();
+		if (!opt.no_action)
+			fsync_clone(fd_out);
+		exit(0);
+	}
+
+	setup_lcn_bitmap();
+	memset(&image, 0, sizeof(image));
+	backup_clusters.image = &image;
+
+	walk_clusters(vol, &backup_clusters);
+	image.more_use = compare_bitmaps(&lcn_bitmap,
+				opt.metadata && !opt.metadata_image);
+	print_disk_usage("", vol->cluster_size, vol->nr_clusters, image.inuse);
+
+	check_dest_free_space(vol->cluster_size * image.inuse);
+
+	ignore_bad_clusters(&image);
+
+	if (opt.save_image)
+		initialise_image_hdr(device_size, image.inuse);
+
+	if ((opt.std_out && !opt.metadata_image) || !opt.metadata) {
+		s64 nr_clusters_to_save = image.inuse;
+		if (opt.std_out && !opt.save_image)
+			nr_clusters_to_save = vol->nr_clusters;
+		nr_clusters_to_save++; /* account for the backup boot sector */
+
+		clone_ntfs(nr_clusters_to_save, image.more_use);
+		fsync_clone(fd_out);
+		if (opt.save_image)
+			fclose(stream_out);
+		ntfs_umount(vol,FALSE);
+		free(lcn_bitmap.bm);
+		exit(0);
+	}
+
+	wipe = 1;
+	if (opt.metadata_image) {
+		initialise_image_hdr(device_size, image.inuse);
+		write_image_hdr();
+	} else {
+		if (dev_out) {
+			(dev_out->d_ops->close)(dev_out);
+			dev_out = NULL;
+		} else
+			fsync_clone(fd_out); /* sync copy before mounting */
+		opt.volume = opt.output;
+	/* 'force' again mount for dirty volumes (e.g. after resize).
+	   FIXME: use mount flags to avoid potential side-effects in future */
+		opt.force++;
+		ntfs_umount(vol,FALSE);
+		mount_volume(0 /*NTFS_MNT_NOATIME*/);
+	}
+
+	free(lcn_bitmap.bm);
+	setup_lcn_bitmap();
+	memset(&image, 0, sizeof(image));
+	backup_clusters.image = &image;
+
+	walk_clusters(vol, &backup_clusters);
+
+	Printf("Num of MFT records       = %10lld\n",
+			(long long)vol->mft_na->initialized_size >>
+			vol->mft_record_size_bits);
+	Printf("Num of used MFT records  = %10u\n", nr_used_mft_records);
+
+	Printf("Wiped unused MFT data    = %10u\n", wiped_unused_mft_data);
+	Printf("Wiped deleted MFT data   = %10u\n", wiped_unused_mft);
+	Printf("Wiped resident user data = %10u\n", wiped_resident_data);
+	Printf("Wiped timestamp data     = %10u\n", wiped_timestamp_data);
+
+	wiped_total += wiped_unused_mft_data;
+	wiped_total += wiped_unused_mft;
+	wiped_total += wiped_resident_data;
+	wiped_total += wiped_timestamp_data;
+	Printf("Wiped totally            = %10u\n", wiped_total);
+
+	if (opt.metadata_image)
+		fclose(stream_out);
+	else
+		fsync_clone(fd_out);
+	ntfs_umount(vol,FALSE);
+	free(lcn_bitmap.bm);
+	return (0);
+}
diff --git a/ntfsprogs/ntfscluster.8 b/ntfsprogs/ntfscluster.8
new file mode 100755
index 0000000000000000000000000000000000000000..7fc537b5d63001bb0476b8070b8368f546aa094d
--- /dev/null
+++ b/ntfsprogs/ntfscluster.8
@@ -0,0 +1,124 @@
+.\" Copyright (c) 2003\-2005 Richard Russon.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSCLUSTER 8 "November 2005" "ntfs-3g 2015.3.14"
+.SH NAME
+ntfscluster \- identify files in a specified region of an NTFS volume.
+.SH SYNOPSIS
+.B ntfscluster
+[\fIoptions\fR] \fIdevice\fR
+.SH DESCRIPTION
+.B ntfscluster
+has three modes of operation:
+.IR info ,
+.I sector
+and
+.IR cluster .
+.SS Info
+.PP
+The default mode,
+.I info
+is currently not implemented.  It will display general information about the
+NTFS volume when it is working.
+.SS Sector
+.PP
+The
+.I sector
+mode will display a list of files that have data in the specified range of
+sectors.
+.SS Cluster
+The
+.I cluster
+mode will display a list of files that have data in the specified range of
+clusters.  When the cluster size is one sector, this will be equivalent to the
+.I sector
+mode of operation.
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfscluster
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-c\fR, \fB\-\-cluster\fR RANGE
+Any files whose data is in this range of clusters will be displayed.
+.TP
+\fB\-F\fR, \fB\-\-filename\fR NAME
+Show information about this file.
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+This will override some sensible defaults, such as not working with a mounted
+volume.  Use this option with caution.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.TP
+\fB\-I\fR, \fB\-\-inode\fR NUM
+Show information about this inode.
+.TP
+\fB\-i\fR, \fB\-\-info\fR
+This option is not yet implemented.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Reduce the amount of output to a minimum.  Naturally, it doesn't make sense to
+combine this option with
+.TP
+\fB\-s\fR, \fB\-\-sector\fR RANGE
+Any files whose data is in this range of sectors will be displayed.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Increase the amount of output that
+.B ntfscluster
+prints.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Show the version number, copyright and license for
+.BR ntfscluster .
+.SH EXAMPLES
+Get some information about the volume /dev/hda1.
+.RS
+.sp
+.B ntfscluster /dev/hda1
+.sp
+.RE
+Look for files in the first 500 clusters of /dev/hda1.
+.RS
+.sp
+.B ntfscluster \-c 0\-500 /dev/hda1
+.sp
+.RE
+.SH BUGS
+The
+.I info
+mode isn't implemented yet.
+.B ntfscluster
+is quite limited, but it has no known bugs.  If you find a bug please send an
+email describing the problem to the development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+.B ntfscluster
+was written by Richard Russon, with contributions from Anton Altaparmakov.
+It was ported to ntfs-3g by Erik Larsson.
+.SH AVAILABILITY
+.B ntfscluster
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR ntfsinfo (8),
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/ntfscluster.8.in b/ntfsprogs/ntfscluster.8.in
new file mode 100755
index 0000000000000000000000000000000000000000..9186a64872456b1399bf7de48d6b4ea3a07c0398
--- /dev/null
+++ b/ntfsprogs/ntfscluster.8.in
@@ -0,0 +1,124 @@
+.\" Copyright (c) 2003\-2005 Richard Russon.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSCLUSTER 8 "November 2005" "ntfs-3g @VERSION@"
+.SH NAME
+ntfscluster \- identify files in a specified region of an NTFS volume.
+.SH SYNOPSIS
+.B ntfscluster
+[\fIoptions\fR] \fIdevice\fR
+.SH DESCRIPTION
+.B ntfscluster
+has three modes of operation:
+.IR info ,
+.I sector
+and
+.IR cluster .
+.SS Info
+.PP
+The default mode,
+.I info
+is currently not implemented.  It will display general information about the
+NTFS volume when it is working.
+.SS Sector
+.PP
+The
+.I sector
+mode will display a list of files that have data in the specified range of
+sectors.
+.SS Cluster
+The
+.I cluster
+mode will display a list of files that have data in the specified range of
+clusters.  When the cluster size is one sector, this will be equivalent to the
+.I sector
+mode of operation.
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfscluster
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-c\fR, \fB\-\-cluster\fR RANGE
+Any files whose data is in this range of clusters will be displayed.
+.TP
+\fB\-F\fR, \fB\-\-filename\fR NAME
+Show information about this file.
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+This will override some sensible defaults, such as not working with a mounted
+volume.  Use this option with caution.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.TP
+\fB\-I\fR, \fB\-\-inode\fR NUM
+Show information about this inode.
+.TP
+\fB\-i\fR, \fB\-\-info\fR
+This option is not yet implemented.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Reduce the amount of output to a minimum.  Naturally, it doesn't make sense to
+combine this option with
+.TP
+\fB\-s\fR, \fB\-\-sector\fR RANGE
+Any files whose data is in this range of sectors will be displayed.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Increase the amount of output that
+.B ntfscluster
+prints.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Show the version number, copyright and license for
+.BR ntfscluster .
+.SH EXAMPLES
+Get some information about the volume /dev/hda1.
+.RS
+.sp
+.B ntfscluster /dev/hda1
+.sp
+.RE
+Look for files in the first 500 clusters of /dev/hda1.
+.RS
+.sp
+.B ntfscluster \-c 0\-500 /dev/hda1
+.sp
+.RE
+.SH BUGS
+The
+.I info
+mode isn't implemented yet.
+.B ntfscluster
+is quite limited, but it has no known bugs.  If you find a bug please send an
+email describing the problem to the development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+.B ntfscluster
+was written by Richard Russon, with contributions from Anton Altaparmakov.
+It was ported to ntfs-3g by Erik Larsson.
+.SH AVAILABILITY
+.B ntfscluster
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR ntfsinfo (8),
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/ntfscluster.c b/ntfsprogs/ntfscluster.c
new file mode 100755
index 0000000000000000000000000000000000000000..6a7e72897e3f7640c0882abdec7335f5d4b6eda5
--- /dev/null
+++ b/ntfsprogs/ntfscluster.c
@@ -0,0 +1,567 @@
+/**
+ * ntfscluster - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2002-2003 Richard Russon
+ * Copyright (c) 2005 Anton Altaparmakov
+ * Copyright (c) 2005-2006 Szabolcs Szakacsits
+ *
+ * This utility will locate the owner of any given sector or cluster.
+ *
+ * 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 Linux-NTFS
+ * 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_GETOPT_H
+#include <getopt.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#include "ntfscluster.h"
+#include "types.h"
+#include "attrib.h"
+#include "utils.h"
+#include "volume.h"
+#include "debug.h"
+#include "dir.h"
+#include "cluster.h"
+/* #include "version.h" */
+#include "logging.h"
+
+static const char *EXEC_NAME = "ntfscluster";
+static struct options opts;
+
+/**
+ * version - Print version information about the program
+ *
+ * Print a copyright statement and a brief description of the program.
+ *
+ * Return:  none
+ */
+static void version(void)
+{
+	ntfs_log_info("\n%s v%s (libntfs-3g) - Find the owner of any given sector or "
+			"cluster.\n\n", EXEC_NAME, VERSION);
+	ntfs_log_info("Copyright (c) 2002-2003 Richard Russon\n");
+	ntfs_log_info("Copyright (c) 2005 Anton Altaparmakov\n");
+	ntfs_log_info("Copyright (c) 2005-2006 Szabolcs Szakacsits\n");
+	ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
+}
+
+/**
+ * usage - Print a list of the parameters to the program
+ *
+ * Print a list of the parameters and options for the program.
+ *
+ * Return:  none
+ */
+static void usage(void)
+{
+	ntfs_log_info("\nUsage: %s [options] device\n"
+		"    -i, --info           Print information about the volume (default)\n"
+		"\n"
+		"    -c, --cluster RANGE  Look for objects in this range of clusters\n"
+		"    -s, --sector RANGE   Look for objects in this range of sectors\n"
+		"    -I, --inode NUM      Show information about this inode\n"
+		"    -F, --filename NAME  Show information about this file\n"
+	/*	"    -l, --last           Find the last file on the volume\n" */
+		"\n"
+		"    -f, --force          Use less caution\n"
+		"    -q, --quiet          Less output\n"
+		"    -v, --verbose        More output\n"
+		"    -V, --version        Version information\n"
+		"    -h, --help           Print this help\n\n",
+		EXEC_NAME);
+	ntfs_log_info("%s%s\n", ntfs_bugs, ntfs_home);
+}
+
+/**
+ * parse_options - Read and validate the programs command line
+ *
+ * Read the command line, verify the syntax and parse the options.
+ * This function is very long, but quite simple.
+ *
+ * Return:  1 Success
+ *	    0 Error, one or more problems
+ */
+static int parse_options(int argc, char **argv)
+{
+	static const char *sopt = "-c:F:fh?I:ilqs:vV";
+	static const struct option lopt[] = {
+		{ "cluster",	required_argument,	NULL, 'c' },
+		{ "filename",	required_argument,	NULL, 'F' },
+		{ "force",	no_argument,		NULL, 'f' },
+		{ "help",	no_argument,		NULL, 'h' },
+		{ "info",	no_argument,		NULL, 'i' },
+		{ "inode",	required_argument,	NULL, 'I' },
+		{ "last",	no_argument,		NULL, 'l' },
+		{ "quiet",	no_argument,		NULL, 'q' },
+		{ "sector",	required_argument,	NULL, 's' },
+		{ "verbose",	no_argument,		NULL, 'v' },
+		{ "version",	no_argument,		NULL, 'V' },
+		{ NULL,		0,			NULL, 0   }
+	};
+
+	int c = -1;
+	int err  = 0;
+	int ver  = 0;
+	int help = 0;
+	int levels = 0;
+	char *end = NULL;
+
+	opterr = 0; /* We'll handle the errors, thank you. */
+
+	opts.action      = act_none;
+	opts.range_begin = -1;
+	opts.range_end   = -1;
+
+	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
+		switch (c) {
+		case 1:	/* A non-option argument */
+			if (!opts.device) {
+				opts.device = argv[optind-1];
+			} else {
+				opts.device = NULL;
+				err++;
+			}
+			break;
+
+		case 'c':
+			if ((opts.action == act_none) &&
+			    (utils_parse_range(optarg, &opts.range_begin, &opts.range_end, FALSE)))
+				opts.action = act_cluster;
+			else
+				opts.action = act_error;
+			break;
+		case 'F':
+			if (opts.action == act_none) {
+				opts.action = act_file;
+				opts.filename = optarg;
+			} else {
+				opts.action = act_error;
+			}
+			break;
+		case 'f':
+			opts.force++;
+			break;
+		case 'h':
+			help++;
+			break;
+		case 'I':
+			if (opts.action == act_none) {
+				opts.action = act_inode;
+				opts.inode = strtol(optarg, &end, 0);
+				if (end && *end)
+					err++;
+			} else {
+				opts.action = act_error;
+			}
+			break;
+		case 'i':
+			if (opts.action == act_none)
+				opts.action = act_info;
+			else
+				opts.action = act_error;
+			break;
+		case 'l':
+			if (opts.action == act_none)
+				opts.action = act_last;
+			else
+				opts.action = act_error;
+			break;
+		case 'q':
+			opts.quiet++;
+			ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
+			break;
+		case 's':
+			if ((opts.action == act_none) &&
+			    (utils_parse_range(optarg, &opts.range_begin, &opts.range_end, FALSE)))
+				opts.action = act_sector;
+			else
+				opts.action = act_error;
+			break;
+		case 'v':
+			opts.verbose++;
+			ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
+			break;
+		case 'V':
+			ver++;
+			break;
+		case '?':
+			if (strncmp (argv[optind-1], "--log-", 6) == 0) {
+				if (!ntfs_log_parse_option (argv[optind-1]))
+					err++;
+				break;
+			}
+			/* fall through */
+		default:
+			if ((optopt == 'c') || (optopt == 's'))
+				ntfs_log_error("Option '%s' requires an argument.\n", argv[optind-1]);
+			else
+				ntfs_log_error("Unknown option '%s'.\n", argv[optind-1]);
+			err++;
+			break;
+		}
+	}
+
+	/* Make sure we're in sync with the log levels */
+	levels = ntfs_log_get_levels();
+	if (levels & NTFS_LOG_LEVEL_VERBOSE)
+		opts.verbose++;
+	if (!(levels & NTFS_LOG_LEVEL_QUIET))
+		opts.quiet++;
+
+	if (help || ver) {
+		opts.quiet = 0;
+	} else {
+		if (opts.action == act_none)
+			opts.action = act_info;
+		if (opts.action == act_info)
+			opts.quiet = 0;
+
+		if (opts.device == NULL) {
+			if (argc > 1)
+				ntfs_log_error("You must specify exactly one device.\n");
+			err++;
+		}
+
+		if (opts.quiet && opts.verbose) {
+			ntfs_log_error("You may not use --quiet and --verbose at the same time.\n");
+			err++;
+		}
+
+		if (opts.action == act_error) {
+			ntfs_log_error("You may only specify one action: --info, --cluster, --sector or --last.\n");
+			err++;
+		} else if (opts.range_begin > opts.range_end) {
+			ntfs_log_error("The range must be in ascending order.\n");
+			err++;
+		}
+	}
+
+	if (ver)
+		version();
+	if (help || err)
+		usage();
+
+		/* tri-state 0 : done, 1 : error, -1 : proceed */
+	return (err ? 1 : (help || ver ? 0 : -1));
+}
+
+
+/**
+ * info
+ */
+static int info(ntfs_volume *vol)
+{
+	u64 a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u;
+	int cb, sb, cps;
+	u64 uc = 0, mc = 0, fc = 0;
+
+	struct mft_search_ctx *m_ctx;
+	ntfs_attr_search_ctx *a_ctx;
+	runlist_element *rl;
+	ATTR_RECORD *rec;
+	int z;
+	int inuse = 0;
+
+	m_ctx = mft_get_search_ctx(vol);
+	m_ctx->flags_search = FEMR_IN_USE | FEMR_METADATA | FEMR_BASE_RECORD | FEMR_NOT_BASE_RECORD;
+	while (mft_next_record(m_ctx) == 0) {
+
+		if (!(m_ctx->flags_match & FEMR_IN_USE))
+			continue;
+
+		inuse++;
+
+		a_ctx = ntfs_attr_get_search_ctx(m_ctx->inode, NULL);
+
+		while ((rec = find_attribute(AT_UNUSED, a_ctx))) {
+
+			if (!rec->non_resident)
+				continue;
+
+			rl = ntfs_mapping_pairs_decompress(vol, rec, NULL);
+
+			for (z = 0; rl[z].length > 0; z++)
+			{
+				if (rl[z].lcn >= 0) {
+					if (m_ctx->flags_match & FEMR_METADATA)
+						mc += rl[z].length;
+					else
+						uc += rl[z].length;
+				}
+
+			}
+
+			free(rl);
+		}
+
+		ntfs_attr_put_search_ctx(a_ctx);
+	}
+	mft_put_search_ctx(m_ctx);
+
+	cb  = vol->cluster_size_bits;
+	sb  = vol->sector_size_bits;
+	cps = cb - sb;
+
+	fc  = vol->nr_clusters-mc-uc;
+	fc  <<= cb;
+	mc  <<= cb;
+	uc  <<= cb;
+
+	a = vol->sector_size;
+	b = vol->cluster_size;
+	c = 1 << cps;
+	d = vol->nr_clusters << cb;
+	e = vol->nr_clusters;
+	f = vol->nr_clusters >> cps;
+	g = vol->mft_na->initialized_size >> vol->mft_record_size_bits;
+	h = inuse;
+	i = h * 100 / g;
+	j = fc;
+	k = fc >> sb;
+	l = fc >> cb;
+	m = fc * 100 / b / e;
+	n = uc;
+	o = uc >> sb;
+	p = uc >> cb;
+	q = uc * 100 / b / e;
+	r = mc;
+	s = mc >> sb;
+	t = mc >> cb;
+	u = mc * 100 / b / e;
+
+	ntfs_log_info("bytes per sector        : %llu\n", (unsigned long long)a);
+	ntfs_log_info("bytes per cluster       : %llu\n", (unsigned long long)b);
+	ntfs_log_info("sectors per cluster     : %llu\n", (unsigned long long)c);
+	ntfs_log_info("bytes per volume        : %llu\n", (unsigned long long)d);
+	ntfs_log_info("sectors per volume      : %llu\n", (unsigned long long)e);
+	ntfs_log_info("clusters per volume     : %llu\n", (unsigned long long)f);
+	ntfs_log_info("initialized mft records : %llu\n", (unsigned long long)g);
+	ntfs_log_info("mft records in use      : %llu\n", (unsigned long long)h);
+	ntfs_log_info("mft records percentage  : %llu\n", (unsigned long long)i);
+	ntfs_log_info("bytes of free space     : %llu\n", (unsigned long long)j);
+	ntfs_log_info("sectors of free space   : %llu\n", (unsigned long long)k);
+	ntfs_log_info("clusters of free space  : %llu\n", (unsigned long long)l);
+	ntfs_log_info("percentage free space   : %llu\n", (unsigned long long)m);
+	ntfs_log_info("bytes of user data      : %llu\n", (unsigned long long)n);
+	ntfs_log_info("sectors of user data    : %llu\n", (unsigned long long)o);
+	ntfs_log_info("clusters of user data   : %llu\n", (unsigned long long)p);
+	ntfs_log_info("percentage user data    : %llu\n", (unsigned long long)q);
+	ntfs_log_info("bytes of metadata       : %llu\n", (unsigned long long)r);
+	ntfs_log_info("sectors of metadata     : %llu\n", (unsigned long long)s);
+	ntfs_log_info("clusters of metadata    : %llu\n", (unsigned long long)t);
+	ntfs_log_info("percentage metadata     : %llu\n", (unsigned long long)u);
+
+	return 0;
+}
+
+/**
+ * dump_file
+ */
+static int dump_file(ntfs_volume *vol, ntfs_inode *ino)
+{
+	char buffer[1024];
+	ntfs_attr_search_ctx *ctx;
+	ATTR_RECORD *rec;
+	int i;
+	runlist *runs;
+
+	utils_inode_get_name(ino, buffer, sizeof(buffer));
+
+	ntfs_log_info("Dump: %s\n", buffer);
+
+	ctx = ntfs_attr_get_search_ctx(ino, NULL);
+
+	while ((rec = find_attribute(AT_UNUSED, ctx))) {
+		ntfs_log_info("    0x%02x - ", (int)le32_to_cpu(rec->type));
+		if (rec->non_resident) {
+			ntfs_log_info("non-resident\n");
+			runs = ntfs_mapping_pairs_decompress(vol, rec, NULL);
+			if (runs) {
+				ntfs_log_info("             VCN     LCN     Length\n");
+				for (i = 0; runs[i].length > 0; i++) {
+					ntfs_log_info("        %8lld %8lld %8lld\n",
+							(long long)runs[i].vcn,
+							(long long)runs[i].lcn,
+							(long long)
+							runs[i].length);
+				}
+				free(runs);
+			}
+		} else {
+			ntfs_log_info("resident\n");
+		}
+	}
+
+	ntfs_attr_put_search_ctx(ctx);
+	return 0;
+}
+
+/**
+ * print_match
+ */
+static int print_match(ntfs_inode *ino, ATTR_RECORD *attr,
+	runlist_element *run, void *data __attribute__((unused)))
+{
+	char *buffer;
+
+	if (!ino || !attr || !run)
+		return 1;
+
+	buffer = malloc(MAX_PATH);
+	if (!buffer) {
+		ntfs_log_error("!buffer\n");
+		return 1;
+	}
+
+	utils_inode_get_name(ino, buffer, MAX_PATH);
+	ntfs_log_info("Inode %llu %s", (unsigned long long)ino->mft_no, buffer);
+
+	utils_attr_get_name(ino->vol, attr, buffer, MAX_PATH);
+	ntfs_log_info("/%s\n", buffer);
+
+	free(buffer);
+	return 0;
+}
+
+/**
+ * find_last
+ */
+static int find_last(ntfs_inode *ino, ATTR_RECORD *attr, runlist_element *run,
+	void *data)
+{
+	struct match *m;
+
+	if (!ino || !attr || !run || !data)
+		return 1;
+
+	m = data;
+
+	if ((run->lcn + run->length) > m->lcn) {
+		m->inum = ino->mft_no;
+		m->lcn  = run->lcn + run->length;
+	}
+
+	return 0;
+}
+
+/**
+ * main - Begin here
+ *
+ * Start from here.
+ *
+ * Return:  0  Success, the program worked
+ *	    1  Error, something went wrong
+ */
+int main(int argc, char *argv[])
+{
+	ntfs_volume *vol;
+	ntfs_inode *ino = NULL;
+	struct match m;
+	int res;
+	int result = 1;
+
+	ntfs_log_set_handler(ntfs_log_handler_outerr);
+
+	res = parse_options(argc, argv);
+	if (res >= 0)
+		return (res);
+
+	utils_set_locale();
+
+	vol = utils_mount_volume(opts.device, NTFS_MNT_RDONLY |
+			(opts.force ? NTFS_MNT_RECOVER : 0));
+	if (!vol)
+		return 1;
+
+	switch (opts.action) {
+		case act_sector:
+			if (opts.range_begin == opts.range_end)
+				ntfs_log_quiet("Searching for sector %llu\n",
+						(unsigned long long)opts.range_begin);
+			else
+				ntfs_log_quiet("Searching for sector range %llu-%llu\n", (unsigned long long)opts.range_begin, (unsigned long long)opts.range_end);
+			/* Convert to clusters */
+			opts.range_begin >>= (vol->cluster_size_bits - vol->sector_size_bits);
+			opts.range_end   >>= (vol->cluster_size_bits - vol->sector_size_bits);
+			result = cluster_find(vol, opts.range_begin, opts.range_end, (cluster_cb*)&print_match, NULL);
+			break;
+		case act_cluster:
+			if (opts.range_begin == opts.range_end)
+				ntfs_log_quiet("Searching for cluster %llu\n",
+						(unsigned long long)opts.range_begin);
+			else
+				ntfs_log_quiet("Searching for cluster range %llu-%llu\n", (unsigned long long)opts.range_begin, (unsigned long long)opts.range_end);
+			result = cluster_find(vol, opts.range_begin, opts.range_end, (cluster_cb*)&print_match, NULL);
+			break;
+		case act_file:
+			ino = ntfs_pathname_to_inode(vol, NULL, opts.filename);
+			if (ino)
+				result = dump_file(vol, ino);
+			break;
+		case act_inode:
+			ino = ntfs_inode_open(vol, opts.inode);
+			if (ino) {
+				result = dump_file(vol, ino);
+				ntfs_inode_close(ino);
+			} else {
+				ntfs_log_error("Cannot open inode %llu\n",
+						(unsigned long long)opts.inode);
+			}
+			break;
+		case act_last:
+			memset(&m, 0, sizeof(m));
+			m.lcn = -1;
+			result = cluster_find(vol, 0, LONG_MAX, (cluster_cb*)&find_last, &m);
+			if (m.lcn >= 0) {
+				ino = ntfs_inode_open(vol, m.inum);
+				if (ino) {
+					result = dump_file(vol, ino);
+					ntfs_inode_close(ino);
+				} else {
+					ntfs_log_error("Cannot open inode %llu\n",
+							(unsigned long long)
+							opts.inode);
+				}
+				result = 0;
+			} else {
+				result = 1;
+			}
+			break;
+		case act_info:
+		default:
+			result = info(vol);
+			break;
+	}
+
+	ntfs_umount(vol, FALSE);
+	return result;
+}
+
+
diff --git a/ntfsprogs/ntfscluster.h b/ntfsprogs/ntfscluster.h
new file mode 100755
index 0000000000000000000000000000000000000000..5a3d6b3c0483460c2dd1a3f386af5ee2e755cc06
--- /dev/null
+++ b/ntfsprogs/ntfscluster.h
@@ -0,0 +1,63 @@
+/*
+ * ntfscluster - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2002-2003 Richard Russon
+ *
+ * This utility will locate the owner of any given sector or cluster.
+ *
+ * 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 Linux-NTFS
+ * 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 _NTFSCLUSTER_H_
+#define _NTFSCLUSTER_H_
+
+#include "types.h"
+#include "layout.h"
+
+enum action {
+	act_none,
+	act_info,
+	act_cluster,
+	act_sector,
+	act_inode,
+	act_file,
+	act_last,
+	act_error,
+};
+
+struct options {
+	char		*device;	/* Device/File to work with */
+	enum action	 action;	/* What to do */
+	int		 quiet;		/* Less output */
+	int		 verbose;	/* Extra output */
+	int		 force;		/* Override common sense */
+	char		*filename;	/* File to examine */
+	u64		 inode;		/* Inode to examine */
+	s64		 range_begin;	/* Look for objects in this range */
+	s64		 range_end;
+};
+
+struct match {
+	u64		 inum;		/* Inode number */
+	LCN		 lcn;		/* Last cluster in use */
+	ATTR_TYPES	 type;		/* Attribute type */
+	ntfschar	*name;		/* Attribute name */
+	int		 name_len;	/* Length of attribute name */
+};
+
+#endif /* _NTFSCLUSTER_H_ */
+
+
diff --git a/ntfsprogs/ntfscmp.8 b/ntfsprogs/ntfscmp.8
new file mode 100755
index 0000000000000000000000000000000000000000..1686fc4fa0ae1de5cdac1144c8beb0c87fc1b2df
--- /dev/null
+++ b/ntfsprogs/ntfscmp.8
@@ -0,0 +1,77 @@
+.\" Copyright (c) 2005\-2006 Szabolcs Szakacsits.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSCMP 8 "April 2006" "ntfs-3g 2015.3.14"
+.SH NAME
+ntfscmp \- compare two NTFS filesystems and tell the differences
+.SH SYNOPSIS
+.B ntfscmp
+[\fIOPTIONS\fR]
+.I DEVICE1
+.I DEVICE2
+.br
+.SH DESCRIPTION
+The
+.B ntfscmp
+program makes a comparison between two NTFS filesystems from all aspects and 
+reports all variances it finds.
+The filesystems can be on block devices or images files. Ntfscmp can be used
+for volume verification however its primary purpose was to be an efficient
+development tool, used to quickly locate, identify and check the correctness
+of the metadata changes made to NTFS. 
+
+If one is interested only in the NTFS metadata changes then it could be useful
+to compare the metadata images created by 
+using the --metadata option of
+.BR ntfsclone (8)
+to eliminate the usually uninteresting timestamp changes.
+
+The terse output of
+.B ntfscmp
+is intentional because the provided information is enough in each case
+to determine the exact differences. This can be achieved, for instance,
+if one compares the verbose outputs of
+.BR ntfsinfo (8)
+for each reported inodes by the 
+.BR diff (1)
+utility.
+.SH OPTIONS
+Below is a summary of the options that
+.B ntfscmp
+accepts.
+.TP
+\fB\-P\fR, \fB\-\-no\-progress\-bar\fR
+Don't show progress bars.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+More informational output.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Display help and exit.
+.SH EXIT CODES
+The exit code is 0 on success, non\-zero otherwise.
+.SH KNOWN ISSUES
+No problem is known. If you would find otherwise then please send
+your report to the development team:
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHOR
+.B ntfscmp
+was written by Szabolcs Szakacsits.
+It was ported to ntfs-3g by Erik Larsson.
+.SH AVAILABILITY
+.B ntfscmp
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR ntfsinfo (8),
+.BR ntfscat (8),
+.BR diff (1),
+.BR ntfsclone (8),
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/ntfscmp.8.in b/ntfsprogs/ntfscmp.8.in
new file mode 100755
index 0000000000000000000000000000000000000000..647cf5449ac4b4415e7e0624f978f1689f5eb28d
--- /dev/null
+++ b/ntfsprogs/ntfscmp.8.in
@@ -0,0 +1,77 @@
+.\" Copyright (c) 2005\-2006 Szabolcs Szakacsits.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSCMP 8 "April 2006" "ntfs-3g @VERSION@"
+.SH NAME
+ntfscmp \- compare two NTFS filesystems and tell the differences
+.SH SYNOPSIS
+.B ntfscmp
+[\fIOPTIONS\fR]
+.I DEVICE1
+.I DEVICE2
+.br
+.SH DESCRIPTION
+The
+.B ntfscmp
+program makes a comparison between two NTFS filesystems from all aspects and 
+reports all variances it finds.
+The filesystems can be on block devices or images files. Ntfscmp can be used
+for volume verification however its primary purpose was to be an efficient
+development tool, used to quickly locate, identify and check the correctness
+of the metadata changes made to NTFS. 
+
+If one is interested only in the NTFS metadata changes then it could be useful
+to compare the metadata images created by 
+using the --metadata option of
+.BR ntfsclone (8)
+to eliminate the usually uninteresting timestamp changes.
+
+The terse output of
+.B ntfscmp
+is intentional because the provided information is enough in each case
+to determine the exact differences. This can be achieved, for instance,
+if one compares the verbose outputs of
+.BR ntfsinfo (8)
+for each reported inodes by the 
+.BR diff (1)
+utility.
+.SH OPTIONS
+Below is a summary of the options that
+.B ntfscmp
+accepts.
+.TP
+\fB\-P\fR, \fB\-\-no\-progress\-bar\fR
+Don't show progress bars.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+More informational output.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Display help and exit.
+.SH EXIT CODES
+The exit code is 0 on success, non\-zero otherwise.
+.SH KNOWN ISSUES
+No problem is known. If you would find otherwise then please send
+your report to the development team:
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHOR
+.B ntfscmp
+was written by Szabolcs Szakacsits.
+It was ported to ntfs-3g by Erik Larsson.
+.SH AVAILABILITY
+.B ntfscmp
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR ntfsinfo (8),
+.BR ntfscat (8),
+.BR diff (1),
+.BR ntfsclone (8),
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/ntfscmp.c b/ntfsprogs/ntfscmp.c
new file mode 100755
index 0000000000000000000000000000000000000000..469d1d9a4a19628976bcd6c066033c5de4b7541c
--- /dev/null
+++ b/ntfsprogs/ntfscmp.c
@@ -0,0 +1,1012 @@
+/**
+ * ntfscmp - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2005-2006 Szabolcs Szakacsits
+ * Copyright (c) 2005      Anton Altaparmakov
+ * Copyright (c) 2007      Yura Pakhuchiy
+ *
+ * This utility compare two NTFS volumes.
+ *
+ * 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 Linux-NTFS
+ * 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"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <getopt.h>
+
+#include "mst.h"
+#include "support.h"
+#include "utils.h"
+#include "misc.h"
+/* #include "version.h" */
+
+static const char *EXEC_NAME = "ntfscmp";
+
+static const char *invalid_ntfs_msg =
+"Apparently device '%s' doesn't have a valid NTFS.\n"
+"Maybe you selected the wrong partition? Or the whole disk instead of a\n"
+"partition (e.g. /dev/hda, not /dev/hda1)?\n";
+
+static const char *corrupt_volume_msg =
+"Apparently you have a corrupted NTFS. Please run the filesystem checker\n"
+"on Windows by invoking chkdsk /f. Don't forget the /f (force) parameter,\n"
+"it's important! You probably also need to reboot Windows to take effect.\n";
+
+static const char *hibernated_volume_msg =
+"Apparently the NTFS partition is hibernated. Windows must be resumed and\n"
+"turned off properly\n";
+
+
+static struct {
+	int debug;
+	int show_progress;
+	int verbose;
+	char *vol1;
+	char *vol2;
+} opt;
+
+
+#define NTFS_PROGBAR		0x0001
+#define NTFS_PROGBAR_SUPPRESS	0x0002
+
+struct progress_bar {
+	u64 start;
+	u64 stop;
+	int resolution;
+	int flags;
+	float unit;
+};
+
+/* WARNING: don't modify the text, external tools grep for it */
+#define ERR_PREFIX   "ERROR"
+#define PERR_PREFIX  ERR_PREFIX "(%d): "
+#define NERR_PREFIX  ERR_PREFIX ": "
+
+__attribute__((format(printf, 2, 3)))
+static void perr_printf(int newline, const char *fmt, ...)
+{
+	va_list ap;
+	int eo = errno;
+
+	fprintf(stdout, PERR_PREFIX, eo);
+	va_start(ap, fmt);
+	vfprintf(stdout, fmt, ap);
+	va_end(ap);
+	fprintf(stdout, ": %s", strerror(eo));
+	if (newline)
+		fprintf(stdout, "\n");
+	fflush(stdout);
+	fflush(stderr);
+}
+
+#define perr_print(...)     perr_printf(0, __VA_ARGS__)
+#define perr_println(...)   perr_printf(1, __VA_ARGS__)
+
+__attribute__((format(printf, 1, 2)))
+static void err_printf(const char *fmt, ...)
+{
+	va_list ap;
+
+	fprintf(stdout, NERR_PREFIX);
+	va_start(ap, fmt);
+	vfprintf(stdout, fmt, ap);
+	va_end(ap);
+	fflush(stdout);
+	fflush(stderr);
+}
+
+/**
+ * err_exit
+ *
+ * Print and error message and exit the program.
+ */
+__attribute__((noreturn))
+__attribute__((format(printf, 1, 2)))
+static int err_exit(const char *fmt, ...)
+{
+	va_list ap;
+
+	fprintf(stdout, NERR_PREFIX);
+	va_start(ap, fmt);
+	vfprintf(stdout, fmt, ap);
+	va_end(ap);
+	fflush(stdout);
+	fflush(stderr);
+	exit(1);
+}
+
+/**
+ * perr_exit
+ *
+ * Print and error message and exit the program
+ */
+__attribute__((noreturn))
+__attribute__((format(printf, 1, 2)))
+static int perr_exit(const char *fmt, ...)
+{
+	va_list ap;
+	int eo = errno;
+
+	fprintf(stdout, PERR_PREFIX, eo);
+	va_start(ap, fmt);
+	vfprintf(stdout, fmt, ap);
+	va_end(ap);
+	printf(": %s\n", strerror(eo));
+	fflush(stdout);
+	fflush(stderr);
+	exit(1);
+}
+
+/**
+ * usage - Print a list of the parameters to the program
+ *
+ * Print a list of the parameters and options for the program.
+ *
+ * Return:  none
+ */
+__attribute__((noreturn))
+static void usage(void)
+{
+
+	printf("\nUsage: %s [OPTIONS] DEVICE1 DEVICE2\n"
+		"    Compare two NTFS volumes and tell the differences.\n"
+		"\n"
+		"    -P, --no-progress-bar  Don't show progress bar\n"
+		"    -v, --verbose          More output\n"
+		"    -h, --help             Display this help\n"
+#ifdef DEBUG
+		"    -d, --debug            Show debug information\n"
+#endif
+		"\n", EXEC_NAME);
+	printf("%s%s", ntfs_bugs, ntfs_home);
+	exit(1);
+}
+
+
+static void parse_options(int argc, char **argv)
+{
+	static const char *sopt = "-dhPv";
+	static const struct option lopt[] = {
+#ifdef DEBUG
+		{ "debug",		no_argument,	NULL, 'd' },
+#endif
+		{ "help",		no_argument,	NULL, 'h' },
+		{ "no-progress-bar",	no_argument,	NULL, 'P' },
+		{ "verbose",		no_argument,	NULL, 'v' },
+		{ NULL, 0, NULL, 0 }
+	};
+
+	int c;
+
+	memset(&opt, 0, sizeof(opt));
+	opt.show_progress = 1;
+
+	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
+		switch (c) {
+		case 1:	/* A non-option argument */
+			if (!opt.vol1) {
+				opt.vol1 = argv[optind - 1];
+			} else if (!opt.vol2) {
+				opt.vol2 = argv[optind - 1];
+			} else {
+				err_printf("Too many arguments!\n");
+				usage();
+			}
+			break;
+#ifdef DEBUG
+		case 'd':
+			opt.debug++;
+			break;
+#endif
+		case 'h':
+		case '?':
+			usage();
+		case 'P':
+			opt.show_progress = 0;
+			break;
+		case 'v':
+			opt.verbose++;
+			break;
+		default:
+			err_printf("Unknown option '%s'.\n", argv[optind - 1]);
+			usage();
+			break;
+		}
+	}
+
+	if (opt.vol1 == NULL || opt.vol2 == NULL) {
+		err_printf("You must specify exactly 2 volumes.\n");
+		usage();
+	}
+
+	/* Redirect stderr to stdout, note fflush()es are essential! */
+	fflush(stdout);
+	fflush(stderr);
+	if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1) {
+		perror("Failed to redirect stderr to stdout");
+		exit(1);
+	}
+	fflush(stdout);
+	fflush(stderr);
+
+#ifdef DEBUG
+	 if (!opt.debug)
+		if (!freopen("/dev/null", "w", stderr))
+			perr_exit("Failed to redirect stderr to /dev/null");
+#endif
+}
+
+static ntfs_attr_search_ctx *attr_get_search_ctx(ntfs_inode *ni)
+{
+	ntfs_attr_search_ctx *ret;
+
+	if ((ret = ntfs_attr_get_search_ctx(ni, NULL)) == NULL)
+		perr_println("ntfs_attr_get_search_ctx");
+
+	return ret;
+}
+
+static void progress_init(struct progress_bar *p, u64 start, u64 stop, int flags)
+{
+	p->start = start;
+	p->stop = stop;
+	p->unit = 100.0 / (stop - start);
+	p->resolution = 100;
+	p->flags = flags;
+}
+
+static void progress_update(struct progress_bar *p, u64 current)
+{
+	float percent;
+
+	if (!(p->flags & NTFS_PROGBAR))
+		return;
+	if (p->flags & NTFS_PROGBAR_SUPPRESS)
+		return;
+
+	/* WARNING: don't modify the texts, external tools grep for them */
+	percent = p->unit * current;
+	if (current != p->stop) {
+		if ((current - p->start) % p->resolution)
+			return;
+		printf("%6.2f percent completed\r", percent);
+	} else
+		printf("100.00 percent completed\n");
+	fflush(stdout);
+}
+
+static u64 inumber(ntfs_inode *ni)
+{
+	if (ni->nr_extents >= 0)
+		return ni->mft_no;
+
+	return ni->base_ni->mft_no;
+}
+
+static int inode_close(ntfs_inode *ni)
+{
+	if (ni == NULL)
+		return 0;
+
+	if (ntfs_inode_close(ni)) {
+		perr_println("ntfs_inode_close: inode %llu",
+				(unsigned long long)inumber(ni));
+		return -1;
+	}
+	return 0;
+}
+
+static inline s64 get_nr_mft_records(ntfs_volume *vol)
+{
+	return vol->mft_na->initialized_size >> vol->mft_record_size_bits;
+}
+
+#define  NTFSCMP_OK				0
+#define  NTFSCMP_INODE_OPEN_ERROR		1
+#define  NTFSCMP_INODE_OPEN_IO_ERROR		2
+#define  NTFSCMP_INODE_OPEN_ENOENT_ERROR	3
+#define  NTFSCMP_EXTENSION_RECORD		4
+#define  NTFSCMP_INODE_CLOSE_ERROR		5
+
+static const char *ntfscmp_errs[] = {
+	"OK",
+	"INODE_OPEN_ERROR",
+	"INODE_OPEN_IO_ERROR",
+	"INODE_OPEN_ENOENT_ERROR",
+	"EXTENSION_RECORD",
+	"INODE_CLOSE_ERROR",
+	""
+};
+
+
+static const char *err2string(int err)
+{
+	return ntfscmp_errs[err];
+}
+
+static const char *pret2str(void *p)
+{
+	if (p == NULL)
+		return "FAILED";
+	return "OK";
+}
+
+static int inode_open(ntfs_volume *vol, MFT_REF mref, ntfs_inode **ni)
+{
+	*ni = ntfs_inode_open(vol, mref);
+	if (*ni == NULL) {
+		if (errno == EIO)
+			return NTFSCMP_INODE_OPEN_IO_ERROR;
+		if (errno == ENOENT)
+			return NTFSCMP_INODE_OPEN_ENOENT_ERROR;
+
+		perr_println("Reading inode %lld failed", (long long)mref);
+		return NTFSCMP_INODE_OPEN_ERROR;
+	}
+
+	if ((*ni)->mrec->base_mft_record) {
+
+		if (inode_close(*ni) != 0)
+			return NTFSCMP_INODE_CLOSE_ERROR;
+
+		return NTFSCMP_EXTENSION_RECORD;
+	}
+
+	return NTFSCMP_OK;
+}
+
+static ntfs_inode *base_inode(ntfs_attr_search_ctx *ctx)
+{
+	if (ctx->base_ntfs_ino)
+		return ctx->base_ntfs_ino;
+
+	return ctx->ntfs_ino;
+}
+
+static void print_inode(u64 inum)
+{
+	printf("Inode %llu ", (unsigned long long)inum);
+}
+
+static void print_inode_ni(ntfs_inode *ni)
+{
+	print_inode(inumber(ni));
+}
+
+static void print_attribute_type(ATTR_TYPES atype)
+{
+	printf("attribute 0x%x", atype);
+}
+
+static void print_attribute_name(char *name)
+{
+	if (name)
+		printf(":%s", name);
+}
+
+#define	GET_ATTR_NAME(a) \
+	((ntfschar *)(((u8 *)(a)) + le16_to_cpu((a)->name_offset))), \
+	((a)->name_length)
+
+static void free_name(char **name)
+{
+	if (*name) {
+		free(*name);
+		*name = NULL;
+	}
+}
+
+static char *get_attr_name(u64 mft_no,
+			   ATTR_TYPES atype,
+			   const ntfschar *uname,
+			   const int uname_len)
+{
+	char *name = NULL;
+	int name_len;
+
+	if (atype == AT_END)
+		return NULL;
+
+	name_len = ntfs_ucstombs(uname, uname_len, &name, 0);
+	if (name_len < 0) {
+		perr_print("ntfs_ucstombs");
+		print_inode(mft_no);
+		print_attribute_type(atype);
+		puts("");
+		exit(1);
+
+	} else if (name_len > 0)
+		return name;
+
+	free_name(&name);
+	return NULL;
+}
+
+static char *get_attr_name_na(ntfs_attr *na)
+{
+	return get_attr_name(inumber(na->ni), na->type, na->name, na->name_len);
+}
+
+static char *get_attr_name_ctx(ntfs_attr_search_ctx *ctx)
+{
+	u64 mft_no = inumber(ctx->ntfs_ino);
+	ATTR_TYPES atype = ctx->attr->type;
+
+	return get_attr_name(mft_no, atype, GET_ATTR_NAME(ctx->attr));
+}
+
+static void print_attribute(ATTR_TYPES atype, char *name)
+{
+	print_attribute_type(atype);
+	print_attribute_name(name);
+	printf(" ");
+}
+
+static void print_na(ntfs_attr *na)
+{
+	char *name = get_attr_name_na(na);
+	print_inode_ni(na->ni);
+	print_attribute(na->type, name);
+	free_name(&name);
+}
+
+static void print_attribute_ctx(ntfs_attr_search_ctx *ctx)
+{
+	char *name = get_attr_name_ctx(ctx);
+	print_attribute(ctx->attr->type, name);
+	free_name(&name);
+}
+
+static void print_ctx(ntfs_attr_search_ctx *ctx)
+{
+	char *name = get_attr_name_ctx(ctx);
+	print_inode_ni(base_inode(ctx));
+	print_attribute(ctx->attr->type, name);
+	free_name(&name);
+}
+
+static void print_differ(ntfs_attr *na)
+{
+	print_na(na);
+	printf("content:   DIFFER\n");
+}
+
+static int cmp_buffer(u8 *buf1, u8 *buf2, long long int size, ntfs_attr *na)
+{
+	if (memcmp(buf1, buf2, size)) {
+		print_differ(na);
+		return -1;
+	}
+	return 0;
+}
+
+struct cmp_ia {
+	INDEX_ALLOCATION *ia;
+	INDEX_ALLOCATION *tmp_ia;
+	u8 *bitmap;
+	u8 *byte;
+	s64 bm_size;
+};
+
+static int setup_cmp_ia(ntfs_attr *na, struct cmp_ia *cia)
+{
+	cia->bitmap = ntfs_attr_readall(na->ni, AT_BITMAP, na->name,
+					na->name_len, &cia->bm_size);
+	if (!cia->bitmap) {
+		perr_println("Failed to readall BITMAP");
+		return -1;
+	}
+	cia->byte = cia->bitmap;
+
+	cia->tmp_ia = cia->ia = ntfs_malloc(na->data_size);
+	if (!cia->tmp_ia)
+		goto free_bm;
+
+	if (ntfs_attr_pread(na, 0, na->data_size, cia->ia) != na->data_size) {
+		perr_println("Failed to pread INDEX_ALLOCATION");
+		goto free_ia;
+	}
+
+	return 0;
+free_ia:
+	free(cia->ia);
+free_bm:
+	free(cia->bitmap);
+	return -1;
+}
+
+static void cmp_index_allocation(ntfs_attr *na1, ntfs_attr *na2)
+{
+	struct cmp_ia cia1, cia2;
+	int bit, ret1, ret2;
+	u32 ib_size;
+
+	if (setup_cmp_ia(na1, &cia1))
+		return;
+	if (setup_cmp_ia(na2, &cia2))
+		return;
+	/*
+	 *  FIXME: ia can be the same even if the bitmap sizes are different.
+	 */
+	if (cia1.bm_size != cia1.bm_size)
+		goto out;
+
+	if (cmp_buffer(cia1.bitmap, cia2.bitmap, cia1.bm_size, na1))
+		goto out;
+
+	if (cmp_buffer((u8 *)cia1.ia, (u8 *)cia2.ia, 0x18, na1))
+		goto out;
+
+	ib_size = le32_to_cpu(cia1.ia->index.allocated_size) + 0x18;
+
+	bit = 0;
+	while ((u8 *)cia1.tmp_ia < (u8 *)cia1.ia + na1->data_size) {
+		if (*cia1.byte & (1 << bit)) {
+			ret1 = ntfs_mst_post_read_fixup((NTFS_RECORD *)
+					cia1.tmp_ia, ib_size);
+			ret2 = ntfs_mst_post_read_fixup((NTFS_RECORD *)
+					cia2.tmp_ia, ib_size);
+			if (ret1 != ret2) {
+				print_differ(na1);
+				goto out;
+			}
+
+			if (ret1 == -1)
+				continue;
+
+			if (cmp_buffer(((u8 *)cia1.tmp_ia) + 0x18,
+					((u8 *)cia2.tmp_ia) + 0x18,
+					le32_to_cpu(cia1.ia->
+					index.index_length), na1))
+				goto out;
+		}
+
+		cia1.tmp_ia = (INDEX_ALLOCATION *)((u8 *)cia1.tmp_ia + ib_size);
+		cia2.tmp_ia = (INDEX_ALLOCATION *)((u8 *)cia2.tmp_ia + ib_size);
+
+		bit++;
+		if (bit > 7) {
+			bit = 0;
+			cia1.byte++;
+		}
+	}
+out:
+	free(cia1.ia);
+	free(cia2.ia);
+	free(cia1.bitmap);
+	free(cia2.bitmap);
+	return;
+}
+
+static void cmp_attribute_data(ntfs_attr *na1, ntfs_attr *na2)
+{
+	s64 pos;
+	s64 count1 = 0, count2;
+	u8  buf1[NTFS_BUF_SIZE];
+	u8  buf2[NTFS_BUF_SIZE];
+
+	for (pos = 0; pos <= na1->data_size; pos += count1) {
+
+		count1 = ntfs_attr_pread(na1, pos, NTFS_BUF_SIZE, buf1);
+		count2 = ntfs_attr_pread(na2, pos, NTFS_BUF_SIZE, buf2);
+
+		if (count1 != count2) {
+			print_na(na1);
+			printf("abrupt length:   %lld  !=  %lld ",
+				(long long)na1->data_size,
+				(long long)na2->data_size);
+			printf("(count: %lld  !=  %lld)",
+				(long long)count1, (long long)count2);
+			puts("");
+			return;
+		}
+
+		if (count1 == -1) {
+			err_printf("%s read error: ", __FUNCTION__);
+			print_na(na1);
+			printf("len = %lld, pos = %lld\n",
+				(long long)na1->data_size, (long long)pos);
+			exit(1);
+		}
+
+		if (count1 == 0) {
+
+			if (pos + count1 == na1->data_size)
+				return; /* we are ready */
+
+			err_printf("%s read error before EOF: ", __FUNCTION__);
+			print_na(na1);
+			printf("%lld  !=  %lld\n", (long long)pos + count1,
+					(long long)na1->data_size);
+			exit(1);
+		}
+
+		if (cmp_buffer(buf1, buf2, count1, na1))
+			return;
+	}
+
+	err_printf("%s read overrun: ", __FUNCTION__);
+	print_na(na1);
+	err_printf("(len = %lld, pos = %lld, count = %lld)\n",
+		  (long long)na1->data_size, (long long)pos, (long long)count1);
+	exit(1);
+}
+
+static int cmp_attribute_header(ATTR_RECORD *a1, ATTR_RECORD *a2)
+{
+	u32 header_size = offsetof(ATTR_RECORD, resident_end);
+
+	if (a1->non_resident != a2->non_resident)
+		return 1;
+
+	if (a1->non_resident) {
+		/*
+		 * FIXME: includes paddings which are not handled by ntfsinfo!
+		 */
+		header_size = le32_to_cpu(a1->length);
+	}
+
+	return memcmp(a1, a2, header_size);
+}
+
+static void cmp_attribute(ntfs_attr_search_ctx *ctx1,
+			  ntfs_attr_search_ctx *ctx2)
+{
+	ATTR_RECORD *a1 = ctx1->attr;
+	ATTR_RECORD *a2 = ctx2->attr;
+	ntfs_attr *na1, *na2;
+
+	if (cmp_attribute_header(a1, a2)) {
+		print_ctx(ctx1);
+		printf("header:    DIFFER\n");
+	}
+
+	na1 = ntfs_attr_open(base_inode(ctx1), a1->type, GET_ATTR_NAME(a1));
+	na2 = ntfs_attr_open(base_inode(ctx2), a2->type, GET_ATTR_NAME(a2));
+
+	if ((!na1 && na2) || (na1 && !na2)) {
+		print_ctx(ctx1);
+		printf("open:   %s  !=  %s\n", pret2str(na1), pret2str(na2));
+		goto close_attribs;
+	}
+
+	if (na1 == NULL)
+		goto close_attribs;
+
+	if (na1->data_size != na2->data_size) {
+		print_na(na1);
+		printf("length:   %lld  !=  %lld\n",
+			(long long)na1->data_size, (long long)na2->data_size);
+		goto close_attribs;
+	}
+
+	if (ntfs_inode_badclus_bad(inumber(ctx1->ntfs_ino), ctx1->attr) == 1) {
+		/*
+		 * If difference exists then it's already reported at the
+		 * attribute header since the mapping pairs must differ.
+		 */
+		goto close_attribs;
+	}
+
+	if (na1->type == AT_INDEX_ALLOCATION)
+		cmp_index_allocation(na1, na2);
+	else
+		cmp_attribute_data(na1, na2);
+
+close_attribs:
+	ntfs_attr_close(na1);
+	ntfs_attr_close(na2);
+}
+
+static void vprint_attribute(ATTR_TYPES atype, char  *name)
+{
+	if (!opt.verbose)
+		return;
+
+	printf("0x%x", atype);
+	if (name)
+		printf(":%s", name);
+	printf(" ");
+}
+
+static void print_attributes(ntfs_inode *ni,
+			     ATTR_TYPES atype1,
+			     ATTR_TYPES atype2,
+			     char  *name1,
+			     char  *name2)
+{
+	if (!opt.verbose)
+		return;
+
+	printf("Walking inode %llu attributes: ",
+			(unsigned long long)inumber(ni));
+	vprint_attribute(atype1, name1);
+	vprint_attribute(atype2, name2);
+	printf("\n");
+}
+
+static int new_name(ntfs_attr_search_ctx *ctx, char *prev_name)
+{
+	int ret = 0;
+	char *name = get_attr_name_ctx(ctx);
+
+	if (prev_name && name) {
+		if (strcmp(prev_name, name) != 0)
+			ret = 1;
+	} else if (prev_name || name)
+		ret = 1;
+
+	free_name(&name);
+	return ret;
+
+}
+
+static int new_attribute(ntfs_attr_search_ctx *ctx,
+			 ATTR_TYPES prev_atype,
+			 char *prev_name)
+{
+	if (!prev_atype && !prev_name)
+		return 1;
+
+	if (!ctx->attr->non_resident)
+		return 1;
+
+	if (prev_atype != ctx->attr->type)
+		return 1;
+
+	if (new_name(ctx, prev_name))
+		return 1;
+
+	if (opt.verbose) {
+		print_inode(base_inode(ctx)->mft_no);
+		print_attribute_ctx(ctx);
+		printf("record %llu lowest_vcn %lld:    SKIPPED\n",
+			(unsigned long long)ctx->ntfs_ino->mft_no,
+			(long long)ctx->attr->lowest_vcn);
+	}
+
+	return 0;
+}
+
+static void set_prev(char **prev_name, ATTR_TYPES *prev_atype,
+		     char *name, ATTR_TYPES atype)
+{
+	free_name(prev_name);
+	if (name) {
+		*prev_name = strdup(name);
+		if (!*prev_name)
+			perr_exit("strdup error");
+	}
+
+	*prev_atype = atype;
+}
+
+static void set_cmp_attr(ntfs_attr_search_ctx *ctx, ATTR_TYPES *atype, char **name)
+{
+	*atype = ctx->attr->type;
+
+	free_name(name);
+	*name = get_attr_name_ctx(ctx);
+}
+
+static int next_attr(ntfs_attr_search_ctx *ctx, ATTR_TYPES *atype, char **name,
+		     int *err)
+{
+	int ret;
+
+	ret = ntfs_attrs_walk(ctx);
+	*err = errno;
+	if (ret) {
+		*atype = AT_END;
+		free_name(name);
+	} else
+		set_cmp_attr(ctx, atype, name);
+
+	return ret;
+}
+
+static int cmp_attributes(ntfs_inode *ni1, ntfs_inode *ni2)
+{
+	int ret = -1;
+	int old_ret1, ret1 = 0, ret2 = 0;
+	int errno1 = 0, errno2 = 0;
+	char  *prev_name = NULL, *name1 = NULL, *name2 = NULL;
+	ATTR_TYPES old_atype1, prev_atype = 0, atype1, atype2;
+	ntfs_attr_search_ctx *ctx1, *ctx2;
+
+	if (!(ctx1 = attr_get_search_ctx(ni1)))
+		return -1;
+	if (!(ctx2 = attr_get_search_ctx(ni2)))
+		goto out;
+
+	set_cmp_attr(ctx1, &atype1, &name1);
+	set_cmp_attr(ctx2, &atype2, &name2);
+
+	while (1) {
+
+		old_atype1 = atype1;
+		old_ret1 = ret1;
+		if (!ret1 && (le32_to_cpu(atype1) <= le32_to_cpu(atype2) ||
+				ret2))
+			ret1 = next_attr(ctx1, &atype1, &name1, &errno1);
+		if (!ret2 && (le32_to_cpu(old_atype1) >= le32_to_cpu(atype2) ||
+					old_ret1))
+			ret2 = next_attr(ctx2, &atype2, &name2, &errno2);
+
+		print_attributes(ni1, atype1, atype2, name1, name2);
+
+		if (ret1 && ret2) {
+			if (errno1 != errno2) {
+				print_inode_ni(ni1);
+				printf("attribute walk (errno):   %d  !=  %d\n",
+				       errno1, errno2);
+			}
+			break;
+		}
+
+		if (ret2 || le32_to_cpu(atype1) < le32_to_cpu(atype2)) {
+			if (new_attribute(ctx1, prev_atype, prev_name)) {
+				print_ctx(ctx1);
+				printf("presence:   EXISTS   !=   MISSING\n");
+				set_prev(&prev_name, &prev_atype, name1,
+						atype1);
+			}
+
+		} else if (ret1 || le32_to_cpu(atype1) > le32_to_cpu(atype2)) {
+			if (new_attribute(ctx2, prev_atype, prev_name)) {
+				print_ctx(ctx2);
+				printf("presence:   MISSING  !=  EXISTS \n");
+				set_prev(&prev_name, &prev_atype, name2, atype2);
+			}
+
+		} else /* atype1 == atype2 */ {
+			if (new_attribute(ctx1, prev_atype, prev_name)) {
+				cmp_attribute(ctx1, ctx2);
+				set_prev(&prev_name, &prev_atype, name1, atype1);
+			}
+		}
+	}
+
+	free_name(&prev_name);
+	ret = 0;
+	ntfs_attr_put_search_ctx(ctx2);
+out:
+	ntfs_attr_put_search_ctx(ctx1);
+	return ret;
+}
+
+static int cmp_inodes(ntfs_volume *vol1, ntfs_volume *vol2)
+{
+	u64 inode;
+	int ret1, ret2;
+	ntfs_inode *ni1, *ni2;
+	struct progress_bar progress;
+	int pb_flags = 0;	/* progress bar flags */
+	u64 nr_mft_records, nr_mft_records2;
+
+	if (opt.show_progress)
+		pb_flags |= NTFS_PROGBAR;
+
+	nr_mft_records  = get_nr_mft_records(vol1);
+	nr_mft_records2 = get_nr_mft_records(vol2);
+
+	if (nr_mft_records != nr_mft_records2) {
+
+		printf("Number of mft records:   %lld  !=  %lld\n",
+		       (long long)nr_mft_records, (long long)nr_mft_records2);
+
+		if (nr_mft_records > nr_mft_records2)
+			nr_mft_records = nr_mft_records2;
+	}
+
+	progress_init(&progress, 0, nr_mft_records - 1, pb_flags);
+	progress_update(&progress, 0);
+
+	for (inode = 0; inode < nr_mft_records; inode++) {
+
+		ret1 = inode_open(vol1, (MFT_REF)inode, &ni1);
+		ret2 = inode_open(vol2, (MFT_REF)inode, &ni2);
+
+		if (ret1 != ret2) {
+			print_inode(inode);
+			printf("open:   %s  !=  %s\n",
+			       err2string(ret1), err2string(ret2));
+			goto close_inodes;
+		}
+
+		if (ret1 != NTFSCMP_OK)
+			goto close_inodes;
+
+		if (cmp_attributes(ni1, ni2) != 0) {
+			inode_close(ni1);
+			inode_close(ni2);
+			return -1;
+		}
+close_inodes:
+		if (inode_close(ni1) != 0)
+			return -1;
+		if (inode_close(ni2) != 0)
+			return -1;
+
+		progress_update(&progress, inode);
+	}
+	return 0;
+}
+
+static ntfs_volume *mount_volume(const char *volume)
+{
+	unsigned long mntflag;
+	ntfs_volume *vol = NULL;
+
+	if (ntfs_check_if_mounted(volume, &mntflag)) {
+		perr_println("Failed to check '%s' mount state", volume);
+		printf("Probably /etc/mtab is missing. It's too risky to "
+		       "continue. You might try\nan another Linux distro.\n");
+		exit(1);
+	}
+	if (mntflag & NTFS_MF_MOUNTED) {
+		if (!(mntflag & NTFS_MF_READONLY))
+			err_exit("Device '%s' is mounted read-write. "
+				 "You must 'umount' it first.\n", volume);
+	}
+
+	vol = ntfs_mount(volume, NTFS_MNT_RDONLY);
+	if (vol == NULL) {
+
+		int err = errno;
+
+		perr_println("Opening '%s' as NTFS failed", volume);
+		if (err == EINVAL)
+			printf(invalid_ntfs_msg, volume);
+		else if (err == EIO)
+			puts(corrupt_volume_msg);
+		else if (err == EPERM)
+			puts(hibernated_volume_msg);
+		exit(1);
+	}
+
+	return vol;
+}
+
+int main(int argc, char **argv)
+{
+	ntfs_volume *vol1;
+	ntfs_volume *vol2;
+
+	printf("%s v%s (libntfs-3g)\n", EXEC_NAME, VERSION);
+
+	parse_options(argc, argv);
+
+	utils_set_locale();
+
+	vol1 = mount_volume(opt.vol1);
+        vol2 = mount_volume(opt.vol2);
+
+	if (cmp_inodes(vol1, vol2) != 0)
+		exit(1);
+
+	ntfs_umount(vol1, FALSE);
+	ntfs_umount(vol2, FALSE);
+
+	return (0);
+}
+
diff --git a/ntfsprogs/ntfscp.8 b/ntfsprogs/ntfscp.8
new file mode 100755
index 0000000000000000000000000000000000000000..4f5838e6912d026fe2218e1290ad196c99408297
--- /dev/null
+++ b/ntfsprogs/ntfscp.8
@@ -0,0 +1,115 @@
+.\" Copyright (c) 2004\-2007 Yura Pakhuchiy.
+.\" Copyright (c) 2005 Richard Russon.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSCP 8 "September 2007" "ntfs-3g 2015.3.14"
+.SH NAME
+ntfscp \- copy file to an NTFS volume.
+.SH SYNOPSIS
+\fBntfscp\fR [\fIoptions\fR] \fIdevice source_file destination\fR
+.SH DESCRIPTION
+\fBntfscp\fR will copy file to an NTFS volume. \fIdestination\fR can be either
+file or directory. In case if \fIdestination\fR is directory specified by name
+then \fIsource_file\fR is copied into this directory, in case if
+\fIdestination\fR is directory and specified by inode number then unnamed data
+attribute is created for this inode and \fIsource_file\fR is copied into it
+(WARNING: it's unusual to have unnamed data streams in the directories, think
+twice before specifying directory by inode number).
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfscp
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-a\fR, \fB\-\-attribute\fR NUM
+Write to this attribute.
+.TP
+\fB\-i\fR, \fB\-\-inode\fR
+Treat
+.I destination
+as inode number.
+.TP
+\fB\-m\fR, \fB\-\-min-fragments\fR
+Minimize fragmentation when allocating space to the attribute. This is
+mostly useful when creating big files.
+.TP
+\fB\-N\fR, \fB\-\-attr\-name\fR NAME
+Write to attribute with this name.
+.TP
+\fB\-n\fR, \fB\-\-no\-action\fR
+Use this option to make a test run before doing the real copy operation.
+Volume will be opened read\-only and no write will be done.
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+This will override some sensible defaults, such as not working with a mounted
+volume.  Use this option with caution.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Suppress some debug/warning/error messages.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Show the version number, copyright and license
+.BR ntfscp .
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Display more debug/warning/error messages.
+.SH DATA STREAMS
+All data on NTFS is stored in streams, which can have names. A file can have
+more than one data streams, but exactly one must have no name. The size of a
+file is the size of its unnamed data stream. Usually when you don't specify
+stream name you are access to unnamed data stream. If you want access to named
+data stream you need to add ":stream_name" to the filename. For example: by
+opening "some.mp3:artist" you will open stream "artist" in "some.mp3". But
+windows usually prevent you from accessing to named data streams, so you need
+to use some program like FAR or utils from cygwin to access named data streams.
+.SH EXAMPLES
+Copy new_boot.ini from /home/user as boot.ini to the root of an /dev/hda1 NTFS
+volume:
+.RS
+.sp
+.B ntfscp /dev/hda1 /home/user/new_boot.ini boot.ini
+.sp
+.RE
+Copy myfile to C:\\some\\path\\myfile:stream (assume that /dev/hda1 letter in
+windows is C):
+.RS
+.sp
+.B ntfscp \-N stream /dev/hda1 myfile /some/path
+.sp
+.RE
+.SH BUGS
+There are no known problems with \fBntfscp\fR. If you find a bug please send an
+email describing the problem to the development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+\fBntfscp\fR was written by Yura Pakhuchiy, with contributions from Anton
+Altaparmakov and Hil Liao.
+It was ported to ntfs-3g by Erik Larsson.
+.SH DEDICATION
+With love to Marina Sapego.
+.SH AVAILABILITY
+.B ntfscp
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/ntfscp.8.in b/ntfsprogs/ntfscp.8.in
new file mode 100755
index 0000000000000000000000000000000000000000..bf5127baecf0119c38722ffb36e568e2b1f152d9
--- /dev/null
+++ b/ntfsprogs/ntfscp.8.in
@@ -0,0 +1,115 @@
+.\" Copyright (c) 2004\-2007 Yura Pakhuchiy.
+.\" Copyright (c) 2005 Richard Russon.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSCP 8 "September 2007" "ntfs-3g @VERSION@"
+.SH NAME
+ntfscp \- copy file to an NTFS volume.
+.SH SYNOPSIS
+\fBntfscp\fR [\fIoptions\fR] \fIdevice source_file destination\fR
+.SH DESCRIPTION
+\fBntfscp\fR will copy file to an NTFS volume. \fIdestination\fR can be either
+file or directory. In case if \fIdestination\fR is directory specified by name
+then \fIsource_file\fR is copied into this directory, in case if
+\fIdestination\fR is directory and specified by inode number then unnamed data
+attribute is created for this inode and \fIsource_file\fR is copied into it
+(WARNING: it's unusual to have unnamed data streams in the directories, think
+twice before specifying directory by inode number).
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfscp
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-a\fR, \fB\-\-attribute\fR NUM
+Write to this attribute.
+.TP
+\fB\-i\fR, \fB\-\-inode\fR
+Treat
+.I destination
+as inode number.
+.TP
+\fB\-m\fR, \fB\-\-min-fragments\fR
+Minimize fragmentation when allocating space to the attribute. This is
+mostly useful when creating big files.
+.TP
+\fB\-N\fR, \fB\-\-attr\-name\fR NAME
+Write to attribute with this name.
+.TP
+\fB\-n\fR, \fB\-\-no\-action\fR
+Use this option to make a test run before doing the real copy operation.
+Volume will be opened read\-only and no write will be done.
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+This will override some sensible defaults, such as not working with a mounted
+volume.  Use this option with caution.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Suppress some debug/warning/error messages.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Show the version number, copyright and license
+.BR ntfscp .
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Display more debug/warning/error messages.
+.SH DATA STREAMS
+All data on NTFS is stored in streams, which can have names. A file can have
+more than one data streams, but exactly one must have no name. The size of a
+file is the size of its unnamed data stream. Usually when you don't specify
+stream name you are access to unnamed data stream. If you want access to named
+data stream you need to add ":stream_name" to the filename. For example: by
+opening "some.mp3:artist" you will open stream "artist" in "some.mp3". But
+windows usually prevent you from accessing to named data streams, so you need
+to use some program like FAR or utils from cygwin to access named data streams.
+.SH EXAMPLES
+Copy new_boot.ini from /home/user as boot.ini to the root of an /dev/hda1 NTFS
+volume:
+.RS
+.sp
+.B ntfscp /dev/hda1 /home/user/new_boot.ini boot.ini
+.sp
+.RE
+Copy myfile to C:\\some\\path\\myfile:stream (assume that /dev/hda1 letter in
+windows is C):
+.RS
+.sp
+.B ntfscp \-N stream /dev/hda1 myfile /some/path
+.sp
+.RE
+.SH BUGS
+There are no known problems with \fBntfscp\fR. If you find a bug please send an
+email describing the problem to the development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+\fBntfscp\fR was written by Yura Pakhuchiy, with contributions from Anton
+Altaparmakov and Hil Liao.
+It was ported to ntfs-3g by Erik Larsson.
+.SH DEDICATION
+With love to Marina Sapego.
+.SH AVAILABILITY
+.B ntfscp
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/ntfscp.c b/ntfsprogs/ntfscp.c
new file mode 100755
index 0000000000000000000000000000000000000000..87a7da30055fba51f590823c5dfd5d92a87c12cd
--- /dev/null
+++ b/ntfsprogs/ntfscp.c
@@ -0,0 +1,1133 @@
+/**
+ * ntfscp - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2004-2007 Yura Pakhuchiy
+ * Copyright (c) 2005 Anton Altaparmakov
+ * Copyright (c) 2006 Hil Liao
+ * Copyright (c) 2014 Jean-Pierre Andre
+ *
+ * This utility will copy file to an NTFS volume.
+ *
+ * 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 Linux-NTFS
+ * 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_GETOPT_H
+#include <getopt.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#include <signal.h>
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_LIBGEN_H
+#include <libgen.h>
+#endif
+
+#include "types.h"
+#include "attrib.h"
+#include "utils.h"
+#include "volume.h"
+#include "dir.h"
+#include "bitmap.h"
+#include "debug.h"
+/* #include "version.h" */
+#include "logging.h"
+#include "misc.h"
+
+struct options {
+	char		*device;	/* Device/File to work with */
+	char		*src_file;	/* Source file */
+	char		*dest_file;	/* Destination file */
+	char		*attr_name;	/* Write to attribute with this name. */
+	int		 force;		/* Override common sense */
+	int		 quiet;		/* Less output */
+	int		 verbose;	/* Extra output */
+	int		 minfragments;	/* Do minimal fragmentation */
+	int		 noaction;	/* Do not write to disk */
+	ATTR_TYPES	 attribute;	/* Write to this attribute. */
+	int		 inode;		/* Treat dest_file as inode number. */
+};
+
+struct ALLOC_CONTEXT {
+	ntfs_volume *vol;
+	ntfs_attr *na;
+	runlist_element *rl;
+	unsigned char *buf;
+	s64 gathered_clusters;
+	s64 wanted_clusters;
+	s64 new_size;
+	s64 lcn;
+	int rl_allocated;
+	int rl_count;
+} ;
+
+enum STEP { STEP_ERR, STEP_ZERO, STEP_ONE } ;
+
+static const char *EXEC_NAME = "ntfscp";
+static struct options opts;
+static volatile sig_atomic_t caught_terminate = 0;
+
+/**
+ * version - Print version information about the program
+ *
+ * Print a copyright statement and a brief description of the program.
+ *
+ * Return:  none
+ */
+static void version(void)
+{
+	ntfs_log_info("\n%s v%s (libntfs-3g) - Copy file to an NTFS "
+		"volume.\n\n", EXEC_NAME, VERSION);
+	ntfs_log_info("Copyright (c) 2004-2007 Yura Pakhuchiy\n");
+	ntfs_log_info("Copyright (c) 2005 Anton Altaparmakov\n");
+	ntfs_log_info("Copyright (c) 2006 Hil Liao\n");
+	ntfs_log_info("Copyright (c) 2014 Jean-Pierre Andre\n");
+	ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
+}
+
+/**
+ * usage - Print a list of the parameters to the program
+ *
+ * Print a list of the parameters and options for the program.
+ *
+ * Return:  none
+ */
+static void usage(void)
+{
+	ntfs_log_info("\nUsage: %s [options] device src_file dest_file\n\n"
+		"    -a, --attribute NUM   Write to this attribute\n"
+		"    -i, --inode           Treat dest_file as inode number\n"
+		"    -f, --force           Use less caution\n"
+		"    -h, --help            Print this help\n"
+		"    -m, --min_fragments   Do minimal fragmentation\n"
+		"    -N, --attr-name NAME  Write to attribute with this name\n"
+		"    -n, --no-action       Do not write to disk\n"
+		"    -q, --quiet           Less output\n"
+		"    -V, --version         Version information\n"
+		"    -v, --verbose         More output\n\n",
+		EXEC_NAME);
+	ntfs_log_info("%s%s\n", ntfs_bugs, ntfs_home);
+}
+
+/**
+ * parse_options - Read and validate the programs command line
+ *
+ * Read the command line, verify the syntax and parse the options.
+ * This function is very long, but quite simple.
+ *
+ * Return:  1 Success
+ *	    0 Error, one or more problems
+ */
+static int parse_options(int argc, char **argv)
+{
+	static const char *sopt = "-a:ifh?mN:no:qVv";
+	static const struct option lopt[] = {
+		{ "attribute",	required_argument,	NULL, 'a' },
+		{ "inode",	no_argument,		NULL, 'i' },
+		{ "force",	no_argument,		NULL, 'f' },
+		{ "help",	no_argument,		NULL, 'h' },
+		{ "min-fragments", no_argument,		NULL, 'm' },
+		{ "attr-name",	required_argument,	NULL, 'N' },
+		{ "no-action",	no_argument,		NULL, 'n' },
+		{ "quiet",	no_argument,		NULL, 'q' },
+		{ "version",	no_argument,		NULL, 'V' },
+		{ "verbose",	no_argument,		NULL, 'v' },
+		{ NULL,		0,			NULL, 0   }
+	};
+
+	char *s;
+	int c = -1;
+	int err  = 0;
+	int ver  = 0;
+	int help = 0;
+	int levels = 0;
+	s64 attr;
+
+	opts.device = NULL;
+	opts.src_file = NULL;
+	opts.dest_file = NULL;
+	opts.attr_name = NULL;
+	opts.inode = 0;
+	opts.attribute = AT_DATA;
+
+	opterr = 0; /* We'll handle the errors, thank you. */
+
+	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
+		switch (c) {
+		case 1:	/* A non-option argument */
+			if (!opts.device) {
+				opts.device = argv[optind - 1];
+			} else if (!opts.src_file) {
+				opts.src_file = argv[optind - 1];
+			} else if (!opts.dest_file) {
+				opts.dest_file = argv[optind - 1];
+			} else {
+				ntfs_log_error("You must specify exactly two "
+						"files.\n");
+				err++;
+			}
+			break;
+		case 'a':
+			if (opts.attribute != AT_DATA) {
+				ntfs_log_error("You can specify only one "
+						"attribute.\n");
+				err++;
+				break;
+			}
+
+			attr = strtol(optarg, &s, 0);
+			if (*s) {
+				ntfs_log_error("Couldn't parse attribute.\n");
+				err++;
+			} else
+				opts.attribute = (ATTR_TYPES)cpu_to_le32(attr);
+			break;
+		case 'i':
+			opts.inode++;
+			break;
+		case 'f':
+			opts.force++;
+			break;
+		case 'h':
+			help++;
+			break;
+		case 'm':
+			opts.minfragments++;
+			break;
+		case 'N':
+			if (opts.attr_name) {
+				ntfs_log_error("You can specify only one "
+						"attribute name.\n");
+				err++;
+			} else
+				opts.attr_name = argv[optind - 1];
+			break;
+		case 'n':
+			opts.noaction++;
+			break;
+		case 'q':
+			opts.quiet++;
+			ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
+			break;
+		case 'V':
+			ver++;
+			break;
+		case 'v':
+			opts.verbose++;
+			ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
+			break;
+		case '?':
+			if (strncmp(argv[optind - 1], "--log-", 6) == 0) {
+				if (!ntfs_log_parse_option(argv[optind - 1]))
+					err++;
+				break;
+			}
+			/* fall through */
+		default:
+			ntfs_log_error("Unknown option '%s'.\n",
+					argv[optind - 1]);
+			err++;
+			break;
+		}
+	}
+
+	/* Make sure we're in sync with the log levels */
+	levels = ntfs_log_get_levels();
+	if (levels & NTFS_LOG_LEVEL_VERBOSE)
+		opts.verbose++;
+	if (!(levels & NTFS_LOG_LEVEL_QUIET))
+		opts.quiet++;
+
+	if (help || ver) {
+		opts.quiet = 0;
+	} else {
+		if (!opts.device) {
+			ntfs_log_error("You must specify a device.\n");
+			err++;
+		} else if (!opts.src_file) {
+			ntfs_log_error("You must specify a source file.\n");
+			err++;
+		} else if (!opts.dest_file) {
+			ntfs_log_error("You must specify a destination "
+					"file.\n");
+			err++;
+		}
+
+		if (opts.quiet && opts.verbose) {
+			ntfs_log_error("You may not use --quiet and --verbose "
+					"at the same time.\n");
+			err++;
+		}
+	}
+
+	if (ver)
+		version();
+	if (help || err)
+		usage();
+
+		/* tri-state 0 : done, 1 : error, -1 : proceed */
+	return (err ? 1 : (help || ver ? 0 : -1));
+}
+
+/**
+ * signal_handler - Handle SIGINT and SIGTERM: abort write, sync and exit.
+ */
+static void signal_handler(int arg __attribute__((unused)))
+{
+	caught_terminate++;
+}
+
+/*
+ *		Search for the next '0' in a bitmap chunk
+ *
+ *	Returns the position of next '0'
+ *		or -1 if there are no more '0's
+ */
+
+static int next_zero(struct ALLOC_CONTEXT *alctx, s32 bufpos, s32 count)
+{
+	s32 index;
+	unsigned int q,b;
+
+	index = -1;
+	while ((index < 0) && (bufpos < count)) {
+		q = alctx->buf[bufpos >> 3];
+		if (q == 255)
+			bufpos = (bufpos | 7) + 1;
+		else {
+			b = bufpos & 7;
+			while ((b < 8)
+			    && ((1 << b) & q))
+				b++;
+			if (b < 8) {
+				index = (bufpos & -8) | b;
+			} else {
+				bufpos = (bufpos | 7) + 1;
+			}
+		}
+	}
+	return (index);
+}
+
+/*
+ *		Search for the next '1' in a bitmap chunk
+ *
+ *	Returns the position of next '1'
+ *		or -1 if there are no more '1's
+ */
+
+static int next_one(struct ALLOC_CONTEXT *alctx, s32 bufpos, s32 count)
+{
+	s32 index;
+	unsigned int q,b;
+
+	index = -1;
+	while ((index < 0) && (bufpos < count)) {
+		q = alctx->buf[bufpos >> 3];
+		if (q == 0)
+			bufpos = (bufpos | 7) + 1;
+		else {
+			b = bufpos & 7;
+			while ((b < 8)
+			    && !((1 << b) & q))
+				b++;
+			if (b < 8) {
+				index = (bufpos & -8) | b;
+			} else {
+				bufpos = (bufpos | 7) + 1;
+			}
+		}
+	}
+	return (index);
+}
+
+/*
+ *		Allocate a bigger runlist when needed
+ *
+ *	The allocation is done by multiple of 4096 entries to avoid
+ *	frequent reallocations.
+ *
+ *	Returns 0 if successful
+ *		-1 otherwise, with errno set accordingly
+ */
+
+static int run_alloc(struct ALLOC_CONTEXT *alctx, s32 count)
+{
+	runlist_element *prl;
+	int err;
+
+	err = 0;
+	if (count > alctx->rl_allocated) {
+		prl = (runlist_element*)ntfs_malloc(
+			(alctx->rl_allocated + 4096)*sizeof(runlist_element));
+		if (prl) {
+			if (alctx->rl) {
+				memcpy(prl, alctx->rl, alctx->rl_allocated
+						*sizeof(runlist_element));
+				free(alctx->rl);
+			}
+			alctx->rl = prl;
+			alctx->rl_allocated += 4096;
+		} else
+			err = -1;
+	}
+	return (err);
+}
+
+/*
+ *		Merge a new run into the current optimal runlist
+ *
+ *	The new run is inserted only if it leads to improving the runlist.
+ *	Runs in the current list are dropped when inserting the new one
+ *	make them unneeded.
+ *	The current runlist is sorted by run sizes, and there is no
+ *	terminator.
+ *
+ *	Returns 0 if successful
+ *		-1 otherwise, with errno set accordingly
+ */
+
+static int merge_run(struct ALLOC_CONTEXT *alctx, s64 lcn, s32 count)
+{
+	s64 excess;
+	BOOL replace;
+	int k;
+	int drop;
+	int err;
+
+	err = 0;
+	if (alctx->rl_count) {
+		excess = alctx->gathered_clusters + count
+				- alctx->wanted_clusters;
+		if (alctx->rl_count > 1)
+			/* replace if we can reduce the number of runs */
+			replace = excess > (alctx->rl[0].length
+						+ alctx->rl[1].length);
+		else
+			/* replace if we can shorten a single run */
+			replace = (excess > alctx->rl[0].length)
+				&& (count < alctx->rl[0].length);
+	} else
+		replace = FALSE;
+	if (replace) {
+			/* Using this run, we can now drop smaller runs */
+		drop = 0;
+		excess = alctx->gathered_clusters + count
+					- alctx->wanted_clusters;
+			/* Compute how many clusters we can drop */
+		while ((drop < alctx->rl_count)
+		    && (alctx->rl[drop].length <= excess)) {
+			excess -= alctx->rl[drop].length;
+			drop++;
+		}
+		k = 0;
+		while (((k + drop) < alctx->rl_count)
+		   && (alctx->rl[k + drop].length < count)) {
+			alctx->rl[k] = alctx->rl[k + drop];
+			k++;
+		}
+		alctx->rl[k].length = count;
+		alctx->rl[k].lcn = lcn;
+		if (drop > 1) {
+			while ((k + drop) < alctx->rl_count) {
+				alctx->rl[k + 1] = alctx->rl[k + drop];
+				k++;
+			}
+		}
+		alctx->rl_count -= (drop - 1);
+		alctx->gathered_clusters = alctx->wanted_clusters + excess;
+	} else {
+		if (alctx->gathered_clusters < alctx->wanted_clusters) {
+			/* We had not gathered enough clusters */
+			if (!run_alloc(alctx, alctx->rl_count + 1)) {
+				k = alctx->rl_count - 1;
+				while ((k >= 0)
+				    && (alctx->rl[k].length > count)) {
+					alctx->rl[k+1] = alctx->rl[k];
+					k--;
+				}
+				alctx->rl[k+1].length = count;
+				alctx->rl[k+1].lcn = lcn;
+				alctx->rl_count++;
+				alctx->gathered_clusters += count;
+			}
+		}
+	}
+	return (err);
+}
+
+/*
+ *		Examine a buffer from the global bitmap
+ *	in order to locate free runs of clusters
+ *
+ *	Returns STEP_ZERO or STEP_ONE depending on whether the last
+ *		bit examined was in a search for '0' or '1'. This must be
+ *		put as argument to next examination.
+ *	Returns STEP_ERR if there was an error.
+ */
+
+static enum STEP examine_buf(struct ALLOC_CONTEXT *alctx, s64 pos, s64 br,
+			enum STEP step)
+{
+	s32 count;
+	s64 offbuf; /* first bit available in buf */
+	s32 bufpos; /* bit index in buf */
+	s32 index;
+
+	bufpos = pos & ((alctx->vol->cluster_size << 3) - 1);
+	offbuf = pos - bufpos;
+	while (bufpos < (br << 3)) {
+		if (step == STEP_ZERO) {
+				/* find first zero */
+			index = next_zero(alctx, bufpos, br << 3);
+			if (index >= 0) {
+				alctx->lcn = offbuf + index;
+				step = STEP_ONE;
+				bufpos = index;
+			} else {
+				bufpos = br << 3;
+			}
+		} else {
+				/* find first one */
+			index = next_one(alctx, bufpos, br << 3);
+			if (index >= 0) {
+				count = offbuf + index - alctx->lcn;
+				step = STEP_ZERO;
+				bufpos = index;
+				if (merge_run(alctx, alctx->lcn, count)) {
+					step = STEP_ERR;
+					bufpos = br << 3;
+				}
+			} else {
+				bufpos = br << 3;
+			}
+		}
+	}
+	return (step);
+}
+
+/*
+ *		Sort the final runlist by lcn's and insert a terminator
+ *
+ *	Returns 0 if successful
+ *		-1 otherwise, with errno set accordingly
+ */
+
+static int sort_runlist(struct ALLOC_CONTEXT *alctx)
+{
+	LCN lcn;
+	VCN vcn;
+	s64 length;
+	BOOL sorted;
+	int err;
+	int k;
+
+	err = 0;
+			/* This sorting can be much improved... */
+	do {
+		sorted = TRUE;
+		for (k=0; (k+1)<alctx->rl_count; k++) {
+			if (alctx->rl[k+1].lcn < alctx->rl[k].lcn) {
+				length = alctx->rl[k].length;
+				lcn = alctx->rl[k].lcn;
+				alctx->rl[k] = alctx->rl[k+1];
+				alctx->rl[k+1].length = length;
+				alctx->rl[k+1].lcn = lcn;
+				sorted = FALSE;
+			}
+		}
+	} while (!sorted);
+		/* compute the vcns */
+	vcn = 0;
+	for (k=0; k<alctx->rl_count; k++) {
+		alctx->rl[k].vcn = vcn;
+		vcn += alctx->rl[k].length;
+	}
+		/* Shorten the last run if we got too much */
+	if (vcn > alctx->wanted_clusters) {
+		k = alctx->rl_count - 1;
+		alctx->rl[k].length -= vcn - alctx->wanted_clusters;
+		vcn = alctx->wanted_clusters;
+	}
+		/* Append terminator */
+	if (run_alloc(alctx, alctx->rl_count + 1))
+		err = -1;
+	else {
+		k = alctx->rl_count++;
+		alctx->rl[k].vcn = vcn;
+		alctx->rl[k].length = 0;
+		alctx->rl[k].lcn = LCN_ENOENT;
+	}
+	return (err);
+}
+
+/*
+ *		Update the sizes of an attribute
+ *
+ *	Returns 0 if successful
+ *		-1 otherwise, with errno set accordingly
+ */
+
+static int set_sizes(struct ALLOC_CONTEXT *alctx, ntfs_attr_search_ctx *ctx)
+{
+	ntfs_attr *na;
+	ntfs_inode *ni;
+	ATTR_RECORD *attr;
+
+	na = alctx->na;
+				/* Compute the sizes */
+	na->data_size = alctx->new_size;
+	na->initialized_size = 0;
+	na->allocated_size = alctx->wanted_clusters
+					<< alctx->vol->cluster_size_bits;
+		/* Feed the sizes into the attribute */
+	attr = ctx->attr;
+	attr->non_resident = 1;
+	attr->data_size = cpu_to_le64(na->data_size);
+	attr->initialized_size = cpu_to_le64(na->initialized_size);
+	attr->allocated_size = cpu_to_le64(na->allocated_size);
+	if (na->data_flags & ATTR_IS_SPARSE)
+		attr->compressed_size = cpu_to_le64(na->compressed_size);
+		/* Copy the unnamed data attribute sizes to inode */
+	if ((opts.attribute == AT_DATA) && !na->name_len) {
+		ni = na->ni;
+		ni->data_size = na->data_size;
+		if (na->data_flags & ATTR_IS_SPARSE) {
+			ni->allocated_size = na->compressed_size;
+			ni->flags |= FILE_ATTR_SPARSE_FILE;
+		} else
+			ni->allocated_size = na->allocated_size;
+	}
+	return (0);
+}
+
+/*
+ *		Assign a runlist to an attribute and store
+ *
+ *	Returns 0 if successful
+ *		-1 otherwise, with errno set accordingly
+ */
+
+static int assign_runlist(struct ALLOC_CONTEXT *alctx)
+{
+	ntfs_attr *na;
+	ntfs_attr_search_ctx *ctx;
+	int k;
+	int err;
+
+	err = 0;
+	na = alctx->na;
+	if (na->rl)
+		free(na->rl);
+	na->rl = alctx->rl;
+			/* Allocate the clusters */
+	for (k=0; ((k + 1) < alctx->rl_count) && !err; k++) {
+		if (ntfs_bitmap_set_run(alctx->vol->lcnbmp_na,
+				alctx->rl[k].lcn, alctx->rl[k].length)) {
+			err = -1;
+		}
+	}
+	na->allocated_size = alctx->wanted_clusters
+					<< alctx->vol->cluster_size_bits;
+	NAttrSetNonResident(na);
+	NAttrSetFullyMapped(na);
+	if (err || ntfs_attr_update_mapping_pairs(na, 0)) {
+		err = -1;
+	} else {
+		ctx = ntfs_attr_get_search_ctx(alctx->na->ni, NULL);
+		if (ctx) {
+			if (ntfs_attr_lookup(opts.attribute, na->name,
+					na->name_len,
+					CASE_SENSITIVE, 0, NULL, 0, ctx)) {
+				err = -1;
+			} else {
+				if (set_sizes(alctx, ctx))
+					err = -1;
+			}
+		} else
+			err = -1;
+		ntfs_attr_put_search_ctx(ctx);
+	}
+	return (err);
+}
+
+/*
+ *		Find the runs which minimize fragmentation
+ *
+ *	Only the first and second data zones are examined, the MFT zone
+ *	is preserved.
+ *
+ *	Returns 0 if successful
+ *		-1 otherwise, with errno set accordingly
+ */
+
+static int find_best_runs(struct ALLOC_CONTEXT *alctx)
+{
+	ntfs_volume *vol;
+	s64 pos; /* bit index in bitmap */
+	s64 br; /* byte count in buf */
+	int err;
+	enum STEP step;
+
+	err = 0;
+	vol = alctx->vol;
+			/* examine the first data zone */
+	pos = vol->mft_zone_end;
+	br = vol->cluster_size;
+	step = STEP_ZERO;
+	while ((step != STEP_ERR)
+	    && (br == vol->cluster_size)
+	    && (pos < vol->nr_clusters)) {
+		br = ntfs_attr_pread(vol->lcnbmp_na,
+			(pos >> 3) & -vol->cluster_size,
+			vol->cluster_size, alctx->buf);
+		if (br > 0) {
+			step = examine_buf(alctx, pos, br, step);
+			pos = (pos | ((vol->cluster_size << 3) - 1)) + 1;
+		}
+	}
+			/* examine the second data zone */
+	pos = 0;
+	br = vol->cluster_size;
+	step = STEP_ZERO;
+	while ((step != STEP_ERR)
+	    && (br == vol->cluster_size)
+	    && (pos < vol->mft_zone_start)) {
+		br = ntfs_attr_pread(vol->lcnbmp_na,
+			(pos >> 3) & -vol->cluster_size,
+			vol->cluster_size, alctx->buf);
+		if (br > 0) {
+			step = examine_buf(alctx, pos, br, step);
+			pos = (pos | ((vol->cluster_size << 3) - 1)) + 1;
+		}
+	}
+	if (alctx->gathered_clusters < alctx->wanted_clusters) {
+		errno = ENOSPC;
+		ntfs_log_error("Error : not enough space on device\n");
+		err = -1;
+	} else {
+		if ((step == STEP_ERR) || sort_runlist(alctx))
+			err = -1;
+	}
+	return (err);
+}
+
+/*
+ *		Preallocate clusters with minimal fragmentation
+ *
+ *	Returns 0 if successful
+ *		-1 otherwise, with errno set accordingly
+ */
+
+static int preallocate(ntfs_attr *na, s64 new_size)
+{
+	struct ALLOC_CONTEXT *alctx;
+	ntfs_volume *vol;
+	int err;
+
+	err = 0;
+	vol = na->ni->vol;
+	alctx = (struct ALLOC_CONTEXT*)ntfs_malloc(sizeof(struct ALLOC_CONTEXT));
+	if (alctx) {
+		alctx->buf = (unsigned char*)ntfs_malloc(vol->cluster_size);
+		if (alctx->buf) {
+			alctx->na = na;
+			alctx->vol = vol;
+			alctx->rl_count = 0;
+			alctx->rl_allocated = 0;
+			alctx->rl = (runlist_element*)NULL;
+			alctx->new_size = new_size;
+			alctx->wanted_clusters = (new_size
+				+ vol->cluster_size - 1)
+					>> vol->cluster_size_bits;
+			alctx->gathered_clusters = 0;
+			if (find_best_runs(alctx))
+				err = -1;
+			if (!err && !opts.noaction) {
+				if (assign_runlist(alctx))
+					err = -1;
+			} else
+				free(alctx->rl);
+			free(alctx->buf);
+		} else
+			err = -1;
+		free(alctx);
+	} else
+		err = -1;
+	return (err);
+}
+
+/**
+ * Create a regular file under the given directory inode
+ *
+ * It is a wrapper function to ntfs_create(...)
+ *
+ * Return:  the created file inode
+ */
+static ntfs_inode *ntfs_new_file(ntfs_inode *dir_ni,
+			  const char *filename)
+{
+	ntfschar *ufilename;
+	/* inode to the file that is being created */
+	ntfs_inode *ni;
+	int ufilename_len;
+
+	/* ntfs_mbstoucs(...) will allocate memory for ufilename if it's NULL */
+	ufilename = NULL;
+	ufilename_len = ntfs_mbstoucs(filename, &ufilename);
+	if (ufilename_len == -1) {
+		ntfs_log_perror("ERROR: Failed to convert '%s' to unicode",
+					filename);
+		return NULL;
+	}
+	ni = ntfs_create(dir_ni, 0, ufilename, ufilename_len, S_IFREG);
+	free(ufilename);
+	return ni;
+}
+
+/**
+ * main - Begin here
+ *
+ * Start from here.
+ *
+ * Return:  0  Success, the program worked
+ *	    1  Error, something went wrong
+ */
+int main(int argc, char *argv[])
+{
+	FILE *in;
+	ntfs_volume *vol;
+	ntfs_inode *out;
+	ntfs_attr *na;
+	int flags = 0;
+	int res;
+	int result = 1;
+	s64 new_size;
+	u64 offset;
+	char *buf;
+	s64 br, bw;
+	ntfschar *attr_name;
+	int attr_name_len = 0;
+
+	ntfs_log_set_handler(ntfs_log_handler_stderr);
+
+	res = parse_options(argc, argv);
+	if (res >= 0)
+		return (res);
+
+	utils_set_locale();
+
+	/* Set SIGINT handler. */
+	if (signal(SIGINT, signal_handler) == SIG_ERR) {
+		ntfs_log_perror("Failed to set SIGINT handler");
+		return 1;
+	}
+	/* Set SIGTERM handler. */
+	if (signal(SIGTERM, signal_handler) == SIG_ERR) {
+		ntfs_log_perror("Failed to set SIGTERM handler");
+		return 1;
+	}
+
+	if (opts.noaction)
+		flags = NTFS_MNT_RDONLY;
+	if (opts.force)
+		flags |= NTFS_MNT_RECOVER;
+
+	vol = utils_mount_volume(opts.device, flags);
+	if (!vol) {
+		ntfs_log_perror("ERROR: couldn't mount volume");
+		return 1;
+	}
+
+	if ((vol->flags & VOLUME_IS_DIRTY) && !opts.force)
+		goto umount;
+
+	NVolSetCompression(vol); /* allow compression */
+	if (ntfs_volume_get_free_space(vol)) {
+		ntfs_log_perror("ERROR: couldn't get free space");
+		goto umount;
+	}
+
+	{
+		struct stat fst;
+		if (stat(opts.src_file, &fst) == -1) {
+			ntfs_log_perror("ERROR: Couldn't stat source file");
+			goto umount;
+		}
+		new_size = fst.st_size;
+	}
+	ntfs_log_verbose("New file size: %lld\n", (long long)new_size);
+
+	in = fopen(opts.src_file, "r");
+	if (!in) {
+		ntfs_log_perror("ERROR: Couldn't open source file");
+		goto umount;
+	}
+
+	if (opts.inode) {
+		s64 inode_num;
+		char *s;
+
+		inode_num = strtoll(opts.dest_file, &s, 0);
+		if (*s) {
+			ntfs_log_error("ERROR: Couldn't parse inode number.\n");
+			goto close_src;
+		}
+		out = ntfs_inode_open(vol, inode_num);
+	} else
+		out = ntfs_pathname_to_inode(vol, NULL, opts.dest_file);
+	if (!out) {
+		/* Copy the file if the dest_file's parent dir can be opened. */
+		char *parent_dirname;
+		char *filename;
+		ntfs_inode *dir_ni;
+		ntfs_inode *ni;
+		char *dirname_last_whack;
+
+		filename = basename(opts.dest_file);
+		parent_dirname = strdup(opts.dest_file);
+		if (!parent_dirname) {
+			ntfs_log_perror("strdup() failed");
+			goto close_src;
+		}
+		dirname_last_whack = strrchr(parent_dirname, '/');
+		if (dirname_last_whack) {
+			if (dirname_last_whack == parent_dirname)
+				dirname_last_whack[1] = 0;
+			else
+				*dirname_last_whack = 0;
+			dir_ni = ntfs_pathname_to_inode(vol, NULL,
+					parent_dirname);
+		} else {
+			ntfs_log_verbose("Target path does not contain '/'. "
+					"Using root directory as parent.\n");
+			dir_ni = ntfs_inode_open(vol, FILE_root);
+		}
+		if (dir_ni) {
+			if (!(dir_ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
+				/* Remove the last '/' for estetic reasons. */
+				dirname_last_whack[0] = 0;
+				ntfs_log_error("The file '%s' already exists "
+						"and is not a directory. "
+						"Aborting.\n", parent_dirname);
+				free(parent_dirname);
+				ntfs_inode_close(dir_ni);
+				goto close_src;
+			}
+			ntfs_log_verbose("Creating a new file '%s' under '%s'"
+					 "\n", filename, parent_dirname);
+			ni = ntfs_new_file(dir_ni, filename);
+			ntfs_inode_close(dir_ni);
+			if (!ni) {
+				ntfs_log_perror("Failed to create '%s' under "
+						"'%s'", filename,
+						parent_dirname);
+				free(parent_dirname);
+				goto close_src;
+			}
+			out = ni;
+		} else {
+			ntfs_log_perror("ERROR: Couldn't open '%s'",
+					parent_dirname);
+			free(parent_dirname);
+			goto close_src;
+		}
+		free(parent_dirname);
+	}
+	/* The destination is a directory. */
+	if ((out->mrec->flags & MFT_RECORD_IS_DIRECTORY) && !opts.inode) {
+		char *filename;
+		char *overwrite_filename;
+		int overwrite_filename_len;
+		ntfs_inode *ni;
+		ntfs_inode *dir_ni;
+		int filename_len;
+		int dest_dirname_len;
+
+		filename = basename(opts.src_file);
+		dir_ni = out;
+		filename_len = strlen(filename);
+		dest_dirname_len = strlen(opts.dest_file);
+		overwrite_filename_len = filename_len+dest_dirname_len + 2;
+		overwrite_filename = malloc(overwrite_filename_len);
+		if (!overwrite_filename) {
+			ntfs_log_perror("ERROR: Failed to allocate %i bytes "
+					"memory for the overwrite filename",
+					overwrite_filename_len);
+			ntfs_inode_close(out);
+			goto close_src;
+		}
+		strcpy(overwrite_filename, opts.dest_file);
+		if (opts.dest_file[dest_dirname_len - 1] != '/') {
+			strcat(overwrite_filename, "/");
+		}
+		strcat(overwrite_filename, filename);
+		ni = ntfs_pathname_to_inode(vol, dir_ni, overwrite_filename);
+		/* Does a file with the same name exist in the dest dir? */
+		if (ni) {
+			ntfs_log_verbose("Destination path has a file with "
+					"the same name\nOverwriting the file "
+					"'%s'\n", overwrite_filename);
+			ntfs_inode_close(out);
+			out = ni;
+		} else {
+			ntfs_log_verbose("Creating a new file '%s' under "
+					"'%s'\n", filename, opts.dest_file);
+			ni = ntfs_new_file(dir_ni, filename);
+			ntfs_inode_close(dir_ni);
+			if (!ni) {
+				ntfs_log_perror("ERROR: Failed to create the "
+						"destination file under '%s'",
+						opts.dest_file);
+				free(overwrite_filename);
+				goto close_src;
+			}
+			out = ni;
+		}
+		free(overwrite_filename);
+	}
+
+	attr_name = ntfs_str2ucs(opts.attr_name, &attr_name_len);
+	if (!attr_name) {
+		ntfs_log_perror("ERROR: Failed to parse attribute name '%s'",
+				opts.attr_name);
+		goto close_dst;
+	}
+
+	na = ntfs_attr_open(out, opts.attribute, attr_name, attr_name_len);
+	if (!na) {
+		if (errno != ENOENT) {
+			ntfs_log_perror("ERROR: Couldn't open attribute");
+			goto close_dst;
+		}
+		/* Requested attribute isn't present, add it. */
+		if (ntfs_attr_add(out, opts.attribute, attr_name,
+				attr_name_len, NULL, 0)) {
+			ntfs_log_perror("ERROR: Couldn't add attribute");
+			goto close_dst;
+		}
+		na = ntfs_attr_open(out, opts.attribute, attr_name,
+				attr_name_len);
+		if (!na) {
+			ntfs_log_perror("ERROR: Couldn't open just added "
+					"attribute");
+			goto close_dst;
+		}
+	}
+
+	ntfs_log_verbose("Old file size: %lld\n", (long long)na->data_size);
+	if (opts.minfragments && NAttrCompressed(na)) {
+		ntfs_log_info("Warning : Cannot avoid fragmentation"
+				" of a compressed attribute\n");
+		opts.minfragments = 0;
+		}
+	if (na->data_size && opts.minfragments) {
+		if (ntfs_attr_truncate(na, 0)) {
+			ntfs_log_perror(
+				"ERROR: Couldn't truncate existing attribute");
+			goto close_attr;
+		}
+	}
+	if (na->data_size != new_size) {
+		if (opts.minfragments) {
+			/*
+			 * Do a standard truncate() to check whether the
+			 * attribute has to be made non-resident.
+			 * If still resident, preallocation is not needed.
+			 */
+			if (ntfs_attr_truncate(na, new_size)) {
+				ntfs_log_perror(
+					"ERROR: Couldn't resize attribute");
+				goto close_attr;
+			}
+			if (NAttrNonResident(na)
+			   && preallocate(na, new_size)) {
+				ntfs_log_perror(
+				    "ERROR: Couldn't preallocate attribute");
+				goto close_attr;
+			}
+		} else {
+			if (ntfs_attr_truncate_solid(na, new_size)) {
+				ntfs_log_perror(
+					"ERROR: Couldn't resize attribute");
+				goto close_attr;
+			}
+		}
+	}
+
+	buf = malloc(NTFS_BUF_SIZE);
+	if (!buf) {
+		ntfs_log_perror("ERROR: malloc failed");
+		goto close_attr;
+	}
+
+	ntfs_log_verbose("Starting write.\n");
+	offset = 0;
+	while (!feof(in)) {
+		if (caught_terminate) {
+			ntfs_log_error("SIGTERM or SIGINT received.  "
+					"Aborting write.\n");
+			break;
+		}
+		br = fread(buf, 1, NTFS_BUF_SIZE, in);
+		if (!br) {
+			if (!feof(in)) ntfs_log_perror("ERROR: fread failed");
+			break;
+		}
+		bw = ntfs_attr_pwrite(na, offset, br, buf);
+		if (bw != br) {
+			ntfs_log_perror("ERROR: ntfs_attr_pwrite failed");
+			break;
+		}
+		offset += bw;
+	}
+	if ((na->data_flags & ATTR_COMPRESSION_MASK)
+	    && ntfs_attr_pclose(na))
+		ntfs_log_perror("ERROR: ntfs_attr_pclose failed");
+	ntfs_log_verbose("Syncing.\n");
+	result = 0;
+	free(buf);
+close_attr:
+	ntfs_attr_close(na);
+close_dst:
+	while (ntfs_inode_close(out) && !opts.noaction) {
+		if (errno != EBUSY) {
+			ntfs_log_error("Sync failed. Run chkdsk.\n");
+			break;
+		}
+		ntfs_log_error("Device busy.  Will retry sync in 3 seconds.\n");
+		sleep(3);
+	}
+close_src:
+	fclose(in);
+umount:
+	ntfs_umount(vol, FALSE);
+	ntfs_log_verbose("Done.\n");
+	return result;
+}
diff --git a/ntfsprogs/ntfsdecrypt.8 b/ntfsprogs/ntfsdecrypt.8
new file mode 100755
index 0000000000000000000000000000000000000000..3320d3d13ae0518151b50d72beaf282fffe636ee
--- /dev/null
+++ b/ntfsprogs/ntfsdecrypt.8
@@ -0,0 +1,129 @@
+.\" Copyright (c) 2014 Jean-Pierre Andre
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSDECRYPT 8 "June 2014" "ntfs-3g 2015.3.14"
+.SH NAME
+ntfsdecrypt \- decrypt or update NTFS files encrypted according to EFS
+.SH SYNOPSIS
+\fBntfsdecrypt\fR [\fIoptions\fR] -k \fIkey.pfx \fIdevice file\fR
+.SH DESCRIPTION
+.B ntfsdecrypt
+decrypts a file from an unmounted device and print the decrypted data
+on the standard output.
+It can also update an encrypted file with the encryption key unchanged.
+.PP
+The NTFS file encryption (known as EFS) uses a two-level encryption :
+first, the file contents is encrypted with a random symmetric key, then
+this symmetric key is encrypted with the public keys of each of the users
+allowed to decrypt the file (RSA public key encryptions).
+.P
+Three symmetric encryption modes are currently implemented in ntfsdecrypt :
+DESX (a DES variant), 3DES (triple DES) and AES_256 (an AES variant).
+.P
+All the encrypted symmetric keys are stored along with the file in a
+special extended attribute named "$LOGGED_UTILITY_STREAM".
+Usually, at least two users are allowed to read the file : its owner and
+the recovery manager who is able to decrypt all the files in a company.
+When backing up an encrypted file, it is important to also backup the
+corresponding $LOGGED_UTILITY_STREAM, otherwise the file cannot be
+decrypted, even by the recovery manager. Also note that encrypted files
+are slightly bigger than apparent, and the option "efs_raw" has
+to be used when backing up encrypted files with ntfs-3g.
+.P
+When ntfsdecrypt is used to update a file, the keys and the
+$LOGGED_UTILITY_STREAM are kept unchanged, so a single key file has to
+be designated.
+.P
+Note : the EFS encryption is only available in professional versions
+of Windows;
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfsdecrypt
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-i\fR, \fB\-\-inode\fR NUM
+Display or update the contents of a file designated through its inode number
+instead of its name.
+.TP
+\fB\-e\fR, \fB\-\-encrypt\fR
+Update an existing encrypted file and get the new contents from the
+standard input. The full public and private key file has to be designated,
+as the symmetric key is kept unchanged, so the private key is needed to
+extract it.
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+This will override some sensible defaults, such as not using a mounted volume.
+Use this option with caution.
+.TP
+\fB\-k\fR, \fB\-\-keyfile\-name\fR key.pfx
+Define the file which contains the public and private keys in PKCS#12 format.
+This file obviously contains the keys of one of the users allowed to decrypt
+or update the file. It has to be extracted from Windows in PKCS#12 format
+(its usual suffix is .p12 or .pfx), and it is protected by a passphrase
+which has to be typed in for the keys to be extracted. This can be the
+key file of any user allowed to read the file, including the one of the
+recovery manager.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Suppress some debug/warning/error messages.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Show the version number, copyright and license of
+.BR ntfsdecrypt .
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Display more debug/warning/error messages.
+.SH EXAMPLES
+Display the contents of the file hamlet.doc in the directory Documents of
+the root of the NTFS file system on the device /dev/sda1
+.RS
+.sp
+.B ntfsdecrypt -k foo.key /dev/sda1 Documents/hamlet.doc
+.sp
+.RE
+Update the file hamlet.doc
+.RS
+.sp
+.B ntfsdecrypt -k foo.key /dev/sda1 Documents/hamlet.doc < new.doc
+.sp
+.RE
+.SH BUGS
+There are no known problems with
+.BR ntfsdecrypt .
+If you find a bug please send an email describing the problem to the
+development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+.B ntfsdecrypt
+was written by Yuval Fledel, Anton Altaparmakov and Yura Pakhuchiy.
+It was ported to ntfs-3g by Erik Larsson and upgraded by Jean-Pierre Andre.
+.SH AVAILABILITY
+.B ntfsdecrypt
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+Read \fBntfs-3g\fR(8) for details on option efs_raw,
+.RE
+.BR ntfscat (8),
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/ntfsdecrypt.8.in b/ntfsprogs/ntfsdecrypt.8.in
new file mode 100755
index 0000000000000000000000000000000000000000..fd156b071845db08232416e7304732a280fa057c
--- /dev/null
+++ b/ntfsprogs/ntfsdecrypt.8.in
@@ -0,0 +1,129 @@
+.\" Copyright (c) 2014 Jean-Pierre Andre
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSDECRYPT 8 "June 2014" "ntfs-3g @VERSION@"
+.SH NAME
+ntfsdecrypt \- decrypt or update NTFS files encrypted according to EFS
+.SH SYNOPSIS
+\fBntfsdecrypt\fR [\fIoptions\fR] -k \fIkey.pfx \fIdevice file\fR
+.SH DESCRIPTION
+.B ntfsdecrypt
+decrypts a file from an unmounted device and print the decrypted data
+on the standard output.
+It can also update an encrypted file with the encryption key unchanged.
+.PP
+The NTFS file encryption (known as EFS) uses a two-level encryption :
+first, the file contents is encrypted with a random symmetric key, then
+this symmetric key is encrypted with the public keys of each of the users
+allowed to decrypt the file (RSA public key encryptions).
+.P
+Three symmetric encryption modes are currently implemented in ntfsdecrypt :
+DESX (a DES variant), 3DES (triple DES) and AES_256 (an AES variant).
+.P
+All the encrypted symmetric keys are stored along with the file in a
+special extended attribute named "$LOGGED_UTILITY_STREAM".
+Usually, at least two users are allowed to read the file : its owner and
+the recovery manager who is able to decrypt all the files in a company.
+When backing up an encrypted file, it is important to also backup the
+corresponding $LOGGED_UTILITY_STREAM, otherwise the file cannot be
+decrypted, even by the recovery manager. Also note that encrypted files
+are slightly bigger than apparent, and the option "efs_raw" has
+to be used when backing up encrypted files with ntfs-3g.
+.P
+When ntfsdecrypt is used to update a file, the keys and the
+$LOGGED_UTILITY_STREAM are kept unchanged, so a single key file has to
+be designated.
+.P
+Note : the EFS encryption is only available in professional versions
+of Windows;
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfsdecrypt
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-i\fR, \fB\-\-inode\fR NUM
+Display or update the contents of a file designated through its inode number
+instead of its name.
+.TP
+\fB\-e\fR, \fB\-\-encrypt\fR
+Update an existing encrypted file and get the new contents from the
+standard input. The full public and private key file has to be designated,
+as the symmetric key is kept unchanged, so the private key is needed to
+extract it.
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+This will override some sensible defaults, such as not using a mounted volume.
+Use this option with caution.
+.TP
+\fB\-k\fR, \fB\-\-keyfile\-name\fR key.pfx
+Define the file which contains the public and private keys in PKCS#12 format.
+This file obviously contains the keys of one of the users allowed to decrypt
+or update the file. It has to be extracted from Windows in PKCS#12 format
+(its usual suffix is .p12 or .pfx), and it is protected by a passphrase
+which has to be typed in for the keys to be extracted. This can be the
+key file of any user allowed to read the file, including the one of the
+recovery manager.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Suppress some debug/warning/error messages.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Show the version number, copyright and license of
+.BR ntfsdecrypt .
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Display more debug/warning/error messages.
+.SH EXAMPLES
+Display the contents of the file hamlet.doc in the directory Documents of
+the root of the NTFS file system on the device /dev/sda1
+.RS
+.sp
+.B ntfsdecrypt -k foo.key /dev/sda1 Documents/hamlet.doc
+.sp
+.RE
+Update the file hamlet.doc
+.RS
+.sp
+.B ntfsdecrypt -k foo.key /dev/sda1 Documents/hamlet.doc < new.doc
+.sp
+.RE
+.SH BUGS
+There are no known problems with
+.BR ntfsdecrypt .
+If you find a bug please send an email describing the problem to the
+development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+.B ntfsdecrypt
+was written by Yuval Fledel, Anton Altaparmakov and Yura Pakhuchiy.
+It was ported to ntfs-3g by Erik Larsson and upgraded by Jean-Pierre Andre.
+.SH AVAILABILITY
+.B ntfsdecrypt
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+Read \fBntfs-3g\fR(8) for details on option efs_raw,
+.RE
+.BR ntfscat (8),
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/ntfsdecrypt.c b/ntfsprogs/ntfsdecrypt.c
new file mode 100755
index 0000000000000000000000000000000000000000..ab58cbd989c8a75d0edce972cbf5d8005deeb1ae
--- /dev/null
+++ b/ntfsprogs/ntfsdecrypt.c
@@ -0,0 +1,1623 @@
+/**
+ * ntfsdecrypt - Decrypt ntfs encrypted files.  Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2005 Yuval Fledel
+ * Copyright (c) 2005-2007 Anton Altaparmakov
+ * Copyright (c) 2007 Yura Pakhuchiy
+ * Copyright (c) 2014 Jean-Pierre Andre
+ *
+ * This utility will decrypt files and print the decrypted data on the standard
+ * output.
+ *
+ * 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 Linux-NTFS
+ * 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_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <gcrypt.h>
+#include <gnutls/pkcs12.h>
+
+#include "types.h"
+#include "attrib.h"
+#include "utils.h"
+#include "volume.h"
+#include "debug.h"
+#include "dir.h"
+#include "layout.h"
+/* #include "version.h" */
+#include "misc.h"
+
+typedef gcry_sexp_t ntfs_rsa_private_key;
+
+#define NTFS_SHA1_THUMBPRINT_SIZE 0x14
+
+#define NTFS_CRED_TYPE_CERT_THUMBPRINT const_cpu_to_le32(3)
+
+#define NTFS_EFS_CERT_PURPOSE_OID_DDF "1.3.6.1.4.1.311.10.3.4" /* decryption */
+#define NTFS_EFS_CERT_PURPOSE_OID_DRF "1.3.6.1.4.1.311.10.3.4.1" /* recovery */
+
+typedef enum {
+	DF_TYPE_UNKNOWN,
+	DF_TYPE_DDF, /* decryption */
+	DF_TYPE_DRF, /* recovery */
+} NTFS_DF_TYPES;
+
+/**
+ * enum NTFS_CRYPTO_ALGORITHMS - List of crypto algorithms used by EFS (32 bit)
+ *
+ * To choose which one is used in Windows, create or set the REG_DWORD registry
+ * key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\EFS\
+ * AlgorithmID to the value of your chosen crypto algorithm, e.g. to use DesX,
+ * set AlgorithmID to 0x6604.
+ *
+ * Note that the Windows versions I have tried so far (all are high crypto
+ * enabled) ignore the AlgorithmID value if it is not one of CALG_3DES,
+ * CALG_DESX, or CALG_AES_256, i.e. you cannot select CALG_DES at all using
+ * this registry key.  It would be interesting to check out encryption on one
+ * of the "crippled" crypto Windows versions...
+ */
+typedef enum {
+	CALG_DES	= const_cpu_to_le32(0x6601),
+	/* If not one of the below three, fall back to standard Des. */
+	CALG_3DES	= const_cpu_to_le32(0x6603),
+	CALG_DESX	= const_cpu_to_le32(0x6604),
+	CALG_AES_256	= const_cpu_to_le32(0x6610),
+} NTFS_CRYPTO_ALGORITHMS;
+
+typedef struct {
+	u64 in_whitening, out_whitening;
+	u8 des_key[8];
+} ntfs_desx_ctx;
+
+/**
+ * struct ntfs_fek - Decrypted, in-memory file encryption key.
+ */
+
+typedef struct {
+	gcry_cipher_hd_t gcry_cipher_hd;
+	le32 alg_id;
+	u8 *key_data;
+	gcry_cipher_hd_t *des_gcry_cipher_hd_ptr;
+	ntfs_desx_ctx desx_ctx;
+} ntfs_fek;
+
+struct options {
+	char *keyfile;	/* .pfx file containing the user's private key. */
+	char *device;		/* Device/File to work with */
+	char *file;		/* File to display */
+	s64 inode;		/* Inode to work with */
+	ATTR_TYPES attr;	/* Attribute type to display */
+	int force;		/* Override common sense */
+	int quiet;		/* Less output */
+	int verbose;		/* Extra output */
+	int encrypt;		/* Encrypt */
+};
+
+static const char *EXEC_NAME = "ntfsdecrypt";
+static struct options opts;
+
+static ntfschar EFS[5] = {
+	const_cpu_to_le16('$'), const_cpu_to_le16('E'), const_cpu_to_le16('F'),
+	const_cpu_to_le16('S'), const_cpu_to_le16('\0')
+};
+
+/**
+ * version - Print version information about the program
+ *
+ * Print a copyright statement and a brief description of the program.
+ *
+ * Return:  none
+ */
+static void version(void)
+{
+	ntfs_log_info("\n%s v%s (libntfs-3g) - Decrypt files and print on the "
+			"standard output.\n\n", EXEC_NAME, VERSION);
+	ntfs_log_info("Copyright (c) 2005 Yuval Fledel\n");
+	ntfs_log_info("Copyright (c) 2005 Anton Altaparmakov\n");
+	ntfs_log_info("Copyright (c) 2014 Jean-Pierre Andre\n");
+	ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
+}
+
+/**
+ * usage - Print a list of the parameters to the program
+ *
+ * Print a list of the parameters and options for the program.
+ *
+ * Return:  none
+ */
+static void usage(void)
+{
+	ntfs_log_info("\nUsage: %s [options] -k name.pfx device [file]\n\n"
+	       "    -i, --inode num         Display this inode\n\n"
+	       "    -k  --keyfile name.pfx  Use file name as the user's private key file.\n"
+	       "    -e  --encrypt           Update an encrypted file\n"
+	       "    -f  --force             Use less caution\n"
+	       "    -h  --help              Print this help\n"
+	       "    -q  --quiet             Less output\n"
+	       "    -V  --version           Version information\n"
+	       "    -v  --verbose           More output\n\n",
+	       EXEC_NAME);
+	ntfs_log_info("%s%s\n", ntfs_bugs, ntfs_home);
+}
+
+/**
+ * parse_options - Read and validate the programs command line
+ *
+ * Read the command line, verify the syntax and parse the options.
+ * This function is very long, but quite simple.
+ *
+ * Return:  1 Success
+ *	    0 Error, one or more problems
+ */
+static int parse_options(int argc, char **argv)
+{
+	static const char *sopt = "-fh?ei:k:qVv";
+	static const struct option lopt[] = {
+		{"encrypt", no_argument, NULL, 'e'},
+		{"force", no_argument, NULL, 'f'},
+		{"help", no_argument, NULL, 'h'},
+		{"inode", required_argument, NULL, 'i'},
+		{"keyfile", required_argument, NULL, 'k'},
+		{"quiet", no_argument, NULL, 'q'},
+		{"version", no_argument, NULL, 'V'},
+		{"verbose", no_argument, NULL, 'v'},
+		{NULL, 0, NULL, 0}
+	};
+
+	int c = -1;
+	int err = 0;
+	int ver = 0;
+	int help = 0;
+
+	opterr = 0;		/* We'll handle the errors, thank you. */
+
+	opts.inode = -1;
+
+	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
+		switch (c) {
+		case 1:	/* A non-option argument */
+			if (!opts.device)
+				opts.device = argv[optind - 1];
+			else if (!opts.file)
+				opts.file = argv[optind - 1];
+			else {
+				ntfs_log_error("You must specify exactly one "
+					"file.\n");
+				err++;
+			}
+			break;
+		case 'e':
+			opts.encrypt++;
+			break;
+		case 'f':
+			opts.force++;
+			break;
+		case 'h':
+			help++;
+			break;
+		case 'k':
+			if (!opts.keyfile)
+				opts.keyfile = argv[optind - 1];
+			else {
+				ntfs_log_error("You must specify exactly one "
+						"key file.\n");
+				err++;
+			}
+			break;
+		case 'i':
+			if (opts.inode != -1)
+				ntfs_log_error("You must specify exactly one "
+						"inode.\n");
+			else if (utils_parse_size(optarg, &opts.inode, FALSE))
+				break;
+			else
+				ntfs_log_error("Couldn't parse inode number.\n");
+			err++;
+			break;
+		case 'q':
+			opts.quiet++;
+			ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
+			break;
+		case 'V':
+			ver++;
+			break;
+		case 'v':
+			opts.verbose++;
+			ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
+			break;
+		case '?':
+		default:
+			ntfs_log_error("Unknown option '%s'.\n",
+				argv[optind - 1]);
+			err++;
+			break;
+		}
+	}
+
+	if (help || ver) {
+		opts.quiet = 0;
+		ntfs_log_set_levels(NTFS_LOG_LEVEL_QUIET);
+	} else {
+		if (!opts.keyfile) {
+			ntfs_log_error("You must specify a key file.\n");
+			err++;
+		} else if (opts.device == NULL) {
+			ntfs_log_error("You must specify a device.\n");
+			err++;
+		} else if (opts.file == NULL && opts.inode == -1) {
+			ntfs_log_error("You must specify a file or inode with "
+				"the -i option.\n");
+			err++;
+		} else if (opts.file != NULL && opts.inode != -1) {
+			ntfs_log_error("You can't specify both a file and "
+				"inode.\n");
+			err++;
+		}
+		if (opts.quiet && opts.verbose) {
+			ntfs_log_error("You may not use --quiet and --verbose "
+				"at the same time.\n");
+			err++;
+		}
+	}
+
+	if (ver)
+		version();
+	if (help || err)
+		usage();
+
+		/* tri-state 0 : done, 1 : error, -1 : proceed */
+	return (err ? 1 : (help || ver ? 0 : -1));
+}
+
+/**
+ * ntfs_pkcs12_load_pfxfile
+ */
+static int ntfs_pkcs12_load_pfxfile(const char *keyfile, u8 **pfx,
+		unsigned *pfx_size)
+{
+	int f, to_read, total, attempts, br;
+	struct stat key_stat;
+
+	if (!keyfile || !pfx || !pfx_size) {
+		ntfs_log_error("You have to specify the key file, a pointer "
+				"to hold the key file contents, and a pointer "
+				"to hold the size of the key file contents.\n");
+		return -1;
+	}
+	f = open(keyfile, O_RDONLY);
+	if (f == -1) {
+		ntfs_log_perror("Failed to open key file");
+		return -1;
+	}
+	if (fstat(f, &key_stat) == -1) {
+		ntfs_log_perror("Failed to stat key file");
+		goto file_out;
+	}
+	if (!S_ISREG(key_stat.st_mode)) {
+		ntfs_log_error("Key file is not a regular file, cannot read "
+				"it.\n");
+		goto file_out;
+	}
+	if (!key_stat.st_size) {
+		ntfs_log_error("Key file has zero size.\n");
+		goto file_out;
+	}
+	*pfx = malloc(key_stat.st_size + 1);
+	if (!*pfx) {
+		ntfs_log_perror("Failed to allocate buffer for key file "
+			"contents");
+		goto file_out;
+	}
+	to_read = key_stat.st_size;
+	total = attempts = 0;
+	do {
+		br = read(f, *pfx + total, to_read);
+		if (br == -1) {
+			ntfs_log_perror("Failed to read from key file");
+			goto free_out;
+		}
+		if (!br)
+			attempts++;
+		to_read -= br;
+		total += br;
+	} while (to_read > 0 && attempts < 3);
+	close(f);
+	/* Make sure it is zero terminated. */
+	(*pfx)[key_stat.st_size] = 0;
+	*pfx_size = key_stat.st_size;
+	return 0;
+free_out:
+	free(*pfx);
+file_out:
+	close(f);
+	return -1;
+}
+
+/**
+ * ntfs_crypto_init
+ */
+static int ntfs_crypto_init(void)
+{
+	int err;
+
+	/* Initialize gcrypt library.  Note: Must come before GNU TLS init. */
+	if (gcry_control(GCRYCTL_DISABLE_SECMEM, 0) != GPG_ERR_NO_ERROR) {
+		ntfs_log_error("Failed to initialize the gcrypt library.\n");
+		return -1;
+	}
+	/* Initialize GNU TLS library.  Note: Must come after libgcrypt init. */
+	err = gnutls_global_init();
+	if (err < 0) {
+		ntfs_log_error("Failed to initialize GNU TLS library: %s\n",
+				gnutls_strerror(err));
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * ntfs_crypto_deinit
+ */
+static void ntfs_crypto_deinit(void)
+{
+	gnutls_global_deinit();
+}
+
+/**
+ * ntfs_rsa_private_key_import_from_gnutls
+ */
+static ntfs_rsa_private_key ntfs_rsa_private_key_import_from_gnutls(
+		gnutls_x509_privkey_t priv_key)
+{
+	int i, j;
+	size_t tmp_size;
+	gnutls_datum_t rd[6];
+	gcry_mpi_t rm[6];
+	gcry_sexp_t rsa_key;
+
+	/* Extract the RSA parameters from the GNU TLS private key. */
+	if (gnutls_x509_privkey_export_rsa_raw(priv_key, &rd[0], &rd[1],
+			&rd[2], &rd[3], &rd[4], &rd[5])) {
+		ntfs_log_error("Failed to export rsa parameters.  (Is the "
+				"key an RSA private key?)\n");
+		return NULL;
+	}
+	/* Convert each RSA parameter to mpi format. */
+	for (i = 0; i < 6; i++) {
+		if (gcry_mpi_scan(&rm[i], GCRYMPI_FMT_USG, rd[i].data,
+				rd[i].size, &tmp_size) != GPG_ERR_NO_ERROR) {
+			ntfs_log_error("Failed to convert RSA parameter %i "
+					"to mpi format (size %d)\n", i,
+					rd[i].size);
+			rsa_key = NULL;
+			break;
+		}
+	}
+	/* Release the no longer needed datum values. */
+	for (j = 0; j < 6; j++) {
+		if (rd[j].data && rd[j].size)
+			gnutls_free(rd[j].data);
+	}
+	/*
+	 * Build the gcrypt private key, note libgcrypt uses p and q inversed
+	 * to what gnutls uses.
+	 */
+	if (i == 6 && gcry_sexp_build(&rsa_key, NULL,
+			"(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
+			rm[0], rm[1], rm[2], rm[4], rm[3], rm[5]) !=
+			GPG_ERR_NO_ERROR) {
+		ntfs_log_error("Failed to build RSA private key s-exp.\n");
+		rsa_key = NULL;
+	}
+	/* Release the no longer needed mpi values. */
+	for (j = 0; j < i; j++)
+		gcry_mpi_release(rm[j]);
+	return (ntfs_rsa_private_key)rsa_key;
+}
+
+/**
+ * ntfs_rsa_private_key_release
+ */
+static void ntfs_rsa_private_key_release(ntfs_rsa_private_key rsa_key)
+{
+	gcry_sexp_release((gcry_sexp_t)rsa_key);
+}
+
+/**
+ * ntfs_pkcs12_extract_rsa_key
+ */
+static ntfs_rsa_private_key ntfs_pkcs12_extract_rsa_key(u8 *pfx, int pfx_size,
+		char *password, char *thumbprint, int thumbprint_size,
+		NTFS_DF_TYPES *df_type)
+{
+	int err, bag_index, flags;
+	gnutls_datum_t dpfx, dkey;
+	gnutls_pkcs12_t pkcs12 = NULL;
+	gnutls_pkcs12_bag_t bag = NULL;
+	gnutls_x509_privkey_t pkey = NULL;
+	gnutls_x509_crt_t crt = NULL;
+	ntfs_rsa_private_key rsa_key = NULL;
+	char purpose_oid[100];
+	size_t purpose_oid_size = sizeof(purpose_oid);
+	int oid_index;
+	size_t tp_size = thumbprint_size;
+	BOOL have_thumbprint = FALSE;
+
+	*df_type = DF_TYPE_UNKNOWN;
+	/* Create a pkcs12 structure. */
+	err = gnutls_pkcs12_init(&pkcs12);
+	if (err) {
+		ntfs_log_error("Failed to initialize PKCS#12 structure: %s\n",
+				gnutls_strerror(err));
+		return NULL;
+	}
+	/* Convert the PFX file (DER format) to native pkcs12 format. */
+	dpfx.data = pfx;
+	dpfx.size = pfx_size;
+	err = gnutls_pkcs12_import(pkcs12, &dpfx, GNUTLS_X509_FMT_DER, 0);
+	if (err) {
+		ntfs_log_error("Failed to convert the PFX file from DER to "
+				"native PKCS#12 format: %s\n",
+				gnutls_strerror(err));
+		goto err;
+	}
+	/*
+	 * Verify that the password is correct and that the key file has not
+	 * been tampered with.  Note if the password has zero length and the
+	 * verification fails, retry with password set to NULL.  This is needed
+	 * to get passwordless .pfx files generated with Windows XP SP1 (and
+	 * probably earlier versions of Windows) to work.
+	 */
+retry_verify:
+	err = gnutls_pkcs12_verify_mac(pkcs12, password);
+	if (err) {
+		if (err == GNUTLS_E_MAC_VERIFY_FAILED &&
+				password && !strlen(password)) {
+			password = NULL;
+			goto retry_verify;
+		}
+		ntfs_log_error("Failed to verify the MAC: %s  Is the "
+				"password correct?\n", gnutls_strerror(err));
+		goto err;
+	}
+	for (bag_index = 0; ; bag_index++) {
+		err = gnutls_pkcs12_bag_init(&bag);
+		if (err) {
+			ntfs_log_error("Failed to initialize PKCS#12 Bag "
+					"structure: %s\n",
+					gnutls_strerror(err));
+			goto err;
+		}
+		err = gnutls_pkcs12_get_bag(pkcs12, bag_index, bag);
+		if (err) {
+			if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
+				err = 0;
+				break;
+			}
+			ntfs_log_error("Failed to obtain Bag from PKCS#12 "
+					"structure: %s\n",
+					gnutls_strerror(err));
+			goto err;
+		}
+check_again:
+		err = gnutls_pkcs12_bag_get_count(bag);
+		if (err < 0) {
+			ntfs_log_error("Failed to obtain Bag count: %s\n",
+					gnutls_strerror(err));
+			goto err;
+		}
+		err = gnutls_pkcs12_bag_get_type(bag, 0);
+		if (err < 0) {
+			ntfs_log_error("Failed to determine Bag type: %s\n",
+					gnutls_strerror(err));
+			goto err;
+		}
+		flags = 0;
+		switch (err) {
+		case GNUTLS_BAG_PKCS8_KEY:
+			flags = GNUTLS_PKCS_PLAIN;
+		case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
+			err = gnutls_pkcs12_bag_get_data(bag, 0, &dkey);
+			if (err < 0) {
+				ntfs_log_error("Failed to obtain Bag data: "
+						"%s\n", gnutls_strerror(err));
+				goto err;
+			}
+			err = gnutls_x509_privkey_init(&pkey);
+			if (err) {
+				ntfs_log_error("Failed to initialized "
+						"private key structure: %s\n",
+						gnutls_strerror(err));
+				goto err;
+			}
+			/* Decrypt the private key into GNU TLS format. */
+			err = gnutls_x509_privkey_import_pkcs8(pkey, &dkey,
+					GNUTLS_X509_FMT_DER, password, flags);
+			if (err) {
+				ntfs_log_error("Failed to convert private "
+						"key from DER to GNU TLS "
+						"format: %s\n",
+						gnutls_strerror(err));
+				goto err;
+			}
+#if 0
+			/*
+			 * Export the key again, but unencrypted, and output it
+			 * to stderr.  Note the output has an RSA header so to
+			 * compare to openssl pkcs12 -nodes -in myfile.pfx
+			 * output need to ignore the part of the key between
+			 * the first "MII..." up to the second "MII...".  The
+			 * actual RSA private key begins at the second "MII..."
+			 * and in my testing at least was identical to openssl
+			 * output and was also identical both on big and little
+			 * endian so gnutls should be endianness safe.
+			 */
+			char *buf = malloc(8192);
+			size_t bufsize = 8192;
+			err = gnutls_x509_privkey_export_pkcs8(pkey,
+				GNUTLS_X509_FMT_PEM, "", GNUTLS_PKCS_PLAIN, buf,
+				&bufsize);
+			if (err) {
+				ntfs_log_error("eek1\n");
+				exit(1);
+			}
+			ntfs_log_error("%s\n", buf);
+			free(buf);
+#endif
+			/* Convert the private key to our internal format. */
+			rsa_key = ntfs_rsa_private_key_import_from_gnutls(pkey);
+			if (!rsa_key)
+				goto err;
+			break;
+		case GNUTLS_BAG_ENCRYPTED:
+			err = gnutls_pkcs12_bag_decrypt(bag, password);
+			if (err) {
+				ntfs_log_error("Failed to decrypt Bag: %s\n",
+						gnutls_strerror(err));
+				goto err;
+			}
+			goto check_again;
+		case GNUTLS_BAG_CERTIFICATE:
+			err = gnutls_pkcs12_bag_get_data(bag, 0, &dkey);
+			if (err < 0) {
+				ntfs_log_error("Failed to obtain Bag data: "
+						"%s\n", gnutls_strerror(err));
+				goto err;
+			}
+			err = gnutls_x509_crt_init(&crt);
+			if (err) {
+				ntfs_log_error("Failed to initialize "
+						"certificate structure: %s\n",
+						gnutls_strerror(err));
+				goto err;
+			}
+			err = gnutls_x509_crt_import(crt, &dkey,
+					GNUTLS_X509_FMT_DER);
+			if (err) {
+				ntfs_log_error("Failed to convert certificate "
+						"from DER to GNU TLS format: "
+						"%s\n", gnutls_strerror(err));
+				goto err;
+			}
+			oid_index = 0;
+				/*
+				 * Search in the key purposes for an EFS
+				 * encryption purpose or an EFS recovery
+				 * purpose, and use the first one found.
+				 */
+			do {
+				purpose_oid_size = sizeof(purpose_oid);
+				err = gnutls_x509_crt_get_key_purpose_oid(crt,
+					oid_index,
+					purpose_oid, &purpose_oid_size, NULL);
+				if (!err) {
+					purpose_oid[purpose_oid_size - 1]
+							= '\0';
+					if (!strcmp(purpose_oid,
+						NTFS_EFS_CERT_PURPOSE_OID_DRF))
+					*df_type = DF_TYPE_DRF;
+					else if (!strcmp(purpose_oid,
+						NTFS_EFS_CERT_PURPOSE_OID_DDF))
+						*df_type = DF_TYPE_DDF;
+					else
+						oid_index++;
+				}
+			} while (!err && (*df_type == DF_TYPE_UNKNOWN));
+			if (*df_type == DF_TYPE_UNKNOWN) {
+				/* End of list reached ? */
+				if (err
+				    == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
+					ntfs_log_error("Key does not have an "
+						"EFS purpose OID\n");
+				else
+					ntfs_log_error("Failed to get a key "
+							"purpose OID : %s ",
+							gnutls_strerror(err));
+				goto err;
+			}
+			/* Return the thumbprint to the caller. */
+			err = gnutls_x509_crt_get_fingerprint(crt,
+					GNUTLS_DIG_SHA1, thumbprint, &tp_size);
+			if (err) {
+				ntfs_log_error("Failed to get thumbprint: "
+						"%s\n", gnutls_strerror(err));
+				goto err;
+			}
+			if (tp_size != NTFS_SHA1_THUMBPRINT_SIZE) {
+				ntfs_log_error("Invalid thumbprint size %zd.  "
+						"Should be %d.\n", tp_size,
+						thumbprint_size);
+				err = EINVAL;
+				goto err;
+			}
+			have_thumbprint = TRUE;
+			gnutls_x509_crt_deinit(crt);
+			crt = NULL;
+			break;
+		default:
+			/* We do not care about other types. */
+			break;
+		}
+		gnutls_pkcs12_bag_deinit(bag);
+	}
+err:
+	if (rsa_key && (err || *df_type == DF_TYPE_UNKNOWN ||
+			!have_thumbprint)) {
+		if (!err)
+			ntfs_log_error("Key type or thumbprint not found, "
+					"aborting.\n");
+		ntfs_rsa_private_key_release(rsa_key);
+		rsa_key = NULL;
+	}
+	if (crt)
+		gnutls_x509_crt_deinit(crt);
+	if (pkey)
+		gnutls_x509_privkey_deinit(pkey);
+	if (bag)
+		gnutls_pkcs12_bag_deinit(bag);
+	if (pkcs12)
+		gnutls_pkcs12_deinit(pkcs12);
+	return rsa_key;
+}
+
+/**
+ * ntfs_buffer_reverse -
+ *
+ * This is a utility function for reversing the order of a buffer in place.
+ * Users of this function should be very careful not to sweep byte order
+ * problems under the rug.
+ */
+static inline void ntfs_buffer_reverse(u8 *buf, unsigned buf_size)
+{
+	unsigned i;
+	u8 t;
+
+	for (i = 0; i < buf_size / 2; i++) {
+		t = buf[i];
+		buf[i] = buf[buf_size - i - 1];
+		buf[buf_size - i - 1] = t;
+	}
+}
+
+#ifndef HAVE_STRNLEN
+/**
+ * strnlen - strnlen is a gnu extension so emulate it if not present
+ */
+static size_t strnlen(const char *s, size_t maxlen)
+{
+	const char *p, *end;
+
+	/* Look for a '\0' character. */
+	for (p = s, end = s + maxlen; p < end && *p; p++)
+		;
+	return p - s;
+}
+#endif /* ! HAVE_STRNLEN */
+
+/**
+ * ntfs_raw_fek_decrypt -
+ *
+ * Note: decrypting into the input buffer.
+ */
+static unsigned ntfs_raw_fek_decrypt(u8 *fek, u32 fek_size,
+		ntfs_rsa_private_key rsa_key)
+{
+	gcry_mpi_t fek_mpi;
+	gcry_sexp_t fek_sexp, fek_sexp2;
+	gcry_error_t err;
+	size_t size, padding;
+
+	/* Reverse the raw FEK. */
+	ntfs_buffer_reverse(fek, fek_size);
+	/* Convert the FEK to internal MPI format. */
+	err = gcry_mpi_scan(&fek_mpi, GCRYMPI_FMT_USG, fek, fek_size, NULL);
+	if (err != GPG_ERR_NO_ERROR) {
+		ntfs_log_error("Failed to convert file encryption key to "
+				"internal MPI format: %s\n",
+				gcry_strerror(err));
+		return 0;
+	}
+	/* Create an internal S-expression from the FEK. */
+	err = gcry_sexp_build(&fek_sexp, NULL,
+			"(enc-val (flags) (rsa (a %m)))", fek_mpi);
+	gcry_mpi_release(fek_mpi);
+	if (err != GPG_ERR_NO_ERROR) {
+		ntfs_log_error("Failed to create internal S-expression of "
+				"the file encryption key: %s\n",
+				gcry_strerror(err));
+		return 0;
+	}
+	/* Decrypt the FEK. */
+	err = gcry_pk_decrypt(&fek_sexp2, fek_sexp, (gcry_sexp_t)rsa_key);
+	gcry_sexp_release(fek_sexp);
+	if (err != GPG_ERR_NO_ERROR) {
+		ntfs_log_error("Failed to decrypt the file encryption key: "
+				"%s\n", gcry_strerror(err));
+		return 0;
+	}
+	/* Extract the actual FEK from the decrypted raw S-expression. */
+	fek_sexp = gcry_sexp_find_token(fek_sexp2, "value", 0);
+	gcry_sexp_release(fek_sexp2);
+	if (!fek_sexp) {
+		ntfs_log_error("Failed to find the decrypted file encryption "
+				"key in the internal S-expression.\n");
+		return 0;
+	}
+	/* Convert the decrypted FEK S-expression into MPI format. */
+	fek_mpi = gcry_sexp_nth_mpi(fek_sexp, 1, GCRYMPI_FMT_USG);
+	gcry_sexp_release(fek_sexp);
+	if (!fek_mpi) {
+		ntfs_log_error("Failed to convert the decrypted file "
+				"encryption key S-expression to internal MPI "
+				"format.\n");
+		return 0;
+	}
+	/* Convert the decrypted FEK from MPI format to binary data. */
+	err = gcry_mpi_print(GCRYMPI_FMT_USG, fek, fek_size, &size, fek_mpi);
+	gcry_mpi_release(fek_mpi);
+	if (err != GPG_ERR_NO_ERROR || !size) {
+		ntfs_log_error("Failed to convert decrypted file encryption "
+				"key from internal MPI format to binary data: "
+				"%s\n", gcry_strerror(err));
+		return 0;
+	}
+	/*
+	 * Finally, remove the PKCS#1 padding and return the size of the
+	 * decrypted FEK.
+	 */
+	padding = strnlen((char *)fek, size) + 1;
+	if (padding > size) {
+		ntfs_log_error("Failed to remove PKCS#1 padding from "
+				"decrypted file encryption key.\n");
+		return 0;
+	}
+	size -= padding;
+	memmove(fek, fek + padding, size);
+	return size;
+}
+
+/**
+ * ntfs_desx_key_expand - expand a 128-bit desx key to the needed 192-bit key
+ * @src:	source buffer containing 128-bit key
+ *
+ * Expands the on-disk 128-bit desx key to the needed des key, the in-, and the
+ * out-whitening keys required to perform desx {de,en}cryption.
+ */
+static gcry_error_t ntfs_desx_key_expand(const u8 *src, u32 *des_key,
+		u64 *out_whitening, u64 *in_whitening)
+{
+	static const u8 *salt1 = (const u8*)"Dan Simon  ";
+	static const u8 *salt2 = (const u8*)"Scott Field";
+	static const int salt_len = 12;
+	gcry_md_hd_t hd1, hd2;
+	u32 *md;
+	gcry_error_t err;
+
+	err = gcry_md_open(&hd1, GCRY_MD_MD5, 0);
+	if (err != GPG_ERR_NO_ERROR) {
+		ntfs_log_error("Failed to open MD5 digest.\n");
+		return err;
+	}
+	/* Hash the on-disk key. */
+	gcry_md_write(hd1, src, 128 / 8);
+	/* Copy the current hash for efficiency. */
+	err = gcry_md_copy(&hd2, hd1);
+	if (err != GPG_ERR_NO_ERROR) {
+		ntfs_log_error("Failed to copy MD5 digest object.\n");
+		goto out;
+	}
+	/* Hash with the first salt and store the result. */
+	gcry_md_write(hd1, salt1, salt_len);
+	md = (u32*)gcry_md_read(hd1, 0);
+	des_key[0] = md[0] ^ md[1];
+	des_key[1] = md[2] ^ md[3];
+	/* Hash with the second salt and store the result. */
+	gcry_md_write(hd2, salt2, salt_len);
+	md = (u32*)gcry_md_read(hd2, 0);
+	*out_whitening = *(u64*)md;
+	*in_whitening = *(u64*)(md + 2);
+	gcry_md_close(hd2);
+out:
+	gcry_md_close(hd1);
+	return err;
+}
+
+/**
+ * ntfs_desx_decrypt
+ */
+static void ntfs_desx_decrypt(ntfs_fek *fek, u8 *outbuf, const u8 *inbuf)
+{
+	gcry_error_t err;
+	ntfs_desx_ctx *ctx = &fek->desx_ctx;
+
+	err = gcry_cipher_reset(fek->gcry_cipher_hd);
+	if (err != GPG_ERR_NO_ERROR)
+		ntfs_log_error("Failed to reset des cipher (error 0x%x).\n",
+				err);
+	*(u64*)outbuf = *(const u64*)inbuf ^ ctx->out_whitening;
+	err = gcry_cipher_encrypt(fek->gcry_cipher_hd, outbuf, 8, NULL, 0);
+	if (err != GPG_ERR_NO_ERROR)
+		ntfs_log_error("Des decryption failed (error 0x%x).\n", err);
+	*(u64*)outbuf ^= ctx->in_whitening;
+}
+
+/**
+ * ntfs_desx_encrypt
+ */
+static void ntfs_desx_encrypt(ntfs_fek *fek, u8 *outbuf, const u8 *inbuf)
+{
+	gcry_error_t err;
+	ntfs_desx_ctx *ctx = &fek->desx_ctx;
+
+	err = gcry_cipher_reset(fek->gcry_cipher_hd);
+	if (err != GPG_ERR_NO_ERROR)
+		ntfs_log_error("Failed to reset des cipher (error 0x%x).\n",
+				err);
+	*(u64*)outbuf = *(const u64*)inbuf ^ ctx->in_whitening;
+	err = gcry_cipher_decrypt(fek->gcry_cipher_hd, outbuf, 8, NULL, 0);
+	if (err != GPG_ERR_NO_ERROR)
+		ntfs_log_error("Des decryption failed (error 0x%x).\n", err);
+	*(u64*)outbuf ^= ctx->out_whitening;
+}
+
+//#define DO_CRYPTO_TESTS 1
+
+#ifdef DO_CRYPTO_TESTS
+
+/* Do not remove this test code from this file! AIA */
+/**
+ * ntfs_desx_key_expand_test
+ */
+static BOOL ntfs_desx_key_expand_test(void)
+{
+	const u8 known_desx_on_disk_key[16] = {
+		0xa1, 0xf9, 0xe0, 0xb2, 0x53, 0x23, 0x9e, 0x8f,
+		0x0f, 0x91, 0x45, 0xd9, 0x8e, 0x20, 0xec, 0x30
+	};
+	const u8 known_des_key[8] = {
+		0x27, 0xd1, 0x93, 0x09, 0xcb, 0x78, 0x93, 0x1f,
+	};
+	const u8 known_out_whitening[8] = {
+		0xed, 0xda, 0x4c, 0x47, 0x60, 0x49, 0xdb, 0x8d,
+	};
+	const u8 known_in_whitening[8] = {
+		0x75, 0xf6, 0xa0, 0x1a, 0xc0, 0xca, 0x28, 0x1e
+	};
+	u64 test_out_whitening, test_in_whitening;
+	union {
+		u64 u64;
+		u32 u32[2];
+	} test_des_key;
+	gcry_error_t err;
+	BOOL res;
+
+	err = ntfs_desx_key_expand(known_desx_on_disk_key, test_des_key.u32,
+			&test_out_whitening, &test_in_whitening);
+	if (err != GPG_ERR_NO_ERROR)
+		res = FALSE;
+	else
+		res = test_des_key.u64 == *(u64*)known_des_key &&
+				test_out_whitening ==
+				*(u64*)known_out_whitening &&
+				test_in_whitening ==
+				*(u64*)known_in_whitening;
+	ntfs_log_error("Testing whether ntfs_desx_key_expand() works: %s\n",
+			res ? "SUCCESS" : "FAILED");
+	return res;
+}
+
+/**
+ * ntfs_des_test
+ */
+static BOOL ntfs_des_test(void)
+{
+	const u8 known_des_key[8] = {
+		0x27, 0xd1, 0x93, 0x09, 0xcb, 0x78, 0x93, 0x1f
+	};
+	const u8 known_des_encrypted_data[8] = {
+		0xdc, 0xf7, 0x68, 0x2a, 0xaf, 0x48, 0x53, 0x0f
+	};
+	const u8 known_decrypted_data[8] = {
+		0xd8, 0xd9, 0x15, 0x23, 0x5b, 0x88, 0x0e, 0x09
+	};
+	u8 test_decrypted_data[8];
+	int res;
+	gcry_error_t err;
+	gcry_cipher_hd_t gcry_cipher_hd;
+
+	err = gcry_cipher_open(&gcry_cipher_hd, GCRY_CIPHER_DES,
+			GCRY_CIPHER_MODE_ECB, 0);
+	if (err != GPG_ERR_NO_ERROR) {
+		ntfs_log_error("Failed to open des cipher (error 0x%x).\n",
+				err);
+		return FALSE;
+	}
+	err = gcry_cipher_setkey(gcry_cipher_hd, known_des_key,
+			sizeof(known_des_key));
+	if (err != GPG_ERR_NO_ERROR) {
+		ntfs_log_error("Failed to set des key (error 0x%x.\n", err);
+		gcry_cipher_close(gcry_cipher_hd);
+		return FALSE;
+	}
+	/*
+	 * Apply DES decryption (ntfs actually uses encryption when decrypting).
+	 */
+	err = gcry_cipher_encrypt(gcry_cipher_hd, test_decrypted_data,
+			sizeof(test_decrypted_data), known_des_encrypted_data,
+			sizeof(known_des_encrypted_data));
+	gcry_cipher_close(gcry_cipher_hd);
+	if (err) {
+		ntfs_log_error("Failed to des decrypt test data (error "
+				"0x%x).\n", err);
+		return FALSE;
+	}
+	res = !memcmp(test_decrypted_data, known_decrypted_data,
+			sizeof(known_decrypted_data));
+	ntfs_log_error("Testing whether des decryption works: %s\n",
+			res ? "SUCCESS" : "FAILED");
+	return res;
+}
+
+#else /* !defined(DO_CRYPTO_TESTS) */
+
+/**
+ * ntfs_desx_key_expand_test
+ */
+static inline BOOL ntfs_desx_key_expand_test(void)
+{
+	return TRUE;
+}
+
+/**
+ * ntfs_des_test
+ */
+static inline BOOL ntfs_des_test(void)
+{
+	return TRUE;
+}
+
+#endif /* !defined(DO_CRYPTO_TESTS) */
+
+/**
+ * ntfs_fek_import_from_raw
+ */
+static ntfs_fek *ntfs_fek_import_from_raw(u8 *fek_buf, unsigned fek_size)
+{
+	ntfs_fek *fek;
+	u32 key_size, wanted_key_size, gcry_algo;
+	int gcry_mode;
+	gcry_error_t err;
+	ntfs_desx_ctx *ctx;
+
+	key_size = le32_to_cpup(fek_buf);
+	ntfs_log_debug("key_size 0x%x\n", key_size);
+	if (key_size + 16 > fek_size) {
+		ntfs_log_debug("Invalid FEK.  It was probably decrypted with "
+				"the incorrect RSA key.");
+		errno = EINVAL;
+		return NULL;
+	}
+	fek = malloc(((((sizeof(*fek) + 7) & ~7) + key_size + 7) & ~7) +
+			sizeof(gcry_cipher_hd_t));
+	if (!fek) {
+		errno = ENOMEM;
+		return NULL;
+	}
+	ctx = &fek->desx_ctx;
+	fek->alg_id = *(le32*)(fek_buf + 8);
+	//ntfs_log_debug("alg_id 0x%x\n", le32_to_cpu(fek->alg_id));
+	fek->key_data = (u8*)fek + ((sizeof(*fek) + 7) & ~7);
+	memcpy(fek->key_data, fek_buf + 16, key_size);
+	fek->des_gcry_cipher_hd_ptr = NULL;
+	*(gcry_cipher_hd_t***)(fek->key_data + ((key_size + 7) & ~7)) =
+			&fek->des_gcry_cipher_hd_ptr;
+	switch (fek->alg_id) {
+	case CALG_DESX:
+		wanted_key_size = 16;
+		gcry_algo = GCRY_CIPHER_DES;
+		gcry_mode = GCRY_CIPHER_MODE_ECB;
+		break;
+	case CALG_3DES:
+		wanted_key_size = 24;
+		gcry_algo = GCRY_CIPHER_3DES;
+		gcry_mode = GCRY_CIPHER_MODE_CBC;
+		break;
+	case CALG_AES_256:
+		wanted_key_size = 32;
+		gcry_algo = GCRY_CIPHER_AES256;
+		gcry_mode = GCRY_CIPHER_MODE_CBC;
+		break;
+	default:
+		wanted_key_size = 8;
+		gcry_algo = GCRY_CIPHER_DES;
+		gcry_mode = GCRY_CIPHER_MODE_CBC;
+		if (fek->alg_id == CALG_DES)
+			ntfs_log_error("DES is not supported at present\n");
+		else
+			ntfs_log_error("Unknown crypto algorithm 0x%x\n",
+					le32_to_cpu(fek->alg_id));
+		ntfs_log_error(".  Please email %s and say that you saw this "
+				"message.  We will then try to implement "
+				"support for this algorithm.\n", NTFS_DEV_LIST);
+		err = EOPNOTSUPP;
+		goto out;
+	}
+	if (key_size != wanted_key_size) {
+		ntfs_log_error("%s key of %u bytes but needed size is %u "
+				"bytes, assuming corrupt or incorrect key.  "
+				"Aborting.\n",
+				gcry_cipher_algo_name(gcry_algo),
+				(unsigned)key_size, (unsigned)wanted_key_size);
+		err = EIO;
+		goto out;
+	}
+	err = gcry_cipher_open(&fek->gcry_cipher_hd, gcry_algo,
+				gcry_mode, 0);
+
+	if (err != GPG_ERR_NO_ERROR) {
+		ntfs_log_error("gcry_cipher_open() failed: %s\n",
+				gcry_strerror(err));
+		err = EINVAL;
+		goto out;
+	}
+	if (fek->alg_id == CALG_DESX) {
+		err = ntfs_desx_key_expand(fek->key_data, (u32*)ctx->des_key,
+				&ctx->out_whitening, &ctx->in_whitening);
+		if (err == GPG_ERR_NO_ERROR)
+			err = gcry_cipher_setkey(fek->gcry_cipher_hd,
+							ctx->des_key, 8);
+	} else {
+		err = gcry_cipher_setkey(fek->gcry_cipher_hd, fek->key_data,
+							key_size);
+	}
+	if (err != GPG_ERR_NO_ERROR) {
+		ntfs_log_error("gcry_cipher_setkey() failed: %s\n",
+				gcry_strerror(err));
+		gcry_cipher_close(fek->gcry_cipher_hd);
+		err = EINVAL;
+		goto out;
+	}
+	return fek;
+out:
+	free(fek);
+	errno = err;
+	return NULL;
+}
+
+/**
+ * ntfs_fek_release
+ */
+static void ntfs_fek_release(ntfs_fek *fek)
+{
+	if (fek->des_gcry_cipher_hd_ptr)
+		gcry_cipher_close(*fek->des_gcry_cipher_hd_ptr);
+	gcry_cipher_close(fek->gcry_cipher_hd);
+	free(fek);
+}
+
+/**
+ * ntfs_df_array_fek_get
+ */
+static ntfs_fek *ntfs_df_array_fek_get(EFS_DF_ARRAY_HEADER *df_array,
+		ntfs_rsa_private_key rsa_key, char *thumbprint,
+		int thumbprint_size)
+{
+	EFS_DF_HEADER *df_header;
+	EFS_DF_CREDENTIAL_HEADER *df_cred;
+	EFS_DF_CERT_THUMBPRINT_HEADER *df_cert;
+	u8 *fek_buf;
+	ntfs_fek *fek;
+	u32 df_count, fek_size;
+	unsigned i;
+
+	df_count = le32_to_cpu(df_array->df_count);
+	if (!df_count)
+		ntfs_log_error("There are no elements in the DF array.\n");
+	df_header = (EFS_DF_HEADER*)(df_array + 1);
+	for (i = 0; i < df_count; i++, df_header = (EFS_DF_HEADER*)(
+			(u8*)df_header + le32_to_cpu(df_header->df_length))) {
+		df_cred = (EFS_DF_CREDENTIAL_HEADER*)((u8*)df_header +
+				le32_to_cpu(df_header->cred_header_offset));
+		if (df_cred->type != NTFS_CRED_TYPE_CERT_THUMBPRINT) {
+			ntfs_log_debug("Credential type is not certificate "
+					"thumbprint, skipping DF entry.\n");
+			continue;
+		}
+		df_cert = (EFS_DF_CERT_THUMBPRINT_HEADER*)((u8*)df_cred +
+				le32_to_cpu(
+				df_cred->cert_thumbprint_header_offset));
+		if ((int)le32_to_cpu(df_cert->thumbprint_size)
+						!= thumbprint_size) {
+			ntfs_log_error("Thumbprint size %d is not valid "
+					"(should be %d), skipping this DF "
+					"entry.\n",
+					le32_to_cpu(df_cert->thumbprint_size),
+					thumbprint_size);
+			continue;
+		}
+		if (memcmp((u8*)df_cert +
+				le32_to_cpu(df_cert->thumbprint_offset),
+				thumbprint, thumbprint_size)) {
+			ntfs_log_debug("Thumbprints do not match, skipping "
+					"this DF entry.\n");
+			continue;
+		}
+		/*
+		 * The thumbprints match so this is probably the DF entry
+		 * matching the RSA key.  Try to decrypt the FEK with it.
+		 */
+		fek_size = le32_to_cpu(df_header->fek_size);
+		fek_buf = (u8*)df_header + le32_to_cpu(df_header->fek_offset);
+		/* Decrypt the FEK.  Note: This is done in place. */
+		fek_size = ntfs_raw_fek_decrypt(fek_buf, fek_size, rsa_key);
+		if (fek_size) {
+			/* Convert the FEK to our internal format. */
+			fek = ntfs_fek_import_from_raw(fek_buf, fek_size);
+			if (fek)
+				return fek;
+			ntfs_log_error("Failed to convert the decrypted file "
+					"encryption key to internal format.\n");
+		} else
+			ntfs_log_error("Failed to decrypt the file "
+					"encryption key.\n");
+	}
+	return NULL;
+}
+
+/**
+ * ntfs_inode_fek_get -
+ */
+static ntfs_fek *ntfs_inode_fek_get(ntfs_inode *inode,
+		ntfs_rsa_private_key rsa_key, char *thumbprint,
+		int thumbprint_size, NTFS_DF_TYPES df_type)
+{
+	EFS_ATTR_HEADER *efs;
+	EFS_DF_ARRAY_HEADER *df_array = NULL;
+	ntfs_fek *fek = NULL;
+
+	/* Obtain the $EFS contents. */
+	efs = ntfs_attr_readall(inode, AT_LOGGED_UTILITY_STREAM, EFS, 4, NULL);
+	if (!efs) {
+		ntfs_log_perror("Failed to read $EFS attribute");
+		return NULL;
+	}
+	/*
+	 * Depending on whether the key is a normal key or a data recovery key,
+	 * iterate through the DDF or DRF array, respectively.
+	 */
+	if (df_type == DF_TYPE_DDF) {
+		if (efs->offset_to_ddf_array)
+			df_array = (EFS_DF_ARRAY_HEADER*)((u8*)efs +
+					le32_to_cpu(efs->offset_to_ddf_array));
+		else
+			ntfs_log_error("There are no entries in the DDF "
+					"array.\n");
+	} else if (df_type == DF_TYPE_DRF) {
+		if (efs->offset_to_drf_array)
+			df_array = (EFS_DF_ARRAY_HEADER*)((u8*)efs +
+					le32_to_cpu(efs->offset_to_drf_array));
+		else
+			ntfs_log_error("There are no entries in the DRF "
+					"array.\n");
+	} else
+		ntfs_log_error("Invalid DF type.\n");
+	if (df_array)
+		fek = ntfs_df_array_fek_get(df_array, rsa_key, thumbprint,
+				thumbprint_size);
+	free(efs);
+	return fek;
+}
+
+/**
+ * ntfs_fek_decrypt_sector
+ */
+static int ntfs_fek_decrypt_sector(ntfs_fek *fek, u8 *data, const u64 offset)
+{
+	gcry_error_t err;
+
+	err = gcry_cipher_reset(fek->gcry_cipher_hd);
+	if (err != GPG_ERR_NO_ERROR) {
+		ntfs_log_error("Failed to reset cipher: %s\n",
+				gcry_strerror(err));
+		return -1;
+	}
+	/*
+	 * Note: You may wonder why we are not calling gcry_cipher_setiv() here
+	 * instead of doing it by hand after the decryption.  The answer is
+	 * that gcry_cipher_setiv() wants an iv of length 8 bytes but we give
+	 * it a length of 16 for AES256 so it does not like it.
+	 */
+	if (fek->alg_id == CALG_DESX) {
+		int k;
+
+		for (k=0; k<512; k+=8) {
+			ntfs_desx_decrypt(fek, &data[k], &data[k]);
+		}
+	} else
+		err = gcry_cipher_decrypt(fek->gcry_cipher_hd, data, 512, NULL, 0);
+	if (err != GPG_ERR_NO_ERROR) {
+		ntfs_log_error("Decryption failed: %s\n", gcry_strerror(err));
+		return -1;
+	}
+	/* Apply the IV. */
+	if (fek->alg_id == CALG_AES_256) {
+		((le64*)data)[0] ^= cpu_to_le64(0x5816657be9161312ULL + offset);
+		((le64*)data)[1] ^= cpu_to_le64(0x1989adbe44918961ULL + offset);
+	} else {
+		/* All other algos (Des, 3Des, DesX) use the same IV. */
+		((le64*)data)[0] ^= cpu_to_le64(0x169119629891ad13ULL + offset);
+	}
+	return 512;
+}
+
+/**
+ * ntfs_fek_encrypt_sector
+ */
+static int ntfs_fek_encrypt_sector(ntfs_fek *fek, u8 *data, const u64 offset)
+{
+	gcry_error_t err;
+
+	err = gcry_cipher_reset(fek->gcry_cipher_hd);
+	if (err != GPG_ERR_NO_ERROR) {
+		ntfs_log_error("Failed to reset cipher: %s\n",
+				gcry_strerror(err));
+		return -1;
+	}
+	/*
+	 * Note: You may wonder why we are not calling gcry_cipher_setiv() here
+	 * instead of doing it by hand after the decryption.  The answer is
+	 * that gcry_cipher_setiv() wants an iv of length 8 bytes but we give
+	 * it a length of 16 for AES256 so it does not like it.
+	 */
+	/* Apply the IV. */
+	if (fek->alg_id == CALG_AES_256) {
+		((le64*)data)[0] ^= cpu_to_le64(0x5816657be9161312ULL + offset);
+		((le64*)data)[1] ^= cpu_to_le64(0x1989adbe44918961ULL + offset);
+	} else {
+		/* All other algos (Des, 3Des, DesX) use the same IV. */
+		((le64*)data)[0] ^= cpu_to_le64(0x169119629891ad13ULL + offset);
+	}
+	if (fek->alg_id == CALG_DESX) {
+		int k;
+
+		for (k=0; k<512; k+=8) {
+			ntfs_desx_encrypt(fek, &data[k], &data[k]);
+		}
+	} else
+		err = gcry_cipher_encrypt(fek->gcry_cipher_hd, data, 512, NULL, 0);
+	if (err != GPG_ERR_NO_ERROR) {
+		ntfs_log_error("Encryption failed: %s\n", gcry_strerror(err));
+		return -1;
+	}
+	return 512;
+}
+
+/**
+ * ntfs_cat_decrypt - Decrypt the contents of an encrypted file to stdout.
+ * @inode:	An encrypted file's inode structure, as obtained by
+ * 		ntfs_inode_open().
+ * @fek:	A file encryption key. As obtained by ntfs_inode_fek_get().
+ */
+static int ntfs_cat_decrypt(ntfs_inode *inode, ntfs_fek *fek)
+{
+	int bufsize = 512;
+	unsigned char *buffer;
+	ntfs_attr *attr;
+	s64 bytes_read, written, offset, total;
+	s64 old_data_size, old_initialized_size;
+	int i;
+
+	buffer = malloc(bufsize);
+	if (!buffer)
+		return 1;
+	attr = ntfs_attr_open(inode, AT_DATA, NULL, 0);
+	if (!attr) {
+		ntfs_log_error("Cannot cat a directory.\n");
+		free(buffer);
+		return 1;
+	}
+	total = attr->data_size;
+
+	// hack: make sure attr will not be commited to disk if you use this.
+	// clear the encrypted bit, otherwise the library won't allow reading.
+	NAttrClearEncrypted(attr);
+	// extend the size, we may need to read past the end of the stream.
+	old_data_size = attr->data_size;
+	old_initialized_size = attr->initialized_size;
+	attr->data_size = attr->initialized_size = attr->allocated_size;
+
+	offset = 0;
+	while (total > 0) {
+		bytes_read = ntfs_attr_pread(attr, offset, 512, buffer);
+		if (bytes_read == -1) {
+			ntfs_log_perror("ERROR: Couldn't read file");
+			break;
+		}
+		if (!bytes_read)
+			break;
+		if ((i = ntfs_fek_decrypt_sector(fek, buffer, offset)) <
+				bytes_read) {
+			ntfs_log_perror("ERROR: Couldn't decrypt all data!");
+			ntfs_log_error("%u/%lld/%lld/%lld\n", i,
+				(long long)bytes_read, (long long)offset,
+				(long long)total);
+			break;
+		}
+		if (bytes_read > total)
+			bytes_read = total;
+		written = fwrite(buffer, 1, bytes_read, stdout);
+		if (written != bytes_read) {
+			ntfs_log_perror("ERROR: Couldn't output all data!");
+			break;
+		}
+		offset += bytes_read;
+		total -= bytes_read;
+	}
+	attr->data_size = old_data_size;
+	attr->initialized_size = old_initialized_size;
+	NAttrSetEncrypted(attr);
+	ntfs_attr_close(attr);
+	free(buffer);
+	return 0;
+}
+
+/**
+ * ntfs_feed_encrypt - Encrypt the contents of stdin to an encrypted file
+ * @inode:	An encrypted file's inode structure, as obtained by
+ * 		ntfs_inode_open().
+ * @fek:	A file encryption key. As obtained by ntfs_inode_fek_get().
+ */
+static int ntfs_feed_encrypt(ntfs_inode *inode, ntfs_fek *fek)
+{
+	const int bufsize = 512;
+	unsigned char *buffer;
+	ntfs_attr *attr;
+	s64 bytes_read, written, offset, total;
+	unsigned char *b;
+	long val;
+	int count;
+	int i;
+
+	buffer = (unsigned char*)malloc(bufsize);
+	if (!buffer)
+		return 1;
+	attr = ntfs_attr_open(inode, AT_DATA, NULL, 0);
+	if (!attr) {
+		ntfs_log_error("Cannot feed into a directory.\n");
+		goto rejected;
+	}
+	total = 0;
+
+	if (!(attr->data_flags & ATTR_IS_ENCRYPTED)) {
+		ntfs_log_error("The data stream was not encrypted\n");
+		goto rejected;
+	}
+	inode->vol->efs_raw = TRUE;
+
+	if (ntfs_attr_truncate(attr, 0)) {
+		ntfs_log_error("Failed to truncate the data stream\n");
+		goto rejected;
+	}
+	offset = 0;
+	do {
+		bytes_read = fread(buffer, 1, bufsize, stdin);
+		if (bytes_read <= 0) {
+			if (bytes_read < 0)
+				ntfs_log_perror("ERROR: Couldn't read data");
+		} else {
+			if (bytes_read < bufsize) {
+				/* Fill with random data */
+				srandom((unsigned int)(sle64_to_cpu(
+					inode->last_data_change_time)
+					/100000000));
+				count = bufsize - bytes_read;
+				b = &buffer[bytes_read];
+				do {
+					val = random();
+					switch (count) {
+						default :
+							*b++ = val;
+							val >>= 8;
+						case 3 :
+							*b++ = val;
+							val >>= 8;
+						case 2 :
+							*b++ = val;
+							val >>= 8;
+						case 1 :
+							*b++ = val;
+							val >>= 8;
+					}
+					count -= 4;
+				} while (count > 0);
+			}
+			if ((i = ntfs_fek_encrypt_sector(fek, buffer, offset))
+					< bufsize) {
+				ntfs_log_perror("ERROR: Couldn't encrypt all data!");
+				ntfs_log_error("%u/%lld/%lld/%lld\n", i,
+					(long long)bytes_read, (long long)offset,
+					(long long)total);
+				break;
+			}
+		written = ntfs_attr_pwrite(attr, offset, bufsize, buffer);
+		if (written != bufsize) {
+			ntfs_log_perror("ERROR: Couldn't output all data!");
+			break;
+		}
+		offset += bufsize;
+		total += bytes_read;
+		}
+	} while (bytes_read == bufsize);
+	ntfs_attr_truncate(attr, total);
+	inode->last_data_change_time = ntfs_current_time();
+	NAttrSetEncrypted(attr);
+	ntfs_attr_close(attr);
+	free(buffer);
+	return 0;
+rejected :
+	free(buffer);
+	return (-1);
+}
+
+/**
+ * main - Begin here
+ *
+ * Start from here.
+ *
+ * Return:  0  Success, the program worked
+ *	    1  Error, something went wrong
+ */
+int main(int argc, char *argv[])
+{
+	u8 *pfx_buf;
+	char *password;
+	ntfs_rsa_private_key rsa_key;
+	ntfs_volume *vol;
+	ntfs_inode *inode;
+	ntfs_fek *fek;
+	unsigned pfx_size;
+	int res;
+	NTFS_DF_TYPES df_type;
+	char thumbprint[NTFS_SHA1_THUMBPRINT_SIZE];
+
+	ntfs_log_set_handler(ntfs_log_handler_stderr);
+
+	res = parse_options(argc, argv);
+	if (res >= 0)
+		return (res);
+	utils_set_locale();
+
+	/* Initialize crypto in ntfs. */
+	if (ntfs_crypto_init()) {
+		ntfs_log_error("Failed to initialize crypto.  Aborting.\n");
+		return 1;
+	}
+	/* Load the PKCS#12 (.pfx) file containing the user's private key. */
+	if (ntfs_pkcs12_load_pfxfile(opts.keyfile, &pfx_buf, &pfx_size)) {
+		ntfs_log_error("Failed to load key file.  Aborting.\n");
+		ntfs_crypto_deinit();
+		return 1;
+	}
+	/* Ask the user for their password. */
+	password = getpass("Enter the password with which the private key was "
+			"encrypted: ");
+	if (!password) {
+		ntfs_log_perror("Failed to obtain user password");
+		free(pfx_buf);
+		ntfs_crypto_deinit();
+		return 1;
+	}
+	/* Obtain the user's private RSA key from the key file. */
+	rsa_key = ntfs_pkcs12_extract_rsa_key(pfx_buf, pfx_size, password,
+			thumbprint, sizeof(thumbprint), &df_type);
+	/* Destroy the password. */
+	memset(password, 0, strlen(password));
+	/* No longer need the pfx file contents. */
+	free(pfx_buf);
+	if (!rsa_key) {
+		ntfs_log_error("Failed to extract the private RSA key.\n");
+		ntfs_crypto_deinit();
+		return 1;
+	}
+	/* Mount the ntfs volume. */
+	vol = utils_mount_volume(opts.device,
+			(opts.encrypt ? 0 :  NTFS_MNT_RDONLY) |
+			(opts.force ? NTFS_MNT_RECOVER : 0));
+	if (!vol) {
+		ntfs_log_error("Failed to mount ntfs volume.  Aborting.\n");
+		ntfs_rsa_private_key_release(rsa_key);
+		ntfs_crypto_deinit();
+		return 1;
+	}
+	/* Open the encrypted ntfs file. */
+	if (opts.inode != -1)
+		inode = ntfs_inode_open(vol, opts.inode);
+	else
+		inode = ntfs_pathname_to_inode(vol, NULL, opts.file);
+	if (!inode) {
+		ntfs_log_error("Failed to open encrypted file.  Aborting.\n");
+		ntfs_umount(vol, FALSE);
+		ntfs_rsa_private_key_release(rsa_key);
+		ntfs_crypto_deinit();
+		return 1;
+	}
+	/* Obtain the file encryption key of the encrypted file. */
+	fek = ntfs_inode_fek_get(inode, rsa_key, thumbprint,
+			sizeof(thumbprint), df_type);
+	ntfs_rsa_private_key_release(rsa_key);
+	if (fek) {
+		if (opts.encrypt)
+			res = ntfs_feed_encrypt(inode, fek);
+		else
+			res = ntfs_cat_decrypt(inode, fek);
+		ntfs_fek_release(fek);
+	} else {
+		ntfs_log_error("Failed to obtain file encryption key.  "
+				"Aborting.\n");
+		res = 1;
+	}
+	ntfs_inode_close(inode);
+	ntfs_umount(vol, FALSE);
+	ntfs_crypto_deinit();
+	return res;
+}
diff --git a/ntfsprogs/ntfsdump_logfile.c b/ntfsprogs/ntfsdump_logfile.c
new file mode 100755
index 0000000000000000000000000000000000000000..279ebac2bdb611bab58771c9a03fc4eb4431a394
--- /dev/null
+++ b/ntfsprogs/ntfsdump_logfile.c
@@ -0,0 +1,779 @@
+/**
+ * ntfsdump_logfile - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2000-2005 Anton Altaparmakov
+ *
+ * This utility will interpret the contents of the journal ($LogFile) of an
+ * NTFS partition and display the results on stdout.  Errors will be output to
+ * stderr.
+ *
+ * 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 Linux-NTFS source
+ * in the file COPYING); if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+/* TODO:
+ *	- Remove the need for clipping at 64MiB.
+ *	- Add normal command line switchs (use getopt_long()).
+ *	- For a volume: allow dumping only uncommitted records.
+ *	- For a file:   get an optional command line parameter for the last SN.
+ *	- Sanity checks.
+ */
+
+#include "config.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.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
+
+#include "types.h"
+#include "endians.h"
+#include "volume.h"
+#include "inode.h"
+#include "attrib.h"
+#include "layout.h"
+#include "logfile.h"
+#include "mst.h"
+#include "utils.h"
+/* #include "version.h" */
+#include "logging.h"
+
+typedef struct {
+	BOOL is_volume;
+	const char *filename;
+	s64 data_size;
+	union {
+		struct {
+			ntfs_volume *vol;
+			ntfs_inode *ni;
+			ntfs_attr *na;
+		};
+		struct {
+			int fd;
+		};
+	};
+} logfile_file;
+
+/**
+ * logfile_close
+ */
+static int logfile_close(logfile_file *logfile)
+{
+	if (logfile->is_volume) {
+		if (logfile->na)
+			ntfs_attr_close(logfile->na);
+		if (logfile->ni && ntfs_inode_close(logfile->ni))
+			ntfs_log_perror("Warning: Failed to close $LogFile "
+					"(inode %i)", FILE_LogFile);
+		if (ntfs_umount(logfile->vol, 0))
+			ntfs_log_perror("Warning: Failed to umount %s",
+				logfile->filename);
+	} else {
+		if (close(logfile->fd))
+			ntfs_log_perror("Warning: Failed to close file %s",
+				logfile->filename);
+	}
+	return 0;
+}
+
+/**
+ * device_err_exit - put an error message, cleanup and exit.
+ * @vol: volume to unmount.
+ * @ni:  Inode to free.
+ * @na:  Attribute to close.
+ *
+ * Use when you wish to exit and collate all the cleanups together.
+ * if you don't have some parameter to pass, just pass NULL.
+ */
+__attribute__((noreturn))
+__attribute__((format(printf, 4, 5)))
+static void device_err_exit(ntfs_volume *vol, ntfs_inode *ni,
+		ntfs_attr *na, const char *fmt, ...)
+{
+	va_list ap;
+
+	if (na)
+		ntfs_attr_close(na);
+	if (ni && ntfs_inode_close(ni))
+		ntfs_log_perror("Warning: Failed to close $LogFile (inode %i)",
+			FILE_LogFile);
+	if (ntfs_umount(vol, 0))
+		ntfs_log_perror("Warning: Failed to umount");
+
+	fprintf(stderr, "ERROR: ");
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+
+	ntfs_log_error("Aborting...\n");
+	exit(1);
+}
+
+/**
+ * log_err_exit -
+ */
+__attribute__((noreturn))
+__attribute__((format(printf, 2, 3)))
+static void log_err_exit(u8 *buf, const char *fmt, ...)
+{
+	va_list ap;
+
+	free(buf);
+
+	fprintf(stderr, "ERROR: ");
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+
+	ntfs_log_error("Aborting...\n");
+	exit(1);
+}
+
+/**
+ * usage -
+ */
+__attribute__((noreturn))
+static void usage(const char *exec_name)
+{
+	ntfs_log_error("%s v%s (libntfs-3g) - Interpret and display information "
+			"about the journal\n($LogFile) of an NTFS volume.\n"
+			"Copyright (c) 2000-2005 Anton Altaparmakov.\n"
+			"%s is free software, released under the GNU General "
+			"Public License\nand you are welcome to redistribute "
+			"it under certain conditions.\n%s comes with "
+			"ABSOLUTELY NO WARRANTY; for details read the GNU\n"
+			"General Public License to be found in the file "
+			"COPYING in the main Linux-NTFS\ndistribution "
+			"directory.\nUsage: %s device\n    e.g. %s /dev/hda6\n"
+			"Alternative usage: %s -f file\n    e.g. %s -f "
+			"MyCopyOfTheLogFile\n", exec_name, VERSION,
+			exec_name, exec_name,
+			exec_name, exec_name, exec_name, exec_name);
+	exit(1);
+}
+
+/**
+ * logfile_open
+ */
+static int logfile_open(BOOL is_volume, const char *filename,
+		logfile_file *logfile)
+{
+	if (is_volume) {
+		ntfs_volume *vol;
+		ntfs_inode *ni;
+		ntfs_attr *na;
+
+		/* Porting note: NTFS_MNT_FORENSIC is not needed when we mount
+		 * the volume in read-only mode. No changes will be made to the
+		 * logfile or anything else when we are in read only-mode. */
+		vol = ntfs_mount(filename, NTFS_MNT_RDONLY);
+		if (!vol)
+			log_err_exit(NULL, "Failed to mount %s: %s\n",
+					filename, strerror(errno));
+		ntfs_log_info("Mounted NTFS volume %s (NTFS v%i.%i) on device %s.\n",
+				vol->vol_name ? vol->vol_name : "<NO_NAME>",
+				vol->major_ver, vol->minor_ver, filename);
+		if (ntfs_version_is_supported(vol))
+			device_err_exit(vol, NULL, NULL,
+					"Unsupported NTFS version.\n");
+		ni = ntfs_inode_open(vol, FILE_LogFile);
+		if (!ni)
+			device_err_exit(vol, NULL, NULL, "Failed to "
+					"open $LogFile (inode %i): %s\n",
+					FILE_LogFile, strerror(errno));
+		na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
+		if (!na)
+			device_err_exit(vol, ni, NULL, "Failed to open "
+					"$LogFile/$DATA (attribute 0x%x):"
+					" %s\n", (unsigned int)
+					le32_to_cpu(AT_DATA), strerror(errno));
+		if (!na->data_size)
+			device_err_exit(vol, ni, na, "$LogFile has zero "
+					"length.  Run chkdsk /f to correct "
+					"this.\n");
+		logfile->data_size = na->data_size;
+		logfile->vol = vol;
+		logfile->ni = ni;
+		logfile->na = na;
+	} else {
+		struct stat sbuf;
+		int fd;
+
+		if (stat(filename, &sbuf) == -1) {
+			if (errno == ENOENT)
+				log_err_exit(NULL, "The file %s does not "
+						"exist.  Did you specify it "
+						"correctly?\n", filename);
+			log_err_exit(NULL, "Error getting information about "
+					"%s: %s\n", filename, strerror(errno));
+		}
+
+		fd = open(filename, O_RDONLY);
+		if (fd == -1)
+			log_err_exit(NULL, "Failed to open file %s: %s\n",
+					filename, strerror(errno));
+		logfile->data_size = sbuf.st_size;
+		logfile->fd = fd;
+	}
+
+	logfile->is_volume = is_volume;
+	logfile->filename = filename;
+
+	return 0;
+}
+
+/**
+ * logfile_read
+ */
+static int logfile_pread(logfile_file *logfile, int ofs, int count, u8 *buf)
+{
+	int br;
+
+	if (logfile->is_volume) {
+		br = (int)ntfs_attr_pread(logfile->na, ofs, count, buf);
+	} else {
+		if (lseek(logfile->fd, ofs, SEEK_SET)==-1) {
+			ntfs_log_error("Could not seek to offset %u\n", ofs);
+			return 0;
+		}
+		br = read(logfile->fd, buf, count);
+	}
+	if (br != count) {
+		ntfs_log_error("Only %d out of %d bytes read starting at %d\n",
+			br, count, ofs);
+	}
+	return br;
+}
+
+/**
+ * restart_header_sanity()
+ */
+static void restart_header_sanity(RESTART_PAGE_HEADER *rstr, u8 *buf)
+{
+	unsigned int usa_end_ofs, page_size;
+
+	/* Only CHKD records are allowed to have chkdsk_lsn set. */
+	if (!ntfs_is_chkd_record(rstr->magic) &&
+			sle64_to_cpu(rstr->chkdsk_lsn))
+		log_err_exit(buf, "$LogFile is corrupt:  Restart page header "
+				"magic is not CHKD but a chkdsk LSN is "
+				"specified.  Cannot handle this yet.\n");
+	/* Both system and log page size must be >= 512 and a power of 2. */
+	page_size = le32_to_cpu(rstr->log_page_size);
+	if (page_size < 512 || page_size & (page_size - 1))
+		log_err_exit(buf, "$LogFile is corrupt:  Restart page header "
+				"specifies invalid log page size.  Cannot "
+				"handle this yet.\n");
+	if (page_size != le32_to_cpu(rstr->system_page_size)) {
+		page_size = le32_to_cpu(rstr->system_page_size);
+		if (page_size < 512 || page_size & (page_size - 1))
+			log_err_exit(buf, "$LogFile is corrupt:  Restart page "
+					"header specifies invalid system page "
+					"size.  Cannot handle this yet.\n");
+	}
+	/* Abort if the version number is not 1.1. */
+	if (sle16_to_cpu(rstr->major_ver != 1) ||
+			sle16_to_cpu(rstr->minor_ver != 1))
+		log_err_exit(buf, "Unknown $LogFile version %i.%i.  Only know "
+				"how to handle version 1.1.\n",
+				sle16_to_cpu(rstr->major_ver),
+				sle16_to_cpu(rstr->minor_ver));
+	/* Verify the location and size of the update sequence array. */
+	usa_end_ofs = le16_to_cpu(rstr->usa_ofs) +
+			le16_to_cpu(rstr->usa_count) * sizeof(u16);
+	if (page_size / NTFS_BLOCK_SIZE + 1 != le16_to_cpu(rstr->usa_count))
+		log_err_exit(buf, "Restart page header in $LogFile is "
+				"corrupt:  Update sequence array size is "
+				"wrong.  Cannot handle this yet.\n");
+	if (le16_to_cpu(rstr->usa_ofs) < sizeof(RESTART_PAGE_HEADER))
+		log_err_exit(buf, "Restart page header in $LogFile is "
+				"corrupt:  Update sequence array overlaps "
+				"restart page header.  Cannot handle this "
+				"yet.\n");
+	if (usa_end_ofs > NTFS_BLOCK_SIZE - sizeof(u16))
+		log_err_exit(buf, "Restart page header in $LogFile is "
+				"corrupt:  Update sequence array overlaps or "
+				"is behind first protected sequence number.  "
+				"Cannot handle this yet.\n");
+	if (usa_end_ofs > le16_to_cpu(rstr->restart_area_offset))
+		log_err_exit(buf, "Restart page header in $LogFile is "
+				"corrupt:  Update sequence array overlaps or "
+				"is behind restart area.  Cannot handle this "
+				"yet.\n");
+	/* Finally, verify the offset of the restart area. */
+	if (le16_to_cpu(rstr->restart_area_offset) & 7)
+		log_err_exit(buf, "Restart page header in $LogFile is "
+				"corrupt:  Restart area offset is not aligned "
+				"to 8-byte boundary.  Cannot handle this "
+				"yet.\n");
+}
+
+/**
+ * dump_restart_areas_header
+ */
+static void dump_restart_areas_header(RESTART_PAGE_HEADER *rstr)
+{
+	ntfs_log_info("\nRestart page header:\n");
+	ntfs_log_info("magic = %s\n", ntfs_is_rstr_record(rstr->magic) ? "RSTR" :
+			"CHKD");
+	ntfs_log_info("usa_ofs = %u (0x%x)\n", le16_to_cpu(rstr->usa_ofs),
+			le16_to_cpu(rstr->usa_ofs));
+	ntfs_log_info("usa_count = %u (0x%x)\n", le16_to_cpu(rstr->usa_count),
+			le16_to_cpu(rstr->usa_count));
+	ntfs_log_info("chkdsk_lsn = %lli (0x%llx)\n",
+			(long long)sle64_to_cpu(rstr->chkdsk_lsn),
+			(unsigned long long)sle64_to_cpu(rstr->chkdsk_lsn));
+	ntfs_log_info("system_page_size = %u (0x%x)\n",
+			(unsigned int)le32_to_cpu(rstr->system_page_size),
+			(unsigned int)le32_to_cpu(rstr->system_page_size));
+	ntfs_log_info("log_page_size = %u (0x%x)\n",
+			(unsigned int)le32_to_cpu(rstr->log_page_size),
+			(unsigned int)le32_to_cpu(rstr->log_page_size));
+	ntfs_log_info("restart_offset = %u (0x%x)\n",
+			le16_to_cpu(rstr->restart_area_offset),
+			le16_to_cpu(rstr->restart_area_offset));
+}
+
+/**
+ * dump_restart_areas_area
+ */
+static void dump_restart_areas_area(RESTART_PAGE_HEADER *rstr)
+{
+	LOG_CLIENT_RECORD *lcr;
+	RESTART_AREA *ra;
+	int client;
+
+	ra = (RESTART_AREA*)((u8*)rstr +
+			le16_to_cpu(rstr->restart_area_offset));
+	ntfs_log_info("current_lsn = %lli (0x%llx)\n",
+			(long long)sle64_to_cpu(ra->current_lsn),
+			(unsigned long long)sle64_to_cpu(ra->current_lsn));
+	ntfs_log_info("log_clients = %u (0x%x)\n", le16_to_cpu(ra->log_clients),
+			le16_to_cpu(ra->log_clients));
+	ntfs_log_info("client_free_list = %i (0x%x)\n",
+			(s16)le16_to_cpu(ra->client_free_list),
+			le16_to_cpu(ra->client_free_list));
+	ntfs_log_info("client_in_use_list = %i (0x%x)\n",
+			(s16)le16_to_cpu(ra->client_in_use_list),
+			le16_to_cpu(ra->client_in_use_list));
+	ntfs_log_info("flags = 0x%.4x\n", le16_to_cpu(ra->flags));
+	ntfs_log_info("seq_number_bits = %u (0x%x)\n",
+			(unsigned int)le32_to_cpu(ra->seq_number_bits),
+			(unsigned int)le32_to_cpu(ra->seq_number_bits));
+	ntfs_log_info("restart_area_length = %u (0x%x)\n",
+			le16_to_cpu(ra->restart_area_length),
+			le16_to_cpu(ra->restart_area_length));
+	ntfs_log_info("client_array_offset = %u (0x%x)\n",
+			le16_to_cpu(ra->client_array_offset),
+			le16_to_cpu(ra->client_array_offset));
+	ntfs_log_info("file_size = %lli (0x%llx)\n",
+			(long long)sle64_to_cpu(ra->file_size),
+			(unsigned long long)sle64_to_cpu(ra->file_size));
+	ntfs_log_info("last_lsn_data_length = %u (0x%x)\n",
+			(unsigned int)le32_to_cpu(ra->last_lsn_data_length),
+			(unsigned int)le32_to_cpu(ra->last_lsn_data_length));
+	ntfs_log_info("log_record_header_length = %u (0x%x)\n",
+			le16_to_cpu(ra->log_record_header_length),
+			le16_to_cpu(ra->log_record_header_length));
+	ntfs_log_info("log_page_data_offset = %u (0x%x)\n",
+			le16_to_cpu(ra->log_page_data_offset),
+			le16_to_cpu(ra->log_page_data_offset));
+	ntfs_log_info("restart_log_open_count = %u (0x%x)\n",
+			(unsigned)le32_to_cpu(ra->restart_log_open_count),
+			(unsigned)le32_to_cpu(ra->restart_log_open_count));
+	lcr = (LOG_CLIENT_RECORD*)((u8*)ra +
+			le16_to_cpu(ra->client_array_offset));
+	for (client = 0; client < le16_to_cpu(ra->log_clients); client++) {
+		char *client_name;
+
+		ntfs_log_info("\nLog client record number %i:\n", client + 1);
+		ntfs_log_info("oldest_lsn = %lli (0x%llx)\n",
+				(long long)sle64_to_cpu(lcr->oldest_lsn),
+				(unsigned long long)
+				sle64_to_cpu(lcr->oldest_lsn));
+		ntfs_log_info("client_restart_lsn = %lli (0x%llx)\n", (long long)
+				sle64_to_cpu(lcr->client_restart_lsn),
+				(unsigned long long)
+				sle64_to_cpu(lcr->client_restart_lsn));
+		ntfs_log_info("prev_client = %i (0x%x)\n",
+				(s16)le16_to_cpu(lcr->prev_client),
+				le16_to_cpu(lcr->prev_client));
+		ntfs_log_info("next_client = %i (0x%x)\n",
+				(s16)le16_to_cpu(lcr->next_client),
+				le16_to_cpu(lcr->next_client));
+		ntfs_log_info("seq_number = %u (0x%x)\n", le16_to_cpu(lcr->seq_number),
+				le16_to_cpu(lcr->seq_number));
+		ntfs_log_info("client_name_length = %u (0x%x)\n",
+				(unsigned int)le32_to_cpu(lcr->client_name_length) / 2,
+				(unsigned int)le32_to_cpu(lcr->client_name_length) / 2);
+		if (le32_to_cpu(lcr->client_name_length)) {
+			client_name = NULL;
+			if (ntfs_ucstombs(lcr->client_name,
+					le32_to_cpu(lcr->client_name_length) /
+					2, &client_name, 0) < 0) {
+				ntfs_log_perror("Failed to convert log client name");
+				client_name = strdup("<conversion error>");
+			}
+		} else
+			client_name = strdup("<unnamed>");
+		ntfs_log_info("client_name = %s\n", client_name);
+		free(client_name);
+		/*
+		 * Log client records are fixed size so we can simply use the
+		 * C increment operator to get to the next one.
+		 */
+		lcr++;
+	}
+}
+
+/**
+ * dump_restart_areas()
+ */
+static void *dump_restart_areas(RESTART_PAGE_HEADER *rstr, u8 *buf,
+		unsigned int page_size)
+{
+	int pass = 1;
+
+rstr_pass_loc:
+	if (ntfs_is_chkd_record(rstr->magic))
+		log_err_exit(buf, "The %s restart page header in $LogFile has "
+				"been modified by chkdsk.  Do not know how to "
+				"handle this yet.  Reboot into Windows to fix "
+				"this.\n", (u8*)rstr == buf ? "first" :
+				"second");
+	if (ntfs_mst_post_read_fixup((NTFS_RECORD*)rstr, page_size) ||
+			ntfs_is_baad_record(rstr->magic))
+		log_err_exit(buf, "$LogFile incomplete multi sector transfer "
+				"detected in restart page header.  Cannot "
+				"handle this yet.\n");
+	if (pass == 1)
+		ntfs_log_info("$LogFile version %i.%i.\n",
+				sle16_to_cpu(rstr->major_ver),
+				sle16_to_cpu(rstr->minor_ver));
+	else /* if (pass == 2) */ {
+		RESTART_AREA *ra;
+
+		/*
+		 * rstr is now the second restart page so we declare rstr1
+		 * as the first restart page as this one has been verified in
+		 * the first pass so we can use all its members safely.
+		 */
+		RESTART_PAGE_HEADER *rstr1 = (RESTART_PAGE_HEADER*)buf;
+
+		/* Exclude the usa from the comparison. */
+		ra = (RESTART_AREA*)((u8*)rstr1 +
+				le16_to_cpu(rstr1->restart_area_offset));
+		if (!memcmp(rstr1, rstr, le16_to_cpu(rstr1->usa_ofs)) &&
+				!memcmp((u8*)rstr1 + le16_to_cpu(
+				rstr1->restart_area_offset), (u8*)rstr +
+				le16_to_cpu(rstr->restart_area_offset),
+				le16_to_cpu(ra->restart_area_length))) {
+			puts("\nSkipping analysis of second restart page "
+					"because it fully matches the first "
+					"one.");
+			goto skip_rstr_pass;
+		}
+		/*
+		 * The $LogFile versions specified in each of the two restart
+		 * page headers must match.
+		 */
+		if (rstr1->major_ver != rstr->major_ver ||
+				rstr1->minor_ver != rstr->minor_ver)
+			log_err_exit(buf, "Second restart area specifies "
+					"different $LogFile version to first "
+					"restart area.  Cannot handle this "
+					"yet.\n");
+	}
+	/* The restart page header is in rstr and it is mst deprotected. */
+	ntfs_log_info("\n%s restart page:\n", pass == 1 ? "1st" : "2nd");
+	dump_restart_areas_header(rstr);
+
+	ntfs_log_info("\nRestart area:\n");
+	dump_restart_areas_area(rstr);
+
+skip_rstr_pass:
+	if (pass == 1) {
+		rstr = (RESTART_PAGE_HEADER*)((u8*)rstr + page_size);
+		++pass;
+		goto rstr_pass_loc;
+	}
+
+	return rstr;
+}
+
+/**
+ * dump_log_records()
+ */
+static void dump_log_record(LOG_RECORD *lr)
+{
+	unsigned int i;
+	ntfs_log_info("this lsn = 0x%llx\n",
+			(unsigned long long)le64_to_cpu(lr->this_lsn));
+	ntfs_log_info("client previous lsn = 0x%llx\n", (unsigned long long)
+			le64_to_cpu(lr->client_previous_lsn));
+	ntfs_log_info("client undo next lsn = 0x%llx\n", (unsigned long long)
+			le64_to_cpu(lr->client_undo_next_lsn));
+	ntfs_log_info("client data length = 0x%x\n",
+			(unsigned int)le32_to_cpu(lr->client_data_length));
+	ntfs_log_info("client_id.seq_number = 0x%x\n",
+			le16_to_cpu(lr->client_id.seq_number));
+	ntfs_log_info("client_id.client_index = 0x%x\n",
+			le16_to_cpu(lr->client_id.client_index));
+	ntfs_log_info("record type = 0x%x\n",
+			(unsigned int)le32_to_cpu(lr->record_type));
+	ntfs_log_info("transaction_id = 0x%x\n",
+			(unsigned int)le32_to_cpu(lr->transaction_id));
+	ntfs_log_info("flags = 0x%x:", lr->flags);
+	if (!lr->flags)
+		ntfs_log_info(" NONE\n");
+	else {
+		int _b = 0;
+
+		if (lr->flags & LOG_RECORD_MULTI_PAGE) {
+			ntfs_log_info(" LOG_RECORD_MULTI_PAGE");
+			_b = 1;
+		}
+		if (lr->flags & ~LOG_RECORD_MULTI_PAGE) {
+			if (_b)
+				ntfs_log_info(" |");
+			ntfs_log_info(" Unknown flags");
+		}
+		ntfs_log_info("\n");
+	}
+	ntfs_log_info("redo_operation = 0x%x\n", le16_to_cpu(lr->redo_operation));
+	ntfs_log_info("undo_operation = 0x%x\n", le16_to_cpu(lr->undo_operation));
+	ntfs_log_info("redo_offset = 0x%x\n", le16_to_cpu(lr->redo_offset));
+	ntfs_log_info("redo_length = 0x%x\n", le16_to_cpu(lr->redo_length));
+	ntfs_log_info("undo_offset = 0x%x\n", le16_to_cpu(lr->undo_offset));
+	ntfs_log_info("undo_length = 0x%x\n", le16_to_cpu(lr->undo_length));
+	ntfs_log_info("target_attribute = 0x%x\n", le16_to_cpu(lr->target_attribute));
+	ntfs_log_info("lcns_to_follow = 0x%x\n", le16_to_cpu(lr->lcns_to_follow));
+	ntfs_log_info("record_offset = 0x%x\n", le16_to_cpu(lr->record_offset));
+	ntfs_log_info("attribute_offset = 0x%x\n", le16_to_cpu(lr->attribute_offset));
+	ntfs_log_info("target_vcn = 0x%llx\n",
+			(unsigned long long)sle64_to_cpu(lr->target_vcn));
+	if (le16_to_cpu(lr->lcns_to_follow) > 0)
+		ntfs_log_info("Array of lcns:\n");
+	for (i = 0; i < le16_to_cpu(lr->lcns_to_follow); i++)
+		ntfs_log_info("lcn_list[%u].lcn = 0x%llx\n", i, (unsigned long long)
+				sle64_to_cpu(lr->lcn_list[i].lcn));
+}
+
+/**
+ * dump_log_records()
+ */
+static void dump_log_records(RECORD_PAGE_HEADER *rcrd, u8 *buf,
+		int buf_size, unsigned int page_size)
+{
+	LOG_RECORD *lr;
+	int pass = 0;
+	int client;
+
+	/* Reuse pass for log area. */
+rcrd_pass_loc:
+	rcrd = (RECORD_PAGE_HEADER*)((u8*)rcrd + page_size);
+	if ((u8*)rcrd + page_size > buf + buf_size)
+		return;
+	ntfs_log_info("\nLog record page number %i", pass);
+	if (!ntfs_is_rcrd_record(rcrd->magic) &&
+			!ntfs_is_chkd_record(rcrd->magic)) {
+		unsigned int i;
+		for (i = 0; i < page_size; i++)
+			if (((u8*)rcrd)[i] != (u8)-1)
+				break;
+		if (i < page_size)
+			puts(" is corrupt (magic is not RCRD or CHKD).");
+		else
+			puts(" is empty.");
+		pass++;
+		goto rcrd_pass_loc;
+	} else
+		puts(":");
+	/* Dump log record page */
+	ntfs_log_info("magic = %s\n", ntfs_is_rcrd_record(rcrd->magic) ? "RCRD" :
+			"CHKD");
+// TODO: I am here... (AIA)
+	ntfs_log_info("copy.last_lsn/file_offset = 0x%llx\n", (unsigned long long)
+			le64_to_cpu(rcrd->copy.last_lsn));
+	ntfs_log_info("flags = 0x%x\n", (unsigned int)le32_to_cpu(rcrd->flags));
+	ntfs_log_info("page count = %i\n", le16_to_cpu(rcrd->page_count));
+	ntfs_log_info("page position = %i\n", le16_to_cpu(rcrd->page_position));
+	ntfs_log_info("header.next_record_offset = 0x%llx\n", (unsigned long long)
+			le64_to_cpu(rcrd->header.packed.next_record_offset));
+	ntfs_log_info("header.last_end_lsn = 0x%llx\n", (unsigned long long)
+			le64_to_cpu(rcrd->header.packed.last_end_lsn));
+	/*
+	 * Where does the 0x40 come from? Is it just usa_offset +
+	 * usa_client * 2 + 7 & ~7 or is it derived from somewhere?
+	 */
+	lr = (LOG_RECORD*)((u8*)rcrd + 0x40);
+	client = 0;
+	do {
+		ntfs_log_info("\nLog record %i:\n", client);
+		dump_log_record(lr);
+		client++;
+		lr = (LOG_RECORD*)((u8*)lr + 0x70);
+	} while (((u8*)lr + 0x70 <= (u8*)rcrd +
+			le64_to_cpu(rcrd->header.packed.next_record_offset)));
+
+	pass++;
+	goto rcrd_pass_loc;
+}
+
+/**
+ * main -
+ */
+int main(int argc, char **argv)
+{
+	RESTART_PAGE_HEADER *rstr;
+	RECORD_PAGE_HEADER *rcrd;
+	unsigned int page_size;
+	int buf_size, br, err;
+	logfile_file logfile;
+	u8 *buf;
+
+	ntfs_log_set_handler(ntfs_log_handler_outerr);
+
+	ntfs_log_info("\n");
+	if (argc < 2 || argc > 3)
+		/* print usage and exit */
+		usage(argv[0]);
+	/*
+	 * If one argument, it is a device containing an NTFS volume which we
+	 * need to mount and read the $LogFile from so we can dump its
+	 * contents.
+	 *
+	 * If two arguments the first one must be "-f" and the second one is
+	 * the path and name of the $LogFile (or copy thereof) which we need to
+	 * read and dump the contents of.
+	 */
+
+	if (argc == 2) {
+		logfile_open(TRUE, argv[1], &logfile);
+	} else /* if (argc == 3) */ {
+		if (strncmp(argv[1], "-f", strlen("-f")))
+			usage(argv[0]);
+
+		logfile_open(FALSE, argv[2], &logfile);
+	}
+
+	buf_size = 64 * 1024 * 1024;
+
+	if (logfile.data_size <= buf_size)
+		buf_size = logfile.data_size;
+	else
+		ntfs_log_error("Warning: $LogFile is too big.  "
+			"Only analysing the first 64MiB.\n");
+
+	/* For simplicity we read all of $LogFile/$DATA into memory. */
+	buf = malloc(buf_size);
+	if (!buf) {
+		ntfs_log_perror("Failed to allocate buffer for file data");
+		logfile_close(&logfile);
+		exit(1);
+	}
+
+	br = logfile_pread(&logfile, 0, buf_size, buf);
+	err = errno;
+	logfile_close(&logfile);
+	if (br != buf_size) {
+		log_err_exit(buf, "Failed to read $LogFile/$DATA: %s\n",
+				br < 0 ? strerror(err) : "Partial read.");
+	}
+
+	/*
+	 * We now have the entirety of the journal ($LogFile/$DATA or argv[2])
+	 * in the memory buffer buf and this has a size of buf_size.  Note we
+	 * apply a size capping at 64MiB, so if the journal is any bigger we
+	 * only have the first 64MiB.  This should not be a problem as I have
+	 * never seen such a large $LogFile.  Usually it is only a few MiB in
+	 * size.
+	 */
+	rstr = (RESTART_PAGE_HEADER*)buf;
+
+	/* Check for presence of restart area signature. */
+	if (!ntfs_is_rstr_record(rstr->magic) &&
+			!ntfs_is_chkd_record(rstr->magic)) {
+		s8 *pos = (s8*)buf;
+		s8 *end = pos + buf_size;
+		while (pos < end && *pos == -1)
+			pos++;
+		if (pos != end)
+			log_err_exit(buf, "$LogFile contents are corrupt "
+					"(magic RSTR is missing).  Cannot "
+					"handle this yet.\n");
+		/* All bytes are -1. */
+		free(buf);
+		puts("$LogFile is not initialized.");
+		return 0;
+	}
+
+	/*
+	 * First, verify the restart page header for consistency.
+	 */
+	restart_header_sanity(rstr, buf);
+	page_size = le32_to_cpu(rstr->log_page_size);
+
+	/*
+	 * Second, verify the restart area itself.
+	 */
+	// TODO: Implement this.
+	ntfs_log_error("Warning:  Sanity checking of restart area not implemented "
+		"yet.\n");
+	/*
+	 * Third and last, verify the array of log client records.
+	 */
+	// TODO: Implement this.
+	ntfs_log_error("Warning:  Sanity checking of array of log client records not "
+		"implemented yet.\n");
+
+	/*
+	 * Dump the restart headers & areas.
+	 */
+	rcrd = (RECORD_PAGE_HEADER*)dump_restart_areas(rstr, buf, page_size);
+	ntfs_log_info("\n\nFinished with restart pages.  "
+		"Beginning with log pages.\n");
+
+	/*
+	 * Dump the log areas.
+	 */
+	dump_log_records(rcrd, buf, buf_size, page_size);
+
+	free(buf);
+	return 0;
+}
+
diff --git a/ntfsprogs/ntfsfallocate.8 b/ntfsprogs/ntfsfallocate.8
new file mode 100755
index 0000000000000000000000000000000000000000..af971de486b110cec2be05dff0fa4e845cc88969
--- /dev/null
+++ b/ntfsprogs/ntfsfallocate.8
@@ -0,0 +1,137 @@
+.\" Copyright (c) 2014 Jean-Pierre Andre
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSFALLOCATE 8 "June 2014" "ntfs-3g 2015.3.14"
+.SH NAME
+ntfsfallocate \- preallocate space to a file on an NTFS volume
+.SH SYNOPSIS
+\fBntfsfallocate\fR [\fIoptions\fR] -l \fIlength\fR \fIdevice\fR \fIfile\fR \fI[attr-type\fR [\fIattr-name\fR]]
+.SH DESCRIPTION
+.B ntfsfallocate
+preallocates space for any attribute of a file or directory, thus reserving
+space before actual contents is written. This is similar to fallocate(1).
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfsfallocate
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+This will override some sensible defaults, such as not using a mounted volume.
+Use this option with caution.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.TP
+\fB\-l\fR, \fB\-\-length\fR LENGTH
+This is a mandatory option to specify the number of bytes to preallocate.
+It will be rounded up to a multiple of the cluster size.
+A suffix of K, M, G, T, P or E may be appended to
+mean a multiplicative factor of a power of 1000. Similarly a suffix of
+Ki, Mi, Gi, Ti, Pi or Ei may be appended to mean a multiplicative factor
+of a power of 1024.
+.TP
+\fB\-n\fR, \fB\-\-no-size-change\fR
+Do not change the apparent size of the file. The space allocated beyond
+the apparent size is not zeroed, but subsequent writing beyond the apparent
+end of file will force zeroing the inner allocated space as it cannot be
+considered as a hole any more, and this may take significant time.
+.TP
+\fB\-N\fR, \fB\-\-no-action\fR
+Simulate the allocation without actually write to device.
+.TP
+\fB\-o\fR, \fB\-\-offset\fR OFFSET
+Specify the offset in the file where preallocation starts. By default,
+the preallocation is counted from the beginning of the file. Space already
+allocated in the area defined by offset and length is preserved.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Suppress some debug/warning/error messages.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Display more debug/warning/error messages.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Show the version number, copyright and license of
+.BR ntfsfallocate .
+.TP
+\fBattr-type\fR
+Define a particular attribute type to be preallocated (advanced use only).
+By default, the unnamed $DATA attribute (the contents of a plain file) will
+be preallocated. The attribute has to be specified by a number in decimal
+or hexadecimal :
+.TS
+box;
+lB lB lB
+l l l.
+Hex	Decimal	Name
+0x10	16	"$STANDARD_INFORMATION"
+0x20	32	"$ATTRIBUTE_LIST"
+0x30	48	"$FILE_NAME"
+0x40	64	"$OBJECT_ID"
+0x50	80	"$SECURITY_DESCRIPTOR"
+0x60	96	"$VOLUME_NAME"
+0x70	112	"$VOLUME_INFORMATION"
+0x80	128	"$DATA"
+0x90	144	"$INDEX_ROOT"
+0xA0	160	"$INDEX_ALLOCATION"
+0xB0	176	"$BITMAP"
+0xC0	192	"$REPARSE_POINT"
+0xD0	208	"$EA_INFORMATION"
+0xE0	224	"$EA"
+0xF0	240	"$PROPERTY_SET"
+0x100	256	"$LOGGED_UTILITY_STREAM"
+.TE
+.sp
+.TP
+\fBattr-name\fR
+Define the name of the particular attribute type to be preallocated
+(advanced use only).
+.SH EXAMPLES
+Preallocate 100MB to the file database.db located in the Data directory
+which is at the root of an NTFS file system.
+.RS
+.sp
+.B ntfsfallocate -l 100M /dev/sda1 Data/database.db
+.sp
+.RE
+.SH BUGS
+There are no known problems with
+.BR ntfsfallocate ,
+however it can lead to configurations not supported by Windows
+and Windows may crash (BSOD) when writing to preallocated clusters
+which were not written to earlier. Files with preallocated space should
+be fully be written to before they are updated by Windows.
+.P
+If you find a bug in \fBntfsfallocate\fR proper, please send an email
+describing the problem to the development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+.B ntfsfallocate
+was written by Jean-Pierre Andre.
+.SH AVAILABILITY
+.B ntfsfallocate
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR ntfs-3g (8),
+.BR ntfstruncate (8),
+.BR ntfsprogs (8),
+.BR fallocate (1)
diff --git a/ntfsprogs/ntfsfallocate.8.in b/ntfsprogs/ntfsfallocate.8.in
new file mode 100755
index 0000000000000000000000000000000000000000..04cc9ea97764d2cdfe6532ad076084ba08c7c762
--- /dev/null
+++ b/ntfsprogs/ntfsfallocate.8.in
@@ -0,0 +1,137 @@
+.\" Copyright (c) 2014 Jean-Pierre Andre
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSFALLOCATE 8 "June 2014" "ntfs-3g @VERSION@"
+.SH NAME
+ntfsfallocate \- preallocate space to a file on an NTFS volume
+.SH SYNOPSIS
+\fBntfsfallocate\fR [\fIoptions\fR] -l \fIlength\fR \fIdevice\fR \fIfile\fR \fI[attr-type\fR [\fIattr-name\fR]]
+.SH DESCRIPTION
+.B ntfsfallocate
+preallocates space for any attribute of a file or directory, thus reserving
+space before actual contents is written. This is similar to fallocate(1).
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfsfallocate
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+This will override some sensible defaults, such as not using a mounted volume.
+Use this option with caution.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.TP
+\fB\-l\fR, \fB\-\-length\fR LENGTH
+This is a mandatory option to specify the number of bytes to preallocate.
+It will be rounded up to a multiple of the cluster size.
+A suffix of K, M, G, T, P or E may be appended to
+mean a multiplicative factor of a power of 1000. Similarly a suffix of
+Ki, Mi, Gi, Ti, Pi or Ei may be appended to mean a multiplicative factor
+of a power of 1024.
+.TP
+\fB\-n\fR, \fB\-\-no-size-change\fR
+Do not change the apparent size of the file. The space allocated beyond
+the apparent size is not zeroed, but subsequent writing beyond the apparent
+end of file will force zeroing the inner allocated space as it cannot be
+considered as a hole any more, and this may take significant time.
+.TP
+\fB\-N\fR, \fB\-\-no-action\fR
+Simulate the allocation without actually write to device.
+.TP
+\fB\-o\fR, \fB\-\-offset\fR OFFSET
+Specify the offset in the file where preallocation starts. By default,
+the preallocation is counted from the beginning of the file. Space already
+allocated in the area defined by offset and length is preserved.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Suppress some debug/warning/error messages.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Display more debug/warning/error messages.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Show the version number, copyright and license of
+.BR ntfsfallocate .
+.TP
+\fBattr-type\fR
+Define a particular attribute type to be preallocated (advanced use only).
+By default, the unnamed $DATA attribute (the contents of a plain file) will
+be preallocated. The attribute has to be specified by a number in decimal
+or hexadecimal :
+.TS
+box;
+lB lB lB
+l l l.
+Hex	Decimal	Name
+0x10	16	"$STANDARD_INFORMATION"
+0x20	32	"$ATTRIBUTE_LIST"
+0x30	48	"$FILE_NAME"
+0x40	64	"$OBJECT_ID"
+0x50	80	"$SECURITY_DESCRIPTOR"
+0x60	96	"$VOLUME_NAME"
+0x70	112	"$VOLUME_INFORMATION"
+0x80	128	"$DATA"
+0x90	144	"$INDEX_ROOT"
+0xA0	160	"$INDEX_ALLOCATION"
+0xB0	176	"$BITMAP"
+0xC0	192	"$REPARSE_POINT"
+0xD0	208	"$EA_INFORMATION"
+0xE0	224	"$EA"
+0xF0	240	"$PROPERTY_SET"
+0x100	256	"$LOGGED_UTILITY_STREAM"
+.TE
+.sp
+.TP
+\fBattr-name\fR
+Define the name of the particular attribute type to be preallocated
+(advanced use only).
+.SH EXAMPLES
+Preallocate 100MB to the file database.db located in the Data directory
+which is at the root of an NTFS file system.
+.RS
+.sp
+.B ntfsfallocate -l 100M /dev/sda1 Data/database.db
+.sp
+.RE
+.SH BUGS
+There are no known problems with
+.BR ntfsfallocate ,
+however it can lead to configurations not supported by Windows
+and Windows may crash (BSOD) when writing to preallocated clusters
+which were not written to earlier. Files with preallocated space should
+be fully be written to before they are updated by Windows.
+.P
+If you find a bug in \fBntfsfallocate\fR proper, please send an email
+describing the problem to the development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+.B ntfsfallocate
+was written by Jean-Pierre Andre.
+.SH AVAILABILITY
+.B ntfsfallocate
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR ntfs-3g (8),
+.BR ntfstruncate (8),
+.BR ntfsprogs (8),
+.BR fallocate (1)
diff --git a/ntfsprogs/ntfsfallocate.c b/ntfsprogs/ntfsfallocate.c
new file mode 100755
index 0000000000000000000000000000000000000000..1b243ae6987fbbc08c50d6a5c0d26cf01e4152db
--- /dev/null
+++ b/ntfsprogs/ntfsfallocate.c
@@ -0,0 +1,903 @@
+/**
+ * ntfsfallocate
+ *
+ * Copyright (c) 2013-2014 Jean-Pierre Andre
+ *
+ * This utility will allocate clusters to a specified attribute belonging
+ * to a specified file or directory, to a specified length.
+ *
+ * WARNING : this can lead to configurations not supported by Windows
+ * and Windows may crash (BSOD) when writing to preallocated clusters
+ * which were not written to.
+ *
+ * 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 Linux-NTFS source
+ * 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_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern char *optarg;
+extern int optind;
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#ifndef LLONG_MAX
+#define LLONG_MAX 9223372036854775807LL
+#endif
+
+#include "types.h"
+#include "attrib.h"
+#include "inode.h"
+#include "layout.h"
+#include "volume.h"
+#include "logging.h"
+#include "runlist.h"
+#include "dir.h"
+#include "bitmap.h"
+#include "lcnalloc.h"
+#include "utils.h"
+#include "misc.h"
+
+const char *EXEC_NAME = "ntfsfallocate";
+
+char *dev_name;
+const char *file_name;
+le32 attr_type;
+ntfschar *attr_name = NULL;
+u32 attr_name_len;
+s64 opt_alloc_offs;
+s64 opt_alloc_len;
+
+ATTR_DEF *attr_defs;
+
+static struct {
+				/* -h, print usage and exit. */
+	int no_action;		/*     do not write to device, only display
+				       what would be done. */
+	int no_size_change;	/* -n, do not change the apparent size */
+	int quiet;		/* -q, quiet execution. */
+	int verbose;		/* -v, verbose execution, given twice, really
+				       verbose execution (debug mode). */
+	int force;		/* -f, force allocation. */
+				/* -V, print version and exit. */
+} opts;
+
+static const struct option lopt[] = {
+	{ "offset",	required_argument,	NULL, 'o' },
+	{ "length",	required_argument,	NULL, 'l' },
+	{ "force",	no_argument,		NULL, 'f' },
+	{ "help",	no_argument,		NULL, 'h' },
+	{ "no-action",	no_argument,		NULL, 'N' },
+	{ "no-size-change",	no_argument,	NULL, 'n' },
+	{ "quiet",	no_argument,		NULL, 'q' },
+	{ "version",	no_argument,		NULL, 'V' },
+	{ "verbose",	no_argument,		NULL, 'v' },
+	{ NULL,		0,			NULL, 0   }
+};
+
+/**
+ * err_exit - error output and terminate; ignores quiet (-q)
+ *
+ *	DO NOT USE when allocations are not in initial state
+ */
+__attribute__((noreturn))
+__attribute__((format(printf, 2, 3)))
+static void err_exit(ntfs_volume *vol, const char *fmt, ...)
+{
+	va_list ap;
+
+	fprintf(stderr, "ERROR: ");
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	fprintf(stderr, "Aborting...\n");
+	if (vol && ntfs_umount(vol, 0))
+		fprintf(stderr, "Warning: Could not umount %s\n", dev_name);
+	exit(1);
+}
+
+/**
+ * copyright - print copyright statements
+ */
+static void copyright(void)
+{
+	fprintf(stderr, "Copyright (c) 2013-2014 Jean-Pierre Andre\n"
+			"Allocate clusters to a specified attribute of "
+			"a specified file.\n");
+}
+
+/**
+ * license - print license statement
+ */
+static void license(void)
+{
+	fprintf(stderr, "%s", ntfs_gpl);
+}
+
+/**
+ * usage - print a list of the parameters to the program
+ */
+__attribute__((noreturn))
+static void usage(int ret)
+{
+	copyright();
+	fprintf(stderr, "Usage: %s [options] -l length device file [attr-type "
+			"[attr-name]]\n"
+			"    If attr-type is not specified, 0x80 (i.e. $DATA) "
+			"is assumed.\n"
+			"    If attr-name is not specified, an unnamed "
+			"attribute is assumed.\n"
+			"    -f         Force execution despite errors\n"
+			"    -n         Do not change the apparent size of file\n"
+			"    -l length  Allocate length bytes\n"
+			"    -o offset  Start allocating at offset\n"
+			"    -v         Verbose execution\n"
+			"    -vv        Very verbose execution\n"
+			"    -V         Display version information\n"
+			"    -h         Display this help\n", EXEC_NAME);
+	fprintf(stderr, "%s%s", ntfs_bugs, ntfs_home);
+	exit(ret);
+}
+
+/**
+ * err_exit - error output, display usage and exit
+ */
+__attribute__((noreturn))
+__attribute__((format(printf, 1, 2)))
+static void err_usage(const char *fmt, ...)
+{
+	va_list ap;
+
+	fprintf(stderr, "ERROR: ");
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	fprintf(stderr, "\n");
+	usage(1);
+}
+
+/*
+ *		Get a value option with a possible multiple suffix
+ */
+
+static s64 option_value(const char *arg)
+{
+	s64 ll;
+	char *s;
+	s64 fact;
+	int count;
+	BOOL err;
+
+	err = FALSE;
+	ll = strtoll(arg, &s, 0);
+	if ((ll >= LLONG_MAX) && (errno == ERANGE))
+		err_exit((ntfs_volume*)NULL, "Too big value : %s\n",arg);
+	if (*s) {
+		count = 0;
+		switch (*s++) {
+		case 'E' : count++;
+		case 'P' : count++;
+		case 'T' : count++;
+		case 'G' : count++;
+		case 'M' : count++;
+		case 'K' : count++;
+			switch (*s++) {
+			case 'i' :
+				fact = 1024;
+				if (*s++ != 'B')
+					err = TRUE;
+				break;
+			case 'B' :
+				fact = 1000;
+				break;
+			case '\0' :
+				fact = 1024;
+				s--;
+				break;
+			default :
+				err = TRUE;
+				fact = 1;
+				break;
+			}
+			if (*s)
+				err = TRUE;
+			break;
+		default :
+			err = TRUE;
+			break;
+		}
+		if (err)
+			err_exit((ntfs_volume*)NULL,
+					"Invalid suffix in : %s\n",arg);
+		else
+			while (count-- > 0) {
+				if (ll > LLONG_MAX/1024)
+					err_exit((ntfs_volume*)NULL,
+						"Too big value : %s\n",arg);
+				ll *= fact;
+			}
+	}
+	return (ll);
+}
+
+
+/**
+ * parse_options
+ */
+static void parse_options(int argc, char *argv[])
+{
+	long long ll;
+	char *s, *s2;
+	int c;
+
+	opt_alloc_len = 0;
+	opt_alloc_offs = 0;
+	if (argc && *argv)
+		EXEC_NAME = *argv;
+	fprintf(stderr, "%s v%s (libntfs-3g)\n", EXEC_NAME, VERSION);
+	while ((c = getopt_long(argc, argv, "fh?no:qvVl:", lopt, NULL)) != EOF) {
+		switch (c) {
+		case 'f':
+			opts.force = 1;
+			break;
+		case 'n':
+			opts.no_size_change = 1;
+			break;
+		case 'N':		/* Not proposed as a short option */
+			opts.no_action = 1;
+			break;
+		case 'q':
+			opts.quiet = 1;
+			ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
+			break;
+		case 'v':
+			opts.verbose++;
+			ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
+			break;
+		case 'V':
+			/* Version number already printed */
+			license();
+			exit(0);
+		case 'l':
+			ll = option_value(argv[optind - 1]);
+			if ((ll <= 0)
+			    || (ll >= LLONG_MAX && errno == ERANGE))
+				err_usage("Invalid length : %s\n",
+					argv[optind - 1]);
+			opt_alloc_len = ll;
+			break;
+		case 'o':
+			ll = option_value(argv[optind - 1]);
+			if ((ll < 0)
+			    || (ll >= LLONG_MAX && errno == ERANGE))
+				err_usage("Invalid offset : %s\n",
+					argv[optind - 1]);
+			opt_alloc_offs = ll;
+			break;
+		case 'h':
+			usage(0);
+		case '?':
+		default:
+			usage(1);
+		}
+	}
+	if (!opt_alloc_len) {
+		err_usage("Missing allocation length\n");
+	}
+
+	ntfs_log_verbose("length = %lli = 0x%llx\n",
+			(long long)opt_alloc_len, (long long)opt_alloc_len);
+	ntfs_log_verbose("offset = %lli = 0x%llx\n",
+			(long long)opt_alloc_offs, (long long)opt_alloc_offs);
+
+	if (optind == argc)
+		usage(1);
+
+	if (opts.verbose > 1)
+		ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG | NTFS_LOG_LEVEL_TRACE |
+			NTFS_LOG_LEVEL_VERBOSE | NTFS_LOG_LEVEL_QUIET);
+
+	/* Get the device. */
+	dev_name = argv[optind++];
+	ntfs_log_verbose("device name = %s\n", dev_name);
+
+	if (optind == argc)
+		usage(1);
+
+	/* Get the file name. */
+	file_name = argv[optind++];
+	ntfs_log_verbose("file name = \"%s\"\n", file_name);
+
+	/* Get the attribute type, if specified. */
+	if (optind == argc) {
+		attr_type = AT_DATA;
+		attr_name = AT_UNNAMED;
+		attr_name_len = 0;
+	} else {
+		unsigned long ul;
+
+		s = argv[optind++];
+		ul = strtoul(s, &s2, 0);
+		if (*s2 || !ul || (ul >= ULONG_MAX && errno == ERANGE))
+			err_usage("Invalid attribute type %s: %s\n", s,
+					strerror(errno));
+		attr_type = cpu_to_le32(ul);
+
+		/* Get the attribute name, if specified. */
+		if (optind != argc) {
+			s = argv[optind++];
+			/* Convert the string to little endian Unicode. */
+			attr_name_len = ntfs_mbstoucs(s, &attr_name);
+			if ((int)attr_name_len < 0)
+				err_usage("Invalid attribute name "
+						"\"%s\": %s\n",
+						s, strerror(errno));
+
+			/* Keep hold of the original string. */
+			s2 = s;
+
+			s = argv[optind++];
+			if (optind != argc)
+				usage(1);
+		} else {
+			attr_name = AT_UNNAMED;
+			attr_name_len = 0;
+		}
+	}
+	ntfs_log_verbose("attribute type = 0x%lx\n",
+					(unsigned long)le32_to_cpu(attr_type));
+	if (attr_name == AT_UNNAMED)
+		ntfs_log_verbose("attribute name = \"\" (UNNAMED)\n");
+	else
+		ntfs_log_verbose("attribute name = \"%s\" (length %u "
+				"Unicode characters)\n", s2,
+				(unsigned int)attr_name_len);
+}
+
+/*
+ *		Save the initial runlist, to be restored on error
+ */
+
+static runlist_element *ntfs_save_rl(runlist_element *rl)
+{
+	runlist_element *save;
+	int n;
+
+	n = 0;
+	save = (runlist_element*)NULL;
+	if (rl) {
+		while (rl[n].length)
+			n++;
+		save = (runlist_element*)malloc((n + 1)*sizeof(runlist_element));
+		if (save) {
+			memcpy(save, rl, (n + 1)*sizeof(runlist_element));
+		}
+	}
+	return (save);
+}
+
+/*
+ *		Free the common part of two runs
+ */
+
+static void free_common(ntfs_volume *vol, runlist_element *brl, s64 blth,
+				runlist_element *grl, s64 glth)
+{
+	VCN begin_common;
+	VCN end_common;
+
+	begin_common = max(grl->vcn, brl->vcn);
+	end_common = min(grl->vcn + glth, brl->vcn + blth);
+	if (end_common > begin_common) {
+		if (ntfs_bitmap_clear_run(vol->lcnbmp_na,
+			brl->lcn + begin_common - brl->vcn,
+					end_common - begin_common))
+			ntfs_log_error("Failed to free %lld clusters "
+				"from 0x%llx\n",
+				(long long)end_common - begin_common,
+				(long long)(brl->lcn + begin_common
+							- brl->vcn));
+	}
+}
+
+/*
+ *		Restore the cluster allocations to initial state
+ *
+ *	If a new error occurs, only output a message
+ */
+
+static void ntfs_restore_rl(ntfs_attr *na, runlist_element *oldrl)
+{
+	runlist_element *brl; /* Pointer to bad runlist */
+	runlist_element *grl; /* Pointer to good runlist */
+	ntfs_volume *vol;
+
+	vol = na->ni->vol;
+		/* Examine allocated entries from the bad runlist */
+	for (brl=na->rl; brl->length; brl++) {
+		if (brl->lcn != LCN_HOLE) {
+// TODO improve by examining both list in parallel
+		/* Find the holes in the good runlist which overlap */
+			for (grl=oldrl; grl->length
+			   && (grl->vcn<=(brl->vcn+brl->length)); grl++) {
+				if (grl->lcn == LCN_HOLE) {
+					free_common(vol, brl, brl->length, grl,
+						grl->length);
+				}
+			}
+			/* Free allocations beyond the end of good runlist */
+			if (grl && !grl->length
+			    && ((brl->vcn + brl->length) > grl->vcn)) {
+				free_common(vol, brl, brl->length, grl,
+					brl->vcn + brl->length - grl->vcn);
+			}
+		}
+	}
+	free(na->rl);
+	na->rl = oldrl;
+	if (ntfs_attr_update_mapping_pairs(na, 0)) {
+		ntfs_log_error("Failed to restore the original runlist\n");
+	}
+}
+
+/*
+ *		Zero newly allocated runs up to initialized_size
+ */
+
+static int ntfs_inner_zero(ntfs_attr *na, runlist_element *rl)
+{
+	ntfs_volume *vol;
+	char *buf;
+	runlist_element *zrl;
+	s64 cofs;
+	s64 pos;
+	s64 zeroed;
+	int err;
+
+	err = 0;
+	vol = na->ni->vol;
+	buf = (char*)malloc(vol->cluster_size);
+	if (buf) {
+		memset(buf, 0, vol->cluster_size);
+		zrl = rl;
+		pos = zrl->vcn << vol->cluster_size_bits;
+		while (zrl->length
+	 	    && !err
+	    	    && (pos < na->initialized_size)) {
+			for (cofs=0; cofs<zrl->length && !err; cofs++) {
+				zeroed = ntfs_pwrite(vol->dev,
+					(rl->lcn + cofs)
+						<< vol->cluster_size_bits,
+					vol->cluster_size, buf);
+				if (zeroed != vol->cluster_size) {
+					ntfs_log_error("Failed to zero at "
+						"offset %lld\n",
+						(long long)pos);
+					errno = EIO;
+					err = -1;
+				}
+				pos += vol->cluster_size;
+			}
+			zrl++;
+			pos = zrl->vcn << vol->cluster_size_bits;
+		}
+		free(buf);
+	} else {
+		ntfs_log_error("Failed to allocate memory\n");
+		errno = ENOSPC;
+		err = -1;
+	}
+	return (err);
+}
+
+/*
+ *		Merge newly allocated runs into runlist
+ */
+
+static int ntfs_merge_allocation(ntfs_attr *na, runlist_element *rl,
+				s64 size)
+{
+	ntfs_volume *vol;
+	int err;
+
+	err = 0;
+	vol = na->ni->vol;
+	/* Newly allocated clusters before initialized size need be zeroed */
+	if ((rl->vcn << vol->cluster_size_bits) < na->initialized_size) {
+		err = ntfs_inner_zero(na, rl);
+	}
+	if (!err) {
+		if (na->data_flags & ATTR_IS_SPARSE) {
+			na->compressed_size += size;
+			if (na->compressed_size >= na->allocated_size) {
+				na->data_flags &= ~ATTR_IS_SPARSE;
+				if (na->compressed_size > na->allocated_size) {
+					ntfs_log_error("File size error : "
+						"apparent %lld, "
+						"compressed %lld > "
+						"allocated %lld",
+						(long long)na->data_size,
+						(long long)na->compressed_size,
+						(long long)na->allocated_size);
+					errno = EIO;
+					err = -1;
+				}
+			}
+		}
+	}
+	if (!err) {
+		rl = ntfs_runlists_merge(na->rl, rl);
+		if (!rl) {
+			ntfs_log_error("Failed to merge the new allocation\n");
+			err = -1;
+		} else {
+			na->rl = rl;
+				/* Update the runlist */
+			if (ntfs_attr_update_mapping_pairs(na, 0)) {
+				ntfs_log_error(
+					"Failed to update the runlist\n");
+				err = -1;
+			}
+		}
+	}
+	return (err);
+}
+
+static int ntfs_inner_allocation(ntfs_attr *na, s64 alloc_offs, s64 alloc_len)
+{
+	ntfs_volume *vol;
+	runlist_element *rl;
+	runlist_element *prl;
+	runlist_element *rlc;
+	VCN from_vcn;
+	VCN end_vcn;
+	LCN lcn_seek_from;
+	VCN from_hole;
+	VCN end_hole;
+	s64 need;
+	int err;
+	BOOL done;
+
+	err = 0;
+	vol = na->ni->vol;
+		/* Find holes which overlap the requested allocation */
+	from_vcn = alloc_offs >> vol->cluster_size_bits;
+	end_vcn = (alloc_offs + alloc_len + vol->cluster_size - 1)
+			>> vol->cluster_size_bits;
+	do {
+		done = FALSE;
+		rl = na->rl;
+		while (rl->length
+		    && ((rl->lcn >= 0)
+		    	|| ((rl->vcn + rl->length) <= from_vcn)
+			|| (rl->vcn >= end_vcn)))
+				rl++;
+		if (!rl->length)
+			done = TRUE;
+		else {
+			from_hole = max(from_vcn, rl->vcn);
+			end_hole = min(end_vcn, rl->vcn + rl->length);
+			need = end_hole - from_hole;
+			lcn_seek_from = -1;
+			if (rl->vcn) {
+					/* Avoid fragmentation when possible */
+				prl = rl;
+				if ((--prl)->lcn >= 0) {
+					lcn_seek_from = prl->lcn
+						+ from_hole - prl->vcn;
+				}
+			}
+			if (need <= 0) {
+				ntfs_log_error("Wrong hole size %lld\n",
+							(long long)need);
+				errno = EIO;
+				err = -1;
+			} else {
+				rlc = ntfs_cluster_alloc(vol, from_hole, need,
+					 lcn_seek_from, DATA_ZONE);
+				if (!rlc)
+					err = -1;
+				else
+					err = ntfs_merge_allocation(na, rlc,
+						need << vol->cluster_size_bits);
+			}
+		}
+	} while (!err && !done);
+	return (err);
+}
+
+static int ntfs_full_allocation(ntfs_attr *na, ntfs_attr_search_ctx *ctx,
+				s64 alloc_offs, s64 alloc_len)
+{
+	ATTR_RECORD *attr;
+	ntfs_inode *ni;
+	s64 initialized_size;
+	s64 data_size;
+	int err;
+
+	err = 0;
+	initialized_size = na->initialized_size;
+	data_size = na->data_size;
+
+	if (na->allocated_size <= alloc_offs) {
+		/*
+		 * Request is fully beyond what was already allocated :
+		 * only need to expand the attribute
+		 */
+		err = ntfs_attr_truncate(na, alloc_offs);
+		if (!err)
+			err = ntfs_attr_truncate_solid(na,
+						alloc_offs + alloc_len);
+	} else {
+		/*
+		 * Request overlaps what was already allocated :
+		 * We may have to fill existing holes, and force zeroes
+		 * into clusters which are visible.
+		 */
+		if ((alloc_offs + alloc_len) > na->allocated_size)
+			err = ntfs_attr_truncate(na, alloc_offs + alloc_len);
+		if (!err)
+			err = ntfs_inner_allocation(na, alloc_offs, alloc_len);
+	}
+		/* Set the sizes, even after an error, to keep consistency */
+	na->initialized_size = initialized_size;
+		/* Restore the original apparent size if requested or error */
+	if (err || opts.no_size_change
+	    || ((alloc_offs + alloc_len) < data_size))
+		na->data_size = data_size;
+	else {
+		/*
+		 * "man 1 fallocate" does not define the new apparent size
+		 * when size change is allowed (no --keep-size).
+		 * Assuming the same as no FALLOC_FL_KEEP_SIZE in fallocate(2) :
+		 * "the file size will be changed if offset + len is greater
+		 * than the  file  size"
+// TODO check the behavior of another file system
+		 */
+		na->data_size = alloc_offs + alloc_len;
+	}
+
+	if (!err) {
+	/* Find the attribute, which may have been relocated for allocations */
+		if (ntfs_attr_lookup(attr_type, attr_name, attr_name_len,
+					CASE_SENSITIVE, 0, NULL, 0, ctx)) {
+			err = -1;
+			ntfs_log_error("Failed to locate the attribute\n");
+		} else {
+				/* Feed the sizes into the attribute */
+			attr = ctx->attr;
+			attr->data_size = cpu_to_le64(na->data_size);
+			attr->initialized_size
+				= cpu_to_le64(na->initialized_size);
+			attr->allocated_size
+				= cpu_to_le64(na->allocated_size);
+			if (na->data_flags & ATTR_IS_SPARSE)
+				attr->compressed_size
+					= cpu_to_le64(na->compressed_size);
+			/* Copy the unnamed data attribute sizes to inode */
+			if ((attr_type == AT_DATA) && !attr_name_len) {
+				ni = na->ni;
+				ni->data_size = na->data_size;
+				if (na->data_flags & ATTR_IS_SPARSE) {
+					ni->allocated_size
+						= na->compressed_size;
+					ni->flags |= FILE_ATTR_SPARSE_FILE;
+				} else
+					ni->allocated_size
+						= na->allocated_size;
+			}
+		}
+	}
+	return (err);
+}
+
+
+/*
+ *		Do the actual allocations
+ */
+
+static int ntfs_fallocate(ntfs_inode *ni, s64 alloc_offs, s64 alloc_len)
+{
+	s64 allocated_size;
+	s64 data_size;
+	ntfs_attr_search_ctx *ctx;
+	ntfs_attr *na;
+	runlist_element *oldrl;
+	const char *errmess;
+	int save_errno;
+	int err;
+
+	err = 0;
+	/* Open the specified attribute. */
+	na = ntfs_attr_open(ni, attr_type, attr_name, attr_name_len);
+	if (!na) {
+		ntfs_log_perror("Failed to open attribute 0x%lx: ",
+				(unsigned long)le32_to_cpu(attr_type));
+		err = -1;
+	} else {
+		errmess = (const char*)NULL;
+		if (na->data_flags & ATTR_IS_COMPRESSED) {
+			errmess= "Cannot fallocate a compressed file";
+		}
+
+		/* Locate the attribute record, needed for updating sizes */
+		ctx = ntfs_attr_get_search_ctx(ni, NULL);
+		if (!ctx) {
+			errmess = "Failed to allocate a search context";
+		}
+		if (errmess) {
+			ntfs_log_error("%s\n",errmess);
+			err = -1;
+		} else {
+			/* Get and save the initial allocations */
+			allocated_size = na->allocated_size;
+			data_size = ni->data_size;
+			err = ntfs_attr_map_whole_runlist(na);
+			if (!err) {
+				oldrl = ntfs_save_rl(na->rl);
+				if (oldrl) {
+					err = ntfs_full_allocation(na, ctx,
+							alloc_offs, alloc_len);
+					if (err) {
+						save_errno = errno;
+						ni->allocated_size
+							= allocated_size;
+						ni->data_size = data_size;
+						ntfs_restore_rl(na, oldrl);
+						errno = save_errno;
+					} else {
+						free(oldrl);
+	/* Mark file name dirty, to update the sizes in directories */
+						NInoFileNameSetDirty(ni);
+						NInoSetDirty(ni);
+					}
+				} else
+					err = -1;
+			}
+			ntfs_attr_put_search_ctx(ctx);
+		}
+		/* Close the attribute. */
+		ntfs_attr_close(na);
+	}
+	return (err);
+}
+
+/**
+ * main
+ */
+int main(int argc, char **argv)
+{
+	unsigned long mnt_flags, ul;
+	int err;
+	ntfs_inode *ni;
+	ntfs_volume *vol;
+#ifdef HAVE_WINDOWS_H
+	char *unix_name;
+#endif
+
+	vol = (ntfs_volume*)NULL;
+	ntfs_log_set_handler(ntfs_log_handler_outerr);
+
+	/* Initialize opts to zero / required values. */
+	memset(&opts, 0, sizeof(opts));
+
+	/* Parse command line options. */
+	parse_options(argc, argv);
+
+	utils_set_locale();
+
+	/* Make sure the file system is not mounted. */
+	if (ntfs_check_if_mounted(dev_name, &mnt_flags))
+		ntfs_log_perror("Failed to determine whether %s is mounted",
+				dev_name);
+	else if (mnt_flags & NTFS_MF_MOUNTED) {
+		ntfs_log_error("%s is mounted.\n", dev_name);
+		if (!opts.force)
+			err_exit((ntfs_volume*)NULL, "Refusing to run!\n");
+		fprintf(stderr, "ntfsfallocate forced anyway. Hope /etc/mtab "
+				"is incorrect.\n");
+	}
+
+	/* Mount the device. */
+	if (opts.no_action) {
+		ntfs_log_quiet("Running in READ-ONLY mode!\n");
+		ul = NTFS_MNT_RDONLY;
+	} else
+		if (opts.force)
+			ul = NTFS_MNT_RECOVER;
+		else
+			ul = 0;
+	vol = ntfs_mount(dev_name, ul);
+	if (!vol)
+		err_exit(vol, "Failed to mount %s: %s\n", dev_name,
+			strerror(errno));
+
+	if ((vol->flags & VOLUME_IS_DIRTY) && !opts.force)
+		err_exit(vol, "Volume is dirty, please run chkdsk.\n");
+
+	if (ntfs_volume_get_free_space(vol))
+		err_exit(vol, "Failed to get free clusters %s: %s\n",
+					dev_name, strerror(errno));
+
+	/* Open the specified inode. */
+#ifdef HAVE_WINDOWS_H
+	unix_name = (char*)malloc(strlen(file_name) + 1);
+	if (unix_name) {
+		int i;
+		for (i=0; file_name[i]; i++)
+			if (file_name[i] == '\\')
+				unix_name[i] = '/';
+			else
+				unix_name[i] = file_name[i];
+		unix_name[i] = 0;
+		ni = ntfs_pathname_to_inode(vol, NULL, unix_name);
+		free(unix_name);
+	} else
+		ni = (ntfs_inode*)NULL;
+#else
+	ni = ntfs_pathname_to_inode(vol, NULL, file_name);
+#endif
+	if (!ni)
+		err_exit(vol, "Failed to open file \"%s\": %s\n", file_name,
+				strerror(errno));
+	if (!opts.no_action)
+		err = ntfs_fallocate(ni, opt_alloc_offs, opt_alloc_len);
+
+	/* Close the inode. */
+	if (ntfs_inode_close(ni)) {
+		err = -1;
+		err_exit(vol, "Failed to close inode \"%s\" : %s\n", file_name,
+				strerror(errno));
+	}
+
+	/* Unmount the volume. */
+	err = ntfs_umount(vol, 0);
+	vol = (ntfs_volume*)NULL;
+	if (err)
+		ntfs_log_perror("Warning: Failed to umount %s", dev_name);
+
+	/* Free the attribute name if it exists. */
+	if (attr_name_len)
+		ntfs_ucsfree(attr_name);
+
+	ntfs_log_quiet("ntfsfallocate completed successfully. Have a nice day.\n");
+	return 0;
+}
diff --git a/ntfsprogs/ntfsfix.8 b/ntfsprogs/ntfsfix.8
new file mode 100755
index 0000000000000000000000000000000000000000..e3d31f479dcfb6b5a6e9497ae8b40780c2249a53
--- /dev/null
+++ b/ntfsprogs/ntfsfix.8
@@ -0,0 +1,82 @@
+.\" Copyright (c) 2005-2006 Szabolcs Szakacsits.
+.\" Copyright (c) 2005 Richard Russon.
+.\" Copyright (c) 2011-2013 Jean-Pierre Andre
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSFIX 8 "January 2013" "ntfs-3g 2015.3.14"
+.SH NAME
+ntfsfix \- fix common errors and force Windows to check NTFS
+.SH SYNOPSIS
+.B ntfsfix
+[\fIoptions\fR] \fIdevice\fR
+.SH DESCRIPTION
+.B ntfsfix
+is a utility that fixes some common NTFS problems.
+.B ntfsfix
+is
+.B NOT
+a Linux version of chkdsk.  It only repairs some fundamental NTFS
+inconsistencies, resets the NTFS journal file and schedules an NTFS consistency
+check for the first boot into Windows.
+.sp
+You may run
+.B ntfsfix
+on an NTFS volume if you think it was damaged by Windows or some other way 
+and it cannot be mounted.
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfsfix
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-b\fR, \fB\-\-clear\-bad\-sectors\fR
+Clear the list of bad sectors. This is useful after cloning an old disk
+with bad sectors to a new disk.
+.TP
+\fB\-d\fR, \fB\-\-clear\-dirty\fR
+Clear the volume dirty flag if the volume can be fixed and mounted.
+If the option is not present or the volume cannot be fixed, the dirty
+volume flag is set to request a volume checking at next mount.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.TP
+\fB\-n\fR, \fB\-\-no\-action\fR
+Do not write anything, just show what would have been done.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Show the version number, copyright and license
+.SH BUGS
+There are no known problems with
+.BR ntfsfix .
+If you find a bug please send an email describing the problem to the
+development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+.B ntfsfix
+was written by Anton Altaparmakov, with contributions from Szabolcs Szakacsits.
+It was ported to ntfs-3g by Erik Larsson and Jean-Pierre Andre.
+.SH AVAILABILITY
+.B ntfsfix
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR mkntfs (8),
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/ntfsfix.8.in b/ntfsprogs/ntfsfix.8.in
new file mode 100755
index 0000000000000000000000000000000000000000..51010001c96f78943d1d21c588f0368f94be05fe
--- /dev/null
+++ b/ntfsprogs/ntfsfix.8.in
@@ -0,0 +1,82 @@
+.\" Copyright (c) 2005-2006 Szabolcs Szakacsits.
+.\" Copyright (c) 2005 Richard Russon.
+.\" Copyright (c) 2011-2013 Jean-Pierre Andre
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSFIX 8 "January 2013" "ntfs-3g @VERSION@"
+.SH NAME
+ntfsfix \- fix common errors and force Windows to check NTFS
+.SH SYNOPSIS
+.B ntfsfix
+[\fIoptions\fR] \fIdevice\fR
+.SH DESCRIPTION
+.B ntfsfix
+is a utility that fixes some common NTFS problems.
+.B ntfsfix
+is
+.B NOT
+a Linux version of chkdsk.  It only repairs some fundamental NTFS
+inconsistencies, resets the NTFS journal file and schedules an NTFS consistency
+check for the first boot into Windows.
+.sp
+You may run
+.B ntfsfix
+on an NTFS volume if you think it was damaged by Windows or some other way 
+and it cannot be mounted.
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfsfix
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-b\fR, \fB\-\-clear\-bad\-sectors\fR
+Clear the list of bad sectors. This is useful after cloning an old disk
+with bad sectors to a new disk.
+.TP
+\fB\-d\fR, \fB\-\-clear\-dirty\fR
+Clear the volume dirty flag if the volume can be fixed and mounted.
+If the option is not present or the volume cannot be fixed, the dirty
+volume flag is set to request a volume checking at next mount.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.TP
+\fB\-n\fR, \fB\-\-no\-action\fR
+Do not write anything, just show what would have been done.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Show the version number, copyright and license
+.SH BUGS
+There are no known problems with
+.BR ntfsfix .
+If you find a bug please send an email describing the problem to the
+development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+.B ntfsfix
+was written by Anton Altaparmakov, with contributions from Szabolcs Szakacsits.
+It was ported to ntfs-3g by Erik Larsson and Jean-Pierre Andre.
+.SH AVAILABILITY
+.B ntfsfix
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR mkntfs (8),
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/ntfsfix.c b/ntfsprogs/ntfsfix.c
new file mode 100755
index 0000000000000000000000000000000000000000..59b8a98fbd8bfd23475ecb7c2dd7e7e62ba94096
--- /dev/null
+++ b/ntfsprogs/ntfsfix.c
@@ -0,0 +1,1655 @@
+/**
+ * ntfsfix - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2000-2006 Anton Altaparmakov
+ * Copyright (c) 2002-2006 Szabolcs Szakacsits
+ * Copyright (c) 2007      Yura Pakhuchiy
+ * Copyright (c) 2011-2014 Jean-Pierre Andre
+ *
+ * This utility fixes some common NTFS problems, resets the NTFS journal file
+ * and schedules an NTFS consistency check for the first boot into Windows.
+ *
+ *	Anton Altaparmakov <aia21@cantab.net>
+ *
+ * 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 Linux-NTFS source
+ * in the file COPYING); if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * WARNING: This program might not work on architectures which do not allow
+ * unaligned access. For those, the program would need to start using
+ * get/put_unaligned macros (#include <asm/unaligned.h>), but not doing it yet,
+ * since NTFS really mostly applies to ia32 only, which does allow unaligned
+ * accesses. We might not actually have a problem though, since the structs are
+ * defined as being packed so that might be enough for gcc to insert the
+ * correct code.
+ *
+ * If anyone using a non-little endian and/or an aligned access only CPU tries
+ * this program please let me know whether it works or not!
+ *
+ *	Anton Altaparmakov <aia21@cantab.net>
+ */
+
+#include "config.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+
+#include "types.h"
+#include "attrib.h"
+#include "volume.h"
+#include "bootsect.h"
+#include "mft.h"
+#include "device.h"
+#include "logfile.h"
+#include "runlist.h"
+#include "mst.h"
+#include "utils.h"
+/* #include "version.h" */
+#include "logging.h"
+#include "misc.h"
+
+#ifdef NO_NTFS_DEVICE_DEFAULT_IO_OPS
+#	error "No default device io operations!  Cannot build ntfsfix.  \
+You need to run ./configure without the --disable-default-device-io-ops \
+switch if you want to be able to build the NTFS utilities."
+#endif
+
+static const char *EXEC_NAME = "ntfsfix";
+static const char OK[]       = "OK\n";
+static const char FAILED[]   = "FAILED\n";
+static const char FOUND[]    = "FOUND\n";
+
+#define DEFAULT_SECTOR_SIZE 512
+
+static struct {
+	char *volume;
+	BOOL no_action;
+	BOOL clear_bad_sectors;
+	BOOL clear_dirty;
+} opt;
+
+/*
+ *		Definitions for fixing the self-located MFT bug
+ */
+
+#define SELFLOC_LIMIT 16
+
+struct MFT_SELF_LOCATED {
+	ntfs_volume *vol;
+	MFT_RECORD *mft0;
+	MFT_RECORD *mft1;
+	MFT_RECORD *mft2;
+	ATTR_LIST_ENTRY *attrlist;
+	ATTR_LIST_ENTRY *attrlist_to_ref1;
+	MFT_REF mft_ref0;
+	MFT_REF mft_ref1;
+	LCN attrlist_lcn;
+	BOOL attrlist_resident;
+} ;
+
+/**
+ * usage
+ */
+__attribute__((noreturn))
+static void usage(int ret)
+{
+	ntfs_log_info("%s v%s (libntfs-3g)\n"
+		   "\n"
+		   "Usage: %s [options] device\n"
+		   "    Attempt to fix an NTFS partition.\n"
+		   "\n"
+		   "    -b, --clear-bad-sectors Clear the bad sector list\n"
+		   "    -d, --clear-dirty       Clear the volume dirty flag\n"
+		   "    -h, --help              Display this help\n"
+		   "    -n, --no-action         Do not write anything\n"
+		   "    -V, --version           Display version information\n"
+		   "\n"
+		   "For example: %s /dev/hda6\n\n",
+		   EXEC_NAME, VERSION, EXEC_NAME,
+		   EXEC_NAME);
+	ntfs_log_info("%s%s", ntfs_bugs, ntfs_home);
+	exit(ret);
+}
+
+/**
+ * version
+ */
+__attribute__((noreturn))
+static void version(void)
+{
+	ntfs_log_info("%s v%s\n\n"
+		   "Attempt to fix an NTFS partition.\n\n"
+		   "Copyright (c) 2000-2006 Anton Altaparmakov\n"
+		   "Copyright (c) 2002-2006 Szabolcs Szakacsits\n"
+		   "Copyright (c) 2007      Yura Pakhuchiy\n"
+		   "Copyright (c) 2011-2014 Jean-Pierre Andre\n\n",
+		   EXEC_NAME, VERSION);
+	ntfs_log_info("%s\n%s%s", ntfs_gpl, ntfs_bugs, ntfs_home);
+	exit(0);
+}
+
+/**
+ * parse_options
+ */
+static void parse_options(int argc, char **argv)
+{
+	int c;
+	static const char *sopt = "-bdhnV";
+	static const struct option lopt[] = {
+		{ "help",		no_argument,	NULL, 'h' },
+		{ "no-action",		no_argument,	NULL, 'n' },
+		{ "clear-bad-sectors",	no_argument,	NULL, 'b' },
+		{ "clear-dirty",	no_argument,	NULL, 'd' },
+		{ "version",		no_argument,	NULL, 'V' },
+		{ NULL, 		0, NULL, 0 }
+	};
+
+	memset(&opt, 0, sizeof(opt));
+
+	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
+		switch (c) {
+		case 1:	/* A non-option argument */
+			if (!opt.volume)
+				opt.volume = argv[optind - 1];
+			else {
+				ntfs_log_info("ERROR: Too many arguments.\n");
+				usage(1);
+			}
+			break;
+		case 'b':
+			opt.clear_bad_sectors = TRUE;
+			break;
+		case 'd':
+			opt.clear_dirty = TRUE;
+			break;
+		case 'n':
+			opt.no_action = TRUE;
+			break;
+		case 'h':
+			usage(0);
+		case '?':
+			usage(1);
+			/* fall through */
+		case 'V':
+			version();
+		default:
+			ntfs_log_info("ERROR: Unknown option '%s'.\n", argv[optind - 1]);
+			usage(1);
+		}
+	}
+
+	if (opt.volume == NULL) {
+		ntfs_log_info("ERROR: You must specify a device.\n");
+		usage(1);
+	}
+}
+
+/**
+ * OLD_ntfs_volume_set_flags
+ */
+static int OLD_ntfs_volume_set_flags(ntfs_volume *vol, const le16 flags)
+{
+	MFT_RECORD *m = NULL;
+	ATTR_RECORD *a;
+	VOLUME_INFORMATION *c;
+	ntfs_attr_search_ctx *ctx;
+	int ret = -1;   /* failure */
+
+	if (!vol) {
+		errno = EINVAL;
+		return -1;
+	}
+	if (ntfs_file_record_read(vol, FILE_Volume, &m, NULL)) {
+		ntfs_log_perror("Failed to read $Volume");
+		return -1;
+	}
+	/* Sanity check */
+	if (!(m->flags & MFT_RECORD_IN_USE)) {
+		ntfs_log_error("$Volume has been deleted. Cannot handle this "
+				"yet. Run chkdsk to fix this.\n");
+		errno = EIO;
+		goto err_exit;
+	}
+	/* Get a pointer to the volume information attribute. */
+	ctx = ntfs_attr_get_search_ctx(NULL, m);
+	if (!ctx) {
+		ntfs_log_debug("Failed to allocate attribute search "
+				"context.\n");
+		goto err_exit;
+	}
+	if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, AT_UNNAMED, 0,
+			CASE_SENSITIVE, 0, NULL, 0, ctx)) {
+		ntfs_log_error("Attribute $VOLUME_INFORMATION was not found in "
+				"$Volume!\n");
+		goto err_out;
+	}
+	a = ctx->attr;
+	/* Sanity check. */
+	if (a->non_resident) {
+		ntfs_log_error("Attribute $VOLUME_INFORMATION must be resident "
+				"(and it isn't)!\n");
+		errno = EIO;
+		goto err_out;
+	}
+	/* Get a pointer to the value of the attribute. */
+	c = (VOLUME_INFORMATION*)(le16_to_cpu(a->value_offset) + (char*)a);
+	/* Sanity checks. */
+	if ((char*)c + le32_to_cpu(a->value_length) >
+			(char*)m + le32_to_cpu(m->bytes_in_use) ||
+			le16_to_cpu(a->value_offset) +
+			le32_to_cpu(a->value_length) > le32_to_cpu(a->length)) {
+		ntfs_log_error("Attribute $VOLUME_INFORMATION in $Volume is "
+				"corrupt!\n");
+		errno = EIO;
+		goto err_out;
+	}
+	/* Set the volume flags. */
+	vol->flags = c->flags = flags;
+	if (ntfs_mft_record_write(vol, FILE_Volume, m)) {
+		ntfs_log_perror("Error writing $Volume");
+		goto err_out;
+	}
+	ret = 0; /* success */
+err_out:
+	ntfs_attr_put_search_ctx(ctx);
+err_exit:
+	free(m);
+	return ret;
+}
+
+/**
+ * set_dirty_flag
+ */
+static int set_dirty_flag(ntfs_volume *vol)
+{
+	le16 flags;
+
+	/* Porting note: We test for the current state of VOLUME_IS_DIRTY. This
+	 * should actually be more appropriate than testing for NVolWasDirty. */
+	if (vol->flags & VOLUME_IS_DIRTY)
+		return 0;
+	ntfs_log_info("Setting required flags on partition... ");
+	/*
+	 * Set chkdsk flag, i.e. mark the partition dirty so chkdsk will run
+	 * and fix it for us.
+	 */
+	flags = vol->flags | VOLUME_IS_DIRTY;
+	if (!opt.no_action && OLD_ntfs_volume_set_flags(vol, flags)) {
+		ntfs_log_info(FAILED);
+		ntfs_log_error("Error setting volume flags.\n");
+		return -1;
+	}
+	vol->flags = flags;
+
+	/* Porting note: libntfs-3g does not have the 'WasDirty' flag/property,
+	 * and never touches the 'dirty' bit except when explicitly told to do
+	 * so. Since we just wrote the VOLUME_IS_DIRTY bit to disk, and
+	 * vol->flags is up-to-date, we can just ignore the NVolSetWasDirty
+	 * statement. */
+	/* NVolSetWasDirty(vol); */
+
+	ntfs_log_info(OK);
+	return 0;
+}
+
+/**
+ * empty_journal
+ */
+static int empty_journal(ntfs_volume *vol)
+{
+	if (NVolLogFileEmpty(vol))
+		return 0;
+	ntfs_log_info("Going to empty the journal ($LogFile)... ");
+	if (ntfs_logfile_reset(vol)) {
+		ntfs_log_info(FAILED);
+		ntfs_log_perror("Failed to reset $LogFile");
+		return -1;
+	}
+	ntfs_log_info(OK);
+	return 0;
+}
+
+/**
+ *		Clear the bad cluster marks (option)
+ */
+static int clear_badclus(ntfs_volume *vol)
+{
+	static ntfschar badstream[] = {
+				const_cpu_to_le16('$'), const_cpu_to_le16('B'),
+				const_cpu_to_le16('a'), const_cpu_to_le16('d')
+	} ;
+	ntfs_inode *ni;
+	ntfs_attr *na;
+	BOOL ok;
+
+	ok = FALSE;
+	ntfs_log_info("Going to un-mark the bad clusters ($BadClus)... ");
+	ni = ntfs_inode_open(vol, FILE_BadClus);
+	if (ni) {
+		na = ntfs_attr_open(ni, AT_DATA, badstream, 4);
+			/*
+			 * chkdsk does not adjust the data size when
+			 * moving clusters to $BadClus, so we have to
+			 * check the runlist.
+			 */
+		if (na && !ntfs_attr_map_whole_runlist(na)) {
+			if (na->rl
+			    && na->rl[0].length && na->rl[1].length) {
+			/*
+			 * Truncate the stream to free all its clusters,
+			 * (which requires setting the data size according
+			 * to allocation), then reallocate a sparse stream
+			 * to full size of volume and reset the data size.
+			 */
+				na->data_size = na->allocated_size;
+				na->initialized_size = na->allocated_size;
+				if (!ntfs_attr_truncate(na,0)
+				    && !ntfs_attr_truncate(na,vol->nr_clusters
+						<< vol->cluster_size_bits)) {
+					na->data_size = 0;
+					na->initialized_size = 0;
+					ni->flags |= FILE_ATTR_SPARSE_FILE;
+					NInoFileNameSetDirty(ni);
+					ok = TRUE;
+				} else {
+					ntfs_log_perror("Failed to un-mark the bad clusters");
+				}
+			} else {
+				ntfs_log_info("No bad clusters...");
+				ok = TRUE;
+			}
+			ntfs_attr_close(na);
+		} else {
+			ntfs_log_perror("Failed to open $BadClus::$Bad");
+		}
+		ntfs_inode_close(ni);
+	} else {
+		ntfs_log_perror("Failed to open inode FILE_BadClus");
+	}
+	if (ok)
+		ntfs_log_info(OK);
+	return (ok ? 0 : -1);
+}
+
+/**
+ * fix_mftmirr
+ */
+static int fix_mftmirr(ntfs_volume *vol)
+{
+	s64 l, br;
+	unsigned char *m, *m2;
+	int i, ret = -1; /* failure */
+	BOOL done;
+
+	ntfs_log_info("\nProcessing $MFT and $MFTMirr...\n");
+
+	/* Load data from $MFT and $MFTMirr and compare the contents. */
+	m = (u8*)malloc(vol->mftmirr_size << vol->mft_record_size_bits);
+	if (!m) {
+		ntfs_log_perror("Failed to allocate memory");
+		return -1;
+	}
+	m2 = (u8*)malloc(vol->mftmirr_size << vol->mft_record_size_bits);
+	if (!m2) {
+		ntfs_log_perror("Failed to allocate memory");
+		free(m);
+		return -1;
+	}
+
+	ntfs_log_info("Reading $MFT... ");
+	l = ntfs_attr_mst_pread(vol->mft_na, 0, vol->mftmirr_size,
+			vol->mft_record_size, m);
+	if (l != vol->mftmirr_size) {
+		ntfs_log_info(FAILED);
+		if (l != -1)
+			errno = EIO;
+		ntfs_log_perror("Failed to read $MFT");
+		goto error_exit;
+	}
+	ntfs_log_info(OK);
+
+	ntfs_log_info("Reading $MFTMirr... ");
+	l = ntfs_attr_mst_pread(vol->mftmirr_na, 0, vol->mftmirr_size,
+			vol->mft_record_size, m2);
+	if (l != vol->mftmirr_size) {
+		ntfs_log_info(FAILED);
+		if (l != -1)
+			errno = EIO;
+		ntfs_log_perror("Failed to read $MFTMirr");
+		goto error_exit;
+	}
+	ntfs_log_info(OK);
+
+	/*
+	 * FIXME: Need to actually check the $MFTMirr for being real. Otherwise
+	 * we might corrupt the partition if someone is experimenting with
+	 * software RAID and the $MFTMirr is not actually in the position we
+	 * expect it to be... )-:
+	 * FIXME: We should emit a warning it $MFTMirr is damaged and ask
+	 * user whether to recreate it from $MFT or whether to abort. - The
+	 * warning needs to include the danger of software RAID arrays.
+	 * Maybe we should go as far as to detect whether we are running on a
+	 * MD disk and if yes then bomb out right at the start of the program?
+	 */
+
+	ntfs_log_info("Comparing $MFTMirr to $MFT... ");
+	done = FALSE;
+	for (i = 0; i < vol->mftmirr_size; ++i) {
+		MFT_RECORD *mrec, *mrec2;
+		const char *ESTR[12] = { "$MFT", "$MFTMirr", "$LogFile",
+			"$Volume", "$AttrDef", "root directory", "$Bitmap",
+			"$Boot", "$BadClus", "$Secure", "$UpCase", "$Extend" };
+		const char *s;
+		BOOL use_mirr;
+
+		if (i < 12)
+			s = ESTR[i];
+		else if (i < 16)
+			s = "system file";
+		else
+			s = "mft record";
+
+		use_mirr = FALSE;
+		mrec = (MFT_RECORD*)(m + i * vol->mft_record_size);
+		if (mrec->flags & MFT_RECORD_IN_USE) {
+			if (ntfs_is_baad_record(mrec->magic)) {
+				ntfs_log_info(FAILED);
+				ntfs_log_error("$MFT error: Incomplete multi "
+						"sector transfer detected in "
+						"%s.\nCannot handle this yet. "
+						")-:\n", s);
+				goto error_exit;
+			}
+			if (!ntfs_is_mft_record(mrec->magic)) {
+				ntfs_log_info(FAILED);
+				ntfs_log_error("$MFT error: Invalid mft "
+						"record for %s.\nCannot "
+						"handle this yet. )-:\n", s);
+				goto error_exit;
+			}
+		}
+		mrec2 = (MFT_RECORD*)(m2 + i * vol->mft_record_size);
+		if (mrec2->flags & MFT_RECORD_IN_USE) {
+			if (ntfs_is_baad_record(mrec2->magic)) {
+				ntfs_log_info(FAILED);
+				ntfs_log_error("$MFTMirr error: Incomplete "
+						"multi sector transfer "
+						"detected in %s.\n", s);
+				goto error_exit;
+			}
+			if (!ntfs_is_mft_record(mrec2->magic)) {
+				ntfs_log_info(FAILED);
+				ntfs_log_error("$MFTMirr error: Invalid mft "
+						"record for %s.\n", s);
+				goto error_exit;
+			}
+			/* $MFT is corrupt but $MFTMirr is ok, use $MFTMirr. */
+			if (!(mrec->flags & MFT_RECORD_IN_USE) &&
+					!ntfs_is_mft_record(mrec->magic))
+				use_mirr = TRUE;
+		}
+		if (memcmp(mrec, mrec2, ntfs_mft_record_get_data_size(mrec))) {
+			if (!done) {
+				done = TRUE;
+				ntfs_log_info(FAILED);
+			}
+			ntfs_log_info("Correcting differences in $MFT%s "
+					"record %d...", use_mirr ? "" : "Mirr",
+					i);
+			br = ntfs_mft_record_write(vol, i,
+					use_mirr ? mrec2 : mrec);
+			if (br) {
+				ntfs_log_info(FAILED);
+				ntfs_log_perror("Error correcting $MFT%s",
+						use_mirr ? "" : "Mirr");
+				goto error_exit;
+			}
+			ntfs_log_info(OK);
+		}
+	}
+	if (!done)
+		ntfs_log_info(OK);
+	ntfs_log_info("Processing of $MFT and $MFTMirr completed "
+			"successfully.\n");
+	ret = 0;
+error_exit:
+	free(m);
+	free(m2);
+	return ret;
+}
+
+/*
+ *		Rewrite the $UpCase file as default
+ *
+ *	Returns 0 if could be written
+ */
+
+static int rewrite_upcase(ntfs_volume *vol, ntfs_attr *na)
+{
+	s64 l;
+	int res;
+
+		/* writing the $UpCase may require bitmap updates */
+	res = -1;
+	vol->lcnbmp_ni = ntfs_inode_open(vol, FILE_Bitmap);
+	if (!vol->lcnbmp_ni) {
+		ntfs_log_perror("Failed to open bitmap inode");
+	} else {
+		vol->lcnbmp_na = ntfs_attr_open(vol->lcnbmp_ni, AT_DATA,
+					AT_UNNAMED, 0);
+		if (!vol->lcnbmp_na) {
+			ntfs_log_perror("Failed to open bitmap data attribute");
+		} else {
+			/* minimal consistency check on the bitmap */
+			if (((vol->lcnbmp_na->data_size << 3)
+				< vol->nr_clusters)
+			    || ((vol->lcnbmp_na->data_size << 3)
+				>= (vol->nr_clusters << 1))
+			    || (vol->lcnbmp_na->data_size
+					> vol->lcnbmp_na->allocated_size)) {
+				ntfs_log_error("Corrupt cluster map size %lld"
+					" (allocated %lld minimum %lld)\n",
+					(long long)vol->lcnbmp_na->data_size, 
+					(long long)vol->lcnbmp_na->allocated_size,
+					(long long)(vol->nr_clusters + 7) >> 3);
+			} else {
+				ntfs_log_info("Rewriting $UpCase file\n");
+				l = ntfs_attr_pwrite(na, 0, vol->upcase_len*2,
+							vol->upcase);
+				if (l != vol->upcase_len*2) {
+					ntfs_log_error("Failed to rewrite $UpCase\n");
+				} else {
+					ntfs_log_info("$UpCase has been set to default\n");
+					res = 0;
+				}
+			}
+			ntfs_attr_close(vol->lcnbmp_na);
+			vol->lcnbmp_na = (ntfs_attr*)NULL;
+		}
+		ntfs_inode_close(vol->lcnbmp_ni);
+		vol->lcnbmp_ni = (ntfs_inode*)NULL;
+	}
+	return (res);
+}
+
+/*
+ *		Fix the $UpCase file
+ *
+ *	Returns 0 if the table is valid or has been fixed
+ */
+
+static int fix_upcase(ntfs_volume *vol)
+{
+	ntfs_inode *ni;
+	ntfs_attr *na;
+	ntfschar *upcase;
+	s64 l;
+	u32 upcase_len;
+	u32 k;
+	int res;
+
+	res = -1;
+	ni = (ntfs_inode*)NULL;
+	na = (ntfs_attr*)NULL;
+	/* Now load the upcase table from $UpCase. */
+	ntfs_log_debug("Loading $UpCase...\n");
+	ni = ntfs_inode_open(vol, FILE_UpCase);
+	if (!ni) {
+		ntfs_log_perror("Failed to open inode FILE_UpCase");
+		goto error_exit;
+	}
+	/* Get an ntfs attribute for $UpCase/$DATA. */
+	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
+	if (!na) {
+		ntfs_log_perror("Failed to open ntfs attribute");
+		goto error_exit;
+	}
+	/*
+	 * Note: Normally, the upcase table has a length equal to 65536
+	 * 2-byte Unicode characters but allow for different cases, so no
+	 * checks done. Just check we don't overflow 32-bits worth of Unicode
+	 * characters.
+	 */
+	if (na->data_size & ~0x1ffffffffULL) {
+		ntfs_log_error("Error: Upcase table is too big (max 32-bit "
+				"allowed).\n");
+		errno = EINVAL;
+		goto error_exit;
+	}
+	upcase_len = na->data_size >> 1;
+	upcase = (ntfschar*)ntfs_malloc(na->data_size);
+	if (!upcase)
+		goto error_exit;
+	/* Read in the $DATA attribute value into the buffer. */
+	l = ntfs_attr_pread(na, 0, na->data_size, upcase);
+	if (l != na->data_size) {
+		ntfs_log_error("Failed to read $UpCase, unexpected length "
+			       "(%lld != %lld).\n", (long long)l,
+			       (long long)na->data_size);
+		errno = EIO;
+		goto error_exit;
+	}
+	/* Consistency check of $UpCase, restricted to plain ASCII chars */
+	k = 0x20;
+	while ((k < upcase_len)
+	    && (k < 0x7f)
+	    && (le16_to_cpu(upcase[k])
+			== ((k < 'a') || (k > 'z') ? k : k + 'A' - 'a')))
+		k++;
+	if (k < 0x7f) {
+		ntfs_log_error("Corrupted file $UpCase\n");
+		if (!opt.no_action) {
+			/* rewrite the $UpCase file from default */
+			res = rewrite_upcase(vol, na);
+			/* free the bad upcase record */
+			if (!res)
+				free(upcase);
+		} else {
+			/* keep the default upcase but return an error */
+			free(upcase);
+		}
+	} else {
+			/* accept the upcase table read from $UpCase */
+		free(vol->upcase);
+		vol->upcase = upcase;
+		vol->upcase_len = upcase_len;
+		res = 0;
+	}
+error_exit :
+	/* Done with the $UpCase mft record. */
+	if (na)
+		ntfs_attr_close(na);
+	if (ni && ntfs_inode_close(ni)) {
+		ntfs_log_perror("Failed to close $UpCase");
+	}
+	return (res);
+}
+
+/*
+ *		Rewrite the boot sector
+ *
+ *	Returns 0 if successful
+ */
+
+static int rewrite_boot(struct ntfs_device *dev, char *full_bs,
+				s32 sector_size)
+{
+	s64 bw;
+	int res;
+
+	res = -1;
+	ntfs_log_info("Rewriting the bootsector\n");
+	bw = ntfs_pwrite(dev, 0, sector_size, full_bs);
+	if (bw == sector_size)
+		res = 0;
+	else {
+		if (bw != -1)
+			errno = EINVAL;
+		if (!bw)
+			ntfs_log_error("Failed to rewrite the bootsector (size=0)\n");
+		else
+			ntfs_log_perror("Error rewriting the bootsector");
+	}
+	return (res);
+}
+
+/*
+ *		Locate an unnamed attribute in an MFT record
+ *
+ *	Returns NULL if not found (with no error message)
+ */
+
+static ATTR_RECORD *find_unnamed_attr(MFT_RECORD *mrec, ATTR_TYPES type)
+{
+	ATTR_RECORD *a;
+	u32 offset;
+
+			/* fetch the requested attribute */
+	offset = le16_to_cpu(mrec->attrs_offset);
+	a = (ATTR_RECORD*)((char*)mrec + offset);
+	while ((a->type != AT_END)
+	    && ((a->type != type) || a->name_length)
+	    && (offset < le32_to_cpu(mrec->bytes_in_use))) {
+		offset += le32_to_cpu(a->length);
+		a = (ATTR_RECORD*)((char*)mrec + offset);
+	}
+	if ((a->type != type)
+	    || a->name_length)
+		a = (ATTR_RECORD*)NULL;
+	return (a);
+}
+
+/*
+ *		First condition for having a self-located MFT :
+ *		only 16 MFT records are defined in MFT record 0
+ *
+ *	Only low-level library functions can be used.
+ *
+ *	Returns TRUE if the condition is met.
+ */
+
+static BOOL short_mft_selfloc_condition(struct MFT_SELF_LOCATED *selfloc)
+{
+	BOOL ok;
+	ntfs_volume *vol;
+	MFT_RECORD *mft0;
+	ATTR_RECORD *a;
+	runlist_element *rl;
+	u16 seqn;
+
+	ok = FALSE;
+	vol = selfloc->vol;
+	mft0 = selfloc->mft0;
+	if ((ntfs_pread(vol->dev,
+			vol->mft_lcn << vol->cluster_size_bits,
+			vol->mft_record_size, mft0)
+				== vol->mft_record_size)
+	    && !ntfs_mst_post_read_fixup((NTFS_RECORD*)mft0,
+			vol->mft_record_size)) {
+		a = find_unnamed_attr(mft0,AT_DATA);
+		if (a
+		    && a->non_resident
+		    && (((le64_to_cpu(a->highest_vcn) + 1)
+					<< vol->cluster_size_bits)
+				== (SELFLOC_LIMIT*vol->mft_record_size))) {
+			rl = ntfs_mapping_pairs_decompress(vol, a, NULL);
+			if (rl) {
+				/*
+				 * The first error condition is having only
+				 * 16 entries mapped in the first MFT record.
+				 */
+				if ((rl[0].lcn >= 0)
+				  && ((rl[0].length << vol->cluster_size_bits)
+					== SELFLOC_LIMIT*vol->mft_record_size)
+				  && (rl[1].vcn == rl[0].length)
+				  && (rl[1].lcn == LCN_RL_NOT_MAPPED)) {
+					ok = TRUE;
+					seqn = le16_to_cpu(
+						mft0->sequence_number);
+					selfloc->mft_ref0
+						= ((MFT_REF)seqn) << 48;
+				}
+				free(rl);
+			}
+		}
+	}
+	return (ok);
+}
+
+/*
+ *		Second condition for having a self-located MFT :
+ *		The 16th MFT record is defined in MFT record >= 16
+ *
+ *	Only low-level library functions can be used.
+ *
+ *	Returns TRUE if the condition is met.
+ */
+
+static BOOL attrlist_selfloc_condition(struct MFT_SELF_LOCATED *selfloc)
+{
+	ntfs_volume *vol;
+	ATTR_RECORD *a;
+	ATTR_LIST_ENTRY *attrlist;
+	ATTR_LIST_ENTRY *al;
+	runlist_element *rl;
+	VCN vcn;
+	leVCN levcn;
+	u32 length;
+	int ok;
+
+	ok = FALSE;
+	length = 0;
+	vol = selfloc->vol;
+	a = find_unnamed_attr(selfloc->mft0,AT_ATTRIBUTE_LIST);
+	if (a) {
+		selfloc->attrlist_resident = !a->non_resident;
+		selfloc->attrlist_lcn = 0;
+		if (a->non_resident) {
+			attrlist = selfloc->attrlist;
+			rl = ntfs_mapping_pairs_decompress(vol, a, NULL);
+			if (rl
+			    && (rl->lcn >= 0)
+			    && (le64_to_cpu(a->data_size) < vol->cluster_size)
+			    && (ntfs_pread(vol->dev,
+					rl->lcn << vol->cluster_size_bits,
+					vol->cluster_size, attrlist) == vol->cluster_size)) {
+				selfloc->attrlist_lcn = rl->lcn;
+				al = attrlist;
+				length = le64_to_cpu(a->data_size);
+			}
+		} else {
+			al = (ATTR_LIST_ENTRY*)
+				((char*)a + le16_to_cpu(a->value_offset));
+			length = le32_to_cpu(a->value_length);
+		}
+		if (length) {
+			/* search for a data attribute defining entry 16 */
+			vcn = (SELFLOC_LIMIT*vol->mft_record_size)
+					>> vol->cluster_size_bits;
+			levcn = cpu_to_le64(vcn);
+			while ((length > 0)
+			    && al->length
+			    && ((al->type != AT_DATA)
+				|| ((leVCN)al->lowest_vcn != levcn))) {
+				length -= le16_to_cpu(al->length);
+				al = (ATTR_LIST_ENTRY*)
+					((char*)al + le16_to_cpu(al->length));
+			}
+			if ((length > 0)
+			    && al->length
+			    && (al->type == AT_DATA)
+			    && !al->name_length
+			    && ((leVCN)al->lowest_vcn == levcn)
+			    && (MREF_LE(al->mft_reference) >= SELFLOC_LIMIT)) {
+				selfloc->mft_ref1
+					= le64_to_cpu(al->mft_reference);
+				selfloc->attrlist_to_ref1 = al;
+				ok = TRUE;
+			}
+		}
+	}
+	return (ok);
+}
+
+/*
+ *		Third condition for having a self-located MFT :
+ *		The location of the second part of the MFT is defined in itself
+ *
+ *	To locate the second part, we have to assume the first and the
+ *	second part of the MFT data are contiguous.
+ *
+ *	Only low-level library functions can be used.
+ *
+ *	Returns TRUE if the condition is met.
+ */
+
+static BOOL self_mapped_selfloc_condition(struct MFT_SELF_LOCATED *selfloc)
+{
+	BOOL ok;
+	s64 inum;
+	u64 offs;
+	VCN lowest_vcn;
+	MFT_RECORD *mft1;
+	ATTR_RECORD *a;
+	ntfs_volume *vol;
+	runlist_element *rl;
+
+	ok = FALSE;
+	vol = selfloc->vol;
+	mft1 = selfloc->mft1;
+	inum = MREF(selfloc->mft_ref1);
+	offs = 	(vol->mft_lcn << vol->cluster_size_bits)
+			+ (inum << vol->mft_record_size_bits);
+	if ((ntfs_pread(vol->dev, offs, vol->mft_record_size,
+			mft1) == vol->mft_record_size)
+	    && !ntfs_mst_post_read_fixup((NTFS_RECORD*)mft1,
+			vol->mft_record_size)) {
+		lowest_vcn = (SELFLOC_LIMIT*vol->mft_record_size)
+				>> vol->cluster_size_bits;
+		a = find_unnamed_attr(mft1,AT_DATA);
+		if (a
+		    && (mft1->flags & MFT_RECORD_IN_USE)
+		    && ((VCN)le64_to_cpu(a->lowest_vcn) == lowest_vcn)
+		    && (le64_to_cpu(mft1->base_mft_record)
+				== selfloc->mft_ref0)
+		    && ((u16)MSEQNO(selfloc->mft_ref1)
+				== le16_to_cpu(mft1->sequence_number))) {
+			rl = ntfs_mapping_pairs_decompress(vol, a, NULL);
+			if ((rl[0].lcn == LCN_RL_NOT_MAPPED)
+			   && !rl[0].vcn
+			   && (rl[0].length == lowest_vcn)
+			   && (rl[1].vcn == lowest_vcn)
+			   && ((u64)(rl[1].lcn << vol->cluster_size_bits)
+					<= offs)
+			   && ((u64)((rl[1].lcn + rl[1].length)
+					<< vol->cluster_size_bits) > offs)) {
+				ok = TRUE;
+			}
+		}
+	}
+	return (ok);
+}
+
+/*
+ *		Fourth condition, to be able to fix a self-located MFT :
+ *		The MFT record 15 must be available.
+ *
+ *	The MFT record 15 is expected to be marked in use, we assume
+ *	it is available if it has no parent, no name and no attr list.
+ *
+ *	Only low-level library functions can be used.
+ *
+ *	Returns TRUE if the condition is met.
+ */
+
+static BOOL spare_record_selfloc_condition(struct MFT_SELF_LOCATED *selfloc)
+{
+	BOOL ok;
+	s64 inum;
+	u64 offs;
+	MFT_RECORD *mft2;
+	ntfs_volume *vol;
+
+	ok = FALSE;
+	vol = selfloc->vol;
+	mft2 = selfloc->mft2;
+	inum = SELFLOC_LIMIT - 1;
+	offs = 	(vol->mft_lcn << vol->cluster_size_bits)
+			+ (inum << vol->mft_record_size_bits);
+	if ((ntfs_pread(vol->dev, offs, vol->mft_record_size,
+			mft2) == vol->mft_record_size)
+	    && !ntfs_mst_post_read_fixup((NTFS_RECORD*)mft2,
+			vol->mft_record_size)) {
+		if (!mft2->base_mft_record
+		    && (mft2->flags & MFT_RECORD_IN_USE)
+		    && !find_unnamed_attr(mft2,AT_ATTRIBUTE_LIST)
+		    && !find_unnamed_attr(mft2,AT_FILE_NAME)) {
+			ok = TRUE;
+		}
+	}
+	return (ok);
+}
+
+/*
+ *		Fix a self-located MFT by swapping two MFT records
+ *
+ *	Only low-level library functions can be used.
+ *
+ *	Returns 0 if the MFT corruption could be fixed.
+ */
+static int fix_selfloc_conditions(struct MFT_SELF_LOCATED *selfloc)
+{
+	MFT_RECORD *mft1;
+	MFT_RECORD *mft2;
+	ATTR_RECORD *a;
+	ATTR_LIST_ENTRY *al;
+	ntfs_volume *vol;
+	s64 offs;
+	s64 offsm;
+	s64 offs1;
+	s64 offs2;
+	s64 inum;
+	u16 usa_ofs;
+	int res;
+
+	res = 0;
+			/*
+			 * In MFT1, we must fix :
+			 * - the self-reference, if present,
+			 * - its own sequence number, must be 15
+			 * - the sizes of the data attribute.
+			 */
+	vol = selfloc->vol;
+	mft1 = selfloc->mft1;
+	mft2 = selfloc->mft2;
+	usa_ofs = le16_to_cpu(mft1->usa_ofs);
+	if (usa_ofs >= 48)
+		mft1->mft_record_number = const_cpu_to_le32(SELFLOC_LIMIT - 1);
+	mft1->sequence_number = const_cpu_to_le16(SELFLOC_LIMIT - 1);
+	a = find_unnamed_attr(mft1,AT_DATA);
+	if (a) {
+		a->allocated_size = const_cpu_to_le64(0);
+		a->data_size = const_cpu_to_le64(0);
+		a->initialized_size = const_cpu_to_le64(0);
+	} else
+		res = -1; /* bug : it has been found earlier */
+
+			/*
+			 * In MFT2, we must fix :
+			 * - the self-reference, if present
+			 */
+	usa_ofs = le16_to_cpu(mft2->usa_ofs);
+	if (usa_ofs >= 48)
+		mft2->mft_record_number = cpu_to_le32(MREF(selfloc->mft_ref1));
+
+			/*
+			 * In the attribute list, we must fix :
+			 * - the reference to MFT1
+			 */
+	al = selfloc->attrlist_to_ref1;
+	al->mft_reference = MK_LE_MREF(SELFLOC_LIMIT - 1, SELFLOC_LIMIT - 1);
+
+			/*
+			 * All fixes done, we can write all if allowed
+			 */
+	if (!res && !opt.no_action) {
+		inum = SELFLOC_LIMIT - 1;
+		offs2 = (vol->mft_lcn << vol->cluster_size_bits)
+			+ (inum << vol->mft_record_size_bits);
+		inum = MREF(selfloc->mft_ref1);
+		offs1 = (vol->mft_lcn << vol->cluster_size_bits)
+			+ (inum << vol->mft_record_size_bits);
+
+			/* rewrite the attribute list */
+		if (selfloc->attrlist_resident) {
+				/* write mft0 and mftmirr if it is resident */
+			offs = vol->mft_lcn << vol->cluster_size_bits;
+			offsm = vol->mftmirr_lcn << vol->cluster_size_bits;
+			if (ntfs_mst_pre_write_fixup(
+					(NTFS_RECORD*)selfloc->mft0,
+					vol->mft_record_size)
+			    || (ntfs_pwrite(vol->dev, offs, vol->mft_record_size,
+					selfloc->mft0) != vol->mft_record_size)
+			    || (ntfs_pwrite(vol->dev, offsm, vol->mft_record_size,
+					selfloc->mft0) != vol->mft_record_size))
+				res = -1;
+		} else {
+				/* write a full cluster if non resident */
+			offs = selfloc->attrlist_lcn << vol->cluster_size_bits;
+			if (ntfs_pwrite(vol->dev, offs, vol->cluster_size,
+					selfloc->attrlist) != vol->cluster_size)
+				res = -1;
+		}
+			/* replace MFT2 by MFT1 and replace MFT1 by MFT2 */
+		if (!res 
+		    && (ntfs_mst_pre_write_fixup((NTFS_RECORD*)selfloc->mft1,
+					vol->mft_record_size)
+			|| ntfs_mst_pre_write_fixup((NTFS_RECORD*)selfloc->mft2,
+					vol->mft_record_size)
+			|| (ntfs_pwrite(vol->dev, offs2, vol->mft_record_size,
+					mft1) != vol->mft_record_size)
+			|| (ntfs_pwrite(vol->dev, offs1, vol->mft_record_size,
+					mft2) != vol->mft_record_size)))
+				res = -1;
+	}
+	return (res);
+}
+
+/*
+ *		Detect and fix a Windows XP bug, leading to a corrupt MFT
+ *
+ *	Windows cannot boot anymore, so chkdsk cannot be started, which
+ *	is a good point, because chkdsk would have deleted all the files.
+ *	Older ntfs-3g fell into an endless recursion (recent versions
+ *	refuse to mount).
+ *
+ *	This situation is very rare, but it was fun to fix it.
+ *
+ *	The corrupted condition is :
+ *		- MFT entry 0 has only the runlist for MFT entries 0-15
+ *		- The attribute list for MFT shows the second part
+ *			in an MFT record beyond 15
+ *	Of course, this record has to be read in order to know where it is.
+ *
+ *	Sample case, met in 2011 (Windows XP) :
+ *		MFT record 0 has : stdinfo, nonres attrlist, the first
+ *				part of MFT data (entries 0-15), and bitmap
+ *		MFT record 16 has the name
+ *		MFT record 17 has the third part of MFT data (16-117731)
+ *		MFT record 18 has the second part of MFT data (117732-170908)
+ *
+ *	Assuming the second part of the MFT is contiguous to the first
+ *	part, we can find it, and fix the condition by relocating it
+ *	and swapping it with MFT record 15.
+ *	This record number 15 appears to be hardcoded into Windows NTFS.
+ *
+ *	Only low-level library functions can be used.
+ *
+ *	Returns 0 if the conditions for the error were not met or
+ *			the error could be fixed,
+ *		-1 if some error was encountered
+ */
+
+static int fix_self_located_mft(ntfs_volume *vol)
+{
+	struct MFT_SELF_LOCATED selfloc;
+	BOOL res;
+
+	ntfs_log_info("Checking for self-located MFT segment... ");
+	res = -1;
+	selfloc.vol = vol;
+	selfloc.mft0 = (MFT_RECORD*)malloc(vol->mft_record_size);
+	selfloc.mft1 = (MFT_RECORD*)malloc(vol->mft_record_size);
+	selfloc.mft2 = (MFT_RECORD*)malloc(vol->mft_record_size);
+	selfloc.attrlist = (ATTR_LIST_ENTRY*)malloc(vol->cluster_size);
+	if (selfloc.mft0 && selfloc.mft1 && selfloc.mft2
+	    && selfloc.attrlist) {
+		if (short_mft_selfloc_condition(&selfloc)
+		    && attrlist_selfloc_condition(&selfloc)
+		    && self_mapped_selfloc_condition(&selfloc)
+		    && spare_record_selfloc_condition(&selfloc)) {
+			ntfs_log_info(FOUND);
+			ntfs_log_info("Fixing the self-located MFT segment... ");
+			res = fix_selfloc_conditions(&selfloc);
+			ntfs_log_info(res ? FAILED : OK);
+		} else {
+			ntfs_log_info(OK);
+			res = 0;
+		}
+		free(selfloc.mft0);
+		free(selfloc.mft1);
+		free(selfloc.mft2);
+		free(selfloc.attrlist);
+	}
+	return (res);
+}
+
+/*
+ *		Try an alternate boot sector and fix the real one
+ *
+ *	Only after successful checks is the boot sector rewritten.
+ *
+ *	The alternate boot sector is not rewritten, either because it
+ *	was found correct, or because we truncated the file system
+ *	and the last actual sector might be part of some file.
+ *
+ *	Returns 0 if successful
+ */
+
+static int try_fix_boot(ntfs_volume *vol, char *full_bs,
+			s64 read_sector, s64 fix_sectors, s32 sector_size)
+{
+	s64 br;
+	int res;
+	s64 got_sectors;
+	le16 sector_size_le;
+	NTFS_BOOT_SECTOR *bs;
+
+	res = -1;
+	br = ntfs_pread(vol->dev, read_sector*sector_size,
+					sector_size, full_bs);
+	if (br != sector_size) {
+		if (br != -1)
+			errno = EINVAL;
+		if (!br)
+			ntfs_log_error("Failed to read alternate bootsector (size=0)\n");
+		else
+			ntfs_log_perror("Error reading alternate bootsector");
+	} else {
+		bs = (NTFS_BOOT_SECTOR*)full_bs;
+		got_sectors = le64_to_cpu(bs->number_of_sectors);
+		bs->number_of_sectors = cpu_to_le64(fix_sectors);
+		/* alignment problem on Sparc, even doing memcpy() */
+		sector_size_le = cpu_to_le16(sector_size);
+		if (!memcmp(&sector_size_le, &bs->bpb.bytes_per_sector,2)
+		    && ntfs_boot_sector_is_ntfs(bs)
+		    && !ntfs_boot_sector_parse(vol, bs)) {
+			ntfs_log_info("The alternate bootsector is usable\n");
+			if (fix_sectors != got_sectors)
+				ntfs_log_info("Set sector count to %lld instead of %lld\n",
+						(long long)fix_sectors,
+						(long long)got_sectors);
+			/* fix the normal boot sector */
+			if (!opt.no_action) {
+				res = rewrite_boot(vol->dev, full_bs,
+							sector_size);
+			} else
+				res = 0;
+		}
+		if (!res && !opt.no_action)
+			ntfs_log_info("The boot sector has been rewritten\n");
+	}
+	return (res);
+}
+
+/*
+ *		Try the alternate boot sector if the normal one is bad
+ *
+ *	Actually :
+ *	- first try the last sector of the partition (expected location)
+ *	- then try the last sector as shown in the main boot sector,
+ *		(could be meaningful for an undersized partition)
+ *	- finally try truncating the file system actual size of partition
+ *		(could be meaningful for an oversized partition)
+ *
+ *	if successful, rewrite the normal boot sector accordingly
+ *
+ *	Returns 0 if successful
+ */
+
+static int try_alternate_boot(ntfs_volume *vol, char *full_bs,
+			s32 sector_size, s64 shown_sectors)
+{
+	s64 actual_sectors;
+	int res;
+
+	res = -1;
+	ntfs_log_info("Trying the alternate boot sector\n");
+
+		/*
+		 * We do not rely on the sector size defined in the
+		 * boot sector, supposed to be corrupt, so we try to get
+		 * the actual sector size and defaulting to 512 if failed
+		 * to get. This value is only used to guess the alternate
+		 * boot sector location and it is checked against the
+		 * value found in the sector itself. It should not damage
+		 * anything if wrong.
+		 *
+		 * Note : the real last sector is not accounted for here.
+		 */
+	actual_sectors = ntfs_device_size_get(vol->dev,sector_size) - 1;
+
+		/* first try the actual last sector */
+	if ((actual_sectors > 0)
+	    && !try_fix_boot(vol, full_bs, actual_sectors,
+				actual_sectors, sector_size))
+		res = 0;
+
+		/* then try the shown last sector, if less than actual */
+	if (res
+	    && (shown_sectors > 0)
+	    && (shown_sectors < actual_sectors)
+	    && !try_fix_boot(vol, full_bs, shown_sectors,
+				shown_sectors, sector_size))
+		res = 0;
+
+		/* then try reducing the number of sectors to actual value */
+	if (res
+	    && (shown_sectors > actual_sectors)
+	    && !try_fix_boot(vol, full_bs, 0, actual_sectors, sector_size))
+		res = 0;
+
+	return (res);
+}
+
+/*
+ *		Check and fix the alternate boot sector
+ *
+ *	The alternate boot sector is usually in the last sector of a
+ *	partition, which should not be used by the file system
+ *	(the sector count in the boot sector should be less than
+ *	the total sector count in the partition).
+ *
+ *	chkdsk never changes the count in the boot sector.
+ *	- If this is less than the total count, chkdsk place the
+ *	  alternate boot sector into the sector,
+ *	- if the count is the same as the total count, chkdsk place
+ *	  the alternate boot sector into the middle sector (half
+ *	  the total count rounded upwards)
+ *	- if the count is greater than the total count, chkdsk
+ *	  declares the file system as raw, and refuses to fix anything.
+ *
+ *	Here, we check and fix the alternate boot sector, only in the
+ *	first situation where the file system does not overflow on the
+ *	last sector.
+ *
+ *	Note : when shrinking a partition, ntfsresize cannot determine
+ *	the future size of the partition. As a consequence the number of
+ *	sectors in the boot sectors may be less than the possible size.
+ *
+ *	Returns 0 if successful
+ */
+
+static int check_alternate_boot(ntfs_volume *vol)
+{
+	s64 got_sectors;
+	s64 actual_sectors;
+	s64 last_sector_off;
+	char *full_bs;
+	char *alt_bs;
+	NTFS_BOOT_SECTOR *bs;
+	s64 br;
+	s64 bw;
+	int res;
+
+	res = -1;
+	full_bs = (char*)malloc(vol->sector_size);
+	alt_bs = (char*)malloc(vol->sector_size);
+	if (!full_bs || !alt_bs) {
+		ntfs_log_info("Error : failed to allocate memory\n");
+		goto error_exit;
+	}
+	/* Now read both bootsectors. */
+	br = ntfs_pread(vol->dev, 0, vol->sector_size, full_bs);
+	if (br == vol->sector_size) {
+		bs = (NTFS_BOOT_SECTOR*)full_bs;
+		got_sectors = le64_to_cpu(bs->number_of_sectors);
+		actual_sectors = ntfs_device_size_get(vol->dev,
+						vol->sector_size);
+		if (actual_sectors > got_sectors) {
+			last_sector_off = (actual_sectors - 1)
+						<< vol->sector_size_bits;
+			ntfs_log_info("Checking the alternate boot sector... ");
+			br = ntfs_pread(vol->dev, last_sector_off,
+						vol->sector_size, alt_bs);
+		} else {
+			ntfs_log_info("Checking file system overflow... ");
+			br = -1;
+		}
+		/* accept getting no byte, needed for short image files */
+		if (br >= 0) {
+			if ((br != vol->sector_size)
+			    || memcmp(full_bs, alt_bs, vol->sector_size)) {
+				if (opt.no_action) {
+					ntfs_log_info("BAD\n");
+				} else {
+					bw = ntfs_pwrite(vol->dev,
+						last_sector_off,
+						vol->sector_size, full_bs);
+					if (bw == vol->sector_size) {
+						ntfs_log_info("FIXED\n");
+						res = 0;
+					} else {
+						ntfs_log_info(FAILED);
+					}
+				}
+			} else {
+				ntfs_log_info(OK);
+				res = 0;
+			}
+		} else {
+			ntfs_log_info(FAILED);
+		}
+	} else {
+		ntfs_log_info("Error : could not read the boot sector again\n");
+	}
+	free(full_bs);
+	free(alt_bs);
+
+error_exit :
+	return (res);
+}
+
+/*
+ *		Try to fix problems which may arise in the start up sequence
+ *
+ *	This is a replay of the normal start up sequence with fixes when
+ *	some problem arise.
+ */
+
+static int fix_startup(struct ntfs_device *dev, unsigned long flags)
+{
+	s64 br;
+	ntfs_volume *vol;
+	BOOL dev_open;
+	s64 shown_sectors;
+	char *full_bs;
+	NTFS_BOOT_SECTOR *bs;
+	s32 sector_size;
+	int res;
+	int eo;
+
+	errno = 0;
+	res = -1;
+	dev_open = FALSE;
+	full_bs = (char*)NULL;
+	if (!dev || !dev->d_ops || !dev->d_name) {
+		errno = EINVAL;
+		ntfs_log_perror("%s: dev = %p", __FUNCTION__, dev);
+		vol = (ntfs_volume*)NULL;
+		goto error_exit;
+	}
+
+	/* Allocate the volume structure. */
+	vol = ntfs_volume_alloc();
+	if (!vol)
+		goto error_exit;
+	
+	/* Create the default upcase table. */
+	vol->upcase_len = ntfs_upcase_build_default(&vol->upcase);
+	if (!vol->upcase_len || !vol->upcase)
+		goto error_exit;
+
+	/* Default with no locase table and case sensitive file names */
+	vol->locase = (ntfschar*)NULL;
+	NVolSetCaseSensitive(vol);
+	
+		/* by default, all files are shown and not marked hidden */
+	NVolSetShowSysFiles(vol);
+	NVolSetShowHidFiles(vol);
+	NVolClearHideDotFiles(vol);
+	if (flags & NTFS_MNT_RDONLY)
+		NVolSetReadOnly(vol);
+	
+	/* ...->open needs bracketing to compile with glibc 2.7 */
+	if ((dev->d_ops->open)(dev, NVolReadOnly(vol) ? O_RDONLY: O_RDWR)) {
+		ntfs_log_perror("Error opening '%s'", dev->d_name);
+		goto error_exit;
+	}
+	dev_open = TRUE;
+	/* Attach the device to the volume. */
+	vol->dev = dev;
+	
+	sector_size = ntfs_device_sector_size_get(dev);
+	if (sector_size <= 0)
+		sector_size = DEFAULT_SECTOR_SIZE;
+	full_bs = (char*)malloc(sector_size);
+	if (!full_bs)
+		goto error_exit;
+	/* Now read the bootsector. */
+	br = ntfs_pread(dev, 0, sector_size, full_bs);
+	if (br != sector_size) {
+		if (br != -1)
+			errno = EINVAL;
+		if (!br)
+			ntfs_log_error("Failed to read bootsector (size=0)\n");
+		else
+			ntfs_log_perror("Error reading bootsector");
+		goto error_exit;
+	}
+	bs = (NTFS_BOOT_SECTOR*)full_bs;
+	if (!ntfs_boot_sector_is_ntfs(bs)
+		/* get the bootsector data, only fails when inconsistent */
+	    || (ntfs_boot_sector_parse(vol, bs) < 0)) {
+		shown_sectors = le64_to_cpu(bs->number_of_sectors);
+		/* boot sector is wrong, try the alternate boot sector */
+		if (try_alternate_boot(vol, full_bs, sector_size,
+						shown_sectors)) {
+			errno = EINVAL;
+			goto error_exit;
+		}
+		res = 0;
+	} else {
+		res = fix_self_located_mft(vol);
+	}
+error_exit:
+	if (res) {
+		switch (errno) {
+		case ENOMEM :
+			ntfs_log_error("Failed to allocate memory\n");
+			break;
+		case EINVAL :
+			ntfs_log_error("Unrecoverable error\n");
+			break;
+		default :
+			break;
+		}
+	}
+	eo = errno;
+	free(full_bs);
+	if (vol) {
+		free(vol->upcase);
+		free(vol);
+	}
+	if (dev_open) {
+		(dev->d_ops->close)(dev);
+	}
+	errno = eo;
+	return (res);
+}
+
+/**
+ * fix_mount
+ */
+static int fix_mount(void)
+{
+	int ret = 0; /* default success */
+	ntfs_volume *vol;
+	struct ntfs_device *dev;
+	unsigned long flags;
+
+	ntfs_log_info("Attempting to correct errors... ");
+
+	dev = ntfs_device_alloc(opt.volume, 0, &ntfs_device_default_io_ops,
+			NULL);
+	if (!dev) {
+		ntfs_log_info(FAILED);
+		ntfs_log_perror("Failed to allocate device");
+		return -1;
+	}
+	flags = (opt.no_action ? NTFS_MNT_RDONLY : 0);
+	vol = ntfs_volume_startup(dev, flags);
+	if (!vol) {
+		ntfs_log_info(FAILED);
+		ntfs_log_perror("Failed to startup volume");
+
+		/* Try fixing the bootsector and MFT, then redo the startup */
+		if (!fix_startup(dev, flags)) {
+			if (opt.no_action)
+				ntfs_log_info("The startup data can be fixed, "
+						"but no change was requested\n");
+			else
+				vol = ntfs_volume_startup(dev, flags);
+		}
+		if (!vol) {
+			ntfs_log_error("Volume is corrupt. You should run chkdsk.\n");
+			ntfs_device_free(dev);
+			return -1;
+		}
+		if (opt.no_action)
+			ret = -1; /* error present and not fixed */
+	}
+		/* if option -n proceed despite errors, to display them all */
+	if ((!ret || opt.no_action) && (fix_mftmirr(vol) < 0))
+		ret = -1;
+	if ((!ret || opt.no_action) && (fix_upcase(vol) < 0))
+		ret = -1;
+	if ((!ret || opt.no_action) && (set_dirty_flag(vol) < 0))
+		ret = -1;
+	if ((!ret || opt.no_action) && (empty_journal(vol) < 0))
+		ret = -1;
+	/*
+	 * ntfs_umount() will invoke ntfs_device_free() for us.
+	 * Ignore the returned error resulting from partial mounting.
+	 */
+	ntfs_umount(vol, 1);
+	return ret;
+}
+
+/**
+ * main
+ */
+int main(int argc, char **argv)
+{
+	ntfs_volume *vol;
+	unsigned long mnt_flags;
+	unsigned long flags;
+	int ret = 1; /* failure */
+	BOOL force = FALSE;
+
+	ntfs_log_set_handler(ntfs_log_handler_outerr);
+
+	parse_options(argc, argv);
+
+	if (!ntfs_check_if_mounted(opt.volume, &mnt_flags)) {
+		if ((mnt_flags & NTFS_MF_MOUNTED) &&
+				!(mnt_flags & NTFS_MF_READONLY) && !force) {
+			ntfs_log_error("Refusing to operate on read-write "
+					"mounted device %s.\n", opt.volume);
+			exit(1);
+		}
+	} else
+		ntfs_log_perror("Failed to determine whether %s is mounted",
+				opt.volume);
+	/* Attempt a full mount first. */
+	flags = (opt.no_action ? NTFS_MNT_RDONLY : 0);
+	ntfs_log_info("Mounting volume... ");
+	vol = ntfs_mount(opt.volume, flags);
+	if (vol) {
+		ntfs_log_info(OK);
+		ntfs_log_info("Processing of $MFT and $MFTMirr completed "
+				"successfully.\n");
+	} else {
+		ntfs_log_info(FAILED);
+		if (fix_mount() < 0) {
+			if (opt.no_action)
+				ntfs_log_info("No change made\n");
+			exit(1);
+		}
+		vol = ntfs_mount(opt.volume, 0);
+		if (!vol) {
+			ntfs_log_perror("Remount failed");
+			exit(1);
+		}
+	}
+	if (check_alternate_boot(vol)) {
+		ntfs_log_error("Error: Failed to fix the alternate boot sector\n");
+		exit(1);
+	}
+	/* So the unmount does not clear it again. */
+
+	/* Porting note: The WasDirty flag was set here to prevent ntfs_unmount
+	 * from clearing the dirty bit (which might have been set in
+	 * fix_mount()). So the intention is to leave the dirty bit set.
+	 *
+	 * libntfs-3g does not automatically set or clear dirty flags on
+	 * mount/unmount, this means that the assumption that the dirty flag is
+	 * now set does not hold. So we need to set it if not already set.
+	 *
+	 * However clear the flag if requested to do so, at this stage
+	 * mounting was successful.
+	 */
+	if (opt.clear_dirty)
+		vol->flags &= ~VOLUME_IS_DIRTY;
+	else
+		vol->flags |= VOLUME_IS_DIRTY;
+	if (!opt.no_action && ntfs_volume_write_flags(vol, vol->flags)) {
+		ntfs_log_error("Error: Failed to set volume dirty flag (%d "
+			"(%s))!\n", errno, strerror(errno));
+	}
+
+	/* Check NTFS version is ok for us (in $Volume) */
+	ntfs_log_info("NTFS volume version is %i.%i.\n", vol->major_ver,
+			vol->minor_ver);
+	if (ntfs_version_is_supported(vol)) {
+		ntfs_log_error("Error: Unknown NTFS version.\n");
+		goto error_exit;
+	}
+	if (opt.clear_bad_sectors && !opt.no_action) {
+		if (clear_badclus(vol)) {
+			ntfs_log_error("Error: Failed to un-mark bad sectors.\n");
+			goto error_exit;
+		}
+	}
+	if (vol->major_ver >= 3) {
+		/*
+		 * FIXME: If on NTFS 3.0+, check for presence of the usn
+		 * journal and stamp it if present.
+		 */
+	}
+	/* FIXME: We should be marking the quota out of date, too. */
+	/* That's all for now! */
+	ntfs_log_info("NTFS partition %s was processed successfully.\n",
+			vol->dev->d_name);
+	/* Set return code to 0. */
+	ret = 0;
+error_exit:
+	if (ntfs_umount(vol, 0))
+		ntfs_umount(vol, 1);
+	if (ret)
+		exit(ret);
+	return ret;
+}
+
diff --git a/ntfsprogs/ntfsinfo.8 b/ntfsprogs/ntfsinfo.8
new file mode 100755
index 0000000000000000000000000000000000000000..70550c95326835e266f7bfea09ccf0c0c48980d9
--- /dev/null
+++ b/ntfsprogs/ntfsinfo.8
@@ -0,0 +1,89 @@
+.\" Copyright (c) 2002\-2004 Anton Altaparmakov.
+.\" Copyright (c) 2005 Richard Russon.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSINFO 8 "April 2006" "ntfs-3g 2015.3.14"
+.SH NAME
+ntfsinfo \- dump a file's attributes
+.SH SYNOPSIS
+.B ntfsinfo
+[\fIoptions\fR] \fIdevice\fR
+.SH DESCRIPTION
+.B ntfsinfo
+will dump the attributes of inode
+.I inode\-number
+or the file
+.I path\-filename
+and/or information about the mft (
+.I \-m
+option).
+Run ntfsinfo without arguments for a full list of options.
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfsinfo
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-F\fR, \fB\-\-file\fR FILE
+Show information about this file
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+This will override some sensible defaults, such as not overwriting an existing
+file.  Use this option with caution.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.TP
+\fB\-i\fR, \fB\-\-inode\fR NUM
+Show information about this inode.
+.TP
+\fB\-m\fR, \fB\-\-mft\fR
+Show information about the volume.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Produce less output.
+.TP
+\fB\-t\fR, \fB\-\-notime\fR
+Do not display timestamps in the output.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Increase the amount of output that
+.B ntfsinfo
+prints.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Show the version number, copyright and license.
+.SH BUGS
+There are no known problems with
+.BR ntfsinfo .
+If you find a bug please send an email describing the problem to the
+development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+.B ntfsinfo
+was written by Matthew J. Fanto, Anton Altaparmakov, Richard Russon, Szabolcs
+Szakacsits, Yuval Fledel, Yura Pakhuchiy and Cristian Klein.
+It was ported to ntfs-3g by Erik Larsson and Jean-Pierre Andre.
+.SH AVAILABILITY
+.B ntfsinfo
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/ntfsinfo.8.in b/ntfsprogs/ntfsinfo.8.in
new file mode 100755
index 0000000000000000000000000000000000000000..e0141c79bde974487cd36ad018ce1654343b768d
--- /dev/null
+++ b/ntfsprogs/ntfsinfo.8.in
@@ -0,0 +1,89 @@
+.\" Copyright (c) 2002\-2004 Anton Altaparmakov.
+.\" Copyright (c) 2005 Richard Russon.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSINFO 8 "April 2006" "ntfs-3g @VERSION@"
+.SH NAME
+ntfsinfo \- dump a file's attributes
+.SH SYNOPSIS
+.B ntfsinfo
+[\fIoptions\fR] \fIdevice\fR
+.SH DESCRIPTION
+.B ntfsinfo
+will dump the attributes of inode
+.I inode\-number
+or the file
+.I path\-filename
+and/or information about the mft (
+.I \-m
+option).
+Run ntfsinfo without arguments for a full list of options.
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfsinfo
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-F\fR, \fB\-\-file\fR FILE
+Show information about this file
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+This will override some sensible defaults, such as not overwriting an existing
+file.  Use this option with caution.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.TP
+\fB\-i\fR, \fB\-\-inode\fR NUM
+Show information about this inode.
+.TP
+\fB\-m\fR, \fB\-\-mft\fR
+Show information about the volume.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Produce less output.
+.TP
+\fB\-t\fR, \fB\-\-notime\fR
+Do not display timestamps in the output.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Increase the amount of output that
+.B ntfsinfo
+prints.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Show the version number, copyright and license.
+.SH BUGS
+There are no known problems with
+.BR ntfsinfo .
+If you find a bug please send an email describing the problem to the
+development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+.B ntfsinfo
+was written by Matthew J. Fanto, Anton Altaparmakov, Richard Russon, Szabolcs
+Szakacsits, Yuval Fledel, Yura Pakhuchiy and Cristian Klein.
+It was ported to ntfs-3g by Erik Larsson and Jean-Pierre Andre.
+.SH AVAILABILITY
+.B ntfsinfo
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/ntfsinfo.c b/ntfsprogs/ntfsinfo.c
new file mode 100755
index 0000000000000000000000000000000000000000..817eadc45de715450796a8f74e261a3114fe64a5
--- /dev/null
+++ b/ntfsprogs/ntfsinfo.c
@@ -0,0 +1,2408 @@
+/**
+ * ntfsinfo - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2002-2004 Matthew J. Fanto
+ * Copyright (c) 2002-2006 Anton Altaparmakov
+ * Copyright (c) 2002-2005 Richard Russon
+ * Copyright (c) 2003-2006 Szabolcs Szakacsits
+ * Copyright (c) 2004-2005 Yuval Fledel
+ * Copyright (c) 2004-2007 Yura Pakhuchiy
+ * Copyright (c)      2005 Cristian Klein
+ * Copyright (c) 2011-2014 Jean-Pierre Andre
+ *
+ * This utility will dump a file's attributes.
+ *
+ * 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 Linux-NTFS
+ * distribution in the file COPYING); if not, write to the Free Software
+ * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+/*
+ * TODO LIST:
+ *	- Better error checking. (focus on ntfs_dump_volume)
+ *	- Comment things better.
+ *	- More things at verbose mode.
+ *	- Dump ACLs when security_id exists (NTFS 3+ only).
+ *	- Clean ups.
+ *	- Internationalization.
+ *	- Add more Indexed Attr Types.
+ *	- Make formatting look more like www.flatcap.org/ntfs/info
+ *
+ *	Still not dumping certain attributes. Need to find the best
+ *	way to output some of these attributes.
+ *
+ *	Still need to do:
+ *	    $REPARSE_POINT/$SYMBOLIC_LINK
+ *	    $LOGGED_UTILITY_STREAM
+ */
+
+#include "config.h"
+
+#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_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "types.h"
+#include "mft.h"
+#include "attrib.h"
+#include "layout.h"
+#include "inode.h"
+#include "index.h"
+#include "utils.h"
+#include "security.h"
+#include "mst.h"
+#include "dir.h"
+#include "ntfstime.h"
+/* #include "version.h" */
+#include "support.h"
+#include "misc.h"
+
+static const char *EXEC_NAME = "ntfsinfo";
+
+static struct options {
+	const char *device;	/* Device/File to work with */
+	const char *filename;	/* Resolve this filename to mft number */
+	s64	 inode;		/* Info for this inode */
+	int	 quiet;		/* Less output */
+	int	 verbose;	/* Extra output */
+	int	 force;		/* Override common sense */
+	int	 notime;	/* Don't report timestamps at all */
+	int	 mft;		/* Dump information about the volume as well */
+} opts;
+
+struct RUNCOUNT {
+	unsigned long runs;
+	unsigned long fragments;
+} ;
+
+/**
+ * version - Print version information about the program
+ *
+ * Print a copyright statement and a brief description of the program.
+ *
+ * Return:  none
+ */
+static void version(void)
+{
+	printf("\n%s v%s (libntfs-3g) - Display information about an NTFS "
+			"Volume.\n\n", EXEC_NAME, VERSION);
+	printf("Copyright (c)\n");
+	printf("    2002-2004 Matthew J. Fanto\n");
+	printf("    2002-2006 Anton Altaparmakov\n");
+	printf("    2002-2005 Richard Russon\n");
+	printf("    2003-2006 Szabolcs Szakacsits\n");
+	printf("    2003      Leonard Norrgård\n");
+	printf("    2004-2005 Yuval Fledel\n");
+	printf("    2004-2007 Yura Pakhuchiy\n");
+	printf("    2011-2014 Jean-Pierre Andre\n");
+	printf("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
+}
+
+/**
+ * usage - Print a list of the parameters to the program
+ *
+ * Print a list of the parameters and options for the program.
+ *
+ * Return:  none
+ */
+static void usage(void)
+{
+	printf("\nUsage: %s [options] device\n"
+		"    -i, --inode NUM  Display information about this inode\n"
+		"    -F, --file FILE  Display information about this file (absolute path)\n"
+		"    -m, --mft        Dump information about the volume\n"
+		"    -t, --notime     Don't report timestamps\n"
+		"\n"
+		"    -f, --force      Use less caution\n"
+		"    -q, --quiet      Less output\n"
+		"    -v, --verbose    More output\n"
+		"    -V, --version    Display version information\n"
+		"    -h, --help       Display this help\n"
+	        "\n",
+		EXEC_NAME);
+	printf("%s%s\n", ntfs_bugs, ntfs_home);
+}
+
+/**
+ * parse_options - Read and validate the programs command line
+ *
+ * Read the command line, verify the syntax and parse the options.
+ * This function is very long, but quite simple.
+ *
+ * Return:  1 Success
+ *	    0 Error, one or more problems
+ */
+static int parse_options(int argc, char *argv[])
+{
+	static const char *sopt = "-:dfhi:F:mqtTvV";
+	static const struct option lopt[] = {
+		{ "force",	 no_argument,		NULL, 'f' },
+		{ "help",	 no_argument,		NULL, 'h' },
+		{ "inode",	 required_argument,	NULL, 'i' },
+		{ "file",	 required_argument,	NULL, 'F' },
+		{ "quiet",	 no_argument,		NULL, 'q' },
+		{ "verbose",	 no_argument,		NULL, 'v' },
+		{ "version",	 no_argument,		NULL, 'V' },
+		{ "notime",	 no_argument,		NULL, 'T' },
+		{ "mft",	 no_argument,		NULL, 'm' },
+		{ NULL,		 0,			NULL,  0  }
+	};
+
+	int c = -1;
+	int err  = 0;
+	int ver  = 0;
+	int help = 0;
+	int levels = 0;
+
+	opterr = 0; /* We'll handle the errors, thank you. */
+
+	opts.inode = -1;
+	opts.filename = NULL;
+
+	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
+		switch (c) {
+		case 1:
+			if (!opts.device)
+				opts.device = optarg;
+			else
+				err++;
+			break;
+		case 'i':
+			if ((opts.inode != -1) ||
+			    (!utils_parse_size(optarg, &opts.inode, FALSE))) {
+				err++;
+			}
+			break;
+		case 'F':
+			if (opts.filename == NULL) {
+				/* The inode can not be resolved here,
+				   store the filename */
+				opts.filename = argv[optind-1];
+			} else {
+				/* "-F" can't appear more than once */
+				err++;
+			}
+			break;
+		case 'f':
+			opts.force++;
+			break;
+		case 'h':
+			help++;
+			break;
+		case 'q':
+			opts.quiet++;
+			ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
+			break;
+		case 't':
+			opts.notime++;
+			break;
+		case 'T':
+			/* 'T' is deprecated, notify */
+			ntfs_log_error("Option 'T' is deprecated, it was "
+				"replaced by 't'.\n");
+			err++;
+			break;
+		case 'v':
+			opts.verbose++;
+			ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
+			break;
+		case 'V':
+			ver++;
+			break;
+		case 'm':
+			opts.mft++;
+			break;
+		case '?':
+			if (optopt=='?') {
+				help++;
+				continue;
+			}
+			if (ntfs_log_parse_option(argv[optind-1]))
+				continue;
+			ntfs_log_error("Unknown option '%s'.\n",
+					argv[optind-1]);
+			err++;
+			break;
+		case ':':
+			ntfs_log_error("Option '%s' requires an "
+					"argument.\n", argv[optind-1]);
+			err++;
+			break;
+		default:
+			ntfs_log_error("Unhandled option case: %d.\n", c);
+			err++;
+			break;
+		}
+	}
+
+	/* Make sure we're in sync with the log levels */
+	levels = ntfs_log_get_levels();
+	if (levels & NTFS_LOG_LEVEL_VERBOSE)
+		opts.verbose++;
+	if (!(levels & NTFS_LOG_LEVEL_QUIET))
+		opts.quiet++;
+
+	if (help || ver) {
+		opts.quiet = 0;
+	} else {
+		if (opts.device == NULL) {
+			if (argc > 1)
+				ntfs_log_error("You must specify exactly one "
+					"device.\n");
+			err++;
+		}
+
+		if (opts.inode == -1 && !opts.filename && !opts.mft) {
+			if (argc > 1)
+				ntfs_log_error("You must specify an inode to "
+					"learn about.\n");
+			err++;
+		}
+
+		if (opts.quiet && opts.verbose) {
+			ntfs_log_error("You may not use --quiet and --verbose "
+				"at the same time.\n");
+			err++;
+		}
+
+		if ((opts.inode != -1) && (opts.filename != NULL)) {
+			if (argc > 1)
+				ntfs_log_error("You may not specify --inode "
+					"and --file together.\n");
+			err++;
+		}
+
+	}
+
+	if (ver)
+		version();
+	if (help || err)
+		usage();
+
+		/* tri-state 0 : done, 1 : error, -1 : proceed */
+	return (err ? 1 : (help || ver ? 0 : -1));
+}
+
+
+/* *************** utility functions ******************** */
+/**
+ * ntfsinfo_time_to_str() -
+ * @sle_ntfs_clock:	on disk time format in 100ns units since 1st jan 1601
+ *			in little-endian format
+ *
+ * Return char* in a format 'Thu Jan  1 00:00:00 1970'.
+ * No need to free the returned memory.
+ *
+ * Example of usage:
+ *	char *time_str = ntfsinfo_time_to_str(
+ *			sle64_to_cpu(standard_attr->creation_time));
+ *	printf("\tFile Creation Time:\t %s", time_str);
+ */
+static char *ntfsinfo_time_to_str(const sle64 sle_ntfs_clock)
+{
+		/* JPA display timestamps in UTC */
+	static const char *months[]
+		= { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+		    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" } ;
+	static const char *wdays[]
+		= { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" } ;
+	static char str[30];
+	long long stamp;
+	u32 days;
+	u32 seconds;
+	unsigned int year;
+	unsigned int wday;
+	int mon;
+	int cnt;
+
+	stamp = sle64_to_cpu(sle_ntfs_clock);
+	days = (stamp/(86400*10000000LL)) & 0x7ffff;
+	seconds = ((stamp/10000000LL)%86400) & 0x1ffff;
+	wday = (days + 1)%7;
+	year = 1601;
+				/* periods of 400 years */
+	cnt = days/146097;
+	days -= 146097*cnt;
+	year += 400*cnt;
+				/* periods of 100 years */
+	cnt = (3*days + 3)/109573;
+	days -= 36524*cnt;
+	year += 100*cnt;
+				/* periods of 4 years */
+	cnt = days/1461;
+	days -= 1461*cnt;
+	year += 4*cnt;
+				/* periods of a single year */
+	cnt = (3*days + 3)/1096;
+	days -= 365*cnt;
+	year += cnt;
+
+	if ((!(year % 100) ? (year % 400) : (year % 4))
+		&& (days > 58)) days++;
+	if (days > 59) {
+		mon = (5*days + 161)/153;
+		days -= (153*mon - 162)/5;
+	} else {
+		mon = days/31 + 1;
+		days -= 31*(mon - 1) - 1;
+	}
+	sprintf(str,"%3s %3s %2u %02u:%02u:%02u %4u UTC\n",
+		wdays[wday],
+		months[mon-1],(unsigned int)days,
+		(unsigned int)(seconds/3600),
+		(unsigned int)(seconds/60%60),
+		(unsigned int)(seconds%60),
+		(unsigned int)year);
+	return (str);
+}
+
+/**
+ * ntfs_attr_get_name()
+ * @attr:	a valid attribute record
+ *
+ * return multi-byte string containing the attribute name if exist. the user
+ *             is then responsible of freeing that memory.
+ *        null if no name exists (attr->name_length==0). no memory allocated.
+ *        null if cannot convert to multi-byte string. errno would contain the
+ *             error id. no memory allocated in that case
+ */
+static char *ntfs_attr_get_name_mbs(ATTR_RECORD *attr)
+{
+	ntfschar *ucs_attr_name;
+	char *mbs_attr_name = NULL;
+	int mbs_attr_name_size;
+
+	/* Get name in unicode. */
+	ucs_attr_name = ntfs_attr_get_name(attr);
+	/* Convert unicode to printable format. */
+	mbs_attr_name_size = ntfs_ucstombs(ucs_attr_name, attr->name_length,
+			&mbs_attr_name, 0);
+	if (mbs_attr_name_size > 0)
+		return mbs_attr_name;
+	else
+		return NULL;
+}
+
+
+/* *************** functions for dumping global info ******************** */
+/**
+ * ntfs_dump_volume - dump information about the volume
+ */
+static void ntfs_dump_volume(ntfs_volume *vol)
+{
+	printf("Volume Information \n");
+	printf("\tName of device: %s\n", vol->dev->d_name);
+	printf("\tDevice state: %lu\n", vol->dev->d_state);
+	printf("\tVolume Name: %s\n", vol->vol_name);
+	printf("\tVolume State: %lu\n", vol->state);
+	printf("\tVolume Flags: 0x%04x", (int)vol->flags);
+	if (vol->flags & VOLUME_IS_DIRTY)
+		printf(" DIRTY");
+	if (vol->flags & VOLUME_MODIFIED_BY_CHKDSK)
+		printf(" MODIFIED_BY_CHKDSK");
+	printf("\n");
+	printf("\tVolume Version: %u.%u\n", vol->major_ver, vol->minor_ver);
+	printf("\tSector Size: %hu\n", vol->sector_size);
+	printf("\tCluster Size: %u\n", (unsigned int)vol->cluster_size);
+	printf("\tIndex Block Size: %u\n", (unsigned int)vol->indx_record_size);
+	printf("\tVolume Size in Clusters: %lld\n",
+			(long long)vol->nr_clusters);
+
+	printf("MFT Information \n");
+	printf("\tMFT Record Size: %u\n", (unsigned int)vol->mft_record_size);
+	printf("\tMFT Zone Multiplier: %u\n", vol->mft_zone_multiplier);
+	printf("\tMFT Data Position: %lld\n", (long long)vol->mft_data_pos);
+	printf("\tMFT Zone Start: %lld\n", (long long)vol->mft_zone_start);
+	printf("\tMFT Zone End: %lld\n", (long long)vol->mft_zone_end);
+	printf("\tMFT Zone Position: %lld\n", (long long)vol->mft_zone_pos);
+	printf("\tCurrent Position in First Data Zone: %lld\n",
+			(long long)vol->data1_zone_pos);
+	printf("\tCurrent Position in Second Data Zone: %lld\n",
+			(long long)vol->data2_zone_pos);
+	printf("\tAllocated clusters %lld (%2.1lf%%)\n",
+			(long long)vol->mft_na->allocated_size
+				>> vol->cluster_size_bits,
+			100.0*(vol->mft_na->allocated_size
+				>> vol->cluster_size_bits)
+				/ vol->nr_clusters);
+	printf("\tLCN of Data Attribute for FILE_MFT: %lld\n",
+			(long long)vol->mft_lcn);
+	printf("\tFILE_MFTMirr Size: %d\n", vol->mftmirr_size);
+	printf("\tLCN of Data Attribute for File_MFTMirr: %lld\n",
+			(long long)vol->mftmirr_lcn);
+	printf("\tSize of Attribute Definition Table: %d\n",
+			(int)vol->attrdef_len);
+	printf("\tNumber of Attached Extent Inodes: %d\n",
+			(int)vol->mft_ni->nr_extents);
+
+	printf("FILE_Bitmap Information \n");
+	printf("\tFILE_Bitmap MFT Record Number: %llu\n",
+			(unsigned long long)vol->lcnbmp_ni->mft_no);
+	printf("\tState of FILE_Bitmap Inode: %lu\n", vol->lcnbmp_ni->state);
+	printf("\tLength of Attribute List: %u\n",
+			(unsigned int)vol->lcnbmp_ni->attr_list_size);
+	/* JPA	printf("\tAttribute List: %s\n", vol->lcnbmp_ni->attr_list); */
+	printf("\tNumber of Attached Extent Inodes: %d\n",
+			(int)vol->lcnbmp_ni->nr_extents);
+	/* FIXME: need to add code for the union if nr_extens != 0, but
+	   i dont know if it will ever != 0 with FILE_Bitmap */
+
+	printf("FILE_Bitmap Data Attribute Information\n");
+	printf("\tDecompressed Runlist: not done yet\n");
+	printf("\tBase Inode: %llu\n",
+			(unsigned long long)vol->lcnbmp_na->ni->mft_no);
+	printf("\tAttribute Types: not done yet\n");
+	//printf("\tAttribute Name: %s\n", vol->lcnbmp_na->name);
+	printf("\tAttribute Name Length: %u\n",
+			(unsigned int)vol->lcnbmp_na->name_len);
+	printf("\tAttribute State: %lu\n", vol->lcnbmp_na->state);
+	printf("\tAttribute Allocated Size: %lld\n",
+			(long long)vol->lcnbmp_na->allocated_size);
+	printf("\tAttribute Data Size: %lld\n",
+			(long long)vol->lcnbmp_na->data_size);
+	printf("\tAttribute Initialized Size: %lld\n",
+			(long long)vol->lcnbmp_na->initialized_size);
+	printf("\tAttribute Compressed Size: %lld\n",
+			(long long)vol->lcnbmp_na->compressed_size);
+	printf("\tCompression Block Size: %u\n",
+			(unsigned int)vol->lcnbmp_na->compression_block_size);
+	printf("\tCompression Block Size Bits: %u\n",
+			vol->lcnbmp_na->compression_block_size_bits);
+	printf("\tCompression Block Clusters: %u\n",
+			vol->lcnbmp_na->compression_block_clusters);
+	if (!ntfs_volume_get_free_space(vol))
+		printf("\tFree Clusters: %lld (%2.1lf%%)\n",
+				(long long)vol->free_clusters,
+				100.0*vol->free_clusters
+					/(double)vol->nr_clusters);
+
+	//TODO: Still need to add a few more attributes
+}
+
+/**
+ * ntfs_dump_flags - Dump flags for STANDARD_INFORMATION and FILE_NAME.
+ * @type:	dump flags for this attribute type
+ * @flags:	flags for dumping
+ */
+static void ntfs_dump_flags(const char *indent, ATTR_TYPES type, le32 flags)
+{
+	const le32 original_flags = flags;
+
+	printf("%sFile attributes:\t", indent);
+	if (flags & FILE_ATTR_READONLY) {
+		printf(" READONLY");
+		flags &= ~FILE_ATTR_READONLY;
+	}
+	if (flags & FILE_ATTR_HIDDEN) {
+		printf(" HIDDEN");
+		flags &= ~FILE_ATTR_HIDDEN;
+	}
+	if (flags & FILE_ATTR_SYSTEM) {
+		printf(" SYSTEM");
+		flags &= ~FILE_ATTR_SYSTEM;
+	}
+	if (flags & FILE_ATTR_DIRECTORY) {
+		printf(" DIRECTORY");
+		flags &= ~FILE_ATTR_DIRECTORY;
+	}
+	if (flags & FILE_ATTR_ARCHIVE) {
+		printf(" ARCHIVE");
+		flags &= ~FILE_ATTR_ARCHIVE;
+	}
+	if (flags & FILE_ATTR_DEVICE) {
+		printf(" DEVICE");
+		flags &= ~FILE_ATTR_DEVICE;
+	}
+	if (flags & FILE_ATTR_NORMAL) {
+		printf(" NORMAL");
+		flags &= ~FILE_ATTR_NORMAL;
+	}
+	if (flags & FILE_ATTR_TEMPORARY) {
+		printf(" TEMPORARY");
+		flags &= ~FILE_ATTR_TEMPORARY;
+	}
+	if (flags & FILE_ATTR_SPARSE_FILE) {
+		printf(" SPARSE_FILE");
+		flags &= ~FILE_ATTR_SPARSE_FILE;
+	}
+	if (flags & FILE_ATTR_REPARSE_POINT) {
+		printf(" REPARSE_POINT");
+		flags &= ~FILE_ATTR_REPARSE_POINT;
+	}
+	if (flags & FILE_ATTR_COMPRESSED) {
+		printf(" COMPRESSED");
+		flags &= ~FILE_ATTR_COMPRESSED;
+	}
+	if (flags & FILE_ATTR_OFFLINE) {
+		printf(" OFFLINE");
+		flags &= ~FILE_ATTR_OFFLINE;
+	}
+	if (flags & FILE_ATTR_NOT_CONTENT_INDEXED) {
+		printf(" NOT_CONTENT_INDEXED");
+		flags &= ~FILE_ATTR_NOT_CONTENT_INDEXED;
+	}
+	if (flags & FILE_ATTR_ENCRYPTED) {
+		printf(" ENCRYPTED");
+		flags &= ~FILE_ATTR_ENCRYPTED;
+	}
+	/* We know that FILE_ATTR_I30_INDEX_PRESENT only exists on $FILE_NAME,
+	   and in case we are wrong, let it appear as UNKNOWN */
+	if (type == AT_FILE_NAME) {
+		if (flags & FILE_ATTR_I30_INDEX_PRESENT) {
+			printf(" I30_INDEX");
+			flags &= ~FILE_ATTR_I30_INDEX_PRESENT;
+		}
+	}
+	if (flags & FILE_ATTR_VIEW_INDEX_PRESENT) {
+		printf(" VIEW_INDEX");
+		flags &= ~FILE_ATTR_VIEW_INDEX_PRESENT;
+	}
+	if (flags)
+		printf(" UNKNOWN: 0x%08x", (unsigned int)le32_to_cpu(flags));
+	/* Print all the flags in hex. */
+	printf(" (0x%08x)\n", (unsigned)le32_to_cpu(original_flags));
+}
+
+/**
+ * ntfs_dump_namespace
+ */
+static void ntfs_dump_namespace(const char *indent, u8 file_name_type)
+{
+	const char *mbs_file_type;
+
+	/* name space */
+	switch (file_name_type) {
+	case FILE_NAME_POSIX:
+		mbs_file_type = "POSIX";
+		break;
+	case FILE_NAME_WIN32:
+		mbs_file_type = "Win32";
+		break;
+	case FILE_NAME_DOS:
+		mbs_file_type = "DOS";
+		break;
+	case FILE_NAME_WIN32_AND_DOS:
+		mbs_file_type = "Win32 & DOS";
+		break;
+	default:
+		mbs_file_type = "(unknown)";
+	}
+	printf("%sNamespace:\t\t %s\n", indent, mbs_file_type);
+}
+
+/* *************** functions for dumping attributes ******************** */
+/**
+ * ntfs_dump_standard_information
+ */
+static void ntfs_dump_attr_standard_information(ATTR_RECORD *attr)
+{
+	STANDARD_INFORMATION *standard_attr = NULL;
+	u32 value_length;
+
+	standard_attr = (STANDARD_INFORMATION*)((char *)attr +
+		le16_to_cpu(attr->value_offset));
+
+	/* time conversion stuff */
+	if (!opts.notime) {
+		char *ntfs_time_str = NULL;
+
+		ntfs_time_str = ntfsinfo_time_to_str(standard_attr->creation_time);
+		printf("\tFile Creation Time:\t %s",ntfs_time_str);
+
+		ntfs_time_str = ntfsinfo_time_to_str(
+			standard_attr->last_data_change_time);
+		printf("\tFile Altered Time:\t %s",ntfs_time_str);
+
+		ntfs_time_str = ntfsinfo_time_to_str(
+			standard_attr->last_mft_change_time);
+		printf("\tMFT Changed Time:\t %s",ntfs_time_str);
+
+		ntfs_time_str = ntfsinfo_time_to_str(standard_attr->last_access_time);
+		printf("\tLast Accessed Time:\t %s",ntfs_time_str);
+	}
+	ntfs_dump_flags("\t", attr->type, standard_attr->file_attributes);
+
+	value_length = le32_to_cpu(attr->value_length);
+	if (value_length == 48) {
+		/* Only 12 reserved bytes here */
+	} else if (value_length == 72) {
+		printf("\tMaximum versions:\t %u \n", (unsigned int)
+				le32_to_cpu(standard_attr->maximum_versions));
+		printf("\tVersion number:\t\t %u \n", (unsigned int)
+				le32_to_cpu(standard_attr->version_number));
+		printf("\tClass ID:\t\t %u \n",
+			(unsigned int)le32_to_cpu(standard_attr->class_id));
+		printf("\tUser ID:\t\t %u (0x%x)\n",
+			(unsigned int)le32_to_cpu(standard_attr->owner_id),
+			(unsigned int)le32_to_cpu(standard_attr->owner_id));
+		printf("\tSecurity ID:\t\t %u (0x%x)\n",
+			(unsigned int)le32_to_cpu(standard_attr->security_id),
+			(unsigned int)le32_to_cpu(standard_attr->security_id));
+		printf("\tQuota charged:\t\t %llu (0x%llx)\n",
+				(unsigned long long)
+				le64_to_cpu(standard_attr->quota_charged),
+				(unsigned long long)
+				le64_to_cpu(standard_attr->quota_charged));
+		printf("\tUpdate Sequence Number:\t %llu (0x%llx)\n",
+				(unsigned long long)
+				le64_to_cpu(standard_attr->usn),
+				(unsigned long long)
+				le64_to_cpu(standard_attr->usn));
+	} else {
+		printf("\tSize of STANDARD_INFORMATION is %u (0x%x).  It "
+				"should be either 72 or 48, something is "
+				"wrong...\n", (unsigned int)value_length,
+				(unsigned)value_length);
+	}
+}
+
+static void ntfs_dump_bytes(u8 *buf, int start, int stop)
+{
+	int i;
+
+	for (i = start; i < stop; i++) {
+		printf("%02x ", buf[i]);
+	}
+}
+
+/**
+ * ntfs_dump_attr_list()
+ */
+static void ntfs_dump_attr_list(ATTR_RECORD *attr, ntfs_volume *vol)
+{
+	ATTR_LIST_ENTRY *entry;
+	u8 *value;
+	s64 l;
+
+	if (!opts.verbose)
+		return;
+
+	l = ntfs_get_attribute_value_length(attr);
+	if (!l) {
+		ntfs_log_perror("ntfs_get_attribute_value_length failed");
+		return;
+	}
+	value = ntfs_malloc(l);
+	if (!value)
+		return;
+
+	l = ntfs_get_attribute_value(vol, attr, value);
+	if (!l) {
+		ntfs_log_perror("ntfs_get_attribute_value failed");
+		free(value);
+		return;
+	}
+	printf("\tDumping attribute list:");
+	entry = (ATTR_LIST_ENTRY *) value;
+	for (;(u8 *)entry < (u8 *) value + l; entry = (ATTR_LIST_ENTRY *)
+				((u8 *) entry + le16_to_cpu(entry->length))) {
+		printf("\n");
+		printf("\t\tAttribute type:\t0x%x\n",
+				(unsigned int)le32_to_cpu(entry->type));
+		printf("\t\tRecord length:\t%u (0x%x)\n",
+				(unsigned)le16_to_cpu(entry->length),
+				(unsigned)le16_to_cpu(entry->length));
+		printf("\t\tName length:\t%u (0x%x)\n",
+				(unsigned)entry->name_length,
+				(unsigned)entry->name_length);
+		printf("\t\tName offset:\t%u (0x%x)\n",
+				(unsigned)entry->name_offset,
+				(unsigned)entry->name_offset);
+		printf("\t\tStarting VCN:\t%lld (0x%llx)\n",
+				(long long)sle64_to_cpu(entry->lowest_vcn),
+				(unsigned long long)
+				sle64_to_cpu(entry->lowest_vcn));
+		printf("\t\tMFT reference:\t%lld (0x%llx)\n",
+				(unsigned long long)
+				MREF_LE(entry->mft_reference),
+				(unsigned long long)
+				MREF_LE(entry->mft_reference));
+		printf("\t\tInstance:\t%u (0x%x)\n",
+				(unsigned)le16_to_cpu(entry->instance),
+				(unsigned)le16_to_cpu(entry->instance));
+		printf("\t\tName:\t\t");
+		if (entry->name_length) {
+			char *name = NULL;
+			int name_size;
+
+			name_size = ntfs_ucstombs(entry->name,
+					entry->name_length, &name, 0);
+
+			if (name_size > 0) {
+				printf("%s\n", name);
+				free(name);
+			} else
+				ntfs_log_perror("ntfs_ucstombs failed");
+		} else
+			printf("unnamed\n");
+		printf("\t\tPadding:\t");
+		ntfs_dump_bytes((u8 *)entry, entry->name_offset +
+				sizeof(ntfschar) * entry->name_length,
+				le16_to_cpu(entry->length));
+		printf("\n");
+	}
+	free(value);
+	printf("\tEnd of attribute list reached.\n");
+}
+
+/**
+ * ntfs_dump_filename()
+ */
+static void ntfs_dump_filename(const char *indent,
+		FILE_NAME_ATTR *file_name_attr)
+{
+	printf("%sParent directory:\t %lld (0x%llx)\n", indent,
+			(long long)MREF_LE(file_name_attr->parent_directory),
+			(long long)MREF_LE(file_name_attr->parent_directory));
+	/* time stuff */
+	if (!opts.notime) {
+		char *ntfs_time_str;
+
+		ntfs_time_str = ntfsinfo_time_to_str(
+				file_name_attr->creation_time);
+		printf("%sFile Creation Time:\t %s", indent, ntfs_time_str);
+
+		ntfs_time_str = ntfsinfo_time_to_str(
+				file_name_attr->last_data_change_time);
+		printf("%sFile Altered Time:\t %s", indent, ntfs_time_str);
+
+		ntfs_time_str = ntfsinfo_time_to_str(
+				file_name_attr->last_mft_change_time);
+		printf("%sMFT Changed Time:\t %s", indent, ntfs_time_str);
+
+		ntfs_time_str = ntfsinfo_time_to_str(
+				file_name_attr->last_access_time);
+		printf("%sLast Accessed Time:\t %s", indent, ntfs_time_str);
+	}
+	/* other basic stuff about the file */
+	printf("%sAllocated Size:\t\t %lld (0x%llx)\n", indent, (long long)
+			sle64_to_cpu(file_name_attr->allocated_size),
+			(unsigned long long)
+			sle64_to_cpu(file_name_attr->allocated_size));
+	printf("%sData Size:\t\t %lld (0x%llx)\n", indent,
+			(long long)sle64_to_cpu(file_name_attr->data_size),
+			(unsigned long long)
+			sle64_to_cpu(file_name_attr->data_size));
+	printf("%sFilename Length:\t %d (0x%x)\n", indent,
+			(unsigned)file_name_attr->file_name_length,
+			(unsigned)file_name_attr->file_name_length);
+	ntfs_dump_flags(indent, AT_FILE_NAME, file_name_attr->file_attributes);
+	if (file_name_attr->file_attributes & FILE_ATTR_REPARSE_POINT &&
+			file_name_attr->reparse_point_tag)
+		printf("%sReparse point tag:\t 0x%x\n", indent, (unsigned)
+				le32_to_cpu(file_name_attr->reparse_point_tag));
+	else if (file_name_attr->reparse_point_tag) {
+		printf("%sEA Length:\t\t %d (0x%x)\n", indent, (unsigned)
+				le16_to_cpu(file_name_attr->packed_ea_size),
+				(unsigned)
+				le16_to_cpu(file_name_attr->packed_ea_size));
+		if (file_name_attr->reserved)
+			printf("%sReserved:\t\t %d (0x%x)\n", indent,
+					(unsigned)
+					le16_to_cpu(file_name_attr->reserved),
+					(unsigned)
+					le16_to_cpu(file_name_attr->reserved));
+	}
+	/* The filename. */
+	ntfs_dump_namespace(indent, file_name_attr->file_name_type);
+	if (file_name_attr->file_name_length > 0) {
+		/* but first we need to convert the little endian unicode string
+		   into a printable format */
+		char *mbs_file_name = NULL;
+		int mbs_file_name_size;
+
+		mbs_file_name_size = ntfs_ucstombs(file_name_attr->file_name,
+			file_name_attr->file_name_length,&mbs_file_name,0);
+
+		if (mbs_file_name_size>0) {
+			printf("%sFilename:\t\t '%s'\n", indent, mbs_file_name);
+			free(mbs_file_name);
+		} else {
+			/* an error occurred, errno holds the reason - notify the user */
+			ntfs_log_perror("ntfsinfo error: could not parse file name");
+		}
+	} else {
+		printf("%sFile Name:\t\t unnamed?!?\n", indent);
+	}
+}
+
+/**
+ * ntfs_dump_attr_file_name()
+ */
+static void ntfs_dump_attr_file_name(ATTR_RECORD *attr)
+{
+	ntfs_dump_filename("\t", (FILE_NAME_ATTR*)((u8*)attr +
+			le16_to_cpu(attr->value_offset)));
+}
+
+/**
+ * ntfs_dump_object_id
+ *
+ * dump the $OBJECT_ID attribute - not present on all systems
+ */
+static void ntfs_dump_attr_object_id(ATTR_RECORD *attr,ntfs_volume *vol)
+{
+	OBJECT_ID_ATTR *obj_id_attr = NULL;
+
+	obj_id_attr = (OBJECT_ID_ATTR *)((u8*)attr +
+			le16_to_cpu(attr->value_offset));
+
+	if (vol->major_ver >= 3.0) {
+		u32 value_length;
+		char printable_GUID[37];
+
+		value_length = le32_to_cpu(attr->value_length);
+
+		/* Object ID is mandatory. */
+		ntfs_guid_to_mbs(&obj_id_attr->object_id, printable_GUID);
+		printf("\tObject ID:\t\t %s\n", printable_GUID);
+
+		/* Dump Birth Volume ID. */
+		if ((value_length > sizeof(GUID)) && !ntfs_guid_is_zero(
+				&obj_id_attr->birth_volume_id)) {
+			ntfs_guid_to_mbs(&obj_id_attr->birth_volume_id,
+					printable_GUID);
+			printf("\tBirth Volume ID:\t\t %s\n", printable_GUID);
+		} else
+			printf("\tBirth Volume ID:\t missing\n");
+
+		/* Dumping Birth Object ID */
+		if ((value_length > sizeof(GUID)) && !ntfs_guid_is_zero(
+				&obj_id_attr->birth_object_id)) {
+			ntfs_guid_to_mbs(&obj_id_attr->birth_object_id,
+					printable_GUID);
+			printf("\tBirth Object ID:\t\t %s\n", printable_GUID);
+		} else
+			printf("\tBirth Object ID:\t missing\n");
+
+		/* Dumping Domain_id - reserved for now */
+		if ((value_length > sizeof(GUID)) && !ntfs_guid_is_zero(
+				&obj_id_attr->domain_id)) {
+			ntfs_guid_to_mbs(&obj_id_attr->domain_id,
+					printable_GUID);
+			printf("\tDomain ID:\t\t\t %s\n", printable_GUID);
+		} else
+			printf("\tDomain ID:\t\t missing\n");
+	} else
+		printf("\t$OBJECT_ID not present. Only NTFS versions > 3.0\n"
+			"\thave $OBJECT_ID. Your version of NTFS is %d.\n",
+				vol->major_ver);
+}
+
+/**
+ * ntfs_dump_acl
+ *
+ * given an acl, print it in a beautiful & lovely way.
+ */
+static void ntfs_dump_acl(const char *prefix, ACL *acl)
+{
+	unsigned int i;
+	u16 ace_count;
+	ACCESS_ALLOWED_ACE *ace;
+
+	printf("%sRevision\t %u\n", prefix, acl->revision);
+
+	/*
+	 * Do not recalculate le16_to_cpu every iteration (minor speedup on
+	 * big-endian machines.
+	 */
+	ace_count = le16_to_cpu(acl->ace_count);
+
+	/* initialize 'ace' to the first ace (if any) */
+	ace = (ACCESS_ALLOWED_ACE *)((char *)acl + 8);
+
+	/* iterate through ACE's */
+	for (i = 1; i <= ace_count; i++) {
+		const char *ace_type;
+		char *sid;
+
+		/* set ace_type. */
+		switch (ace->type) {
+		case ACCESS_ALLOWED_ACE_TYPE:
+			ace_type = "allow";
+			break;
+		case ACCESS_DENIED_ACE_TYPE:
+			ace_type = "deny";
+			break;
+		case SYSTEM_AUDIT_ACE_TYPE:
+			ace_type = "audit";
+			break;
+		default:
+			ace_type = "unknown";
+			break;
+		}
+
+		printf("%sACE:\t\t type:%s  flags:0x%x  access:0x%x\n", prefix,
+			ace_type, (unsigned int)ace->flags,
+			(unsigned int)le32_to_cpu(ace->mask));
+		/* get a SID string */
+		sid = ntfs_sid_to_mbs(&ace->sid, NULL, 0);
+		printf("%s\t\t SID: %s\n", prefix, sid);
+		free(sid);
+
+		/* proceed to next ACE */
+		ace = (ACCESS_ALLOWED_ACE *)(((char *)ace) +
+				le16_to_cpu(ace->size));
+	}
+}
+
+
+static void ntfs_dump_security_descriptor(SECURITY_DESCRIPTOR_ATTR *sec_desc,
+					  const char *indent)
+{
+	char *sid;
+
+	printf("%s\tRevision:\t\t %u\n", indent, sec_desc->revision);
+
+	/* TODO: parse the flags */
+	printf("%s\tControl:\t\t 0x%04x\n", indent,
+			le16_to_cpu(sec_desc->control));
+
+	if (~sec_desc->control & SE_SELF_RELATIVE) {
+		SECURITY_DESCRIPTOR *sd = (SECURITY_DESCRIPTOR *)sec_desc;
+
+		printf("%s\tOwner SID pointer:\t %p\n", indent, sd->owner);
+		printf("%s\tGroup SID pointer:\t %p\n", indent, sd->group);
+		printf("%s\tSACL pointer:\t\t %p\n", indent, sd->sacl);
+		printf("%s\tDACL pointer:\t\t %p\n", indent, sd->dacl);
+
+		return;
+	}
+
+	if (sec_desc->owner) {
+		sid = ntfs_sid_to_mbs((SID *)((char *)sec_desc +
+			le32_to_cpu(sec_desc->owner)), NULL, 0);
+		printf("%s\tOwner SID:\t\t %s\n", indent, sid);
+		free(sid);
+	} else
+		printf("%s\tOwner SID:\t\t missing\n", indent);
+
+	if (sec_desc->group) {
+		sid = ntfs_sid_to_mbs((SID *)((char *)sec_desc +
+			le32_to_cpu(sec_desc->group)), NULL, 0);
+		printf("%s\tGroup SID:\t\t %s\n", indent, sid);
+		free(sid);
+	} else
+		printf("%s\tGroup SID:\t\t missing\n", indent);
+
+	printf("%s\tSystem ACL:\t\t ", indent);
+	if (sec_desc->control & SE_SACL_PRESENT) {
+		if (sec_desc->control & SE_SACL_DEFAULTED) {
+			printf("defaulted");
+		}
+		printf("\n");
+		ntfs_dump_acl(indent ? "\t\t\t" : "\t\t",
+			      (ACL *)((char *)sec_desc +
+				      le32_to_cpu(sec_desc->sacl)));
+	} else {
+		printf("missing\n");
+	}
+
+	printf("%s\tDiscretionary ACL:\t ", indent);
+	if (sec_desc->control & SE_DACL_PRESENT) {
+		if (sec_desc->control & SE_SACL_DEFAULTED) {
+			printf("defaulted");
+		}
+		printf("\n");
+		ntfs_dump_acl(indent ? "\t\t\t" : "\t\t",
+			      (ACL *)((char *)sec_desc +
+				      le32_to_cpu(sec_desc->dacl)));
+	} else {
+		printf("missing\n");
+	}
+}
+
+/**
+ * ntfs_dump_security_descriptor()
+ *
+ * dump the security information about the file
+ */
+static void ntfs_dump_attr_security_descriptor(ATTR_RECORD *attr, ntfs_volume *vol)
+{
+	SECURITY_DESCRIPTOR_ATTR *sec_desc_attr;
+
+	if (attr->non_resident) {
+		/* FIXME: We don't handle fragmented mapping pairs case. */
+		runlist *rl = ntfs_mapping_pairs_decompress(vol, attr, NULL);
+		if (rl) {
+			s64 data_size, bytes_read;
+
+			data_size = sle64_to_cpu(attr->data_size);
+			sec_desc_attr = ntfs_malloc(data_size);
+			if (!sec_desc_attr) {
+				free(rl);
+				return;
+			}
+			bytes_read = ntfs_rl_pread(vol, rl, 0,
+						data_size, sec_desc_attr);
+			if (bytes_read != data_size) {
+				ntfs_log_error("ntfsinfo error: could not "
+						"read security descriptor\n");
+				free(rl);
+				free(sec_desc_attr);
+				return;
+			}
+			free(rl);
+		} else {
+			ntfs_log_error("ntfsinfo error: could not "
+						"decompress runlist\n");
+			return;
+		}
+	} else {
+		sec_desc_attr = (SECURITY_DESCRIPTOR_ATTR *)((u8*)attr +
+				le16_to_cpu(attr->value_offset));
+	}
+
+	ntfs_dump_security_descriptor(sec_desc_attr, "");
+
+	if (attr->non_resident)
+		free(sec_desc_attr);
+}
+
+/**
+ * ntfs_dump_volume_name()
+ *
+ * dump the name of the volume the inode belongs to
+ */
+static void ntfs_dump_attr_volume_name(ATTR_RECORD *attr)
+{
+	ntfschar *ucs_vol_name = NULL;
+
+	if (le32_to_cpu(attr->value_length) > 0) {
+		char *mbs_vol_name = NULL;
+		int mbs_vol_name_size;
+		/* calculate volume name position */
+		ucs_vol_name = (ntfschar*)((u8*)attr +
+				le16_to_cpu(attr->value_offset));
+		/* convert the name to current locale multibyte sequence */
+		mbs_vol_name_size = ntfs_ucstombs(ucs_vol_name,
+				le32_to_cpu(attr->value_length) /
+				sizeof(ntfschar), &mbs_vol_name, 0);
+
+		if (mbs_vol_name_size>0) {
+			/* output the converted name. */
+			printf("\tVolume Name:\t\t '%s'\n", mbs_vol_name);
+			free(mbs_vol_name);
+		} else
+			ntfs_log_perror("ntfsinfo error: could not parse "
+					"volume name");
+	} else
+		printf("\tVolume Name:\t\t unnamed\n");
+}
+
+/**
+ * ntfs_dump_volume_information()
+ *
+ * dump the information for the volume the inode belongs to
+ *
+ */
+static void ntfs_dump_attr_volume_information(ATTR_RECORD *attr)
+{
+	VOLUME_INFORMATION *vol_information = NULL;
+
+	vol_information = (VOLUME_INFORMATION*)((char *)attr+
+		le16_to_cpu(attr->value_offset));
+
+	printf("\tVolume Version:\t\t %d.%d\n", vol_information->major_ver,
+		vol_information->minor_ver);
+	printf("\tVolume Flags:\t\t ");
+	if (vol_information->flags & VOLUME_IS_DIRTY)
+		printf("DIRTY ");
+	if (vol_information->flags & VOLUME_RESIZE_LOG_FILE)
+		printf("RESIZE_LOG ");
+	if (vol_information->flags & VOLUME_UPGRADE_ON_MOUNT)
+		printf("UPG_ON_MOUNT ");
+	if (vol_information->flags & VOLUME_MOUNTED_ON_NT4)
+		printf("MOUNTED_NT4 ");
+	if (vol_information->flags & VOLUME_DELETE_USN_UNDERWAY)
+		printf("DEL_USN ");
+	if (vol_information->flags & VOLUME_REPAIR_OBJECT_ID)
+		printf("REPAIR_OBJID ");
+	if (vol_information->flags & VOLUME_CHKDSK_UNDERWAY)
+		printf("CHKDSK_UNDERWAY ");
+	if (vol_information->flags & VOLUME_MODIFIED_BY_CHKDSK)
+		printf("MOD_BY_CHKDSK ");
+	if (vol_information->flags & VOLUME_FLAGS_MASK) {
+		printf("(0x%04x)\n",
+				(unsigned)le16_to_cpu(vol_information->flags));
+	} else
+		printf("none set (0x0000)\n");
+	if (vol_information->flags & (~VOLUME_FLAGS_MASK))
+		printf("\t\t\t\t Unknown Flags: 0x%04x\n",
+				le16_to_cpu(vol_information->flags &
+					(~VOLUME_FLAGS_MASK)));
+}
+
+static ntfschar NTFS_DATA_SDS[5] = { const_cpu_to_le16('$'),
+	const_cpu_to_le16('S'), const_cpu_to_le16('D'),
+	const_cpu_to_le16('S'), const_cpu_to_le16('\0') };
+
+static void ntfs_dump_sds_entry(SECURITY_DESCRIPTOR_HEADER *sds)
+{
+	SECURITY_DESCRIPTOR_RELATIVE *sd;
+
+	ntfs_log_verbose("\n");
+	ntfs_log_verbose("\t\tHash:\t\t\t 0x%08x\n",
+			(unsigned)le32_to_cpu(sds->hash));
+	ntfs_log_verbose("\t\tSecurity id:\t\t %u (0x%x)\n",
+			(unsigned)le32_to_cpu(sds->security_id),
+			(unsigned)le32_to_cpu(sds->security_id));
+	ntfs_log_verbose("\t\tOffset:\t\t\t %llu (0x%llx)\n",
+			(unsigned long long)le64_to_cpu(sds->offset),
+			(unsigned long long)le64_to_cpu(sds->offset));
+	ntfs_log_verbose("\t\tLength:\t\t\t %u (0x%x)\n",
+			(unsigned)le32_to_cpu(sds->length),
+			(unsigned)le32_to_cpu(sds->length));
+
+	sd = (SECURITY_DESCRIPTOR_RELATIVE *)((char *)sds +
+		sizeof(SECURITY_DESCRIPTOR_HEADER));
+
+	ntfs_dump_security_descriptor(sd, "\t");
+}
+
+static void ntfs_dump_sds(ATTR_RECORD *attr, ntfs_inode *ni)
+{
+	SECURITY_DESCRIPTOR_HEADER *sds, *sd;
+	ntfschar *name;
+	int name_len;
+	s64 data_size;
+	u64 inode;
+
+	inode = ni->mft_no;
+	if (ni->nr_extents < 0)
+		inode = ni->base_ni->mft_no;
+	if (FILE_Secure != inode)
+		return;
+
+	name_len = attr->name_length;
+	if (!name_len)
+		return;
+
+	name = (ntfschar *)((u8 *)attr + le16_to_cpu(attr->name_offset));
+	if (!ntfs_names_are_equal(NTFS_DATA_SDS, sizeof(NTFS_DATA_SDS) / 2 - 1,
+				  name, name_len, CASE_SENSITIVE, NULL, 0))
+		return;
+
+	sd = sds = ntfs_attr_readall(ni, AT_DATA, name, name_len, &data_size);
+	if (!sd) {
+		ntfs_log_perror("Failed to read $SDS attribute");
+		return;
+	}
+	/*
+	 * FIXME: The right way is based on the indexes, so we couldn't
+	 * miss real entries. For now, dump until it makes sense.
+	 */
+	while (sd->length && sd->hash &&
+	       le64_to_cpu(sd->offset) < (u64)data_size &&
+	       le32_to_cpu(sd->length) < (u64)data_size &&
+	       le64_to_cpu(sd->offset) +
+			le32_to_cpu(sd->length) < (u64)data_size) {
+		ntfs_dump_sds_entry(sd);
+		sd = (SECURITY_DESCRIPTOR_HEADER *)((char*)sd +
+				((le32_to_cpu(sd->length) + 15) & ~15));
+	}
+	free(sds);
+}
+
+static const char *get_attribute_type_name(le32 type)
+{
+	switch (type) {
+	case AT_UNUSED:			return "$UNUSED";
+	case AT_STANDARD_INFORMATION:   return "$STANDARD_INFORMATION";
+	case AT_ATTRIBUTE_LIST:         return "$ATTRIBUTE_LIST";
+	case AT_FILE_NAME:              return "$FILE_NAME";
+	case AT_OBJECT_ID:              return "$OBJECT_ID";
+	case AT_SECURITY_DESCRIPTOR:    return "$SECURITY_DESCRIPTOR";
+	case AT_VOLUME_NAME:            return "$VOLUME_NAME";
+	case AT_VOLUME_INFORMATION:     return "$VOLUME_INFORMATION";
+	case AT_DATA:                   return "$DATA";
+	case AT_INDEX_ROOT:             return "$INDEX_ROOT";
+	case AT_INDEX_ALLOCATION:       return "$INDEX_ALLOCATION";
+	case AT_BITMAP:                 return "$BITMAP";
+	case AT_REPARSE_POINT:          return "$REPARSE_POINT";
+	case AT_EA_INFORMATION:         return "$EA_INFORMATION";
+	case AT_EA:                     return "$EA";
+	case AT_PROPERTY_SET:           return "$PROPERTY_SET";
+	case AT_LOGGED_UTILITY_STREAM:  return "$LOGGED_UTILITY_STREAM";
+	case AT_END:                    return "$END";
+	}
+
+	return "$UNKNOWN";
+}
+
+static const char * ntfs_dump_lcn(LCN lcn)
+{
+	switch (lcn) {
+		case LCN_HOLE:
+			return "<HOLE>\t";
+		case LCN_RL_NOT_MAPPED:
+			return "<RL_NOT_MAPPED>";
+		case LCN_ENOENT:
+			return "<ENOENT>\t";
+		case LCN_EINVAL:
+			return "<EINVAL>\t";
+		case LCN_EIO:
+			return "<EIO>\t";
+		default:
+			ntfs_log_error("Invalid LCN value %llx passed to "
+					"ntfs_dump_lcn().\n", (long long)lcn);
+			return "???\t";
+	}
+}
+
+static void ntfs_dump_attribute_header(ntfs_attr_search_ctx *ctx,
+		ntfs_volume *vol, struct RUNCOUNT *runcount)
+{
+	ATTR_RECORD *a = ctx->attr;
+
+	printf("Dumping attribute %s (0x%x) from mft record %lld (0x%llx)\n",
+			get_attribute_type_name(a->type),
+			(unsigned)le32_to_cpu(a->type),
+			(unsigned long long)ctx->ntfs_ino->mft_no,
+			(unsigned long long)ctx->ntfs_ino->mft_no);
+
+	ntfs_log_verbose("\tAttribute length:\t %u (0x%x)\n",
+			(unsigned)le32_to_cpu(a->length),
+			(unsigned)le32_to_cpu(a->length));
+	printf("\tResident: \t\t %s\n", a->non_resident ? "No" : "Yes");
+	ntfs_log_verbose("\tName length:\t\t %u (0x%x)\n",
+			(unsigned)a->name_length, (unsigned)a->name_length);
+	ntfs_log_verbose("\tName offset:\t\t %u (0x%x)\n",
+			(unsigned)le16_to_cpu(a->name_offset),
+			(unsigned)le16_to_cpu(a->name_offset));
+
+	/* Dump the attribute (stream) name */
+	if (a->name_length) {
+		char *attribute_name = NULL;
+
+		attribute_name = ntfs_attr_get_name_mbs(a);
+		if (attribute_name) {
+			printf("\tAttribute name:\t\t '%s'\n", attribute_name);
+			free(attribute_name);
+		} else
+			ntfs_log_perror("Error: couldn't parse attribute name");
+	}
+
+	/* TODO: parse the flags */
+	printf("\tAttribute flags:\t 0x%04x\n",
+			(unsigned)le16_to_cpu(a->flags));
+	printf("\tAttribute instance:\t %u (0x%x)\n",
+			(unsigned)le16_to_cpu(a->instance),
+			(unsigned)le16_to_cpu(a->instance));
+
+	/* Resident attribute */
+	if (!a->non_resident) {
+		printf("\tData size:\t\t %u (0x%x)\n",
+				(unsigned)le32_to_cpu(a->value_length),
+				(unsigned)le32_to_cpu(a->value_length));
+		ntfs_log_verbose("\tData offset:\t\t %u (0x%x)\n",
+				(unsigned)le16_to_cpu(a->value_offset),
+				(unsigned)le16_to_cpu(a->value_offset));
+		/* TODO: parse the flags */
+		printf("\tResident flags:\t\t 0x%02x\n",
+				(unsigned)a->resident_flags);
+		ntfs_log_verbose("\tReservedR:\t\t %d (0x%x)\n",
+				(unsigned)a->reservedR, (unsigned)a->reservedR);
+		return;
+	}
+
+	/* Non-resident attribute */
+	ntfs_log_verbose("\tLowest VCN\t\t %lld (0x%llx)\n",
+			(long long)sle64_to_cpu(a->lowest_vcn),
+			(unsigned long long)sle64_to_cpu(a->lowest_vcn));
+	ntfs_log_verbose("\tHighest VCN:\t\t %lld (0x%llx)\n",
+			(long long)sle64_to_cpu(a->highest_vcn),
+			(unsigned long long)sle64_to_cpu(a->highest_vcn));
+	ntfs_log_verbose("\tMapping pairs offset:\t %u (0x%x)\n",
+			(unsigned)le16_to_cpu(a->mapping_pairs_offset),
+			(unsigned)le16_to_cpu(a->mapping_pairs_offset));
+	printf("\tCompression unit:\t %u (0x%x)\n",
+			(unsigned)a->compression_unit,
+			(unsigned)a->compression_unit);
+	/* TODO: dump the 5 reserved bytes here in verbose mode */
+
+	if (!a->lowest_vcn) {
+		printf("\tData size:\t\t %llu (0x%llx)\n",
+				(long long)sle64_to_cpu(a->data_size),
+				(unsigned long long)sle64_to_cpu(a->data_size));
+		printf("\tAllocated size:\t\t %llu (0x%llx)\n",
+				(long long)sle64_to_cpu(a->allocated_size),
+				(unsigned long long)
+				sle64_to_cpu(a->allocated_size));
+		printf("\tInitialized size:\t %llu (0x%llx)\n",
+				(long long)sle64_to_cpu(a->initialized_size),
+				(unsigned long long)
+				sle64_to_cpu(a->initialized_size));
+		if (a->compression_unit || a->flags & ATTR_IS_COMPRESSED ||
+				a->flags & ATTR_IS_SPARSE)
+			printf("\tCompressed size:\t %llu (0x%llx)\n",
+					(signed long long)
+					sle64_to_cpu(a->compressed_size),
+					(signed long long)
+					sle64_to_cpu(a->compressed_size));
+	}
+
+	if (opts.verbose) {
+		runlist *rl;
+
+		rl = ntfs_mapping_pairs_decompress(vol, a, NULL);
+		if (rl) {
+			runlist *rlc = rl;
+			LCN next_lcn;
+
+			next_lcn = LCN_HOLE;
+			// TODO: Switch this to properly aligned hex...
+			printf("\tRunlist:\tVCN\t\tLCN\t\tLength\n");
+			runcount->fragments++;
+			while (rlc->length) {
+				runcount->runs++;
+				if (rlc->lcn >= 0) {
+					printf("\t\t\t0x%llx\t\t0x%llx\t\t"
+							"0x%llx\n",
+							(long long)rlc->vcn,
+							(long long)rlc->lcn,
+							(long long)rlc->length);
+					if ((next_lcn >= 0)
+					    && (rlc->lcn != next_lcn))
+						runcount->fragments++;
+					next_lcn = rlc->lcn + rlc->length;
+				} else
+					printf("\t\t\t0x%llx\t\t%s\t"
+							"0x%llx\n",
+							(long long)rlc->vcn,
+							ntfs_dump_lcn(rlc->lcn),
+							(long long)rlc->length);
+				rlc++;
+			}
+			free(rl);
+		} else
+			ntfs_log_error("Error: couldn't decompress runlist\n");
+	}
+}
+
+/**
+ * ntfs_dump_data_attr()
+ *
+ * dump some info about the data attribute if it's metadata
+ */
+static void ntfs_dump_attr_data(ATTR_RECORD *attr, ntfs_inode *ni)
+{
+	if (opts.verbose)
+		ntfs_dump_sds(attr, ni);
+}
+
+typedef enum {
+	INDEX_ATTR_UNKNOWN,
+	INDEX_ATTR_DIRECTORY_I30,
+	INDEX_ATTR_SECURE_SII,
+	INDEX_ATTR_SECURE_SDH,
+	INDEX_ATTR_OBJID_O,
+	INDEX_ATTR_REPARSE_R,
+	INDEX_ATTR_QUOTA_O,
+	INDEX_ATTR_QUOTA_Q,
+} INDEX_ATTR_TYPE;
+
+static void ntfs_dump_index_key(INDEX_ENTRY *entry, INDEX_ATTR_TYPE type)
+{
+	char *sid;
+	char printable_GUID[37];
+
+	switch (type) {
+	case INDEX_ATTR_SECURE_SII:
+		ntfs_log_verbose("\t\tKey security id:\t %u (0x%x)\n",
+				(unsigned)
+				le32_to_cpu(entry->key.sii.security_id),
+				(unsigned)
+				le32_to_cpu(entry->key.sii.security_id));
+		break;
+	case INDEX_ATTR_SECURE_SDH:
+		ntfs_log_verbose("\t\tKey hash:\t\t 0x%08x\n",
+				(unsigned)le32_to_cpu(entry->key.sdh.hash));
+		ntfs_log_verbose("\t\tKey security id:\t %u (0x%x)\n",
+				(unsigned)
+				le32_to_cpu(entry->key.sdh.security_id),
+				(unsigned)
+				le32_to_cpu(entry->key.sdh.security_id));
+		break;
+	case INDEX_ATTR_OBJID_O:
+		ntfs_guid_to_mbs(&entry->key.object_id, printable_GUID);
+		ntfs_log_verbose("\t\tKey GUID:\t\t %s\n", printable_GUID);
+		break;
+	case INDEX_ATTR_REPARSE_R:
+		ntfs_log_verbose("\t\tKey reparse tag:\t 0x%08x\n", (unsigned)
+				le32_to_cpu(entry->key.reparse.reparse_tag));
+		ntfs_log_verbose("\t\tKey file id:\t\t %llu (0x%llx)\n",
+				(unsigned long long)
+				le64_to_cpu(entry->key.reparse.file_id),
+				(unsigned long long)
+				le64_to_cpu(entry->key.reparse.file_id));
+		break;
+	case INDEX_ATTR_QUOTA_O:
+		sid = ntfs_sid_to_mbs(&entry->key.sid, NULL, 0);
+		ntfs_log_verbose("\t\tKey SID:\t\t %s\n", sid);
+		free(sid);
+		break;
+	case INDEX_ATTR_QUOTA_Q:
+		ntfs_log_verbose("\t\tKey owner id:\t\t %u (0x%x)\n",
+				(unsigned)le32_to_cpu(entry->key.owner_id),
+				(unsigned)le32_to_cpu(entry->key.owner_id));
+		break;
+	default:
+		ntfs_log_verbose("\t\tIndex attr type is UNKNOWN: \t 0x%08x\n",
+				(unsigned)type);
+		break;
+	}
+}
+
+typedef union {
+	SII_INDEX_DATA sii;		/* $SII index data in $Secure */
+	SDH_INDEX_DATA sdh;		/* $SDH index data in $Secure */
+	QUOTA_O_INDEX_DATA quota_o;	/* $O index data in $Quota    */
+	QUOTA_CONTROL_ENTRY quota_q;	/* $Q index data in $Quota    */
+} __attribute__((__packed__)) INDEX_ENTRY_DATA;
+
+static void ntfs_dump_index_data(INDEX_ENTRY *entry, INDEX_ATTR_TYPE type)
+{
+	INDEX_ENTRY_DATA *data;
+
+	data = (INDEX_ENTRY_DATA *)((u8 *)entry +
+			le16_to_cpu(entry->data_offset));
+
+	switch (type) {
+	case INDEX_ATTR_SECURE_SII:
+		ntfs_log_verbose("\t\tHash:\t\t\t 0x%08x\n",
+				(unsigned)le32_to_cpu(data->sii.hash));
+		ntfs_log_verbose("\t\tSecurity id:\t\t %u (0x%x)\n",
+				(unsigned)le32_to_cpu(data->sii.security_id),
+				(unsigned)le32_to_cpu(data->sii.security_id));
+		ntfs_log_verbose("\t\tOffset in $SDS:\t\t %llu (0x%llx)\n",
+				(unsigned long long)
+				le64_to_cpu(data->sii.offset),
+				(unsigned long long)
+				le64_to_cpu(data->sii.offset));
+		ntfs_log_verbose("\t\tLength in $SDS:\t\t %u (0x%x)\n",
+				(unsigned)le32_to_cpu(data->sii.length),
+				(unsigned)le32_to_cpu(data->sii.length));
+		break;
+	case INDEX_ATTR_SECURE_SDH:
+		ntfs_log_verbose("\t\tHash:\t\t\t 0x%08x\n",
+				(unsigned)le32_to_cpu(data->sdh.hash));
+		ntfs_log_verbose("\t\tSecurity id:\t\t %u (0x%x)\n",
+				(unsigned)le32_to_cpu(data->sdh.security_id),
+				(unsigned)le32_to_cpu(data->sdh.security_id));
+		ntfs_log_verbose("\t\tOffset in $SDS:\t\t %llu (0x%llx)\n",
+				(unsigned long long)
+				le64_to_cpu(data->sdh.offset),
+				(unsigned long long)
+				le64_to_cpu(data->sdh.offset));
+		ntfs_log_verbose("\t\tLength in $SDS:\t\t %u (0x%x)\n",
+				(unsigned)le32_to_cpu(data->sdh.length),
+				(unsigned)le32_to_cpu(data->sdh.length));
+		ntfs_log_verbose("\t\tUnknown (padding):\t 0x%08x\n",
+				(unsigned)le32_to_cpu(data->sdh.reserved_II));
+		break;
+	case INDEX_ATTR_OBJID_O: {
+		OBJ_ID_INDEX_DATA *object_id_data;
+		char printable_GUID[37];
+
+		object_id_data = (OBJ_ID_INDEX_DATA*)((u8*)entry +
+				le16_to_cpu(entry->data_offset));
+		ntfs_log_verbose("\t\tMFT Number:\t\t 0x%llx\n",
+				(unsigned long long)
+				MREF_LE(object_id_data->mft_reference));
+		ntfs_log_verbose("\t\tMFT Sequence Number:\t 0x%x\n",
+				(unsigned)
+				MSEQNO_LE(object_id_data->mft_reference));
+		ntfs_guid_to_mbs(&object_id_data->birth_volume_id,
+				printable_GUID);
+		ntfs_log_verbose("\t\tBirth volume id GUID:\t %s\n",
+				printable_GUID);
+		ntfs_guid_to_mbs(&object_id_data->birth_object_id,
+				printable_GUID);
+		ntfs_log_verbose("\t\tBirth object id GUID:\t %s\n",
+				printable_GUID);
+		ntfs_guid_to_mbs(&object_id_data->domain_id, printable_GUID);
+		ntfs_log_verbose("\t\tDomain id GUID:\t\t %s\n",
+				printable_GUID);
+		}
+		break;
+	case INDEX_ATTR_REPARSE_R:
+		/* TODO */
+		break;
+	case INDEX_ATTR_QUOTA_O:
+		ntfs_log_verbose("\t\tOwner id:\t\t %u (0x%x)\n",
+				(unsigned)le32_to_cpu(data->quota_o.owner_id),
+				(unsigned)le32_to_cpu(data->quota_o.owner_id));
+		ntfs_log_verbose("\t\tUnknown:\t\t %u (0x%x)\n",
+				(unsigned)le32_to_cpu(data->quota_o.unknown),
+				(unsigned)le32_to_cpu(data->quota_o.unknown));
+		break;
+	case INDEX_ATTR_QUOTA_Q:
+		ntfs_log_verbose("\t\tVersion:\t\t %u\n",
+				(unsigned)le32_to_cpu(data->quota_q.version));
+		ntfs_log_verbose("\t\tQuota flags:\t\t 0x%08x\n",
+				(unsigned)le32_to_cpu(data->quota_q.flags));
+		ntfs_log_verbose("\t\tBytes used:\t\t %llu (0x%llx)\n",
+				(unsigned long long)
+				le64_to_cpu(data->quota_q.bytes_used),
+				(unsigned long long)
+				le64_to_cpu(data->quota_q.bytes_used));
+		ntfs_log_verbose("\t\tLast changed:\t\t %s",
+				ntfsinfo_time_to_str(
+				data->quota_q.change_time));
+		ntfs_log_verbose("\t\tThreshold:\t\t %lld (0x%llx)\n",
+				(unsigned long long)
+				sle64_to_cpu(data->quota_q.threshold),
+				(unsigned long long)
+				sle64_to_cpu(data->quota_q.threshold));
+		ntfs_log_verbose("\t\tLimit:\t\t\t %lld (0x%llx)\n",
+				(unsigned long long)
+				sle64_to_cpu(data->quota_q.limit),
+				(unsigned long long)
+				sle64_to_cpu(data->quota_q.limit));
+		ntfs_log_verbose("\t\tExceeded time:\t\t %lld (0x%llx)\n",
+				(unsigned long long)
+				sle64_to_cpu(data->quota_q.exceeded_time),
+				(unsigned long long)
+				sle64_to_cpu(data->quota_q.exceeded_time));
+		if (le16_to_cpu(entry->data_length) > 48) {
+			char *sid;
+			sid = ntfs_sid_to_mbs(&data->quota_q.sid, NULL, 0);
+			ntfs_log_verbose("\t\tOwner SID:\t\t %s\n", sid);
+			free(sid);
+		}
+		break;
+	default:
+		ntfs_log_verbose("\t\tIndex attr type is UNKNOWN: \t 0x%08x\n",
+				(unsigned)type);
+		break;
+	}
+}
+
+/**
+ * ntfs_dump_index_entries()
+ *
+ * dump sequence of index_entries and return number of entries dumped.
+ */
+static int ntfs_dump_index_entries(INDEX_ENTRY *entry, INDEX_ATTR_TYPE type)
+{
+	int numb_entries = 1;
+	while (1) {
+		if (!opts.verbose) {
+			if (entry->ie_flags & INDEX_ENTRY_END)
+				break;
+			entry = (INDEX_ENTRY *)((u8 *)entry +
+						le16_to_cpu(entry->length));
+			numb_entries++;
+			continue;
+		}
+		ntfs_log_verbose("\t\tEntry length:\t\t %u (0x%x)\n",
+				(unsigned)le16_to_cpu(entry->length),
+				(unsigned)le16_to_cpu(entry->length));
+		ntfs_log_verbose("\t\tKey length:\t\t %u (0x%x)\n",
+				(unsigned)le16_to_cpu(entry->key_length),
+				(unsigned)le16_to_cpu(entry->key_length));
+		ntfs_log_verbose("\t\tIndex entry flags:\t 0x%02x\n",
+				(unsigned)le16_to_cpu(entry->ie_flags));
+
+		if (entry->ie_flags & INDEX_ENTRY_NODE)
+			ntfs_log_verbose("\t\tSubnode VCN:\t\t %lld (0x%llx)\n",
+					 (long long)ntfs_ie_get_vcn(entry),
+					 (long long)ntfs_ie_get_vcn(entry));
+		if (entry->ie_flags & INDEX_ENTRY_END)
+			break;
+
+		switch (type) {
+		case INDEX_ATTR_DIRECTORY_I30:
+			ntfs_log_verbose("\t\tFILE record number:\t %llu "
+					"(0x%llx)\n", (unsigned long long)
+					MREF_LE(entry->indexed_file),
+					(unsigned long long)
+					MREF_LE(entry->indexed_file));
+			ntfs_dump_filename("\t\t", &entry->key.file_name);
+			break;
+		default:
+			ntfs_log_verbose("\t\tData offset:\t\t %u (0x%x)\n",
+					(unsigned)
+					le16_to_cpu(entry->data_offset),
+					(unsigned)
+					le16_to_cpu(entry->data_offset));
+			ntfs_log_verbose("\t\tData length:\t\t %u (0x%x)\n",
+					(unsigned)
+					le16_to_cpu(entry->data_length),
+					(unsigned)
+					le16_to_cpu(entry->data_length));
+			ntfs_dump_index_key(entry, type);
+			ntfs_log_verbose("\t\tKey Data:\n");
+			ntfs_dump_index_data(entry, type);
+			break;
+		}
+		if (!entry->length) {
+			ntfs_log_verbose("\tWARNING: Corrupt index entry, "
+					"skipping the remainder of this index "
+					"block.\n");
+			break;
+		}
+		entry = (INDEX_ENTRY*)((u8*)entry + le16_to_cpu(entry->length));
+		numb_entries++;
+		ntfs_log_verbose("\n");
+	}
+	ntfs_log_verbose("\tEnd of index block reached\n");
+	return numb_entries;
+}
+
+#define	COMPARE_INDEX_NAMES(attr, name)					       \
+	ntfs_names_are_equal((name), sizeof(name) / 2 - 1,		       \
+		(ntfschar*)((char*)(attr) + le16_to_cpu((attr)->name_offset)), \
+		(attr)->name_length, CASE_SENSITIVE, NULL, 0)
+
+static INDEX_ATTR_TYPE get_index_attr_type(ntfs_inode *ni, ATTR_RECORD *attr,
+					   INDEX_ROOT *index_root)
+{
+	char file_name[64];
+
+	if (!attr->name_length)
+		return INDEX_ATTR_UNKNOWN;
+
+	if (index_root->type) {
+		if (index_root->type == AT_FILE_NAME)
+			return INDEX_ATTR_DIRECTORY_I30;
+		else
+			/* weird, this should be illegal */
+			ntfs_log_error("Unknown index attribute type: 0x%0X\n",
+				       index_root->type);
+		return INDEX_ATTR_UNKNOWN;
+	}
+
+	if (utils_is_metadata(ni) <= 0)
+		return INDEX_ATTR_UNKNOWN;
+	if (utils_inode_get_name(ni, file_name, sizeof(file_name)) <= 0)
+		return INDEX_ATTR_UNKNOWN;
+
+	if (COMPARE_INDEX_NAMES(attr, NTFS_INDEX_SDH))
+		return INDEX_ATTR_SECURE_SDH;
+	else if (COMPARE_INDEX_NAMES(attr, NTFS_INDEX_SII))
+		return INDEX_ATTR_SECURE_SII;
+	else if (COMPARE_INDEX_NAMES(attr, NTFS_INDEX_SII))
+		return INDEX_ATTR_SECURE_SII;
+	else if (COMPARE_INDEX_NAMES(attr, NTFS_INDEX_Q))
+		return INDEX_ATTR_QUOTA_Q;
+	else if (COMPARE_INDEX_NAMES(attr, NTFS_INDEX_R))
+		return INDEX_ATTR_REPARSE_R;
+	else if (COMPARE_INDEX_NAMES(attr, NTFS_INDEX_O)) {
+		if (!strcmp(file_name, "/$Extend/$Quota"))
+			return INDEX_ATTR_QUOTA_O;
+		else if (!strcmp(file_name, "/$Extend/$ObjId"))
+			return INDEX_ATTR_OBJID_O;
+	}
+
+	return INDEX_ATTR_UNKNOWN;
+}
+
+static void ntfs_dump_index_attr_type(INDEX_ATTR_TYPE type)
+{
+	if (type == INDEX_ATTR_DIRECTORY_I30)
+		printf("DIRECTORY_I30");
+	else if (type == INDEX_ATTR_SECURE_SDH)
+		printf("SECURE_SDH");
+	else if (type == INDEX_ATTR_SECURE_SII)
+		printf("SECURE_SII");
+	else if (type == INDEX_ATTR_OBJID_O)
+		printf("OBJID_O");
+	else if (type == INDEX_ATTR_QUOTA_O)
+		printf("QUOTA_O");
+	else if (type == INDEX_ATTR_QUOTA_Q)
+		printf("QUOTA_Q");
+	else if (type == INDEX_ATTR_REPARSE_R)
+		printf("REPARSE_R");
+	else
+		printf("UNKNOWN");
+	printf("\n");
+}
+
+static void ntfs_dump_index_header(const char *indent, INDEX_HEADER *idx)
+{
+	printf("%sEntries Offset:\t\t %u (0x%x)\n", indent,
+			(unsigned)le32_to_cpu(idx->entries_offset),
+			(unsigned)le32_to_cpu(idx->entries_offset));
+	printf("%sIndex Size:\t\t %u (0x%x)\n", indent,
+			(unsigned)le32_to_cpu(idx->index_length),
+			(unsigned)le32_to_cpu(idx->index_length));
+	printf("%sAllocated Size:\t\t %u (0x%x)\n", indent,
+			(unsigned)le32_to_cpu(idx->allocated_size),
+			(unsigned)le32_to_cpu(idx->allocated_size));
+	printf("%sIndex header flags:\t 0x%02x\n", indent, idx->ih_flags);
+
+	/* FIXME: there are 3 reserved bytes here */
+}
+
+/**
+ * ntfs_dump_attr_index_root()
+ *
+ * dump the index_root attribute
+ */
+static void ntfs_dump_attr_index_root(ATTR_RECORD *attr, ntfs_inode *ni)
+{
+	INDEX_ATTR_TYPE type;
+	INDEX_ROOT *index_root = NULL;
+	INDEX_ENTRY *entry;
+
+	index_root = (INDEX_ROOT*)((u8*)attr + le16_to_cpu(attr->value_offset));
+
+	/* attr_type dumping */
+	type = get_index_attr_type(ni, attr, index_root);
+	printf("\tIndexed Attr Type:\t ");
+	ntfs_dump_index_attr_type(type);
+
+	/* collation rule dumping */
+	printf("\tCollation Rule:\t\t %u (0x%x)\n",
+			(unsigned)le32_to_cpu(index_root->collation_rule),
+			(unsigned)le32_to_cpu(index_root->collation_rule));
+/*	COLLATION_BINARY, COLLATION_FILE_NAME, COLLATION_UNICODE_STRING,
+	COLLATION_NTOFS_ULONG, COLLATION_NTOFS_SID,
+	COLLATION_NTOFS_SECURITY_HASH, COLLATION_NTOFS_ULONGS */
+
+	printf("\tIndex Block Size:\t %u (0x%x)\n",
+			(unsigned)le32_to_cpu(index_root->index_block_size),
+			(unsigned)le32_to_cpu(index_root->index_block_size));
+	if (le32_to_cpu(index_root->index_block_size) < ni->vol->cluster_size)
+		printf("\t512-byte Units Per Block:\t %u (0x%x)\n",
+			(unsigned)index_root->clusters_per_index_block,
+			(unsigned)index_root->clusters_per_index_block);
+	else
+		printf("\tClusters Per Block:\t %u (0x%x)\n",
+			(unsigned)index_root->clusters_per_index_block,
+			(unsigned)index_root->clusters_per_index_block);
+
+	ntfs_dump_index_header("\t", &index_root->index);
+
+	entry = (INDEX_ENTRY*)((u8*)index_root +
+			le32_to_cpu(index_root->index.entries_offset) + 0x10);
+	ntfs_log_verbose("\tDumping index root:\n");
+	printf("\tIndex entries total:\t %d\n",
+			ntfs_dump_index_entries(entry, type));
+}
+
+static void ntfs_dump_usa_lsn(const char *indent, MFT_RECORD *mrec)
+{
+	printf("%sUpd. Seq. Array Off.:\t %u (0x%x)\n", indent,
+			(unsigned)le16_to_cpu(mrec->usa_ofs),
+			(unsigned)le16_to_cpu(mrec->usa_ofs));
+	printf("%sUpd. Seq. Array Count:\t %u (0x%x)\n", indent,
+			(unsigned)le16_to_cpu(mrec->usa_count),
+			(unsigned)le16_to_cpu(mrec->usa_count));
+	printf("%sUpd. Seq. Number:\t %u (0x%x)\n", indent,
+			(unsigned)le16_to_cpup((le16*)((u8*)mrec +
+				le16_to_cpu(mrec->usa_ofs))),
+			(unsigned)le16_to_cpup((le16*)((u8*)mrec +
+				le16_to_cpu(mrec->usa_ofs))));
+	printf("%sLogFile Seq. Number:\t 0x%llx\n", indent,
+			(unsigned long long)sle64_to_cpu(mrec->lsn));
+}
+
+
+static s32 ntfs_dump_index_block(INDEX_BLOCK *ib, INDEX_ATTR_TYPE type,
+		u32 ib_size)
+{
+	INDEX_ENTRY *entry;
+
+	if (ntfs_mst_post_read_fixup((NTFS_RECORD*)ib, ib_size)) {
+		ntfs_log_perror("Damaged INDX record");
+		return -1;
+	}
+	ntfs_log_verbose("\tDumping index block:\n");
+	if (opts.verbose)
+		ntfs_dump_usa_lsn("\t\t", (MFT_RECORD*)ib);
+
+	ntfs_log_verbose("\t\tNode VCN:\t\t %lld (0x%llx)\n",
+			(unsigned long long)sle64_to_cpu(ib->index_block_vcn),
+			(unsigned long long)sle64_to_cpu(ib->index_block_vcn));
+
+	entry = (INDEX_ENTRY*)((u8*)ib +
+				le32_to_cpu(ib->index.entries_offset) + 0x18);
+
+	if (opts.verbose) {
+		ntfs_dump_index_header("\t\t", &ib->index);
+		printf("\n");
+	}
+
+	return ntfs_dump_index_entries(entry, type);
+}
+
+/**
+ * ntfs_dump_attr_index_allocation()
+ *
+ * dump context of the index_allocation attribute
+ */
+static void ntfs_dump_attr_index_allocation(ATTR_RECORD *attr, ntfs_inode *ni)
+{
+	INDEX_ALLOCATION *allocation, *tmp_alloc;
+	INDEX_ROOT *ir;
+	INDEX_ATTR_TYPE type;
+	int total_entries = 0;
+	int total_indx_blocks = 0;
+	u8 *bitmap, *byte;
+	int bit;
+	ntfschar *name;
+	u32 name_len;
+	s64 data_size;
+
+	ir = ntfs_index_root_get(ni, attr);
+	if (!ir) {
+		ntfs_log_perror("Failed to read $INDEX_ROOT attribute");
+		return;
+	}
+
+	type = get_index_attr_type(ni, attr, ir);
+
+	name = (ntfschar *)((u8 *)attr + le16_to_cpu(attr->name_offset));
+	name_len = attr->name_length;
+
+	byte = bitmap = ntfs_attr_readall(ni, AT_BITMAP, name, name_len, NULL);
+	if (!byte) {
+		ntfs_log_perror("Failed to read $BITMAP attribute");
+		goto out_index_root;
+	}
+
+	tmp_alloc = allocation = ntfs_attr_readall(ni, AT_INDEX_ALLOCATION,
+						   name, name_len, &data_size);
+	if (!tmp_alloc) {
+		ntfs_log_perror("Failed to read $INDEX_ALLOCATION attribute");
+		goto out_bitmap;
+	}
+
+	bit = 0;
+	while ((u8 *)tmp_alloc < (u8 *)allocation + data_size) {
+		if (*byte & (1 << bit)) {
+			int entries;
+
+			entries = ntfs_dump_index_block(tmp_alloc, type,
+							le32_to_cpu(
+							ir->index_block_size));
+	       		if (entries != -1) {
+				total_entries += entries;
+				total_indx_blocks++;
+				ntfs_log_verbose("\tIndex entries:\t\t %d\n",
+						entries);
+			}
+		}
+		tmp_alloc = (INDEX_ALLOCATION *)((u8 *)tmp_alloc +
+						le32_to_cpu(
+						ir->index_block_size));
+		bit++;
+		if (bit > 7) {
+			bit = 0;
+			byte++;
+		}
+	}
+
+	printf("\tIndex entries total:\t %d\n", total_entries);
+	printf("\tINDX blocks total:\t %d\n", total_indx_blocks);
+
+	free(allocation);
+out_bitmap:
+	free(bitmap);
+out_index_root:
+	free(ir);
+}
+
+/**
+ * ntfs_dump_attr_bitmap()
+ *
+ * dump the bitmap attribute
+ */
+static void ntfs_dump_attr_bitmap(ATTR_RECORD *attr __attribute__((unused)))
+{
+	/* TODO */
+}
+
+/**
+ * ntfs_dump_attr_reparse_point()
+ *
+ * of ntfs 3.x dumps the reparse_point attribute
+ */
+static void ntfs_dump_attr_reparse_point(ATTR_RECORD *attr __attribute__((unused)))
+{
+	/* TODO */
+}
+
+/**
+ * ntfs_dump_attr_ea_information()
+ *
+ * dump the ea_information attribute
+ */
+static void ntfs_dump_attr_ea_information(ATTR_RECORD *attr)
+{
+	EA_INFORMATION *ea_info;
+
+	ea_info = (EA_INFORMATION*)((u8*)attr +
+			le16_to_cpu(attr->value_offset));
+	printf("\tPacked EA length:\t %u (0x%x)\n",
+			(unsigned)le16_to_cpu(ea_info->ea_length),
+			(unsigned)le16_to_cpu(ea_info->ea_length));
+	printf("\tNEED_EA count:\t\t %u (0x%x)\n",
+			(unsigned)le16_to_cpu(ea_info->need_ea_count),
+			(unsigned)le16_to_cpu(ea_info->need_ea_count));
+	printf("\tUnpacked EA length:\t %u (0x%x)\n",
+			(unsigned)le32_to_cpu(ea_info->ea_query_length),
+			(unsigned)le32_to_cpu(ea_info->ea_query_length));
+}
+
+/**
+ * ntfs_dump_attr_ea()
+ *
+ * dump the ea attribute
+ */
+static void ntfs_dump_attr_ea(ATTR_RECORD *attr, ntfs_volume *vol)
+{
+	const EA_ATTR *ea;
+	const u8 *pvalue;
+	u8 *buf = NULL;
+	const le32 *pval;
+	int offset;
+	int cnt;
+	s64 data_size;
+
+	if (attr->non_resident) {
+		runlist *rl;
+
+		data_size = sle64_to_cpu(attr->data_size);
+		if (!opts.verbose)
+			return;
+		/* FIXME: We don't handle fragmented mapping pairs case. */
+		rl = ntfs_mapping_pairs_decompress(vol, attr, NULL);
+		if (rl) {
+			s64 bytes_read;
+
+			buf = ntfs_malloc(data_size);
+			if (!buf) {
+				free(rl);
+				return;
+			}
+			bytes_read = ntfs_rl_pread(vol, rl, 0, data_size, buf);
+			if (bytes_read != data_size) {
+				ntfs_log_perror("ntfs_rl_pread failed");
+				free(buf);
+				free(rl);
+				return;
+			}
+			free(rl);
+			ea = (EA_ATTR*)buf;
+		} else {
+			ntfs_log_perror("ntfs_mapping_pairs_decompress failed");
+			return;
+		}
+	} else {
+		data_size = le32_to_cpu(attr->value_length);
+		if (!opts.verbose)
+			return;
+		ea = (EA_ATTR*)((u8*)attr + le16_to_cpu(attr->value_offset));
+	}
+	offset = 0;
+	while (1) {
+		printf("\n\tEA flags:\t\t ");
+		if (ea->flags) {
+			if (ea->flags == NEED_EA)
+				printf("NEED_EA\n");
+			else
+				printf("Unknown (0x%02x)\n",
+						(unsigned)ea->flags);
+		} else
+			printf("NONE\n");
+		printf("\tName length:\t %d (0x%x)\n",
+				(unsigned)ea->name_length,
+				(unsigned)ea->name_length);
+		printf("\tValue length:\t %d (0x%x)\n",
+				(unsigned)le16_to_cpu(ea->value_length),
+				(unsigned)le16_to_cpu(ea->value_length));
+			/* Name expected to be null terminated ? */
+		printf("\tName:\t\t '%s'\n", ea->name);
+		printf("\tValue:\t\t ");
+		if (ea->name_length == 11 &&
+				!strncmp((const char*)"SETFILEBITS",
+				(const char*)ea->name, 11)) {
+			pval = (const le32*)(ea->value + ea->name_length + 1);
+			printf("0%lo\n", (unsigned long)le32_to_cpu(*pval));
+		} else {
+			/* No alignment for value */
+			pvalue = ea->value + ea->name_length + 1;
+			/* Hex show a maximum of 32 bytes */
+			cnt = le16_to_cpu(ea->value_length);
+			printf(cnt ? "0x" : "(NONE)");
+			if (cnt > 32)
+				cnt = 32;
+			while (cnt-- > 0)
+				printf("%02x",*pvalue++);
+			if (le16_to_cpu(ea->value_length) > 32)
+				printf("...\n");
+			else
+				printf("\n");
+		}
+		if (ea->next_entry_offset) {
+			offset += le32_to_cpu(ea->next_entry_offset);
+			ea = (const EA_ATTR*)((const u8*)ea
+					+ le32_to_cpu(ea->next_entry_offset));
+		} else
+			break;
+		if (offset >= data_size)
+			break;
+	}
+	free(buf);
+}
+
+/**
+ * ntfs_dump_attr_property_set()
+ *
+ * dump the property_set attribute
+ */
+static void ntfs_dump_attr_property_set(ATTR_RECORD *attr __attribute__((unused)))
+{
+	/* TODO */
+}
+
+static void ntfs_hex_dump(void *buf,unsigned int length);
+
+/**
+ * ntfs_dump_attr_logged_utility_stream()
+ *
+ * dump the property_set attribute
+ */
+static void ntfs_dump_attr_logged_utility_stream(ATTR_RECORD *attr,
+		ntfs_inode *ni)
+{
+	char *buf;
+	s64 size;
+
+	if (!opts.verbose)
+		return;
+	buf = ntfs_attr_readall(ni, AT_LOGGED_UTILITY_STREAM,
+			ntfs_attr_get_name(attr), attr->name_length, &size);
+	if (buf)
+		ntfs_hex_dump(buf, size);
+	free(buf);
+	/* TODO */
+}
+
+/**
+ * ntfs_hex_dump
+ */
+static void ntfs_hex_dump(void *buf,unsigned int length)
+{
+	unsigned int i=0;
+	while (i<length) {
+		unsigned int j;
+
+		/* line start */
+		printf("\t%04X  ",i);
+
+		/* hex content */
+		for (j=i;(j<length) && (j<i+16);j++) {
+			unsigned char c = *((char *)buf + j);
+			printf("%02hhX ",c);
+		}
+
+		/* realign */
+		for (;j<i+16;j++) {
+			printf("   ");
+		}
+
+		/* char content */
+		for (j=i;(j<length) && (j<i+16);j++) {
+			unsigned char c = *((char *)buf + j);
+			/* display unprintable chars as '.' */
+			if ((c<32) || (c>126)) {
+				c = '.';
+			}
+			printf("%c",c);
+		}
+
+		/* end line */
+		printf("\n");
+		i=j;
+	}
+}
+
+/**
+ * ntfs_dump_attr_unknown
+ */
+static void ntfs_dump_attr_unknown(ATTR_RECORD *attr)
+{
+	printf("=====  Please report this unknown attribute type to %s =====\n",
+	       NTFS_DEV_LIST);
+
+	if (!attr->non_resident) {
+		/* hex dump */
+		printf("\tDumping some of the attribute data:\n");
+		ntfs_hex_dump((u8*)attr + le16_to_cpu(attr->value_offset),
+				(le32_to_cpu(attr->value_length) > 128) ?
+				128 : le32_to_cpu(attr->value_length));
+	}
+}
+
+/**
+ * ntfs_dump_inode_general_info
+ */
+static void ntfs_dump_inode_general_info(ntfs_inode *inode)
+{
+	MFT_RECORD *mrec = inode->mrec;
+	le16 inode_flags  = mrec->flags;
+
+	printf("Dumping Inode %llu (0x%llx)\n",
+			(long long)inode->mft_no,
+			(unsigned long long)inode->mft_no);
+
+	ntfs_dump_usa_lsn("", mrec);
+	printf("MFT Record Seq. Numb.:\t %u (0x%x)\n",
+			(unsigned)le16_to_cpu(mrec->sequence_number),
+			(unsigned)le16_to_cpu(mrec->sequence_number));
+	printf("Number of Hard Links:\t %u (0x%x)\n",
+			(unsigned)le16_to_cpu(mrec->link_count),
+			(unsigned)le16_to_cpu(mrec->link_count));
+	printf("Attribute Offset:\t %u (0x%x)\n",
+			(unsigned)le16_to_cpu(mrec->attrs_offset),
+			(unsigned)le16_to_cpu(mrec->attrs_offset));
+
+	printf("MFT Record Flags:\t ");
+	if (inode_flags) {
+		if (MFT_RECORD_IN_USE & inode_flags) {
+			printf("IN_USE ");
+			inode_flags &= ~MFT_RECORD_IN_USE;
+		}
+		if (MFT_RECORD_IS_DIRECTORY & inode_flags) {
+			printf("DIRECTORY ");
+			inode_flags &= ~MFT_RECORD_IS_DIRECTORY;
+		}
+		/* The meaning of IS_4 is illusive but not its existence. */
+		if (MFT_RECORD_IS_4 & inode_flags) {
+			printf("IS_4 ");
+			inode_flags &= ~MFT_RECORD_IS_4;
+		}
+		if (MFT_RECORD_IS_VIEW_INDEX & inode_flags) {
+			printf("VIEW_INDEX ");
+			inode_flags &= ~MFT_RECORD_IS_VIEW_INDEX;
+		}
+		if (inode_flags)
+			printf("UNKNOWN: 0x%04x", (unsigned)le16_to_cpu(
+						inode_flags));
+	} else {
+		printf("none");
+	}
+	printf("\n");
+
+	printf("Bytes Used:\t\t %u (0x%x) bytes\n",
+			(unsigned)le32_to_cpu(mrec->bytes_in_use),
+			(unsigned)le32_to_cpu(mrec->bytes_in_use));
+	printf("Bytes Allocated:\t %u (0x%x) bytes\n",
+			(unsigned)le32_to_cpu(mrec->bytes_allocated),
+			(unsigned)le32_to_cpu(mrec->bytes_allocated));
+
+	if (mrec->base_mft_record) {
+		printf("Base MFT Record:\t %llu (0x%llx)\n",
+				(unsigned long long)
+				MREF_LE(mrec->base_mft_record),
+				(unsigned long long)
+				MREF_LE(mrec->base_mft_record));
+	}
+	printf("Next Attribute Instance: %u (0x%x)\n",
+			(unsigned)le16_to_cpu(mrec->next_attr_instance),
+			(unsigned)le16_to_cpu(mrec->next_attr_instance));
+
+	printf("MFT Padding:\t");
+	ntfs_dump_bytes((u8 *)mrec, le16_to_cpu(mrec->usa_ofs) +
+			2 * le16_to_cpu(mrec->usa_count),
+			le16_to_cpu(mrec->attrs_offset));
+	printf("\n");
+}
+
+/**
+ * ntfs_get_file_attributes
+ */
+static void ntfs_dump_file_attributes(ntfs_inode *inode)
+{
+	struct RUNCOUNT runcount;
+	ntfs_attr_search_ctx *ctx = NULL;
+
+	runcount.runs = 0;
+	runcount.fragments = 0;
+	/* then start enumerating attributes
+	   see ntfs_attr_lookup documentation for detailed explanation */
+	ctx = ntfs_attr_get_search_ctx(inode, NULL);
+	while (!ntfs_attr_lookup(AT_UNUSED, NULL, 0, CASE_SENSITIVE,
+			0, NULL, 0, ctx)) {
+		if (ctx->attr->type == AT_END || ctx->attr->type == AT_UNUSED) {
+			printf("Weird: %s attribute type was found, please "
+					"report this.\n",
+					get_attribute_type_name(
+					ctx->attr->type));
+			continue;
+		}
+
+		ntfs_dump_attribute_header(ctx, inode->vol, &runcount);
+
+		switch (ctx->attr->type) {
+		case AT_STANDARD_INFORMATION:
+			ntfs_dump_attr_standard_information(ctx->attr);
+			break;
+		case AT_ATTRIBUTE_LIST:
+			ntfs_dump_attr_list(ctx->attr, inode->vol);
+			break;
+		case AT_FILE_NAME:
+			ntfs_dump_attr_file_name(ctx->attr);
+			break;
+		case AT_OBJECT_ID:
+			ntfs_dump_attr_object_id(ctx->attr, inode->vol);
+			break;
+		case AT_SECURITY_DESCRIPTOR:
+			ntfs_dump_attr_security_descriptor(ctx->attr,
+					inode->vol);
+			break;
+		case AT_VOLUME_NAME:
+			ntfs_dump_attr_volume_name(ctx->attr);
+			break;
+		case AT_VOLUME_INFORMATION:
+			ntfs_dump_attr_volume_information(ctx->attr);
+			break;
+		case AT_DATA:
+			ntfs_dump_attr_data(ctx->attr, inode);
+			break;
+		case AT_INDEX_ROOT:
+			ntfs_dump_attr_index_root(ctx->attr, inode);
+			break;
+		case AT_INDEX_ALLOCATION:
+			ntfs_dump_attr_index_allocation(ctx->attr, inode);
+			break;
+		case AT_BITMAP:
+			ntfs_dump_attr_bitmap(ctx->attr);
+			break;
+		case AT_REPARSE_POINT:
+			ntfs_dump_attr_reparse_point(ctx->attr);
+			break;
+		case AT_EA_INFORMATION:
+			ntfs_dump_attr_ea_information(ctx->attr);
+			break;
+		case AT_EA:
+			ntfs_dump_attr_ea(ctx->attr, inode->vol);
+			break;
+		case AT_PROPERTY_SET:
+			ntfs_dump_attr_property_set(ctx->attr);
+			break;
+		case AT_LOGGED_UTILITY_STREAM:
+			ntfs_dump_attr_logged_utility_stream(ctx->attr, inode);
+			break;
+		default:
+			ntfs_dump_attr_unknown(ctx->attr);
+		}
+	}
+
+	/* if we exited the loop before we're done - notify the user */
+	if (errno != ENOENT) {
+		ntfs_log_perror("ntfsinfo error: stopped before finished "
+				"enumerating attributes");
+	} else {
+		printf("End of inode reached\n");
+		if (opts.verbose) {
+			printf("Total runs: %lu (fragments: %lu)\n",
+					runcount.runs, runcount.fragments);
+		}
+	}
+
+	/* close all data-structures we used */
+	ntfs_attr_put_search_ctx(ctx);
+	ntfs_inode_close(inode);
+}
+
+/**
+ * main() - Begin here
+ *
+ * Start from here.
+ *
+ * Return:  0  Success, the program worked
+ *	    1  Error, something went wrong
+ */
+int main(int argc, char **argv)
+{
+	ntfs_volume *vol;
+	int res;
+
+	setlinebuf(stdout);
+
+	ntfs_log_set_handler(ntfs_log_handler_outerr);
+
+	res = parse_options(argc, argv);
+	if (res > 0)
+		printf("Failed to parse command line options\n");
+	if (res >= 0)
+		exit(res);
+
+	utils_set_locale();
+
+	vol = utils_mount_volume(opts.device, NTFS_MNT_RDONLY |
+			(opts.force ? NTFS_MNT_RECOVER : 0));
+	if (!vol) {
+		printf("Failed to open '%s'.\n", opts.device);
+		exit(1);
+	}
+
+	/*
+	 * if opts.mft is not 0, then we will print out information about
+	 * the volume, such as the sector size and whatnot.
+	 */
+	if (opts.mft)
+		ntfs_dump_volume(vol);
+
+	if ((opts.inode != -1) || opts.filename) {
+		ntfs_inode *inode;
+		/* obtain the inode */
+		if (opts.filename) {
+			inode = ntfs_pathname_to_inode(vol, NULL,
+					opts.filename);
+		} else {
+			inode = ntfs_inode_open(vol, MK_MREF(opts.inode, 0));
+		}
+
+		/* dump the inode information */
+		if (inode) {
+			/* general info about the inode's mft record */
+			ntfs_dump_inode_general_info(inode);
+			/* dump attributes */
+			ntfs_dump_file_attributes(inode);
+		} else {
+			/* can't open inode */
+			/*
+			 * note: when the specified inode does not exist, either
+			 * EIO or or ESPIPE is returned, we should notify better
+			 * in those cases
+			 */
+			ntfs_log_perror("Error loading node");
+		}
+	}
+
+	ntfs_umount(vol, FALSE);
+	return 0;
+}
+
diff --git a/ntfsprogs/ntfslabel.8 b/ntfsprogs/ntfslabel.8
new file mode 100755
index 0000000000000000000000000000000000000000..20f0690e70d7ee637263f0ff58a711e38f39782a
--- /dev/null
+++ b/ntfsprogs/ntfslabel.8
@@ -0,0 +1,119 @@
+.\" Copyright (c) 2002\-2004 Anton Altaparmakov.
+.\" Copyright (c) 2005 Richard Russon.
+.\" Copyright (c) 2012 Jean-Pierre Andre.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSLABEL 8 "January 2012" "ntfs-3g 2015.3.14"
+.SH NAME
+ntfslabel \- display/change the label on an ntfs file system
+.SH SYNOPSIS
+.B ntfslabel
+[\fIoptions\fR] \fIdevice \fR[\fInew\-label\fR]
+.SH DESCRIPTION
+.B ntfslabel
+will display or change the file system label on the ntfs file system located on
+.IR device .
+It can also change the serial number of the
+.IR device .
+.PP
+If the optional argument
+.I new\-label
+is not present, and no option is present,
+.B ntfslabel
+will simply display the current file system label.
+.PP
+If the optional argument
+.I new\-label
+is present, then
+.B ntfslabel
+will set the file system label to be
+.IR new\-label .
+NTFS file system labels can be at most 128 Unicode characters long; if
+.I new\-label
+is longer than 128 Unicode characters,
+.B ntfslabel
+will truncate it and print a warning message.
+.PP
+It is also possible to set the file system label using the
+.B \-L
+option of
+.BR mkntfs (8)
+during creation of the file system.
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfslabel
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+This will override some sensible defaults, such as not working with a mounted
+volume.  Use this option with caution.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.TP
+\fB\-\-new\-serial\fR[\fI=ssssssssssssssss\fR], or
+.TP
+\fB\-\-new\-half\-serial\fR[\fI=ssssssss\fR]
+Set a new serial number to the device, either the argument value, or a random
+one if no argument is given. The serial number is a 64 bit number,
+represented as a sixteen-digit hexadecimal number, used to identify the
+device during the mounting process. As a consequence, two devices with the
+same serial number cannot be mounted at the same time on the same computer.
+This is not the volume UUID used by Windows to locate files which have been
+moved to another volume.
+
+The option \-\-new\-half\-serial only changes the upper part of the serial
+number, keeping the lower part which is used by Windows unchanged.
+In this case the optional argument is an eight-digit hexadecimal number.
+
+.TP
+\fB\-n\fR, \fB\-\-no\-action\fR
+Don't actually write to disk.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Reduce the amount of output to a minimum.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Increase the amount of output that
+.B ntfslabel
+prints. The label and the serial number are displayed.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Show the version number, copyright and license for
+.BR ntfslabel .
+.SH BUGS
+There are no known problems with
+.BR ntfslabel .
+If you find a bug please send an email describing the problem to the
+development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+.B ntfslabel
+was written by Matthew J. Fanto, with contributions from Anton Altaparmakov and
+Richard Russon.
+It was ported to ntfs-3g by Erik Larsson.
+.SH AVAILABILITY
+.B ntfslabel
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR mkntfs (8),
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/ntfslabel.8.in b/ntfsprogs/ntfslabel.8.in
new file mode 100755
index 0000000000000000000000000000000000000000..dcd4d00ed5d797f9c98c27e86ed76f33538b9172
--- /dev/null
+++ b/ntfsprogs/ntfslabel.8.in
@@ -0,0 +1,119 @@
+.\" Copyright (c) 2002\-2004 Anton Altaparmakov.
+.\" Copyright (c) 2005 Richard Russon.
+.\" Copyright (c) 2012 Jean-Pierre Andre.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSLABEL 8 "January 2012" "ntfs-3g @VERSION@"
+.SH NAME
+ntfslabel \- display/change the label on an ntfs file system
+.SH SYNOPSIS
+.B ntfslabel
+[\fIoptions\fR] \fIdevice \fR[\fInew\-label\fR]
+.SH DESCRIPTION
+.B ntfslabel
+will display or change the file system label on the ntfs file system located on
+.IR device .
+It can also change the serial number of the
+.IR device .
+.PP
+If the optional argument
+.I new\-label
+is not present, and no option is present,
+.B ntfslabel
+will simply display the current file system label.
+.PP
+If the optional argument
+.I new\-label
+is present, then
+.B ntfslabel
+will set the file system label to be
+.IR new\-label .
+NTFS file system labels can be at most 128 Unicode characters long; if
+.I new\-label
+is longer than 128 Unicode characters,
+.B ntfslabel
+will truncate it and print a warning message.
+.PP
+It is also possible to set the file system label using the
+.B \-L
+option of
+.BR mkntfs (8)
+during creation of the file system.
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfslabel
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+This will override some sensible defaults, such as not working with a mounted
+volume.  Use this option with caution.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.TP
+\fB\-\-new\-serial\fR[\fI=ssssssssssssssss\fR], or
+.TP
+\fB\-\-new\-half\-serial\fR[\fI=ssssssss\fR]
+Set a new serial number to the device, either the argument value, or a random
+one if no argument is given. The serial number is a 64 bit number,
+represented as a sixteen-digit hexadecimal number, used to identify the
+device during the mounting process. As a consequence, two devices with the
+same serial number cannot be mounted at the same time on the same computer.
+This is not the volume UUID used by Windows to locate files which have been
+moved to another volume.
+
+The option \-\-new\-half\-serial only changes the upper part of the serial
+number, keeping the lower part which is used by Windows unchanged.
+In this case the optional argument is an eight-digit hexadecimal number.
+
+.TP
+\fB\-n\fR, \fB\-\-no\-action\fR
+Don't actually write to disk.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Reduce the amount of output to a minimum.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Increase the amount of output that
+.B ntfslabel
+prints. The label and the serial number are displayed.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Show the version number, copyright and license for
+.BR ntfslabel .
+.SH BUGS
+There are no known problems with
+.BR ntfslabel .
+If you find a bug please send an email describing the problem to the
+development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+.B ntfslabel
+was written by Matthew J. Fanto, with contributions from Anton Altaparmakov and
+Richard Russon.
+It was ported to ntfs-3g by Erik Larsson.
+.SH AVAILABILITY
+.B ntfslabel
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR mkntfs (8),
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/ntfslabel.c b/ntfsprogs/ntfslabel.c
new file mode 100755
index 0000000000000000000000000000000000000000..c0494ab5fd6246eeff75e7c736731db6ac62d309
--- /dev/null
+++ b/ntfsprogs/ntfslabel.c
@@ -0,0 +1,463 @@
+/**
+ * ntfslabel - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2002 Matthew J. Fanto
+ * Copyright (c) 2002-2005 Anton Altaparmakov
+ * Copyright (c) 2002-2003 Richard Russon
+ * Copyright (c) 2012-2014 Jean-Pierre Andre
+ *
+ * This utility will display/change the label on an NTFS partition.
+ *
+ * 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 Linux-NTFS
+ * 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_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "debug.h"
+#include "mft.h"
+#include "utils.h"
+/* #include "version.h" */
+#include "logging.h"
+#include "misc.h"
+
+static const char *EXEC_NAME = "ntfslabel";
+
+static struct options {
+	char	*device;	/* Device/File to work with */
+	char	*label;		/* Set the label to this */
+	int	 quiet;		/* Less output */
+	int	 verbose;	/* Extra output */
+	int	 force;		/* Override common sense */
+	int	 new_serial;	/* Change the serial number */
+	unsigned long long serial;	/* Forced serial number value */
+	int	 noaction;	/* Do not write to disk */
+} opts;
+
+/**
+ * version - Print version information about the program
+ *
+ * Print a copyright statement and a brief description of the program.
+ *
+ * Return:  none
+ */
+static void version(void)
+{
+	ntfs_log_info("\n%s v%s (libntfs-3g) - Display, or set, the label for an "
+			"NTFS Volume.\n\n", EXEC_NAME, VERSION);
+	ntfs_log_info("Copyright (c)\n");
+	ntfs_log_info("    2002      Matthew J. Fanto\n");
+	ntfs_log_info("    2002-2005 Anton Altaparmakov\n");
+	ntfs_log_info("    2002-2003 Richard Russon\n");
+	ntfs_log_info("    2012-2014 Jean-Pierre Andre\n");
+	ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
+}
+
+/**
+ * usage - Print a list of the parameters to the program
+ *
+ * Print a list of the parameters and options for the program.
+ *
+ * Return:  none
+ */
+static void usage(void)
+{
+	ntfs_log_info("\nUsage: %s [options] device [label]\n"
+	       "    -n, --no-action    Do not write to disk\n"
+	       "    -f, --force        Use less caution\n"
+	       "        --new-serial   Set a new serial number\n"
+	       "        --new-half-serial Set a partial new serial number\n"
+	       "    -q, --quiet        Less output\n"
+	       "    -v, --verbose      More output\n"
+	       "    -V, --version      Display version information\n"
+	       "    -h, --help         Display this help\n\n",
+	       EXEC_NAME);
+	ntfs_log_info("%s%s\n", ntfs_bugs, ntfs_home);
+}
+
+/**
+ * parse_options - Read and validate the programs command line
+ *
+ * Read the command line, verify the syntax and parse the options.
+ * This function is very long, but quite simple.
+ *
+ * Return:  1 Success
+ *	    0 Error, one or more problems
+ */
+static int parse_options(int argc, char *argv[])
+{
+	static const char *sopt = "-fh?IinqvV";
+	static const struct option lopt[] = {
+		{ "force",	 no_argument,		NULL, 'f' },
+		{ "help",	 no_argument,		NULL, 'h' },
+		{ "new-serial",  optional_argument,	NULL, 'I' },
+		{ "new-half-serial", optional_argument,	NULL, 'i' },
+		{ "no-action",	 no_argument,		NULL, 'n' },
+		{ "quiet",	 no_argument,		NULL, 'q' },
+		{ "verbose",	 no_argument,		NULL, 'v' },
+		{ "version",	 no_argument,		NULL, 'V' },
+		{ NULL, 0, NULL, 0 },
+	};
+
+	int c = -1;
+	int err  = 0;
+	int ver  = 0;
+	int help = 0;
+	int levels = 0;
+	char *endserial;
+
+	opterr = 0; /* We'll handle the errors, thank you. */
+
+	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
+		switch (c) {
+		case 1:	/* A non-option argument */
+			if (!err && !opts.device)
+				opts.device = argv[optind-1];
+			else if (!err && !opts.label)
+				opts.label = argv[optind-1];
+			else
+				err++;
+			break;
+		case 'f':
+			opts.force++;
+			break;
+		case 'h':
+			help++;
+			break;
+		case 'I' :	/* not proposed as a short option letter */
+			if (optarg) {
+				opts.serial = strtoull(optarg, &endserial, 16);
+				if (*endserial)
+					ntfs_log_error("Bad hexadecimal serial number.\n");
+			}
+			opts.new_serial |= 2;
+			break;
+		case 'i' :	/* not proposed as a short option letter */
+			if (optarg) {
+				opts.serial = strtoull(optarg, &endserial, 16)
+							<< 32;
+				if (*endserial)
+					ntfs_log_error("Bad hexadecimal serial number.\n");
+			}
+			opts.new_serial |= 1;
+			break;
+		case 'n':
+			opts.noaction++;
+			break;
+		case 'q':
+			opts.quiet++;
+			ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
+			break;
+		case 'v':
+			opts.verbose++;
+			ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
+			break;
+		case 'V':
+			ver++;
+			break;
+		case '?':
+			if (strncmp (argv[optind-1], "--log-", 6) == 0) {
+				if (!ntfs_log_parse_option (argv[optind-1]))
+					err++;
+				break;
+			}
+			/* fall through */
+		default:
+			ntfs_log_error("Unknown option '%s'.\n", argv[optind-1]);
+			err++;
+			break;
+		}
+	}
+
+	/* Make sure we're in sync with the log levels */
+	levels = ntfs_log_get_levels();
+	if (levels & NTFS_LOG_LEVEL_VERBOSE)
+		opts.verbose++;
+	if (!(levels & NTFS_LOG_LEVEL_QUIET))
+		opts.quiet++;
+
+	if (help || ver) {
+		opts.quiet = 0;
+	} else {
+		if (opts.device == NULL) {
+			if (argc > 1)
+				ntfs_log_error("You must specify a device.\n");
+			err++;
+		}
+
+		if (opts.quiet && opts.verbose) {
+			ntfs_log_error("You may not use --quiet and --verbose at "
+					"the same time.\n");
+			err++;
+		}
+	}
+
+	if (ver)
+		version();
+	if (help || err)
+		usage();
+
+		/* tri-state 0 : done, 1 : error, -1 : proceed */
+	return (err ? 1 : (help || ver ? 0 : -1));
+}
+
+static int change_serial(ntfs_volume *vol, u64 sector, le64 serial_number,
+			NTFS_BOOT_SECTOR *bs, NTFS_BOOT_SECTOR *oldbs)
+{
+	int res;
+	le64 mask;
+	BOOL same;
+
+	res = -1;
+        if ((ntfs_pread(vol->dev, sector << vol->sector_size_bits,
+			vol->sector_size, bs) == vol->sector_size)) {
+		same = TRUE;
+		if (!sector)
+				/* save the real bootsector */
+			memcpy(oldbs, bs, vol->sector_size);
+		else
+				/* backup bootsector must be similar */
+			same = !memcmp(oldbs, bs, vol->sector_size);
+		if (same) {
+			if (opts.new_serial & 2)
+				bs->volume_serial_number = serial_number;
+			else {
+				mask = const_cpu_to_le64(~0x0ffffffffULL);
+				bs->volume_serial_number
+				    = (serial_number & mask)
+					| (bs->volume_serial_number & ~mask);
+			}
+			if (opts.noaction
+			    || (ntfs_pwrite(vol->dev,
+				sector << vol->sector_size_bits,
+				vol->sector_size, bs) == vol->sector_size)) {
+				res = 0;
+			}
+		} else {
+			ntfs_log_info("* Warning : the backup boot sector"
+				" does not match (leaving unchanged)\n");
+			res = 0;
+		}
+	}
+	return (res);
+}
+
+static int set_new_serial(ntfs_volume *vol)
+{
+	NTFS_BOOT_SECTOR *bs; /* full boot sectors */
+	NTFS_BOOT_SECTOR *oldbs; /* full original boot sector */
+	le64 serial_number;
+	u64 number_of_sectors;
+	u64 sn;
+	int res;
+
+	res = -1;
+	bs = (NTFS_BOOT_SECTOR*)ntfs_malloc(vol->sector_size);
+	oldbs = (NTFS_BOOT_SECTOR*)ntfs_malloc(vol->sector_size);
+	if (bs && oldbs) {
+		if (opts.serial)
+			serial_number = cpu_to_le64(opts.serial);
+		else {
+			/* different values for parallel processes */
+			srandom(time((time_t*)NULL) ^ (getpid() << 16));
+			sn = ((u64)random() << 32)
+					| ((u64)random() & 0xffffffff);
+			serial_number = cpu_to_le64(sn);
+		}
+		if (!change_serial(vol, 0, serial_number, bs, oldbs)) {
+			number_of_sectors = le64_to_cpu(bs->number_of_sectors);
+			if (!change_serial(vol, number_of_sectors,
+						serial_number, bs, oldbs)) {
+				ntfs_log_info("New serial number : %016llx\n",
+					(long long)le64_to_cpu(
+						bs->volume_serial_number));
+				res = 0;
+				}
+		}
+		free(bs);
+		free(oldbs);
+	}
+	if (res)
+		ntfs_log_info("Error setting a new serial number\n");
+	return (res);
+}
+
+static int print_serial(ntfs_volume *vol)
+{
+	NTFS_BOOT_SECTOR *bs; /* full boot sectors */
+	int res;
+
+	res = -1;
+	bs = (NTFS_BOOT_SECTOR*)ntfs_malloc(vol->sector_size);
+	if (bs
+	    && (ntfs_pread(vol->dev, 0,
+			vol->sector_size, bs) == vol->sector_size)) {
+		ntfs_log_info("Serial number : %016llx\n",
+			(long long)le64_to_cpu(bs->volume_serial_number));
+		res = 0;
+		free(bs);
+	}
+	if (res)
+		ntfs_log_info("Error getting the serial number\n");
+	return (res);
+}
+
+/**
+ * print_label - display the current label of a mounted ntfs partition.
+ * @dev:	device to read the label from
+ * @mnt_flags:	mount flags of the device or 0 if not mounted
+ * @mnt_point:	mount point of the device or NULL
+ *
+ * Print the label of the device @dev.
+ */
+static int print_label(ntfs_volume *vol, unsigned long mnt_flags)
+{
+	int result = 0;
+	//XXX significant?
+	if ((mnt_flags & (NTFS_MF_MOUNTED | NTFS_MF_READONLY)) ==
+			NTFS_MF_MOUNTED) {
+		ntfs_log_error("%s is mounted read-write, results may be "
+			"unreliable.\n", opts.device);
+		result = 1;
+	}
+
+	if (opts.verbose)
+		ntfs_log_info("Volume label :  %s\n", vol->vol_name);
+	else
+		ntfs_log_info("%s\n", vol->vol_name);
+	return result;
+}
+
+/**
+ * change_label - change the current label on a device
+ * @dev:	device to change the label on
+ * @mnt_flags:	mount flags of the device or 0 if not mounted
+ * @mnt_point:	mount point of the device or NULL
+ * @label:	the new label
+ *
+ * Change the label on the device @dev to @label.
+ */
+static int change_label(ntfs_volume *vol, char *label)
+{
+	ntfschar *new_label = NULL;
+	int label_len;
+	int result = 0;
+
+	label_len = ntfs_mbstoucs(label, &new_label);
+	if (label_len == -1) {
+		ntfs_log_perror("Unable to convert label string to Unicode");
+		return 1;
+	}
+	else if (label_len*sizeof(ntfschar) > 0x100) {
+		ntfs_log_warning("New label is too long. Maximum %u characters "
+				"allowed. Truncating %u excess characters.\n",
+				(unsigned)(0x100 / sizeof(ntfschar)),
+				(unsigned)(label_len -
+				(0x100 / sizeof(ntfschar))));
+		label_len = 0x100 / sizeof(ntfschar);
+		label[label_len] = const_cpu_to_le16(0);
+	}
+
+	if(!opts.noaction)
+		result = ntfs_volume_rename(vol, new_label, label_len) ? 1 : 0;
+
+	free(new_label);
+	return result;
+}
+
+/**
+ * main - Begin here
+ *
+ * Start from here.
+ *
+ * Return:  0  Success, the program worked
+ *	    1  Error, something went wrong
+ */
+int main(int argc, char **argv)
+{
+	unsigned long mnt_flags = 0;
+	int result = 0;
+	ntfs_volume *vol;
+
+	ntfs_log_set_handler(ntfs_log_handler_outerr);
+
+	result = parse_options(argc, argv);
+	if (result >= 0)
+		return (result);
+
+	result = 0;
+	utils_set_locale();
+
+	if ((opts.label || opts.new_serial)
+	    && !opts.noaction
+	    && !opts.force
+	    && !ntfs_check_if_mounted(opts.device, &mnt_flags)
+	    && (mnt_flags & NTFS_MF_MOUNTED)) {
+		ntfs_log_error("Cannot make changes to a mounted device\n");
+		result = 1;
+		goto abort;
+	}
+
+	if (!opts.label && !opts.new_serial)
+		opts.noaction++;
+
+	vol = utils_mount_volume(opts.device,
+			(opts.noaction ? NTFS_MNT_RDONLY : 0) |
+			(opts.force ? NTFS_MNT_RECOVER : 0));
+	if (!vol)
+		return 1;
+
+	if (opts.new_serial) {
+		result = set_new_serial(vol);
+		if (result)
+			goto unmount;
+	} else {
+		if (opts.verbose)
+			result = print_serial(vol);
+	}
+	if (opts.label)
+		result = change_label(vol, opts.label);
+	else
+		result = print_label(vol, mnt_flags);
+
+unmount :
+	ntfs_umount(vol, FALSE);
+abort :
+		/* "result" may be a negative reply of a library function */
+	return (result ? 1 : 0);
+}
+
diff --git a/ntfsprogs/ntfsls.8 b/ntfsprogs/ntfsls.8
new file mode 100755
index 0000000000000000000000000000000000000000..382fa3ee11518a5e8bf45060a4dcc8def143c652
--- /dev/null
+++ b/ntfsprogs/ntfsls.8
@@ -0,0 +1,172 @@
+.\" Copyright (c) 2003 Anton Altaparmakov.
+.\" Copyright (c) 2005 Richard Russon.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSLS 8 "November 2005" "ntfs-3g 2015.3.14"
+.SH NAME
+ntfsls \- list directory contents on an NTFS filesystem
+.SH SYNOPSIS
+.B ntfsls
+[\fIoptions\fR] \fIdevice\fR
+.sp
+.B ntfsls
+[
+.B \-a
+|
+.B \-\-all
+]
+[
+.B \-F
+|
+.B \-\-classify
+]
+[
+.B \-f
+|
+.B \-\-force
+]
+[
+.B \-h
+|
+.B \-\-help
+]
+[
+.B \-i
+|
+.B \-\-inode
+]
+[
+.B \-l
+|
+.B \-\-long
+]
+[
+.B \-p
+|
+.B \-\-path
+.I PATH
+]
+[
+.B \-q
+|
+.B \-\-quiet
+]
+[
+.B \-s
+|
+.B \-\-system
+]
+[
+.B \-V
+|
+.B \-\-version
+]
+[
+.B \-v
+|
+.B \-\-verbose
+]
+[
+.B \-x
+|
+.B \-\-dos
+]
+.I device
+.SH DESCRIPTION
+.B ntfsls
+is used to list information about the files specified by the
+.I PATH
+option (the root directory by default).
+.I DEVICE
+is the special file corresponding to the device (e.g
+.IR /dev/hdXX )
+or an NTFS image file.
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfsls
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-a\fR, \fB\-\-all\fR
+Display all files.  If this option is not specified file names in the POSIX
+namespace will not be displayed.
+.TP
+\fB\-F\fR, \fB\-\-classify\fR
+Append indicator (one of */=@|) to entries.
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+Force execution.  For example necessary to run on an NTFS partition stored in
+a normal file.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print the usage information of
+.B ntfsls
+and exit.
+.TP
+\fB\-i\fR, \fB\-\-inode\fR
+Print inode number of each file.  This is the MFT reference number in NTFS
+terminology.
+.TP
+\fB\-l\fR, \fB\-\-long\fR
+Use a long listing format.
+.TP
+\fB\-p\fR, \fB\-\-path\fR PATH
+The directory whose contents to list or the file (including the path) about
+which to display information.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Suppress some debug/warning/error messages.
+.TP
+\fB\-R\fR, \fB\-\-recursive\fR
+Show the contents of all directories beneath the specified directory.
+.TP
+\fB\-s\fR, \fB\-\-system\fR
+Unless this options is specified, all files beginning with a dollar sign
+character will not be listed as these files are usually system files.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Display more debug/warning/error messages.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Print the version number of
+.B ntfsls
+and exit.
+.TP
+\fB\-x\fR, \fB\-\-dos\fR
+Display short file names, i.e. files in the DOS namespace, instead of long
+file names, i.e. files in the WIN32 namespace.
+.SH BUGS
+There are no known problems with
+.BR ntfsls .
+If you find a bug please send an email describing the problem to the
+development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+This version of
+.B ntfsls
+was written by Lode Leroy, Anton Altaparmakov, Richard Russon, Carmelo Kintana
+and Giang Nguyen.
+It was ported to ntfs-3g by Erik Larsson.
+.SH AVAILABILITY
+.B ntfsls
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/ntfsls.8.in b/ntfsprogs/ntfsls.8.in
new file mode 100755
index 0000000000000000000000000000000000000000..f528a3bb1a6447202c5aa580eb4cdaba8e7731ad
--- /dev/null
+++ b/ntfsprogs/ntfsls.8.in
@@ -0,0 +1,172 @@
+.\" Copyright (c) 2003 Anton Altaparmakov.
+.\" Copyright (c) 2005 Richard Russon.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSLS 8 "November 2005" "ntfs-3g @VERSION@"
+.SH NAME
+ntfsls \- list directory contents on an NTFS filesystem
+.SH SYNOPSIS
+.B ntfsls
+[\fIoptions\fR] \fIdevice\fR
+.sp
+.B ntfsls
+[
+.B \-a
+|
+.B \-\-all
+]
+[
+.B \-F
+|
+.B \-\-classify
+]
+[
+.B \-f
+|
+.B \-\-force
+]
+[
+.B \-h
+|
+.B \-\-help
+]
+[
+.B \-i
+|
+.B \-\-inode
+]
+[
+.B \-l
+|
+.B \-\-long
+]
+[
+.B \-p
+|
+.B \-\-path
+.I PATH
+]
+[
+.B \-q
+|
+.B \-\-quiet
+]
+[
+.B \-s
+|
+.B \-\-system
+]
+[
+.B \-V
+|
+.B \-\-version
+]
+[
+.B \-v
+|
+.B \-\-verbose
+]
+[
+.B \-x
+|
+.B \-\-dos
+]
+.I device
+.SH DESCRIPTION
+.B ntfsls
+is used to list information about the files specified by the
+.I PATH
+option (the root directory by default).
+.I DEVICE
+is the special file corresponding to the device (e.g
+.IR /dev/hdXX )
+or an NTFS image file.
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfsls
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-a\fR, \fB\-\-all\fR
+Display all files.  If this option is not specified file names in the POSIX
+namespace will not be displayed.
+.TP
+\fB\-F\fR, \fB\-\-classify\fR
+Append indicator (one of */=@|) to entries.
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+Force execution.  For example necessary to run on an NTFS partition stored in
+a normal file.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print the usage information of
+.B ntfsls
+and exit.
+.TP
+\fB\-i\fR, \fB\-\-inode\fR
+Print inode number of each file.  This is the MFT reference number in NTFS
+terminology.
+.TP
+\fB\-l\fR, \fB\-\-long\fR
+Use a long listing format.
+.TP
+\fB\-p\fR, \fB\-\-path\fR PATH
+The directory whose contents to list or the file (including the path) about
+which to display information.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Suppress some debug/warning/error messages.
+.TP
+\fB\-R\fR, \fB\-\-recursive\fR
+Show the contents of all directories beneath the specified directory.
+.TP
+\fB\-s\fR, \fB\-\-system\fR
+Unless this options is specified, all files beginning with a dollar sign
+character will not be listed as these files are usually system files.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Display more debug/warning/error messages.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Print the version number of
+.B ntfsls
+and exit.
+.TP
+\fB\-x\fR, \fB\-\-dos\fR
+Display short file names, i.e. files in the DOS namespace, instead of long
+file names, i.e. files in the WIN32 namespace.
+.SH BUGS
+There are no known problems with
+.BR ntfsls .
+If you find a bug please send an email describing the problem to the
+development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+This version of
+.B ntfsls
+was written by Lode Leroy, Anton Altaparmakov, Richard Russon, Carmelo Kintana
+and Giang Nguyen.
+It was ported to ntfs-3g by Erik Larsson.
+.SH AVAILABILITY
+.B ntfsls
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/ntfsls.c b/ntfsprogs/ntfsls.c
new file mode 100755
index 0000000000000000000000000000000000000000..909e7bb99f06ba0aad23b59b4c921f063ab8de39
--- /dev/null
+++ b/ntfsprogs/ntfsls.c
@@ -0,0 +1,717 @@
+/**
+ * ntfsls - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2003 Lode Leroy
+ * Copyright (c) 2003-2005 Anton Altaparmakov
+ * Copyright (c) 2003 Richard Russon
+ * Copyright (c) 2004 Carmelo Kintana
+ * Copyright (c) 2004 Giang Nguyen
+ *
+ * This utility will list a directory's files.
+ *
+ * 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 Linux-NTFS
+ * 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_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include "types.h"
+#include "mft.h"
+#include "attrib.h"
+#include "layout.h"
+#include "inode.h"
+#include "utils.h"
+#include "dir.h"
+#include "list.h"
+#include "ntfstime.h"
+/* #include "version.h" */
+#include "logging.h"
+
+static const char *EXEC_NAME = "ntfsls";
+
+/**
+ * To hold sub-directory information for recursive listing.
+ * @depth:     the level of this dir relative to opts.path
+ */
+struct dir {
+	struct ntfs_list_head list;
+	ntfs_inode *ni;
+	char name[MAX_PATH];
+	int depth;
+};
+
+/**
+ * path_component - to store path component strings
+ *
+ * @name: string pointer
+ *
+ * NOTE: @name is not directly allocated memory. It simply points to the
+ * character array name in struct dir.
+ */
+struct path_component {
+	struct ntfs_list_head list;
+	const char *name;
+};
+
+/* The list of sub-dirs is like a "horizontal" tree. The root of
+ * the tree is opts.path, but it is not part of the list because
+ * that's not necessary. The rules of the list are (in order of
+ * precedence):
+ * 1. directories immediately follow their parent.
+ * 2. siblings are next to one another.
+ *
+ * For example, if:
+ *   1. opts.path is /
+ *   2. /    has 2 sub-dirs: dir1 and dir2
+ *   3. dir1 has 2 sub-dirs: dir11 and dir12
+ *   4. dir2 has 0 sub-dirs
+ * then the list will be:
+ * dummy head -> dir1 -> dir11 -> dir12 -> dir2
+ *
+ * dir_list_insert_pos keeps track of where to insert a sub-dir
+ * into the list.
+ */
+static struct ntfs_list_head *dir_list_insert_pos = NULL;
+
+/* The global depth relative to opts.path.
+ * ie: opts.path has depth 0, a sub-dir of opts.path has depth 1
+ */
+static int depth = 0;
+
+static struct options {
+	char *device;	/* Device/File to work with */
+	int quiet;	/* Less output */
+	int verbose;	/* Extra output */
+	int force;	/* Override common sense */
+	int all;
+	int system;
+	int dos;
+	int lng;
+	int inode;
+	int classify;
+	int recursive;
+	const char *path;
+} opts;
+
+typedef struct {
+	ntfs_volume *vol;
+} ntfsls_dirent;
+
+static int list_dir_entry(ntfsls_dirent * dirent, const ntfschar * name,
+			  const int name_len, const int name_type,
+			  const s64 pos, const MFT_REF mref,
+			  const unsigned dt_type);
+
+/**
+ * version - Print version information about the program
+ *
+ * Print a copyright statement and a brief description of the program.
+ *
+ * Return:  none
+ */
+static void version(void)
+{
+	printf("\n%s v%s (libntfs-3g) - Display information about an NTFS "
+			"Volume.\n\n", EXEC_NAME, VERSION);
+	printf("Copyright (c) 2003 Lode Leroy\n");
+	printf("Copyright (c) 2003-2005 Anton Altaparmakov\n");
+	printf("Copyright (c) 2003 Richard Russon\n");
+	printf("Copyright (c) 2004 Carmelo Kintana\n");
+	printf("Copyright (c) 2004 Giang Nguyen\n");
+	printf("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
+}
+
+/**
+ * usage - Print a list of the parameters to the program
+ *
+ * Print a list of the parameters and options for the program.
+ *
+ * Return:  none
+ */
+static void usage(void)
+{
+	printf("\nUsage: %s [options] device\n"
+		"\n"
+		"    -a, --all            Display all files\n"
+		"    -F, --classify       Display classification\n"
+		"    -f, --force          Use less caution\n"
+		"    -h, --help           Display this help\n"
+		"    -i, --inode          Display inode numbers\n"
+		"    -l, --long           Display long info\n"
+		"    -p, --path PATH      Directory whose contents to list\n"
+		"    -q, --quiet          Less output\n"
+		"    -R, --recursive      Recursively list subdirectories\n"
+		"    -s, --system         Display system files\n"
+		"    -V, --version        Display version information\n"
+		"    -v, --verbose        More output\n"
+		"    -x, --dos            Use short (DOS 8.3) names\n"
+		"\n",
+		EXEC_NAME);
+
+	printf("NOTE: If neither -a nor -s is specified, the program defaults to -a.\n\n");
+
+	printf("%s%s\n", ntfs_bugs, ntfs_home);
+}
+
+/**
+ * parse_options - Read and validate the programs command line
+ *
+ * Read the command line, verify the syntax and parse the options.
+ * This function is very long, but quite simple.
+ *
+ * Return:  1 Success
+ *	    0 Error, one or more problems
+ */
+static int parse_options(int argc, char *argv[])
+{
+	static const char *sopt = "-aFfh?ilp:qRsVvx";
+	static const struct option lopt[] = {
+		{ "all",	 no_argument,		NULL, 'a' },
+		{ "classify",	 no_argument,		NULL, 'F' },
+		{ "force",	 no_argument,		NULL, 'f' },
+		{ "help",	 no_argument,		NULL, 'h' },
+		{ "inode",	 no_argument,		NULL, 'i' },
+		{ "long",	 no_argument,		NULL, 'l' },
+		{ "path",	 required_argument,     NULL, 'p' },
+		{ "recursive",	 no_argument,		NULL, 'R' },
+		{ "quiet",	 no_argument,		NULL, 'q' },
+		{ "system",	 no_argument,		NULL, 's' },
+		{ "version",	 no_argument,		NULL, 'V' },
+		{ "verbose",	 no_argument,		NULL, 'v' },
+		{ "dos",	 no_argument,		NULL, 'x' },
+		{ NULL, 0, NULL, 0 },
+	};
+
+	int c = -1;
+	int err  = 0;
+	int ver  = 0;
+	int help = 0;
+	int levels = 0;
+
+	opterr = 0; /* We'll handle the errors, thank you. */
+
+	memset(&opts, 0, sizeof(opts));
+	opts.device = NULL;
+	opts.path = "/";
+
+	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
+		switch (c) {
+		case 1:
+			if (!opts.device)
+				opts.device = optarg;
+			else
+				err++;
+			break;
+		case 'p':
+			opts.path = optarg;
+			break;
+		case 'f':
+			opts.force++;
+			break;
+		case 'h':
+		case '?':
+			if (strncmp (argv[optind-1], "--log-", 6) == 0) {
+				if (!ntfs_log_parse_option (argv[optind-1]))
+					err++;
+				break;
+			}
+			help++;
+			break;
+		case 'q':
+			opts.quiet++;
+			ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
+			break;
+		case 'v':
+			opts.verbose++;
+			ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
+			break;
+		case 'V':
+			ver++;
+			break;
+		case 'x':
+			opts.dos = 1;
+			break;
+		case 'l':
+			opts.lng++;
+			break;
+		case 'i':
+			opts.inode++;
+			break;
+		case 'F':
+			opts.classify++;
+			break;
+		case 'a':
+			opts.all++;
+			break;
+		case 's':
+			opts.system++;
+			break;
+		case 'R':
+			opts.recursive++;
+			break;
+		default:
+			ntfs_log_error("Unknown option '%s'.\n", argv[optind - 1]);
+			err++;
+			break;
+		}
+	}
+
+	/* Make sure we're in sync with the log levels */
+	levels = ntfs_log_get_levels();
+	if (levels & NTFS_LOG_LEVEL_VERBOSE)
+		opts.verbose++;
+	if (!(levels & NTFS_LOG_LEVEL_QUIET))
+		opts.quiet++;
+
+	/* defaults to -a if -s is not specified */
+	if (!opts.system)
+		opts.all++;
+
+	if (help || ver)
+		opts.quiet = 0;
+	else {
+		if (opts.device == NULL) {
+			if (argc > 1)
+				ntfs_log_error("You must specify exactly one "
+						"device.\n");
+			err++;
+		}
+
+		if (opts.quiet && opts.verbose) {
+			ntfs_log_error("You may not use --quiet and --verbose at the "
+					"same time.\n");
+			err++;
+		}
+	}
+
+	if (ver)
+		version();
+	if (help || err)
+		usage();
+
+	return (!err && !help && !ver);
+}
+
+/**
+ * free_dir - free one dir
+ * @tofree:   the dir to free
+ *
+ * Close the inode and then free the dir
+ */
+static void free_dir(struct dir *tofree)
+{
+	if (tofree) {
+		if (tofree->ni) {
+			ntfs_inode_close(tofree->ni);
+			tofree->ni = NULL;
+		}
+		free(tofree);
+	}
+}
+
+/**
+ * free_dirs - walk the list of dir's and free each of them
+ * @dir_list:    the ntfs_list_head of any entry in the list
+ *
+ * Iterate over @dir_list, calling free_dir on each entry
+ */
+static void free_dirs(struct ntfs_list_head *dir_list)
+{
+	struct dir *tofree = NULL;
+	struct ntfs_list_head *walker = NULL;
+
+	if (dir_list) {
+		ntfs_list_for_each(walker, dir_list) {
+			free_dir(tofree);
+			tofree = ntfs_list_entry(walker, struct dir, list);
+		}
+
+		free_dir(tofree);
+	}
+}
+
+/**
+ * readdir_recursive - list a directory and sub-directories encountered
+ * @ni:         ntfs inode of the directory to list
+ * @pos:	current position in directory
+ * @dirent:	context for filldir callback supplied by the caller
+ *
+ * For each directory, print its path relative to opts.path. List a directory,
+ * then list each of its sub-directories.
+ *
+ * Returns 0 on success or -1 on error.
+ *
+ * NOTE: Assumes recursive option. Currently no limit on the depths of
+ * recursion.
+ */
+static int readdir_recursive(ntfs_inode * ni, s64 * pos, ntfsls_dirent * dirent)
+{
+	/* list of dirs to "ls" recursively */
+	static struct dir dirs = {
+		.list = NTFS_LIST_HEAD_INIT(dirs.list),
+		.ni = NULL,
+		.name = {0},
+		.depth = 0
+	};
+
+	static struct path_component paths = {
+		.list = NTFS_LIST_HEAD_INIT(paths.list),
+		.name = NULL
+	};
+
+	static struct path_component base_comp;
+
+	struct dir *subdir = NULL;
+	struct dir *tofree = NULL;
+	struct path_component comp;
+	struct path_component *tempcomp = NULL;
+	struct ntfs_list_head *dir_walker = NULL;
+	struct ntfs_list_head *comp_walker = NULL;
+	s64 pos2 = 0;
+	int ni_depth = depth;
+	int result = 0;
+
+	if (ntfs_list_empty(&dirs.list)) {
+		base_comp.name = opts.path;
+		ntfs_list_add(&base_comp.list, &paths.list);
+		dir_list_insert_pos = &dirs.list;
+		printf("%s:\n", opts.path);
+	}
+
+	depth++;
+
+	result = ntfs_readdir(ni, pos, dirent, (ntfs_filldir_t) list_dir_entry);
+
+	if (result == 0) {
+		ntfs_list_add_tail(&comp.list, &paths.list);
+
+		/* for each of ni's sub-dirs: list in this iteration, then
+		   free at the top of the next iteration or outside of loop */
+		ntfs_list_for_each(dir_walker, &dirs.list) {
+			if (tofree) {
+				free_dir(tofree);
+				tofree = NULL;
+			}
+			subdir = ntfs_list_entry(dir_walker, struct dir, list);
+
+			/* subdir is not a subdir of ni */
+			if (subdir->depth != ni_depth + 1)
+				break;
+
+			pos2 = 0;
+			dir_list_insert_pos = &dirs.list;
+			if (!subdir->ni) {
+				subdir->ni =
+				    ntfs_pathname_to_inode(ni->vol, ni,
+							    subdir->name);
+
+				if (!subdir->ni) {
+					ntfs_log_error
+					    ("ntfsls::readdir_recursive(): cannot get inode from pathname.\n");
+					result = -1;
+					break;
+				}
+			}
+			puts("");
+
+			comp.name = subdir->name;
+
+			/* print relative path header */
+			ntfs_list_for_each(comp_walker, &paths.list) {
+				tempcomp =
+				    ntfs_list_entry(comp_walker,
+					       struct path_component, list);
+				printf("%s", tempcomp->name);
+				if (tempcomp != &comp
+				    && *tempcomp->name != PATH_SEP
+				    && (!opts.classify
+					|| tempcomp == &base_comp))
+					putchar(PATH_SEP);
+			}
+			puts(":");
+
+			result = readdir_recursive(subdir->ni, &pos2, dirent);
+
+			if (result)
+				break;
+
+			tofree = subdir;
+			ntfs_list_del(dir_walker);
+		}
+
+		ntfs_list_del(&comp.list);
+	}
+
+	if (tofree)
+		free_dir(tofree);
+
+	/* if at the outer-most readdir_recursive, then clean up */
+	if (ni_depth == 0) {
+		free_dirs(&dirs.list);
+	}
+
+	depth--;
+
+	return result;
+}
+
+/**
+ * list_dir_entry
+ *
+ * FIXME: Should we print errors as we go along? (AIA)
+ */
+static int list_dir_entry(ntfsls_dirent * dirent, const ntfschar * name,
+			  const int name_len, const int name_type,
+			  const s64 pos __attribute__((unused)),
+			  const MFT_REF mref, const unsigned dt_type)
+{
+	char *filename = NULL;
+	int result = 0;
+
+	struct dir *dir = NULL;
+
+	filename = calloc(1, MAX_PATH);
+	if (!filename)
+		return -1;
+
+	if (ntfs_ucstombs(name, name_len, &filename, MAX_PATH) < 0) {
+		ntfs_log_error("Cannot represent filename in current locale.\n");
+		goto free;
+	}
+
+	result = 0;					// These are successful
+	if ((MREF(mref) < FILE_first_user) && (!opts.system))
+		goto free;
+	if (name_type == FILE_NAME_POSIX && !opts.all)
+		goto free;
+	if (((name_type & FILE_NAME_WIN32_AND_DOS) == FILE_NAME_WIN32) &&
+			opts.dos)
+		goto free;
+	if (((name_type & FILE_NAME_WIN32_AND_DOS) == FILE_NAME_DOS) &&
+			!opts.dos)
+		goto free;
+	if (dt_type == NTFS_DT_DIR && opts.classify)
+		sprintf(filename + strlen(filename), "/");
+
+	if (dt_type == NTFS_DT_DIR && opts.recursive
+	    && strcmp(filename, ".") && strcmp(filename, "./")
+	    && strcmp(filename, "..") && strcmp(filename, "../"))
+	{
+		dir = (struct dir *)calloc(1, sizeof(struct dir));
+
+		if (!dir) {
+			ntfs_log_error("Failed to allocate for subdir.\n");
+			result = -1;
+			goto free;
+		}
+
+		strcpy(dir->name, filename);
+		dir->ni = NULL;
+		dir->depth = depth;
+	}
+
+	if (!opts.lng) {
+		if (!opts.inode)
+			printf("%s\n", filename);
+		else
+			printf("%7llu %s\n", (unsigned long long)MREF(mref),
+					filename);
+		result = 0;
+	} else {
+		s64 filesize = 0;
+		ntfs_inode *ni;
+		ntfs_attr_search_ctx *ctx = NULL;
+		FILE_NAME_ATTR *file_name_attr;
+		ATTR_RECORD *attr;
+		struct timespec change_time;
+		char t_buf[26];
+
+		result = -1;				// Everything else is bad
+
+		ni = ntfs_inode_open(dirent->vol, mref);
+		if (!ni)
+			goto release;
+
+		ctx = ntfs_attr_get_search_ctx(ni, NULL);
+		if (!ctx)
+			goto release;
+
+		if (ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, 0, 0, NULL,
+				0, ctx))
+			goto release;
+		attr = ctx->attr;
+
+		file_name_attr = (FILE_NAME_ATTR *)((char *)attr +
+				le16_to_cpu(attr->value_offset));
+		if (!file_name_attr)
+			goto release;
+
+		change_time = ntfs2timespec(file_name_attr->last_data_change_time);
+		strcpy(t_buf, ctime(&change_time.tv_sec));
+		memmove(t_buf+16, t_buf+19, 5);
+		t_buf[21] = '\0';
+
+		if (dt_type != NTFS_DT_DIR) {
+			if (!ntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, 0,
+					NULL, 0, ctx))
+				filesize = ntfs_get_attribute_value_length(
+						ctx->attr);
+		}
+
+		if (opts.inode)
+			printf("%7llu    %8lld %s %s\n",
+					(unsigned long long)MREF(mref),
+					(long long)filesize, t_buf + 4,
+					filename);
+		else
+			printf("%8lld %s %s\n", (long long)filesize, t_buf + 4,
+					filename);
+
+		if (dir) {
+			dir->ni = ni;
+			ni = NULL;	/* so release does not close inode */
+		}
+
+		result = 0;
+release:
+		/* Release attribute search context and close the inode. */
+		if (ctx)
+			ntfs_attr_put_search_ctx(ctx);
+		if (ni)
+			ntfs_inode_close(ni);
+	}
+
+	if (dir) {
+		if (result == 0) {
+			ntfs_list_add(&dir->list, dir_list_insert_pos);
+			dir_list_insert_pos = &dir->list;
+		} else {
+			free(dir);
+			dir = NULL;
+		}
+	}
+
+free:
+	free(filename);
+	return result;
+}
+
+/**
+ * main - Begin here
+ *
+ * Start from here.
+ *
+ * Return:  0  Success, the program worked
+ *	    1  Error, parsing mount options failed
+ *	    2  Error, mount attempt failed
+ *	    3  Error, failed to open root directory
+ *	    4  Error, failed to open directory in search path
+ */
+int main(int argc, char **argv)
+{
+	s64 pos;
+	ntfs_volume *vol;
+	ntfs_inode *ni;
+	ntfsls_dirent dirent;
+
+	ntfs_log_set_handler(ntfs_log_handler_outerr);
+
+	if (!parse_options(argc, argv)) {
+		// FIXME: Print error... (AIA)
+		return 1;
+	}
+
+	utils_set_locale();
+
+	vol = utils_mount_volume(opts.device, NTFS_MNT_RDONLY |
+			(opts.force ? NTFS_MNT_RECOVER : 0));
+	if (!vol) {
+		// FIXME: Print error... (AIA)
+		return 2;
+	}
+
+	ni = ntfs_pathname_to_inode(vol, NULL, opts.path);
+	if (!ni) {
+		// FIXME: Print error... (AIA)
+		ntfs_umount(vol, FALSE);
+		return 3;
+	}
+
+	/*
+	 * We now are at the final path component.  If it is a file just
+	 * list it.  If it is a directory, list its contents.
+	 */
+	pos = 0;
+	memset(&dirent, 0, sizeof(dirent));
+	dirent.vol = vol;
+	if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
+		if (opts.recursive)
+			readdir_recursive(ni, &pos, &dirent);
+		else
+			ntfs_readdir(ni, &pos, &dirent,
+				     (ntfs_filldir_t) list_dir_entry);
+		// FIXME: error checking... (AIA)
+	} else {
+		ATTR_RECORD *rec;
+		FILE_NAME_ATTR *attr;
+		ntfs_attr_search_ctx *ctx;
+		int space = 4;
+		ntfschar *name = NULL;
+		int name_len = 0;;
+
+		ctx = ntfs_attr_get_search_ctx(ni, NULL);
+		if (!ctx)
+			return -1;
+
+		while ((rec = find_attribute(AT_FILE_NAME, ctx))) {
+			/* We know this will always be resident. */
+			attr = (FILE_NAME_ATTR *) ((char *) rec + le16_to_cpu(rec->value_offset));
+
+			if (attr->file_name_type < space) {
+				name     = attr->file_name;
+				name_len = attr->file_name_length;
+				space    = attr->file_name_type;
+			}
+		}
+
+		list_dir_entry(&dirent, name, name_len, space, pos, ni->mft_no,
+			       NTFS_DT_REG);
+		// FIXME: error checking... (AIA)
+
+		ntfs_attr_put_search_ctx(ctx);
+	}
+
+	/* Finished with the inode; release it. */
+	ntfs_inode_close(ni);
+
+	ntfs_umount(vol, FALSE);
+	return 0;
+}
+
diff --git a/ntfsprogs/ntfsmftalloc.c b/ntfsprogs/ntfsmftalloc.c
new file mode 100755
index 0000000000000000000000000000000000000000..246ab54a88d70894bfb4da556c6fa5947e596617
--- /dev/null
+++ b/ntfsprogs/ntfsmftalloc.c
@@ -0,0 +1,368 @@
+/**
+ * ntfsmftalloc - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2002-2005 Anton Altaparmakov
+ *
+ * This utility will allocate and initialize an mft record.
+ *
+ * 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 Linux-NTFS source
+ * 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_UNISTD_H
+#	include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#	include <stdlib.h>
+#endif
+#ifdef HAVE_STDIO_H
+#	include <stdio.h>
+#endif
+#ifdef HAVE_STDARG_H
+#	include <stdarg.h>
+#endif
+#ifdef HAVE_STRING_H
+#	include <string.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#	include <errno.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_GETOPT_H
+#	include <getopt.h>
+#else
+	extern int optind;
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifndef LLONG_MAX
+#	define LLONG_MAX 9223372036854775807LL
+#endif
+
+#include "types.h"
+#include "attrib.h"
+#include "inode.h"
+#include "layout.h"
+#include "volume.h"
+#include "mft.h"
+#include "utils.h"
+/* #include "version.h" */
+#include "logging.h"
+
+static const char *EXEC_NAME = "ntfsmftalloc";
+
+/* Need these global so ntfsmftalloc_exit can access them. */
+static BOOL success = FALSE;
+
+static char *dev_name;
+
+static ntfs_volume *vol;
+static ntfs_inode *ni = NULL;
+static ntfs_inode *base_ni = NULL;
+static s64 base_mft_no = -1;
+
+static struct {
+				/* -h, print usage and exit. */
+	int no_action;		/* -n, do not write to device, only display
+				       what would be done. */
+	int quiet;		/* -q, quiet execution. */
+	int verbose;		/* -v, verbose execution, given twice, really
+				       verbose execution (debug mode). */
+	int force;		/* -f, force allocation. */
+				/* -V, print version and exit. */
+} opts;
+
+/**
+ * err_exit - error output and terminate; ignores quiet (-q)
+ */
+__attribute__((noreturn))
+__attribute__((format(printf, 1, 2)))
+static void err_exit(const char *fmt, ...)
+{
+	va_list ap;
+
+	fprintf(stderr, "ERROR: ");
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	fprintf(stderr, "Aborting...\n");
+	exit(1);
+}
+
+/**
+ * copyright - print copyright statements
+ */
+static void copyright(void)
+{
+	ntfs_log_info("Copyright (c) 2004-2005 Anton Altaparmakov\n"
+			"Allocate and initialize a base or an extent mft "
+			"record.  If a base mft record\nis not specified, a "
+			"base mft record is allocated and initialized.  "
+			"Otherwise,\nan extent mft record is allocated and "
+			"initialized to point to the specified\nbase mft "
+			"record.\n");
+}
+
+/**
+ * license - print license statement
+ */
+static void license(void)
+{
+	ntfs_log_info("%s", ntfs_gpl);
+}
+
+/**
+ * usage - print a list of the parameters to the program
+ */
+__attribute__((noreturn))
+static void usage(void)
+{
+	copyright();
+	ntfs_log_info("Usage: %s [options] device [base-mft-record]\n"
+			"    -n    Do not write to disk\n"
+			"    -f    Force execution despite errors\n"
+			"    -q    Quiet execution\n"
+			"    -v    Verbose execution\n"
+			"    -vv   Very verbose execution\n"
+			"    -V    Display version information\n"
+			"    -l    Display licensing information\n"
+			"    -h    Display this help\n", EXEC_NAME);
+	ntfs_log_info("%s%s", ntfs_bugs, ntfs_home);
+	exit(1);
+}
+
+/**
+ * parse_options
+ */
+static void parse_options(int argc, char *argv[])
+{
+	long long ll;
+	char *s;
+	int c;
+
+	if (argc && *argv)
+		EXEC_NAME = *argv;
+	ntfs_log_info("%s v%s (libntfs-3g)\n", EXEC_NAME, VERSION);
+	while ((c = getopt(argc, argv, "fh?nqvVl")) != EOF) {
+		switch (c) {
+		case 'f':
+			opts.force = 1;
+			break;
+		case 'n':
+			opts.no_action = 1;
+			break;
+		case 'q':
+			opts.quiet = 1;
+			ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
+			break;
+		case 'v':
+			opts.verbose++;
+			ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
+			break;
+		case 'V':
+			/* Version number already printed, so just exit. */
+			exit(0);
+		case 'l':
+			copyright();
+			license();
+			exit(0);
+		case 'h':
+		case '?':
+		default:
+			usage();
+		}
+	}
+
+	if (opts.verbose > 1)
+		ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG | NTFS_LOG_LEVEL_TRACE |
+			NTFS_LOG_LEVEL_VERBOSE | NTFS_LOG_LEVEL_QUIET);
+
+	if (optind == argc)
+		usage();
+	/* Get the device. */
+	dev_name = argv[optind++];
+	ntfs_log_verbose("device name = %s\n", dev_name);
+	if (optind != argc) {
+		/* Get the base mft record number. */
+		ll = strtoll(argv[optind++], &s, 0);
+		if (*s || !ll || (ll >= LLONG_MAX && errno == ERANGE))
+			err_exit("Invalid base mft record number: %s\n",
+					argv[optind - 1]);
+		base_mft_no = ll;
+		ntfs_log_verbose("base mft record number = 0x%llx\n", (long long)ll);
+	}
+	if (optind != argc)
+		usage();
+}
+
+/**
+ * dump_mft_record
+ */
+static void dump_mft_record(MFT_RECORD *m)
+{
+	ATTR_RECORD *a;
+	unsigned int u;
+	MFT_REF r;
+
+	ntfs_log_info("-- Beginning dump of mft record. --\n");
+	u = le32_to_cpu(m->magic);
+	ntfs_log_info("Mft record signature (magic) = %c%c%c%c\n", u & 0xff,
+			u >> 8 & 0xff, u >> 16 & 0xff, u >> 24 & 0xff);
+	u = le16_to_cpu(m->usa_ofs);
+	ntfs_log_info("Update sequence array offset = %u (0x%x)\n", u, u);
+	ntfs_log_info("Update sequence array size = %u\n", le16_to_cpu(m->usa_count));
+	ntfs_log_info("$LogFile sequence number (lsn) = %llu\n",
+			(unsigned long long)le64_to_cpu(m->lsn));
+	ntfs_log_info("Sequence number = %u\n", le16_to_cpu(m->sequence_number));
+	ntfs_log_info("Reference (hard link) count = %u\n",
+						le16_to_cpu(m->link_count));
+	u = le16_to_cpu(m->attrs_offset);
+	ntfs_log_info("First attribute offset = %u (0x%x)\n", u, u);
+	ntfs_log_info("Flags = %u: ", le16_to_cpu(m->flags));
+	if (m->flags & MFT_RECORD_IN_USE)
+		ntfs_log_info("MFT_RECORD_IN_USE");
+	else
+		ntfs_log_info("MFT_RECORD_NOT_IN_USE");
+	if (m->flags & MFT_RECORD_IS_DIRECTORY)
+		ntfs_log_info(" | MFT_RECORD_IS_DIRECTORY");
+	ntfs_log_info("\n");
+	u = le32_to_cpu(m->bytes_in_use);
+	ntfs_log_info("Bytes in use = %u (0x%x)\n", u, u);
+	u = le32_to_cpu(m->bytes_allocated);
+	ntfs_log_info("Bytes allocated = %u (0x%x)\n", u, u);
+	r = le64_to_cpu(m->base_mft_record);
+	ntfs_log_info("Base mft record reference:\n\tMft record number = %llu\n\t"
+			"Sequence number = %u\n",
+			(unsigned long long)MREF(r), MSEQNO(r));
+	ntfs_log_info("Next attribute instance = %u\n",
+			le16_to_cpu(m->next_attr_instance));
+	a = (ATTR_RECORD*)((char*)m + le16_to_cpu(m->attrs_offset));
+	ntfs_log_info("-- Beginning dump of attributes within mft record. --\n");
+	while ((char*)a < (char*)m + le32_to_cpu(m->bytes_in_use)) {
+		if (a->type == AT_END)
+			break;
+		a = (ATTR_RECORD*)((char*)a + le32_to_cpu(a->length));
+	};
+	ntfs_log_info("-- End of attributes. --\n");
+}
+
+/**
+ * ntfsmftalloc_exit
+ */
+static void ntfsmftalloc_exit(void)
+{
+	if (success)
+		return;
+	/* If there is a base inode, close that instead of the extent inode. */
+	if (base_ni)
+		ni = base_ni;
+	/* Close the inode. */
+	if (ni && ntfs_inode_close(ni)) {
+		ntfs_log_perror("Warning: Failed to close inode 0x%llx",
+				(long long)ni->mft_no);
+	}
+	/* Unmount the volume. */
+	if (ntfs_umount(vol, 0) == -1)
+		ntfs_log_perror("Warning: Could not umount %s", dev_name);
+}
+
+/**
+ * main
+ */
+int main(int argc, char **argv)
+{
+	unsigned long mnt_flags, ul;
+	int err;
+
+	ntfs_log_set_handler(ntfs_log_handler_outerr);
+
+	/* Initialize opts to zero / required values. */
+	memset(&opts, 0, sizeof(opts));
+	/* Parse command line options. */
+	parse_options(argc, argv);
+	utils_set_locale();
+	/* Make sure the file system is not mounted. */
+	if (ntfs_check_if_mounted(dev_name, &mnt_flags))
+		ntfs_log_error("Failed to determine whether %s is mounted: %s\n",
+				dev_name, strerror(errno));
+	else if (mnt_flags & NTFS_MF_MOUNTED) {
+		ntfs_log_error("%s is mounted.\n", dev_name);
+		if (!opts.force)
+			err_exit("Refusing to run!\n");
+		ntfs_log_error("ntfsmftalloc forced anyway. Hope /etc/mtab "
+				"is incorrect.\n");
+	}
+	/* Mount the device. */
+	if (opts.no_action) {
+		ntfs_log_quiet("Running in READ-ONLY mode!\n");
+		ul = NTFS_MNT_RDONLY;
+	} else
+		ul = 0;
+	vol = ntfs_mount(dev_name, ul);
+	if (!vol)
+		err_exit("Failed to mount %s: %s\n", dev_name, strerror(errno));
+	/* Register our exit function which will unlock and close the device. */
+	err = atexit(&ntfsmftalloc_exit);
+	if (err == -1) {
+		ntfs_log_error("Could not set up exit() function because atexit() "
+				"failed: %s Aborting...\n", strerror(errno));
+		ntfsmftalloc_exit();
+		exit(1);
+	}
+	if (base_mft_no != -1) {
+		base_ni = ntfs_inode_open(vol, base_mft_no);
+		if (!base_ni)
+			err_exit("Failed to open base inode 0x%llx: %s\n",
+					(long long)base_mft_no,
+					strerror(errno));
+	}
+	/* Open the specified inode. */
+	ni = ntfs_mft_record_alloc(vol, base_ni);
+	if (!ni)
+		err_exit("Failed to allocate mft record: %s\n",
+				strerror(errno));
+	ntfs_log_info("Allocated %s mft record 0x%llx", base_ni ? "extent" : "base",
+			(long long)ni->mft_no);
+	if (base_ni)
+		ntfs_log_info(" with base mft record 0x%llx",
+				(long long)base_mft_no);
+	ntfs_log_info(".\n");
+	if (!opts.quiet && opts.verbose > 1) {
+		ntfs_log_verbose("Dumping allocated mft record 0x%llx:\n",
+				(long long)ni->mft_no);
+		dump_mft_record(ni->mrec);
+	}
+	/* Close the (base) inode. */
+	if (base_ni)
+		ni = base_ni;
+	err = ntfs_inode_close(ni);
+	if (err)
+		err_exit("Failed to close inode 0x%llx: %s\n",
+				(long long)ni->mft_no, strerror(errno));
+	/* Unmount the volume. */
+	err = ntfs_umount(vol, 0);
+	/* Disable our ntfsmftalloc_exit() handler. */
+	success = TRUE;
+	if (err == -1)
+		ntfs_log_perror("Warning: Failed to umount %s", dev_name);
+	else
+		ntfs_log_quiet("ntfsmftalloc completed successfully.\n");
+	return 0;
+}
diff --git a/ntfsprogs/ntfsmove.c b/ntfsprogs/ntfsmove.c
new file mode 100755
index 0000000000000000000000000000000000000000..571808fdb0f82873fb9612bc6ae74c7f34090733
--- /dev/null
+++ b/ntfsprogs/ntfsmove.c
@@ -0,0 +1,923 @@
+/**
+ * ntfsmove - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2003 Richard Russon
+ * Copyright (c) 2003-2005 Anton Altaparmakov
+ *
+ * This utility will move files on an NTFS volume.
+ *
+ * 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 Linux-NTFS
+ * 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_GETOPT_H
+#include <getopt.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include "types.h"
+#include "attrib.h"
+#include "utils.h"
+#include "volume.h"
+#include "debug.h"
+#include "dir.h"
+#include "bitmap.h"
+#include "ntfsmove.h"
+/* #include "version.h" */
+#include "logging.h"
+
+static const char *EXEC_NAME = "ntfsmove";
+static struct options opts;
+
+/**
+ * version - Print version information about the program
+ *
+ * Print a copyright statement and a brief description of the program.
+ *
+ * Return:  none
+ */
+static void version(void)
+{
+	ntfs_log_info("\n%s v%s (libntfs-3g) - Move files and directories on an "
+			"NTFS volume.\n\n", EXEC_NAME, VERSION);
+	ntfs_log_info("Copyright (c) 2003 Richard Russon\n");
+	ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
+}
+
+/**
+ * usage - Print a list of the parameters to the program
+ *
+ * Print a list of the parameters and options for the program.
+ *
+ * Return:  none
+ */
+static void usage(void)
+{
+	ntfs_log_info("\nUsage: %s [options] device file\n"
+		"\n"
+		"    -S      --start        Move to the start of the volume\n"
+		"    -B      --best         Move to the best place on the volume\n"
+		"    -E      --end          Move to the end of the volume\n"
+		"    -C num  --cluster num  Move to this cluster offset\n"
+		"\n"
+		"    -D      --no-dirty     Do not mark volume dirty (require chkdsk)\n"
+		"    -n      --no-action    Do not write to disk\n"
+		"    -f      --force        Use less caution\n"
+		"    -h      --help         Print this help\n"
+		"    -q      --quiet        Less output\n"
+		"    -V      --version      Version information\n"
+		"    -v      --verbose      More output\n\n",
+		EXEC_NAME);
+	ntfs_log_info("%s%s\n", ntfs_bugs, ntfs_home);
+}
+
+/**
+ * parse_options - Read and validate the programs command line
+ *
+ * Read the command line, verify the syntax and parse the options.
+ * This function is very long, but quite simple.
+ *
+ * Return:  1 Success
+ *	    0 Error, one or more problems
+ */
+static int parse_options(int argc, char **argv)
+{
+	static const char *sopt = "-BC:DEfh?nqSVv";
+	static const struct option lopt[] = {
+		{ "best",	no_argument,		NULL, 'B' },
+		{ "cluster",	required_argument,	NULL, 'C' },
+		{ "end",	no_argument,		NULL, 'E' },
+		{ "force",	no_argument,		NULL, 'f' },
+		{ "help",	no_argument,		NULL, 'h' },
+		{ "no-action",	no_argument,		NULL, 'n' },
+		{ "no-dirty",	no_argument,		NULL, 'D' },
+		{ "quiet",	no_argument,		NULL, 'q' },
+		{ "start",	no_argument,		NULL, 'S' },
+		{ "verbose",	no_argument,		NULL, 'v' },
+		{ "version",	no_argument,		NULL, 'V' },
+		{ NULL,		0,			NULL, 0   }
+	};
+
+	int c = -1;
+	int err  = 0;
+	int ver  = 0;
+	int help = 0;
+	int levels = 0;
+	char *end = NULL;
+
+	opterr = 0; /* We'll handle the errors, thank you. */
+
+	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
+		switch (c) {
+		case 1:	/* A non-option argument */
+			if (!opts.device) {
+				opts.device = argv[optind-1];
+			} else if (!opts.file) {
+				opts.file = argv[optind-1];
+			} else {
+				opts.device = NULL;
+				opts.file   = NULL;
+				err++;
+			}
+			break;
+		case 'B':
+			if (opts.location == 0)
+				opts.location = NTFS_MOVE_LOC_BEST;
+			else
+				opts.location = -1;
+			break;
+		case 'C':
+			if (opts.location == 0) {
+				opts.location = strtoll(optarg, &end, 0);
+				if (end && *end)
+					err++;
+			} else {
+				opts.location = -1;
+			}
+			break;
+		case 'D':
+			opts.nodirty++;
+			break;
+		case 'E':
+			if (opts.location == 0)
+				opts.location = NTFS_MOVE_LOC_END;
+			else
+				opts.location = -1;
+			break;
+		case 'f':
+			opts.force++;
+			break;
+		case 'h':
+		case '?':
+			if (strncmp (argv[optind-1], "--log-", 6) == 0) {
+				if (!ntfs_log_parse_option (argv[optind-1]))
+					err++;
+				break;
+			}
+			help++;
+			break;
+		case 'n':
+			opts.noaction++;
+			break;
+		case 'q':
+			opts.quiet++;
+			ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
+			break;
+		case 'S':
+			if (opts.location == 0)
+				opts.location = NTFS_MOVE_LOC_START;
+			else
+				opts.location = -1;
+			break;
+		case 'V':
+			ver++;
+			break;
+		case 'v':
+			opts.verbose++;
+			ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
+			break;
+		default:
+			ntfs_log_error("Unknown option '%s'.\n", argv[optind-1]);
+			err++;
+			break;
+		}
+	}
+
+	/* Make sure we're in sync with the log levels */
+	levels = ntfs_log_get_levels();
+	if (levels & NTFS_LOG_LEVEL_VERBOSE)
+		opts.verbose++;
+	if (!(levels & NTFS_LOG_LEVEL_QUIET))
+		opts.quiet++;
+
+	if (help || ver) {
+		opts.quiet = 0;
+	} else {
+		if ((opts.device == NULL) ||
+		    (opts.file   == NULL)) {
+			if (argc > 1)
+				ntfs_log_error("You must specify one device and one file.\n");
+			err++;
+		}
+
+		if (opts.quiet && opts.verbose) {
+			ntfs_log_error("You may not use --quiet and --verbose at the "
+					"same time.\n");
+			err++;
+		}
+
+		if (opts.location == -1) {
+			ntfs_log_error("You may only specify one location option: "
+				"--start, --best, --end or --cluster\n");
+			err++;
+		} else if (opts.location == 0) {
+			opts.location = NTFS_MOVE_LOC_BEST;
+		}
+	}
+
+	if (ver)
+		version();
+	if (help || err)
+		usage();
+
+	return (!err && !help && !ver);
+}
+
+#if 0
+
+/**
+ * ntfs_debug_runlist_dump2 - Dump a runlist.
+ */
+static int ntfs_debug_runlist_dump2(const runlist *rl, int abbr, char *prefix)
+{
+	//int abbr = 3;	/* abbreviate long lists */
+	int len = 0;
+	int i;
+	int res = 0;
+	u64 total = 0;
+	const char *lcn_str[5] = { "HOLE", "NOTMAP", "ENOENT", "EINVAL", "XXXX" };
+
+	if (!rl) {
+		ntfs_log_info("    Run list not present.\n");
+		return 0;
+	}
+
+	if (!prefix)
+		prefix = "";
+
+	if (abbr)
+		for (len = 0; rl[len].length; len++) ;
+
+	ntfs_log_info("%s     VCN      LCN      len\n", prefix);
+	for (i = 0; rl->length; i++, rl++) {
+		LCN lcn = rl->lcn;
+
+		total += rl->length;
+		if (abbr)
+			if (len > 20) {
+				if ((i == abbr) && (len > (abbr*2)))
+					ntfs_log_info("%s     ...      ...      ...\n", prefix);
+				if ((i > (abbr-1)) && (i < (len - (abbr-1))))
+					continue;
+			}
+
+		if (rl->vcn < -1)
+			res = -1;
+
+		if (lcn < (LCN)0) {
+			int j = -lcn - 1;
+
+			if ((j < 0) || (j > 4)) {
+				j = 4;
+				res = -1;
+			}
+			ntfs_log_info("%s%8lld %8s %8lld\n", prefix,
+				rl->vcn, lcn_str[j], rl->length);
+		} else
+			ntfs_log_info("%s%8lld %8lld %8lld\n", prefix,
+				rl->vcn, rl->lcn, rl->length);
+	}
+	ntfs_log_info("%s                  --------\n", prefix);
+	ntfs_log_info("%s                  %8lld\n", prefix, total);
+	ntfs_log_info("\n");
+	return res;
+}
+
+#endif /* if 0 */
+
+/**
+ * resize_nonres_attr
+ */
+static int resize_nonres_attr(MFT_RECORD *m, ATTR_RECORD *a, const u32 new_size)
+{
+	int this_attr;
+	int next_attr;
+	int tail_size;
+	int file_size;
+	int old_size;
+	u8 *ptr;
+
+	old_size  = a->length;
+	file_size = m->bytes_in_use;
+	this_attr = p2n(a)-p2n(m);
+	next_attr = this_attr + a->length;
+	tail_size = file_size - next_attr;
+	ptr = (u8*) m;
+
+	/*
+	ntfs_log_info("old_size  = %d\n", old_size);
+	ntfs_log_info("new_size  = %d\n", new_size);
+	ntfs_log_info("file_size = %d\n", file_size);
+	ntfs_log_info("this_attr = %d\n", this_attr);
+	ntfs_log_info("next_attr = %d\n", next_attr);
+	ntfs_log_info("tail_size = %d\n", tail_size);
+	*/
+
+	memmove(ptr + this_attr + new_size, ptr + next_attr, tail_size);
+
+	a->length = new_size;
+	m->bytes_in_use += new_size - old_size;
+
+	return 0;
+}
+
+/**
+ * calc_attr_length
+ */
+static int calc_attr_length(ATTR_RECORD *rec, int runlength)
+{
+	int size;
+
+	if (!rec)
+		return -1;
+	if (!rec->non_resident)
+		return -1;
+
+	size = rec->mapping_pairs_offset + runlength + 7;
+	size &= 0xFFF8;
+	return size;
+}
+
+#if 0
+
+/**
+ * dump_runs
+ */
+static void dump_runs(u8 *buffer, int len)
+{
+	int i;
+	ntfs_log_info("RUN: \e[01;31m");
+
+	for (i = 0; i < len; i++) {
+		ntfs_log_info(" %02x", buffer[i]);
+	}
+	ntfs_log_info("\e[0m\n");
+}
+
+#endif /* if 0 */
+
+/**
+ * find_unused
+ */
+static runlist * find_unused(ntfs_volume *vol, s64 size, u64 loc
+	__attribute__((unused)), int flags __attribute__((unused)))
+{
+	const int bufsize = 8192;
+	u8 *buffer;
+	int clus;
+	int i;
+	int curr = 0;
+	int count = 0;
+	s64 start = 0;
+	int bit = 0;
+	runlist *res = NULL;
+
+	//ntfs_log_info("find_unused\n");
+	buffer = malloc(bufsize);
+	if (!buffer) {
+		ntfs_log_info("!buffer\n");
+		return NULL;
+	}
+
+	//ntfs_log_info("looking for space for %lld clusters\n", size);
+
+	clus = vol->lcnbmp_na->allocated_size / bufsize;
+	//ntfs_log_info("clus = %d\n", clus);
+
+	for (i = 0; i < clus; i++) {
+		int bytes_read, j;
+
+		bytes_read = ntfs_attr_pread(vol->lcnbmp_na, i*bufsize,
+				bufsize, buffer);
+		if (bytes_read != bufsize) {
+			ntfs_log_info("!read\n");
+			return NULL;
+		}
+		for (j = 0; j < bufsize*8; j++) {
+			bit = !!test_bit(j & 7, buffer[j>>3]);
+			if (curr == bit) {
+				count++;
+				if ((!bit) && (count >= size)) {
+					//res = calloc(2, sizeof(*res));
+					res = calloc(1, 4096);
+					if (res) {
+						res[0].vcn    = 0;
+						res[0].lcn    = start;
+						res[0].length = size;
+						res[1].lcn    = LCN_ENOENT;
+					}
+					goto done;
+				}
+			} else {
+				//ntfs_log_info("%d * %d\n", curr, count);
+				curr = bit;
+				count = 1;
+				start = i*bufsize*8 + j;
+			}
+		}
+	}
+done:
+	//ntfs_log_info("%d * %d\n", curr, count);
+
+	free(buffer);
+
+	if (res) {
+		for (i = 0; i < size; i++) {
+			if (utils_cluster_in_use(vol, res->lcn + i)) {
+				ntfs_log_info("ERROR cluster %lld in use\n",
+				(long long)res->lcn + i);
+			}
+		}
+	} else {
+		ntfs_log_info("failed\n");
+	}
+
+	return res;
+}
+
+/**
+ * dont_move
+ *
+ * Don't let the user move:
+ *   ANY metadata
+ *   Any fragmented MFT records
+ *   The boot file 'ntldr'
+ */
+static int dont_move(ntfs_inode *ino)
+{
+	static const ntfschar ntldr[6] = {
+		const_cpu_to_le16('n'), const_cpu_to_le16('t'), const_cpu_to_le16('l'),
+		const_cpu_to_le16('d'), const_cpu_to_le16('r'), const_cpu_to_le16('\0')
+	};
+
+	ATTR_RECORD *rec;
+	FILE_NAME_ATTR *name;
+
+	if (utils_is_metadata(ino)) {
+		ntfs_log_error("metadata\n");
+		return 1;
+	}
+
+	rec = find_first_attribute(AT_ATTRIBUTE_LIST, ino->mrec);
+	if (rec) {
+		ntfs_log_error("attribute list\n");
+		return 1;
+	}
+
+	rec = find_first_attribute(AT_FILE_NAME, ino->mrec);
+	if (!rec) {
+		ntfs_log_error("extend inode\n");
+		return 1;
+	}
+
+	name = (FILE_NAME_ATTR*) ((u8*)rec + rec->value_offset);
+	if (ntfs_names_are_equal(ntldr, 5, name->file_name, name->file_name_length,
+		IGNORE_CASE, ino->vol->upcase, ino->vol->upcase_len)) {
+		ntfs_log_error("ntldr\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+
+/**
+ * bitmap_alloc
+ */
+static int bitmap_alloc(ntfs_volume *vol, runlist_element *rl)
+{
+	int res;
+
+	if (!rl)
+		return -1;
+
+	res = ntfs_bitmap_set_run(vol->lcnbmp_na, rl->lcn, rl->length);
+	if (res < 0) {
+		ntfs_log_error("bitmap alloc returns %d\n", res);
+	}
+
+	return res;
+}
+
+/**
+ * bitmap_free
+ */
+static int bitmap_free(ntfs_volume *vol, runlist_element *rl)
+{
+	int res;
+
+	if (!rl)
+		return -1;
+
+	res = ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn, rl->length);
+	if (res < 0) {
+		ntfs_log_error("bitmap free returns %d\n", res);
+	}
+
+	return res;
+}
+
+/**
+ * data_copy
+ */
+static int data_copy(ntfs_volume *vol, runlist_element *from, runlist_element *to)
+{
+	int i;
+	u8 *buffer;
+	s64 res = 0;
+
+	if (!vol || !from || !to)
+		return -1;
+	if ((from->length != to->length) || (from->lcn < 0) || (to->lcn < 0))
+		return -1;
+
+	//ntfs_log_info("data_copy: from 0x%llx to 0x%llx\n", from->lcn, to->lcn);
+	buffer = malloc(vol->cluster_size);
+	if (!buffer) {
+		ntfs_log_info("!buffer\n");
+		return -1;
+	}
+
+	for (i = 0; i < from->length; i++) {
+		//ntfs_log_info("read  cluster at %8lld\n", from->lcn+i);
+		res = ntfs_pread(vol->dev, (from->lcn+i) * vol->cluster_size,
+				vol->cluster_size, buffer);
+		if (res != vol->cluster_size) {
+			ntfs_log_error("!read\n");
+			res = -1;
+			break;
+		}
+
+		//ntfs_log_info("write cluster to %8lld\n", to->lcn+i);
+		res = ntfs_pwrite(vol->dev, (to->lcn+i) * vol->cluster_size,
+				vol->cluster_size, buffer);
+		if (res != vol->cluster_size) {
+			ntfs_log_error("!write %lld\n", (long long)res);
+			res = -1;
+			break;
+		}
+	}
+
+	free(buffer);
+	return res;
+}
+
+/**
+ * move_runlist
+ *
+ * validate:
+ *   runlists are the same size
+ *   from in use
+ *   to not in use
+ * allocate new space
+ * copy data
+ * deallocate old space
+ */
+static s64 move_runlist(ntfs_volume *vol, runlist_element *from,
+	runlist_element *to)
+{
+	int i;
+
+	if (!vol || !from || !to)
+		return -1;
+	if (from->length != to->length) {
+		ntfs_log_error("diffsizes\n");
+		return -1;
+	}
+
+	if ((from->lcn < 0) || (to->lcn < 0)) {
+		ntfs_log_error("invalid runs\n");
+		return -1;
+	}
+
+	for (i = 0; i < from->length; i++) {
+		if (!utils_cluster_in_use(vol, from->lcn+i)) {
+			ntfs_log_error("from not in use\n");
+			return -1;
+		}
+	}
+
+	for (i = 0; i < to->length; i++) {
+		if (utils_cluster_in_use(vol, to->lcn+i)) {
+			ntfs_log_error("to is in use\n");
+			return -1;
+		}
+	}
+
+	if (bitmap_alloc(vol, to) < 0) {
+		ntfs_log_error("cannot bitmap_alloc\n");
+		return -1;
+	}
+
+	if (data_copy(vol, from, to) < 0) {
+		ntfs_log_error("cannot data_copy\n");
+		return -1;
+	}
+
+	if (bitmap_free(vol, from) < 0) {
+		ntfs_log_error("cannot bitmap_free\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+
+/**original
+ * move_datarun
+ * > 0  Bytes moved / size to be moved
+ * = 0  Nothing to do
+ * < 0  Error
+ */
+
+// get size of runlist
+// find somewhere to put data
+// backup original runlist
+// move the data
+
+// got to get the runlist out of this function
+//      requires a mrec arg, not an ino (ino->mrec will do for now)
+// check size of new runlist before allocating / moving
+// replace one datarun with another (by hand)
+static s64 move_datarun(ntfs_volume *vol, ntfs_inode *ino, ATTR_RECORD *rec,
+	runlist_element *run, u64 loc, int flags)
+{
+	runlist *from;
+	runlist *to;
+	int need_from;
+	int need_to;
+	int i;
+	s64 res = -1;
+
+	// find empty space
+	to = find_unused(vol, run->length, loc, flags);
+	if (!to) {
+		ntfs_log_error("!to\n");
+		return -1;
+	}
+
+	to->vcn = run->vcn;
+
+	// copy original runlist
+	from = ntfs_mapping_pairs_decompress(vol, rec, NULL);
+	if (!from) {
+		ntfs_log_info("!from\n");
+		return -1;
+	}
+
+	ntfs_log_info("move %lld,%lld,%lld to %lld,%lld,%lld\n",
+		(long long)run->vcn, (long long)run->lcn, (long long)run->length,
+		(long long)to->vcn, (long long)to->lcn, (long long)to->length);
+
+	need_from = ntfs_get_size_for_mapping_pairs(vol, from, 0, INT_MAX);
+	ntfs_log_info("orig data run = %d bytes\n", need_from);
+
+	//ntfs_debug_runlist_dump2(from, 5, "\t");
+
+	for (i = 0; to[i].length > 0; i++) {
+		if (from[i].vcn == run->vcn) {
+			from[i].lcn = to->lcn;
+			break;
+		}
+	}
+
+	//ntfs_debug_runlist_dump2(from, 5, "\t");
+
+	need_to = ntfs_get_size_for_mapping_pairs(vol, from, 0, INT_MAX);
+	ntfs_log_info("new  data run = %d bytes\n", need_to);
+
+	need_from = calc_attr_length(rec, need_from);
+	need_to   = calc_attr_length(rec, need_to);
+
+	ntfs_log_info("Before %d, after %d\n", need_from, need_to);
+
+	if (need_from != need_to) {
+		if (resize_nonres_attr(ino->mrec, rec, need_to) < 0) {
+			ntfs_log_info("!resize\n");
+			return -1;
+		}
+	}
+
+	res = move_runlist(vol, run, to);
+	if (res < 0) {
+		ntfs_log_error("!move_runlist\n");
+		return -1;
+	}
+
+	// wipe orig runs
+	memset(((u8*)rec) +rec->mapping_pairs_offset, 0, need_to - rec->mapping_pairs_offset);
+
+	// update data runs
+	ntfs_mapping_pairs_build(vol, ((u8*)rec) + rec->mapping_pairs_offset,
+			need_to, from, 0, NULL);
+
+	// commit
+	ntfs_inode_mark_dirty(ino);
+
+	if (ntfs_inode_sync(ino) < 0) {
+		ntfs_log_info("!sync\n");
+		return -1;
+	}
+
+	free(from);
+	free(to);
+	return res;
+}
+
+/**
+ * move_attribute -
+ *
+ * > 0  Bytes moved / size to be moved
+ * = 0  Nothing to do
+ * < 0  Error
+ */
+static s64 move_attribute(ntfs_volume *vol, ntfs_inode *ino, ATTR_RECORD *rec,
+	u64 loc, int flags)
+{
+	int i;
+	s64 res;
+	s64 count = 0;
+	runlist *runs;
+
+	// NTFS_MOVE_LOC_BEST : assess how much space this attribute will need,
+	// find that space and pass the location to our children.
+	// Anything else we pass directly to move_datarun.
+
+	runs = ntfs_mapping_pairs_decompress(vol, rec, NULL);
+	if (!runs) {
+		ntfs_log_error("!runs\n");
+		return -1;
+	}
+
+	//ntfs_debug_runlist_dump2(runs, 5, "\t");
+
+	//ntfs_log_info("             VCN     LCN     Length\n");
+	for (i = 0; runs[i].length > 0; i++) {
+		if (runs[i].lcn == LCN_RL_NOT_MAPPED) {
+			continue;
+		}
+
+		res = move_datarun(vol, ino, rec, runs+i, loc, flags);
+		//ntfs_log_info("        %8lld %8lld %8lld\n", runs[i].vcn, runs[i].lcn, runs[i].length);
+		if (res < 0) {
+			ntfs_log_error("!move_datarun\n");
+			count = res;
+			break;
+		}
+		count += res;
+	}
+
+	return count;
+}
+
+/**
+ * move_file -
+ *
+ * > 0  Bytes moved / size to be moved
+ * = 0  Nothing to do
+ * < 0  Error
+ */
+static s64 move_file(ntfs_volume *vol, ntfs_inode *ino, u64 loc, int flags)
+{
+	char *buffer;
+	ntfs_attr_search_ctx *ctx;
+	ATTR_RECORD *rec;
+	s64 res;
+	s64 count = 0;
+
+	buffer = malloc(MAX_PATH);
+	if (!buffer) {
+		ntfs_log_error("Out of memory\n");
+		return -1;
+	}
+
+	utils_inode_get_name(ino, buffer, MAX_PATH);
+
+	if (dont_move(ino)) {
+		ntfs_log_error("can't move\n");
+		return -1;
+	}
+
+	ntfs_log_info("Moving %s\n", buffer);
+
+	// NTFS_MOVE_LOC_BEST : assess how much space all the attributes will need,
+	// find that space and pass the location to our children.
+	// Anything else we pass directly to move_attribute.
+
+	ctx = ntfs_attr_get_search_ctx(ino, NULL);
+
+	while ((rec = find_attribute(AT_UNUSED, ctx))) {
+		utils_attr_get_name(vol, rec, buffer, MAX_PATH);
+		ntfs_log_info("\tAttribute 0x%02x %s is ", rec->type, buffer);
+
+		if (rec->non_resident) {
+			ntfs_log_info("non-resident.   Moving it.\n");
+
+			res = move_attribute(vol, ino, rec, loc, flags);
+			if (res < 0) {
+				count = res;
+				break;
+			}
+			count += res;
+		} else {
+			ntfs_log_info("resident.\n\t\tSkipping it.\n");
+		}
+	}
+
+	ntfs_attr_put_search_ctx(ctx);
+	free(buffer);
+	return count;
+}
+
+
+/**
+ * main - Begin here
+ *
+ * Start from here.
+ *
+ * Return:  0  Success, the program worked
+ *	    1  Error, something went wrong
+ */
+int main(int argc, char *argv[])
+{
+	ntfs_volume *vol;
+	ntfs_inode *inode;
+	int flags = 0;
+	int result = 1;
+	s64 count;
+
+	ntfs_log_set_handler(ntfs_log_handler_outerr);
+
+	if (!parse_options(argc, argv))
+		return 1;
+
+	utils_set_locale();
+
+	if (opts.noaction)
+		flags |= NTFS_MNT_RDONLY;
+	if (opts.force)
+		flags |= NTFS_MNT_RECOVER;
+
+	vol = utils_mount_volume(opts.device, flags);
+	if (!vol) {
+		ntfs_log_info("!vol\n");
+		return 1;
+	}
+
+	inode = ntfs_pathname_to_inode(vol, NULL, opts.file);
+	if (!inode) {
+		ntfs_log_info("!inode\n");
+		return 1;
+	}
+
+	count = move_file(vol, inode, opts.location, 0);
+	if ((count > 0) && (!opts.nodirty)) {
+
+		/* Porting note: libntfs-3g does not automatically set or clear
+		 * dirty flags on mount/unmount. It always preserves them until
+		 * they are explicitly changed with ntfs_volume_write_flags.
+		 * This means that the dirty flag is possibly not set, but
+		 * should be set. So we explicitly set it with a call to
+		 * ntfs_volume_write_flags. */
+		if(!(vol->flags & VOLUME_IS_DIRTY) && ntfs_volume_write_flags(
+			vol, vol->flags | VOLUME_IS_DIRTY)) {
+			ntfs_log_error("Error: Failed to set volume dirty "
+				"flag (%d (%s))!\n", errno, strerror(errno));
+		}
+
+		ntfs_log_info("Relocated %lld bytes\n", (long long)count);
+	}
+	if (count >= 0)
+		result = 0;
+
+	if (result)
+		ntfs_log_info("failed\n");
+	else
+		ntfs_log_info("success\n");
+
+	ntfs_inode_close(inode);
+	ntfs_umount(vol, FALSE);
+	return result;
+}
diff --git a/ntfsprogs/ntfsmove.h b/ntfsprogs/ntfsmove.h
new file mode 100755
index 0000000000000000000000000000000000000000..ffc1519a140b36c58ee6f845514a11277d5dd3d2
--- /dev/null
+++ b/ntfsprogs/ntfsmove.h
@@ -0,0 +1,46 @@
+/*
+ * ntfsmove - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2003 Richard Russon
+ *
+ * This utility will move files on an NTFS volume.
+ *
+ * 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 Linux-NTFS
+ * 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 _NTFSMOVE_H_
+#define _NTFSMOVE_H_
+
+#include "types.h"
+					/* Move files to */
+#define NTFS_MOVE_LOC_START	-1000	/*   the first available space */
+#define NTFS_MOVE_LOC_BEST	-1001	/*   place big enough for entire file */
+#define NTFS_MOVE_LOC_END	-1002	/*   the last available space */
+
+struct options {
+	char		*device;	/* Device/File to work with */
+	char		*file;		/* File to display */
+	s64		 location;	/* Where to place the file */
+	int		 force;		/* Override common sense */
+	int		 quiet;		/* Less output */
+	int		 verbose;	/* Extra output */
+	int		 noaction;	/* Do not write to disk */
+	int		 nodirty;	/* Do not mark volume dirty */
+};
+
+#endif /* _NTFSMOVE_H_ */
+
+
diff --git a/ntfsprogs/ntfsprogs.8 b/ntfsprogs/ntfsprogs.8
new file mode 100755
index 0000000000000000000000000000000000000000..43ed9ded75f5072fd2d8b2643b42da8e1a06a983
--- /dev/null
+++ b/ntfsprogs/ntfsprogs.8
@@ -0,0 +1,75 @@
+.\" Copyright (c) 2002\-2005 Richard Russon.
+.\" Copyright (c) 2002\-2003 Anton Altaparmakov.
+.\" Copyright (c) 2005\-2006 Szabolcs Szakacsits.
+.\" Copyright (c) 2005\-2007 Yura Pakhuchiy.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSPROGS 8 "September 2007" "ntfs-3g 2015.3.14"
+.SH NAME
+ntfsprogs \- tools for doing neat things with NTFS
+.SH OVERVIEW
+.B ntfsprogs
+is a suite of NTFS utilities based around a shared library.  The tools are
+available for free and come with full source code.
+.SH TOOLS
+.PP
+.BR mkntfs (8)
+\- Create an NTFS filesystem.
+.PP
+.BR ntfscat (8)
+\- Dump a file's content to the standard output.
+.PP
+.BR ntfsclone (8)
+\- Efficiently clone, backup, restore or rescue NTFS.
+.PP
+.BR ntfscluster (8)
+\- Locate the files which use the given sectors or clusters.
+.PP
+.BR ntfscmp (8)
+\- Compare two NTFS filesystems and tell the differences.
+.PP
+.BR ntfscp (8)
+\- Copy a file to an NTFS volume.
+.PP
+.BR ntfsfix (8)
+\- Check and fix some common errors, clear the LogFile and make Windows
+perform a thorough check next time it boots.
+.PP
+.BR ntfsinfo (8)
+\- Show information about NTFS or one of the files or directories within it.
+.PP
+.BR ntfslabel (8)
+\- Show, or set, an NTFS filesystem's volume label.
+.PP
+.BR ntfsls (8)
+\- List information about files in a directory residing on an NTFS.
+.PP
+.BR ntfsresize (8)
+\- Resize NTFS without losing data.
+.PP
+.BR ntfstruncate (8)
+\- Truncate a file on an NTFS volume.
+.PP
+.BR ntfsundelete (8)
+\- Recover deleted files from NTFS.
+.PP
+.BR ntfswipe (8)
+\- Overwrite unused space on an NTFS volume.
+.SH AUTHORS
+.PP
+The tools were written by Anton Altaparmakov, Carmelo Kintana, Cristian Klein,
+Erik Sornes, Giang Nguyen, Holger Ohmacht, Lode Leroy, Matthew J. Fanto, Per
+Olofsson, Richard Russon, Szabolcs Szakacsits, Yura Pakhuchiy and Yuval Fledel.
+.SH AVAILABILITY
+The
+.B ntfsprogs
+are part of the
+.B ntfs-3g
+package which can be downloaded from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR ntfs\-3g (8)
+
diff --git a/ntfsprogs/ntfsprogs.8.in b/ntfsprogs/ntfsprogs.8.in
new file mode 100755
index 0000000000000000000000000000000000000000..f00f5f493f16b6971bf55bf62b01bf788eaf102c
--- /dev/null
+++ b/ntfsprogs/ntfsprogs.8.in
@@ -0,0 +1,75 @@
+.\" Copyright (c) 2002\-2005 Richard Russon.
+.\" Copyright (c) 2002\-2003 Anton Altaparmakov.
+.\" Copyright (c) 2005\-2006 Szabolcs Szakacsits.
+.\" Copyright (c) 2005\-2007 Yura Pakhuchiy.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSPROGS 8 "September 2007" "ntfs-3g @VERSION@"
+.SH NAME
+ntfsprogs \- tools for doing neat things with NTFS
+.SH OVERVIEW
+.B ntfsprogs
+is a suite of NTFS utilities based around a shared library.  The tools are
+available for free and come with full source code.
+.SH TOOLS
+.PP
+.BR mkntfs (8)
+\- Create an NTFS filesystem.
+.PP
+.BR ntfscat (8)
+\- Dump a file's content to the standard output.
+.PP
+.BR ntfsclone (8)
+\- Efficiently clone, backup, restore or rescue NTFS.
+.PP
+.BR ntfscluster (8)
+\- Locate the files which use the given sectors or clusters.
+.PP
+.BR ntfscmp (8)
+\- Compare two NTFS filesystems and tell the differences.
+.PP
+.BR ntfscp (8)
+\- Copy a file to an NTFS volume.
+.PP
+.BR ntfsfix (8)
+\- Check and fix some common errors, clear the LogFile and make Windows
+perform a thorough check next time it boots.
+.PP
+.BR ntfsinfo (8)
+\- Show information about NTFS or one of the files or directories within it.
+.PP
+.BR ntfslabel (8)
+\- Show, or set, an NTFS filesystem's volume label.
+.PP
+.BR ntfsls (8)
+\- List information about files in a directory residing on an NTFS.
+.PP
+.BR ntfsresize (8)
+\- Resize NTFS without losing data.
+.PP
+.BR ntfstruncate (8)
+\- Truncate a file on an NTFS volume.
+.PP
+.BR ntfsundelete (8)
+\- Recover deleted files from NTFS.
+.PP
+.BR ntfswipe (8)
+\- Overwrite unused space on an NTFS volume.
+.SH AUTHORS
+.PP
+The tools were written by Anton Altaparmakov, Carmelo Kintana, Cristian Klein,
+Erik Sornes, Giang Nguyen, Holger Ohmacht, Lode Leroy, Matthew J. Fanto, Per
+Olofsson, Richard Russon, Szabolcs Szakacsits, Yura Pakhuchiy and Yuval Fledel.
+.SH AVAILABILITY
+The
+.B ntfsprogs
+are part of the
+.B ntfs-3g
+package which can be downloaded from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR ntfs\-3g (8)
+
diff --git a/ntfsprogs/ntfsresize.8 b/ntfsprogs/ntfsresize.8
new file mode 100755
index 0000000000000000000000000000000000000000..389ce614a8cdd854f76afad0606e36235b411ae2
--- /dev/null
+++ b/ntfsprogs/ntfsresize.8
@@ -0,0 +1,327 @@
+.\" Copyright (c) 2002\-2006 Szabolcs Szakacsits.
+.\" Copyright (c) 2005 Richard Russon.
+.\" Copyright (c) 2011\-2013 Jean-Pierre Andre.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSRESIZE 8 "July 2013" "ntfs-3g 2015.3.14"
+.SH NAME
+ntfsresize \- resize an NTFS filesystem without data loss
+.SH SYNOPSIS
+.B ntfsresize
+[\fIOPTIONS\fR]
+.B \-\-info(\-mb\-only)
+.I DEVICE
+.br
+.B ntfsresize
+[\fIOPTIONS\fR]
+[\fB\-\-size \fISIZE\fR[\fBk\fR|\fBM\fR|\fBG\fR]]
+.I DEVICE
+.SH DESCRIPTION
+The
+.B ntfsresize
+program safely resizes Windows XP, Windows Server 2003, Windows 2000, Windows
+NT4 and Longhorn NTFS filesystems without data loss. All NTFS versions are
+supported, used by 32\-bit and 64\-bit Windows.
+.B Defragmentation is NOT required prior to resizing
+because the program can relocate any data if needed, without risking data
+integrity.
+.PP
+Ntfsresize can be used to shrink or enlarge any NTFS filesystem located
+on an unmounted
+.I DEVICE
+(usually a disk partition). The new filesystem will fit in a DEVICE
+whose desired size is
+.I SIZE
+bytes.
+The
+.I SIZE
+parameter may have one of the optional modifiers
+.BR k ,
+.BR M ,
+.BR G ,
+which means the
+.I SIZE
+parameter is given in kilo\-, mega\- or gigabytes respectively.
+.B Ntfsresize
+conforms to the SI, ATA, IEEE standards and the disk manufacturers
+by using k=10^3, M=10^6 and G=10^9.
+
+If both
+.B \-\-info(\-mb\-only)
+and
+.B \-\-size
+are omitted then the
+NTFS filesystem will be enlarged to match the underlying
+.I DEVICE
+size.
+.PP
+To resize a filesystem on a partition, you must resize BOTH the filesystem
+and the partition by editing the partition table on the disk. Similarly to
+other command line filesystem resizers,
+.B ntfsresize
+doesn't manipulate the size of the partitions, hence
+to do that you must use a disk partitioning tool as well, for example
+.BR fdisk (8).
+Alternatively you could use one of the many user friendly partitioners that
+uses
+.B ntfsresize
+internally, like Mandriva's DiskDrake, QTParted, SUSE/Novell's YaST Partitioner,
+IBM's EVMS, GParted or Debian/Ubuntu's Partman.
+.PP
+.B IMPORTANT!
+It's a good practice making REGULAR BACKUPS of your valuable data, especially
+before using ANY partitioning tools. To do so for NTFS, you could use
+.BR ntfsclone (8).
+Don't forget to save the partition table as well!
+.SS Shrinkage
+If you wish to shrink an NTFS partition, first use
+.B ntfsresize
+to shrink the size of the filesystem. Then you could use
+.BR fdisk (8)
+to shrink the size of the partition by deleting the
+partition and recreating it with the smaller size.
+Do not make the partition smaller than the new size of
+NTFS otherwise you won't be able to boot. If you did so notwithstanding
+then just recreate the partition to be as large as NTFS.
+.SS Enlargement
+To enlarge an NTFS filesystem, first you must enlarge the size of the
+underlying partition. This can be done using
+.BR fdisk (8)
+by deleting the partition and recreating it with a larger size.
+Make sure it will not overlap with an other existing partition.
+You may enlarge upwards (first sector unchanged) or downwards (last
+sector unchanged), but you may not enlarge at both ends in a single step.
+If you merge two NTFS partitions, only one of them can be expanded to the
+merged partition.
+After you have enlarged the partition, you may use
+.B ntfsresize
+to enlarge the size of the filesystem.
+.SS Partitioning
+When recreating the partition by a disk partitioning tool,
+make sure you create it at the same
+starting sector and with the same partition type as before.
+Otherwise you won't be able to access your filesystem. Use the 'u'
+fdisk command to switch to the reliable sector unit from the
+default cylinder one.
+
+Also make sure you set the bootable flag for the partition if it
+existed before. Failing to do so you might not be able to boot your
+computer from the disk.
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfsresize
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-c\fR, \fB\-\-check\fR
+By using this option ntfsresize will only check the device to ensure that it
+is ready to be resized. If not, it will print any errors detected. 
+If the device is fine, nothing will be printed.
+.TP
+\fB\-i\fR, \fB\-\-info\fR
+By using this option without \fB\-\-expand\fP, ntfsresize will determine the
+theoretically smallest shrunken filesystem size supported.
+Most of the time the result is the space
+already used on the filesystem. Ntfsresize will refuse shrinking to a
+smaller size than what you got by this option and depending on several
+factors it might be unable to shrink very close to this theoretical
+size. Although the integrity of your data should be never in risk,
+it's still strongly recommended to make a test run by using the
+\fB\-\-no\-action\fR option before real resizing.
+
+Practically the smallest shrunken size generally is
+at around "used space" + (20\-200 MB). Please also take into account
+that Windows might need about 50\-100 MB free space left to boot safely.
+
+If used in association with option \fB\-\-expand\fP, ntfsresize will determine
+the smallest downwards expansion size and the possible increments to the
+size. These are exact byte counts which must not be rounded.
+This option may be used after the partition has been expanded
+provided the upper bound has not been changed.
+
+This option never causes any changes to the filesystem, the partition is
+opened read\-only.
+.TP
+\fB\-m\fR, \fB\-\-info\-mb\-only\fR
+Like the info option, only print out the shrinkable size in MB.  Print nothing
+if the shrink size is the same as the original size (in MB).
+This option cannot be used in association with option \fB\-\-expand\fP.
+.TP
+\fB\-s\fR, \fB\-\-size\fR SIZE\fR[\fBk\fR|\fBM\fR|\fBG\fR]
+Resize filesystem to fit in a partition whose size is
+\fISIZE\fR[\fBk\fR|\fBM\fR|\fBG\fR] bytes by shifting its end and keeping
+its beginning unchanged. The filesystem size is set to be at least one
+sector smaller than the partition.
+The optional modifiers
+.BR k ,
+.BR M ,
+.B G
+mean the
+.I SIZE
+parameter is given in kilo\-, mega\- or gigabytes respectively.
+Conforming to standards, k=10^3, M=10^6 and G=10^9. ki=2^10, Mi=2^20
+and Gi=2^30 are also allowed. Use this option
+with
+.B \-\-no\-action
+first.
+.TP
+\fB\-x\fR, \fB\-\-expand\fR
+Expand the filesystem to the current partition size, shifting down its
+beginning and keeping its end unchanged. The metadata is recreated in the
+expanded space and no user data is relocated. This is incompatible with
+option \-s (or \-\-size) and can only be made if the expanded space is an
+exact multiple of the cluster size. It must also be large enough to hold the
+new metadata.
+
+If the expansion is interrupted for some reason (power outage, etc), you may
+restart the resizing, as the original data and metadata have been kept
+unchanged.
+
+Note : expanding a Windows system partition and filesystem downwards may lead
+to the registry or some files not matching the new system layout, or to
+some important files being located too far from the beginning of the
+partition, thus making Windows not bootable.
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+Forces ntfsresize to proceed with the resize operation either without
+prompting for an explicit acceptance, or if the filesystem is marked for
+consistency check. Double the option (-ff, --force --force) to avoid
+prompting even if the file system is marked for check.
+
+Please note, ntfsresize always marks the filesystem
+for consistency check before a real resize operation
+and it leaves that way for extra
+safety. Thus if NTFS was marked by ntfsresize then it's safe to
+use this option. If you need
+to resize several times without booting into Windows between each
+resizing steps then you must use this option.
+.TP
+.B \-n, \-\-no\-action
+Use this option to make a test run before doing the real resize operation.
+Volume will be opened read\-only and
+.B ntfsresize
+displays what it would do if it were to resize the filesystem.
+Continue with the real resizing only if the test run passed.
+.TP
+\fB\-b\fR, \fB\-\-bad\-sectors\fR
+Support disks having hardware errors, bad sectors with those
+.B ntfsresize
+would refuse to work by default.
+
+Prior using this option, it's strongly recommended to make a backup by
+.BR ntfsclone (8)
+using the \-\-rescue option, then running 'chkdsk /f /r volume:' on Windows
+from the command line. If the disk guarantee is still valid then replace it.
+It's defected. Please also note, that no software can repair these type of
+hardware errors. The most what they can do is to work around the permanent
+defects.
+
+This option doesn't have any effect if the disk is flawless.
+.TP
+\fB\-P\fR, \fB\-\-no\-progress\-bar\fR
+Don't show progress bars.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+More output.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Print the version number of
+.B ntfsresize
+and exit.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Display help and exit.
+.SH EXIT CODES
+The exit code is 0 on success, non\-zero otherwise.
+.SH KNOWN ISSUES
+No reliability problem is known. If you need
+help please try the Ntfsresize FAQ first (see below) and if you
+don't find your answer then send your question, comment or bug report to
+the development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.PP
+There are a few very rarely met restrictions at present: filesystems having
+unknown bad sectors, relocation
+of the first MFT extent and resizing into the middle of a $MFTMirr extent
+aren't supported yet. These cases are detected and
+resizing is restricted to a safe size or the closest safe
+size is displayed.
+.PP
+.B Ntfsresize
+schedules an NTFS consistency check and
+after the first boot into Windows you must see
+.B chkdsk
+running on a blue background. This is intentional and no need to worry about it.
+Windows may force a quick reboot after the consistency check.
+Moreover after repartitioning your disk and depending on the
+hardware configuration, the Windows message
+.B System Settings Change
+may also appear. Just acknowledge it and reboot again.
+.PP
+The disk geometry handling semantic (HDIO_GETGEO ioctl) has changed
+in an incompatible way in Linux 2.6 kernels and this triggered multitudinous
+partition table corruptions resulting in unbootable Windows systems, even if
+NTFS was consistent, if
+.BR parted (8)
+was involved in some way. This problem was often attributed to ntfsresize
+but in fact it's completely independent of NTFS thus ntfsresize. Moreover
+ntfsresize never touches the partition table at all. By changing
+the 'Disk Access Mode' to LBA in the BIOS makes booting work
+again, most of the time. You can find more information about this issue
+in the Troubleshooting section of the below referred Ntfsresize FAQ.
+.SH AUTHORS
+.B ntfsresize
+was written by Szabolcs Szakacsits, with contributions from Anton Altaparmakov
+and Richard Russon.
+It was ported to ntfs-3g by Erik Larsson and Jean-Pierre Andre.
+.SH ACKNOWLEDGEMENT
+Many thanks to Anton Altaparmakov and Richard Russon
+for libntfs, the excellent documentation and comments,
+to Gergely Madarasz, Dewey M. Sasser and Miguel Lastra and his colleagues
+at the University of Granada for their continuous and highly valuable help,
+furthermore to Erik Meade, Martin Fick, Sandro Hawke, Dave Croal,
+Lorrin Nelson, Geert Hendrickx, Robert Bjorkman and Richard Burdick
+for beta testing the relocation support, to Florian Eyben, Fritz Oppliger,
+Richard Ebling, Sid\-Ahmed Touati, Jan Kiszka, Benjamin Redelings, Christopher
+Haney, Ryan Durk, Ralf Beyer, Scott Hansen, Alan Evans for the valued
+contributions and to Theodore Ts'o whose
+.BR resize2fs (8)
+man page originally formed the basis of this page.
+.SH AVAILABILITY
+.B ntfsresize
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.sp
+.B Ntfsresize
+related news, example of usage, troubleshooting, statically linked binary and
+FAQ (frequently asked questions) are maintained at:
+.br
+.nh
+http://mlf.linux.rulez.org/mlf/ezaz/ntfsresize.html
+.hy
+.SH SEE ALSO
+.BR fdisk (8),
+.BR cfdisk (8),
+.BR sfdisk (8),
+.BR parted (8),
+.BR evms (8),
+.BR ntfsclone (8),
+.BR mkntfs (8),
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/ntfsresize.8.in b/ntfsprogs/ntfsresize.8.in
new file mode 100755
index 0000000000000000000000000000000000000000..177eb500b1b1accc65adb96afdbbca455d81c240
--- /dev/null
+++ b/ntfsprogs/ntfsresize.8.in
@@ -0,0 +1,327 @@
+.\" Copyright (c) 2002\-2006 Szabolcs Szakacsits.
+.\" Copyright (c) 2005 Richard Russon.
+.\" Copyright (c) 2011\-2013 Jean-Pierre Andre.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSRESIZE 8 "July 2013" "ntfs-3g @VERSION@"
+.SH NAME
+ntfsresize \- resize an NTFS filesystem without data loss
+.SH SYNOPSIS
+.B ntfsresize
+[\fIOPTIONS\fR]
+.B \-\-info(\-mb\-only)
+.I DEVICE
+.br
+.B ntfsresize
+[\fIOPTIONS\fR]
+[\fB\-\-size \fISIZE\fR[\fBk\fR|\fBM\fR|\fBG\fR]]
+.I DEVICE
+.SH DESCRIPTION
+The
+.B ntfsresize
+program safely resizes Windows XP, Windows Server 2003, Windows 2000, Windows
+NT4 and Longhorn NTFS filesystems without data loss. All NTFS versions are
+supported, used by 32\-bit and 64\-bit Windows.
+.B Defragmentation is NOT required prior to resizing
+because the program can relocate any data if needed, without risking data
+integrity.
+.PP
+Ntfsresize can be used to shrink or enlarge any NTFS filesystem located
+on an unmounted
+.I DEVICE
+(usually a disk partition). The new filesystem will fit in a DEVICE
+whose desired size is
+.I SIZE
+bytes.
+The
+.I SIZE
+parameter may have one of the optional modifiers
+.BR k ,
+.BR M ,
+.BR G ,
+which means the
+.I SIZE
+parameter is given in kilo\-, mega\- or gigabytes respectively.
+.B Ntfsresize
+conforms to the SI, ATA, IEEE standards and the disk manufacturers
+by using k=10^3, M=10^6 and G=10^9.
+
+If both
+.B \-\-info(\-mb\-only)
+and
+.B \-\-size
+are omitted then the
+NTFS filesystem will be enlarged to match the underlying
+.I DEVICE
+size.
+.PP
+To resize a filesystem on a partition, you must resize BOTH the filesystem
+and the partition by editing the partition table on the disk. Similarly to
+other command line filesystem resizers,
+.B ntfsresize
+doesn't manipulate the size of the partitions, hence
+to do that you must use a disk partitioning tool as well, for example
+.BR fdisk (8).
+Alternatively you could use one of the many user friendly partitioners that
+uses
+.B ntfsresize
+internally, like Mandriva's DiskDrake, QTParted, SUSE/Novell's YaST Partitioner,
+IBM's EVMS, GParted or Debian/Ubuntu's Partman.
+.PP
+.B IMPORTANT!
+It's a good practice making REGULAR BACKUPS of your valuable data, especially
+before using ANY partitioning tools. To do so for NTFS, you could use
+.BR ntfsclone (8).
+Don't forget to save the partition table as well!
+.SS Shrinkage
+If you wish to shrink an NTFS partition, first use
+.B ntfsresize
+to shrink the size of the filesystem. Then you could use
+.BR fdisk (8)
+to shrink the size of the partition by deleting the
+partition and recreating it with the smaller size.
+Do not make the partition smaller than the new size of
+NTFS otherwise you won't be able to boot. If you did so notwithstanding
+then just recreate the partition to be as large as NTFS.
+.SS Enlargement
+To enlarge an NTFS filesystem, first you must enlarge the size of the
+underlying partition. This can be done using
+.BR fdisk (8)
+by deleting the partition and recreating it with a larger size.
+Make sure it will not overlap with an other existing partition.
+You may enlarge upwards (first sector unchanged) or downwards (last
+sector unchanged), but you may not enlarge at both ends in a single step.
+If you merge two NTFS partitions, only one of them can be expanded to the
+merged partition.
+After you have enlarged the partition, you may use
+.B ntfsresize
+to enlarge the size of the filesystem.
+.SS Partitioning
+When recreating the partition by a disk partitioning tool,
+make sure you create it at the same
+starting sector and with the same partition type as before.
+Otherwise you won't be able to access your filesystem. Use the 'u'
+fdisk command to switch to the reliable sector unit from the
+default cylinder one.
+
+Also make sure you set the bootable flag for the partition if it
+existed before. Failing to do so you might not be able to boot your
+computer from the disk.
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfsresize
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-c\fR, \fB\-\-check\fR
+By using this option ntfsresize will only check the device to ensure that it
+is ready to be resized. If not, it will print any errors detected. 
+If the device is fine, nothing will be printed.
+.TP
+\fB\-i\fR, \fB\-\-info\fR
+By using this option without \fB\-\-expand\fP, ntfsresize will determine the
+theoretically smallest shrunken filesystem size supported.
+Most of the time the result is the space
+already used on the filesystem. Ntfsresize will refuse shrinking to a
+smaller size than what you got by this option and depending on several
+factors it might be unable to shrink very close to this theoretical
+size. Although the integrity of your data should be never in risk,
+it's still strongly recommended to make a test run by using the
+\fB\-\-no\-action\fR option before real resizing.
+
+Practically the smallest shrunken size generally is
+at around "used space" + (20\-200 MB). Please also take into account
+that Windows might need about 50\-100 MB free space left to boot safely.
+
+If used in association with option \fB\-\-expand\fP, ntfsresize will determine
+the smallest downwards expansion size and the possible increments to the
+size. These are exact byte counts which must not be rounded.
+This option may be used after the partition has been expanded
+provided the upper bound has not been changed.
+
+This option never causes any changes to the filesystem, the partition is
+opened read\-only.
+.TP
+\fB\-m\fR, \fB\-\-info\-mb\-only\fR
+Like the info option, only print out the shrinkable size in MB.  Print nothing
+if the shrink size is the same as the original size (in MB).
+This option cannot be used in association with option \fB\-\-expand\fP.
+.TP
+\fB\-s\fR, \fB\-\-size\fR SIZE\fR[\fBk\fR|\fBM\fR|\fBG\fR]
+Resize filesystem to fit in a partition whose size is
+\fISIZE\fR[\fBk\fR|\fBM\fR|\fBG\fR] bytes by shifting its end and keeping
+its beginning unchanged. The filesystem size is set to be at least one
+sector smaller than the partition.
+The optional modifiers
+.BR k ,
+.BR M ,
+.B G
+mean the
+.I SIZE
+parameter is given in kilo\-, mega\- or gigabytes respectively.
+Conforming to standards, k=10^3, M=10^6 and G=10^9. ki=2^10, Mi=2^20
+and Gi=2^30 are also allowed. Use this option
+with
+.B \-\-no\-action
+first.
+.TP
+\fB\-x\fR, \fB\-\-expand\fR
+Expand the filesystem to the current partition size, shifting down its
+beginning and keeping its end unchanged. The metadata is recreated in the
+expanded space and no user data is relocated. This is incompatible with
+option \-s (or \-\-size) and can only be made if the expanded space is an
+exact multiple of the cluster size. It must also be large enough to hold the
+new metadata.
+
+If the expansion is interrupted for some reason (power outage, etc), you may
+restart the resizing, as the original data and metadata have been kept
+unchanged.
+
+Note : expanding a Windows system partition and filesystem downwards may lead
+to the registry or some files not matching the new system layout, or to
+some important files being located too far from the beginning of the
+partition, thus making Windows not bootable.
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+Forces ntfsresize to proceed with the resize operation either without
+prompting for an explicit acceptance, or if the filesystem is marked for
+consistency check. Double the option (-ff, --force --force) to avoid
+prompting even if the file system is marked for check.
+
+Please note, ntfsresize always marks the filesystem
+for consistency check before a real resize operation
+and it leaves that way for extra
+safety. Thus if NTFS was marked by ntfsresize then it's safe to
+use this option. If you need
+to resize several times without booting into Windows between each
+resizing steps then you must use this option.
+.TP
+.B \-n, \-\-no\-action
+Use this option to make a test run before doing the real resize operation.
+Volume will be opened read\-only and
+.B ntfsresize
+displays what it would do if it were to resize the filesystem.
+Continue with the real resizing only if the test run passed.
+.TP
+\fB\-b\fR, \fB\-\-bad\-sectors\fR
+Support disks having hardware errors, bad sectors with those
+.B ntfsresize
+would refuse to work by default.
+
+Prior using this option, it's strongly recommended to make a backup by
+.BR ntfsclone (8)
+using the \-\-rescue option, then running 'chkdsk /f /r volume:' on Windows
+from the command line. If the disk guarantee is still valid then replace it.
+It's defected. Please also note, that no software can repair these type of
+hardware errors. The most what they can do is to work around the permanent
+defects.
+
+This option doesn't have any effect if the disk is flawless.
+.TP
+\fB\-P\fR, \fB\-\-no\-progress\-bar\fR
+Don't show progress bars.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+More output.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Print the version number of
+.B ntfsresize
+and exit.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Display help and exit.
+.SH EXIT CODES
+The exit code is 0 on success, non\-zero otherwise.
+.SH KNOWN ISSUES
+No reliability problem is known. If you need
+help please try the Ntfsresize FAQ first (see below) and if you
+don't find your answer then send your question, comment or bug report to
+the development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.PP
+There are a few very rarely met restrictions at present: filesystems having
+unknown bad sectors, relocation
+of the first MFT extent and resizing into the middle of a $MFTMirr extent
+aren't supported yet. These cases are detected and
+resizing is restricted to a safe size or the closest safe
+size is displayed.
+.PP
+.B Ntfsresize
+schedules an NTFS consistency check and
+after the first boot into Windows you must see
+.B chkdsk
+running on a blue background. This is intentional and no need to worry about it.
+Windows may force a quick reboot after the consistency check.
+Moreover after repartitioning your disk and depending on the
+hardware configuration, the Windows message
+.B System Settings Change
+may also appear. Just acknowledge it and reboot again.
+.PP
+The disk geometry handling semantic (HDIO_GETGEO ioctl) has changed
+in an incompatible way in Linux 2.6 kernels and this triggered multitudinous
+partition table corruptions resulting in unbootable Windows systems, even if
+NTFS was consistent, if
+.BR parted (8)
+was involved in some way. This problem was often attributed to ntfsresize
+but in fact it's completely independent of NTFS thus ntfsresize. Moreover
+ntfsresize never touches the partition table at all. By changing
+the 'Disk Access Mode' to LBA in the BIOS makes booting work
+again, most of the time. You can find more information about this issue
+in the Troubleshooting section of the below referred Ntfsresize FAQ.
+.SH AUTHORS
+.B ntfsresize
+was written by Szabolcs Szakacsits, with contributions from Anton Altaparmakov
+and Richard Russon.
+It was ported to ntfs-3g by Erik Larsson and Jean-Pierre Andre.
+.SH ACKNOWLEDGEMENT
+Many thanks to Anton Altaparmakov and Richard Russon
+for libntfs, the excellent documentation and comments,
+to Gergely Madarasz, Dewey M. Sasser and Miguel Lastra and his colleagues
+at the University of Granada for their continuous and highly valuable help,
+furthermore to Erik Meade, Martin Fick, Sandro Hawke, Dave Croal,
+Lorrin Nelson, Geert Hendrickx, Robert Bjorkman and Richard Burdick
+for beta testing the relocation support, to Florian Eyben, Fritz Oppliger,
+Richard Ebling, Sid\-Ahmed Touati, Jan Kiszka, Benjamin Redelings, Christopher
+Haney, Ryan Durk, Ralf Beyer, Scott Hansen, Alan Evans for the valued
+contributions and to Theodore Ts'o whose
+.BR resize2fs (8)
+man page originally formed the basis of this page.
+.SH AVAILABILITY
+.B ntfsresize
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.sp
+.B Ntfsresize
+related news, example of usage, troubleshooting, statically linked binary and
+FAQ (frequently asked questions) are maintained at:
+.br
+.nh
+http://mlf.linux.rulez.org/mlf/ezaz/ntfsresize.html
+.hy
+.SH SEE ALSO
+.BR fdisk (8),
+.BR cfdisk (8),
+.BR sfdisk (8),
+.BR parted (8),
+.BR evms (8),
+.BR ntfsclone (8),
+.BR mkntfs (8),
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/ntfsresize.c b/ntfsprogs/ntfsresize.c
new file mode 100755
index 0000000000000000000000000000000000000000..ce3b9f5459658d0301414bd41e6064df44f3600d
--- /dev/null
+++ b/ntfsprogs/ntfsresize.c
@@ -0,0 +1,4527 @@
+/**
+ * ntfsresize - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2002-2006 Szabolcs Szakacsits
+ * Copyright (c) 2002-2005 Anton Altaparmakov
+ * Copyright (c) 2002-2003 Richard Russon
+ * Copyright (c) 2007      Yura Pakhuchiy
+ * Copyright (c) 2011-2014 Jean-Pierre Andre
+ *
+ * This utility will resize an NTFS volume without data loss.
+ *
+ * WARNING FOR DEVELOPERS!!! Several external tools grep for text messages
+ * to control execution thus if you would like to change any message
+ * then PLEASE think twice before doing so then don't modify it. Thanks!
+ *
+ * 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 Linux-NTFS
+ * 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_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#include "debug.h"
+#include "types.h"
+#include "support.h"
+#include "endians.h"
+#include "bootsect.h"
+#include "device.h"
+#include "attrib.h"
+#include "volume.h"
+#include "mft.h"
+#include "bitmap.h"
+#include "inode.h"
+#include "runlist.h"
+#include "utils.h"
+/* #include "version.h" */
+#include "misc.h"
+
+#define BAN_NEW_TEXT 1	/* Respect the ban on new messages */
+#define CLEAN_EXIT 0	/* traditionnally volume is not closed, there must be a reason */
+
+static const char *EXEC_NAME = "ntfsresize";
+
+static const char *resize_warning_msg =
+"WARNING: Every sanity check passed and only the dangerous operations left.\n"
+"Make sure that important data has been backed up! Power outage or computer\n"
+"crash may result major data loss!\n";
+
+static const char *resize_important_msg =
+"You can go on to shrink the device for example with Linux fdisk.\n"
+"IMPORTANT: When recreating the partition, make sure that you\n"
+"  1)  create it at the same disk sector (use sector as the unit!)\n"
+"  2)  create it with the same partition type (usually 7, HPFS/NTFS)\n"
+"  3)  do not make it smaller than the new NTFS filesystem size\n"
+"  4)  set the bootable flag for the partition if it existed before\n"
+"Otherwise you won't be able to access NTFS or can't boot from the disk!\n"
+"If you make a mistake and don't have a partition table backup then you\n"
+"can recover the partition table by TestDisk or Parted's rescue mode.\n";
+
+static const char *invalid_ntfs_msg =
+"The device '%s' doesn't have a valid NTFS.\n"
+"Maybe you selected the wrong partition? Or the whole disk instead of a\n"
+"partition (e.g. /dev/hda, not /dev/hda1)? This error might also occur\n"
+"if the disk was incorrectly repartitioned (see the ntfsresize FAQ).\n";
+
+static const char *corrupt_volume_msg =
+"NTFS is inconsistent. Run chkdsk /f on Windows then reboot it TWICE!\n"
+"The usage of the /f parameter is very IMPORTANT! No modification was\n"
+"and will be made to NTFS by this software until it gets repaired.\n";
+
+static const char *hibernated_volume_msg =
+"The NTFS partition is hibernated. Windows must be resumed and turned off\n"
+"properly, so resizing could be done safely.\n";
+
+static const char *unclean_journal_msg =
+"The NTFS journal file is unclean. Please shutdown Windows properly before\n"
+"using this software! Note, if you have run chkdsk previously then boot\n"
+"Windows again which will automatically initialize the journal correctly.\n";
+
+static const char *opened_volume_msg =
+"This software has detected that the NTFS volume is already opened by another\n"
+"software thus it refuses to progress to preserve data consistency.\n";
+
+static const char *bad_sectors_warning_msg =
+"****************************************************************************\n"
+"* WARNING: The disk has bad sector. This means physical damage on the disk *\n"
+"* surface caused by deterioration, manufacturing faults or other reason.   *\n"
+"* The reliability of the disk may stay stable or degrade fast. We suggest  *\n"
+"* making a full backup urgently by running 'ntfsclone --rescue ...' then   *\n"
+"* run 'chkdsk /f /r' on Windows and rebooot it TWICE! Then you can resize  *\n"
+"* NTFS safely by additionally using the --bad-sectors option of ntfsresize.*\n"
+"****************************************************************************\n";
+
+static const char *many_bad_sectors_msg =
+"***************************************************************************\n"
+"* WARNING: The disk has many bad sectors. This means physical damage      *\n"
+"* on the disk surface caused by deterioration, manufacturing faults or    *\n"
+"* other reason. We suggest to get a replacement disk as soon as possible. *\n"
+"***************************************************************************\n";
+
+static struct {
+	int verbose;
+	int debug;
+	int ro_flag;
+	int force;
+	int info;
+	int infombonly;
+	int expand;
+	int reliable_size;
+	int show_progress;
+	int badsectors;
+	int check;
+	s64 bytes;
+	char *volume;
+} opt;
+
+struct bitmap {
+	s64 size;
+	u8 *bm;
+};
+
+#define NTFS_PROGBAR		0x0001
+#define NTFS_PROGBAR_SUPPRESS	0x0002
+
+struct progress_bar {
+	u64 start;
+	u64 stop;
+	int resolution;
+	int flags;
+	float unit;
+};
+
+struct llcn_t {
+	s64 lcn;	/* last used LCN for a "special" file/attr type */
+	s64 inode;	/* inode using it */
+};
+
+#define NTFSCK_PROGBAR		0x0001
+
+			/* runlists which have to be processed later */
+struct DELAYED {
+	struct DELAYED *next;
+	ATTR_TYPES type;
+	MFT_REF mref;
+	VCN lowest_vcn;
+	int name_len;
+	ntfschar *attr_name;
+	runlist_element *rl;
+	runlist *head_rl;
+} ;
+
+typedef struct {
+	ntfs_inode *ni;		     /* inode being processed */
+	ntfs_attr_search_ctx *ctx;   /* inode attribute being processed */
+	s64 inuse;		     /* num of clusters in use */
+	int multi_ref;		     /* num of clusters referenced many times */
+	int outsider;		     /* num of clusters outside the volume */
+	int show_outsider;	     /* controls showing the above information */
+	int flags;
+	struct bitmap lcn_bitmap;
+} ntfsck_t;
+
+typedef struct {
+	ntfs_volume *vol;
+	ntfs_inode *ni;		     /* inode being processed */
+	s64 new_volume_size;	     /* in clusters; 0 = --info w/o --size */
+	MFT_REF mref;                /* mft reference */
+	MFT_RECORD *mrec;            /* mft record */
+	ntfs_attr_search_ctx *ctx;   /* inode attribute being processed */
+	u64 relocations;	     /* num of clusters to relocate */
+	s64 inuse;		     /* num of clusters in use */
+	runlist mftmir_rl;	     /* $MFTMirr AT_DATA's new position */
+	s64 mftmir_old;		     /* $MFTMirr AT_DATA's old LCN */
+	int dirty_inode;	     /* some inode data got relocated */
+	int shrink;		     /* shrink = 1, enlarge = 0 */
+	s64 badclusters;	     /* num of physically dead clusters */
+	VCN mft_highest_vcn;	     /* used for relocating the $MFT */
+	runlist_element *new_mft_start; /* new first run for $MFT:$DATA */
+	struct DELAYED *delayed_runlists; /* runlists to process later */
+	struct progress_bar progress;
+	struct bitmap lcn_bitmap;
+	/* Temporary statistics until all case is supported */
+	struct llcn_t last_mft;
+	struct llcn_t last_mftmir;
+	struct llcn_t last_multi_mft;
+	struct llcn_t last_sparse;
+	struct llcn_t last_compressed;
+	struct llcn_t last_lcn;
+	s64 last_unsupp;	     /* last unsupported cluster */
+} ntfs_resize_t;
+
+/* FIXME: This, lcn_bitmap and pos from find_free_cluster() will make a cluster
+   allocation related structure, attached to ntfs_resize_t */
+static s64 max_free_cluster_range = 0;
+
+#define NTFS_MBYTE (1000 * 1000)
+
+/* WARNING: don't modify the text, external tools grep for it */
+#define ERR_PREFIX   "ERROR"
+#define PERR_PREFIX  ERR_PREFIX "(%d): "
+#define NERR_PREFIX  ERR_PREFIX ": "
+
+#define DIRTY_NONE		(0)
+#define DIRTY_INODE		(1)
+#define DIRTY_ATTRIB		(2)
+
+#define NTFS_MAX_CLUSTER_SIZE	(65536)
+
+static s64 rounded_up_division(s64 numer, s64 denom)
+{
+	return (numer + (denom - 1)) / denom;
+}
+
+/**
+ * perr_printf
+ *
+ * Print an error message.
+ */
+__attribute__((format(printf, 1, 2)))
+static void perr_printf(const char *fmt, ...)
+{
+	va_list ap;
+	int eo = errno;
+
+	fprintf(stdout, PERR_PREFIX, eo);
+	va_start(ap, fmt);
+	vfprintf(stdout, fmt, ap);
+	va_end(ap);
+	fprintf(stdout, ": %s\n", strerror(eo));
+	fflush(stdout);
+	fflush(stderr);
+}
+
+__attribute__((format(printf, 1, 2)))
+static void err_printf(const char *fmt, ...)
+{
+	va_list ap;
+
+	fprintf(stdout, NERR_PREFIX);
+	va_start(ap, fmt);
+	vfprintf(stdout, fmt, ap);
+	va_end(ap);
+	fflush(stdout);
+	fflush(stderr);
+}
+
+/**
+ * err_exit
+ *
+ * Print and error message and exit the program.
+ */
+__attribute__((noreturn))
+__attribute__((format(printf, 1, 2)))
+static void err_exit(const char *fmt, ...)
+{
+	va_list ap;
+
+	fprintf(stdout, NERR_PREFIX);
+	va_start(ap, fmt);
+	vfprintf(stdout, fmt, ap);
+	va_end(ap);
+	fflush(stdout);
+	fflush(stderr);
+	exit(1);
+}
+
+/**
+ * perr_exit
+ *
+ * Print and error message and exit the program
+ */
+__attribute__((noreturn))
+__attribute__((format(printf, 1, 2)))
+static void perr_exit(const char *fmt, ...)
+{
+	va_list ap;
+	int eo = errno;
+
+	fprintf(stdout, PERR_PREFIX, eo);
+	va_start(ap, fmt);
+	vfprintf(stdout, fmt, ap);
+	va_end(ap);
+	printf(": %s\n", strerror(eo));
+	fflush(stdout);
+	fflush(stderr);
+	exit(1);
+}
+
+/**
+ * usage - Print a list of the parameters to the program
+ *
+ * Print a list of the parameters and options for the program.
+ *
+ * Return:  none
+ */
+__attribute__((noreturn))
+static void usage(int ret)
+{
+
+	printf("\nUsage: %s [OPTIONS] DEVICE\n"
+		"    Resize an NTFS volume non-destructively, safely move any data if needed.\n"
+		"\n"
+		"    -c, --check            Check to ensure that the device is ready for resize\n"
+		"    -i, --info             Estimate the smallest shrunken size or the smallest\n"
+		"                                expansion size\n"
+		"    -m, --info-mb-only     Estimate the smallest shrunken size possible,\n"
+		"                                output size in MB only\n"
+		"    -s, --size SIZE        Resize volume to SIZE[k|M|G] bytes\n"
+		"    -x, --expand           Expand to full partition\n"
+		"\n"
+		"    -n, --no-action        Do not write to disk\n"
+		"    -b, --bad-sectors      Support disks having bad sectors\n"
+		"    -f, --force            Force to progress\n"
+		"    -P, --no-progress-bar  Don't show progress bar\n"
+		"    -v, --verbose          More output\n"
+		"    -V, --version          Display version information\n"
+		"    -h, --help             Display this help\n"
+#ifdef DEBUG
+		"    -d, --debug            Show debug information\n"
+#endif
+		"\n"
+		"    The options -i and -x are exclusive of option -s, and -m is exclusive\n"
+		"    of option -x. If options -i, -m, -s and -x are are all omitted\n"
+		"    then the NTFS volume will be enlarged to the DEVICE size.\n"
+		"\n", EXEC_NAME);
+	printf("%s%s", ntfs_bugs, ntfs_home);
+	printf("Ntfsresize FAQ: http://linux-ntfs.sourceforge.net/info/ntfsresize.html\n");
+	exit(ret);
+}
+
+/**
+ * proceed_question
+ *
+ * Force the user to confirm an action before performing it.
+ * Copy-paste from e2fsprogs
+ */
+static void proceed_question(void)
+{
+	char buf[256];
+	const char *short_yes = "yY";
+
+	fflush(stdout);
+	fflush(stderr);
+	printf("Are you sure you want to proceed (y/[n])? ");
+	buf[0] = 0;
+	if (fgets(buf, sizeof(buf), stdin)
+	    && !strchr(short_yes, buf[0])) {
+		printf("OK quitting. NO CHANGES have been made to your "
+				"NTFS volume.\n");
+		exit(1);
+	}
+}
+
+/**
+ * version - Print version information about the program
+ *
+ * Print a copyright statement and a brief description of the program.
+ *
+ * Return:  none
+ */
+static void version(void)
+{
+	printf("\nResize an NTFS Volume, without data loss.\n\n");
+	printf("Copyright (c) 2002-2006  Szabolcs Szakacsits\n");
+	printf("Copyright (c) 2002-2005  Anton Altaparmakov\n");
+	printf("Copyright (c) 2002-2003  Richard Russon\n");
+	printf("Copyright (c) 2007       Yura Pakhuchiy\n");
+	printf("Copyright (c) 2011-2014  Jean-Pierre Andre\n");
+	printf("\n%s\n%s%s", ntfs_gpl, ntfs_bugs, ntfs_home);
+}
+
+/**
+ * get_new_volume_size
+ *
+ * Convert a user-supplied string into a size.  Without any suffix the number
+ * will be assumed to be in bytes.  If the number has a suffix of k, M or G it
+ * will be scaled up by 1000, 1000000, or 1000000000.
+ */
+static s64 get_new_volume_size(char *s)
+{
+	s64 size;
+	char *suffix;
+	int prefix_kind = 1000;
+
+	size = strtoll(s, &suffix, 10);
+	if (size <= 0 || errno == ERANGE)
+		err_exit("Illegal new volume size\n");
+
+	if (!*suffix) {
+		opt.reliable_size = 1;
+		return size;
+	}
+
+	if (strlen(suffix) == 2 && suffix[1] == 'i')
+		prefix_kind = 1024;
+	else if (strlen(suffix) > 1)
+		usage(1);
+
+	/* We follow the SI prefixes:
+	   http://physics.nist.gov/cuu/Units/prefixes.html
+	   http://physics.nist.gov/cuu/Units/binary.html
+	   Disk partitioning tools use prefixes as,
+	                       k        M          G
+	   fdisk 2.11x-      2^10     2^20      10^3*2^20
+	   fdisk 2.11y+     10^3     10^6       10^9
+	   cfdisk           10^3     10^6       10^9
+	   sfdisk            2^10     2^20
+	   parted            2^10     2^20  (may change)
+	   fdisk (DOS)       2^10     2^20
+	*/
+	/* FIXME: check for overflow */
+	switch (*suffix) {
+	case 'G':
+		size *= prefix_kind;
+	case 'M':
+		size *= prefix_kind;
+	case 'k':
+		size *= prefix_kind;
+		break;
+	default:
+		usage(1);
+	}
+
+	return size;
+}
+
+/**
+ * parse_options - Read and validate the programs command line
+ *
+ * Read the command line, verify the syntax and parse the options.
+ * This function is very long, but quite simple.
+ *
+ * Return:  1 Success
+ *	    0 Error, one or more problems
+ */
+static int parse_options(int argc, char **argv)
+{
+	static const char *sopt = "-bcdfhimnPs:vVx";
+	static const struct option lopt[] = {
+		{ "bad-sectors",no_argument,		NULL, 'b' },
+		{ "check",	no_argument,		NULL, 'c' },
+#ifdef DEBUG
+		{ "debug",	no_argument,		NULL, 'd' },
+#endif
+		{ "force",	no_argument,		NULL, 'f' },
+		{ "help",	no_argument,		NULL, 'h' },
+		{ "info",	no_argument,		NULL, 'i' },
+		{ "info-mb-only", no_argument,		NULL, 'm' },
+		{ "no-action",	no_argument,		NULL, 'n' },
+		{ "no-progress-bar", no_argument,	NULL, 'P' },
+		{ "size",	required_argument,	NULL, 's' },
+		{ "expand",	no_argument,		NULL, 'x' },
+		{ "verbose",	no_argument,		NULL, 'v' },
+		{ "version",	no_argument,		NULL, 'V' },
+		{ NULL, 0, NULL, 0 }
+	};
+
+	int c;
+	int err  = 0;
+	int ver  = 0;
+	int help = 0;
+
+	memset(&opt, 0, sizeof(opt));
+	opt.show_progress = 1;
+
+	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
+		switch (c) {
+		case 1:	/* A non-option argument */
+			if (!err && !opt.volume)
+				opt.volume = argv[optind-1];
+			else
+				err++;
+			break;
+		case 'b':
+			opt.badsectors++;
+			break;
+		case 'c':
+			opt.check++;
+			break;
+		case 'd':
+			opt.debug++;
+			break;
+		case 'f':
+			opt.force++;
+			break;
+		case 'h':
+			help++;
+			break;
+		case 'i':
+			opt.info++;
+			break;
+		case 'm':
+			opt.infombonly++;
+			break;
+		case 'n':
+			opt.ro_flag = NTFS_MNT_RDONLY;
+			break;
+		case 'P':
+			opt.show_progress = 0;
+			break;
+		case 's':
+			if (!err && (opt.bytes == 0))
+				opt.bytes = get_new_volume_size(optarg);
+			else
+				err++;
+			break;
+		case 'v':
+			opt.verbose++;
+			ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
+			break;
+		case 'V':
+			ver++;
+			break;
+		case 'x':
+			opt.expand++;
+			break;
+		case '?':
+		default:
+			if (optopt == 's') {
+				printf("Option '%s' requires an argument.\n", argv[optind-1]);
+			} else {
+				printf("Unknown option '%s'.\n", argv[optind-1]);
+			}
+			err++;
+			break;
+		}
+	}
+
+	if (!help && !ver) {
+		if (opt.volume == NULL) {
+			if (argc > 1)
+				printf("You must specify exactly one device.\n");
+			err++;
+		}
+		if (opt.info || opt.infombonly) {
+			opt.ro_flag = NTFS_MNT_RDONLY;
+		}
+		if (opt.bytes
+		    && (opt.expand || opt.info || opt.infombonly)) {
+			printf(NERR_PREFIX "Options --info(-mb-only) and --expand "
+					"cannot be used with --size.\n");
+			usage(1);
+		}
+		if (opt.expand && opt.infombonly) {
+			printf(NERR_PREFIX "Options --info-mb-only "
+					"cannot be used with --expand.\n");
+			usage(1);
+		}
+	}
+
+	/* Redirect stderr to stdout, note fflush()es are essential! */
+	fflush(stdout);
+	fflush(stderr);
+	if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1)
+		perr_exit("Failed to redirect stderr to stdout");
+	fflush(stdout);
+	fflush(stderr);
+
+#ifdef DEBUG
+	if (!opt.debug)
+		if (!freopen("/dev/null", "w", stderr))
+			perr_exit("Failed to redirect stderr to /dev/null");
+#endif
+
+	if (ver)
+		version();
+	if (help || err)
+		usage(err > 0);
+
+		/* tri-state 0 : done, 1 : error, -1 : proceed */
+	return (err ? 1 : (help || ver ? 0 : -1));
+}
+
+static void print_advise(ntfs_volume *vol, s64 supp_lcn)
+{
+	s64 old_b, new_b, freed_b, old_mb, new_mb, freed_mb;
+
+	old_b = vol->nr_clusters * vol->cluster_size;
+	old_mb = rounded_up_division(old_b, NTFS_MBYTE);
+
+	/* Take the next supported cluster (free or relocatable)
+	   plus reserve a cluster for the backup boot sector */
+	supp_lcn += 2;
+
+	if (supp_lcn > vol->nr_clusters) {
+		err_printf("Very rare fragmentation type detected. "
+			   "Sorry, it's not supported yet.\n"
+			   "Try to defragment your NTFS, perhaps it helps.\n");
+		exit(1);
+	}
+
+	new_b = supp_lcn * vol->cluster_size;
+	new_mb = rounded_up_division(new_b, NTFS_MBYTE);
+	freed_b = (vol->nr_clusters - supp_lcn + 1) * vol->cluster_size;
+	freed_mb = freed_b / NTFS_MBYTE;
+
+	/* WARNING: don't modify the text, external tools grep for it */
+	if (!opt.infombonly)
+		printf("You might resize at %lld bytes ", (long long)new_b);
+	if ((new_mb * NTFS_MBYTE) < old_b) {
+		if (!opt.infombonly)
+			printf("or %lld MB ", (long long)new_mb);
+		else
+			printf("Minsize (in MB): %lld\n", (long long)new_mb);
+	}
+
+	if (!opt.infombonly) {
+		printf("(freeing ");
+		if (freed_mb && (old_mb - new_mb))
+			printf("%lld MB", (long long)(old_mb - new_mb));
+		else
+		        printf("%lld bytes", (long long)freed_b);
+		printf(").\n");
+
+		printf("Please make a test run using both the -n and -s "
+			"options before real resizing!\n");
+	}
+}
+
+static void rl_set(runlist *rl, VCN vcn, LCN lcn, s64 len)
+{
+	rl->vcn = vcn;
+	rl->lcn = lcn;
+	rl->length = len;
+}
+
+static int rl_items(runlist *rl)
+{
+	int i = 0;
+
+	while (rl[i++].length)
+		;
+
+	return i;
+}
+
+static void dump_run(runlist_element *r)
+{
+	ntfs_log_verbose(" %8lld  %8lld (0x%08llx)  %lld\n", (long long)r->vcn,
+			 (long long)r->lcn, (long long)r->lcn,
+			 (long long)r->length);
+}
+
+static void dump_runlist(runlist *rl)
+{
+	while (rl->length)
+		dump_run(rl++);
+}
+
+/**
+ * nr_clusters_to_bitmap_byte_size
+ *
+ * Take the number of clusters in the volume and calculate the size of $Bitmap.
+ * The size must be always a multiple of 8 bytes.
+ */
+static s64 nr_clusters_to_bitmap_byte_size(s64 nr_clusters)
+{
+	s64 bm_bsize;
+
+	bm_bsize = rounded_up_division(nr_clusters, 8);
+	bm_bsize = (bm_bsize + 7) & ~7;
+
+	return bm_bsize;
+}
+
+static void collect_resize_constraints(ntfs_resize_t *resize, runlist *rl)
+{
+	s64 inode, last_lcn;
+	ATTR_FLAGS flags;
+	ATTR_TYPES atype;
+	struct llcn_t *llcn = NULL;
+	int ret, supported = 0;
+
+	last_lcn = rl->lcn + (rl->length - 1);
+
+	inode = resize->ni->mft_no;
+	flags = resize->ctx->attr->flags;
+	atype = resize->ctx->attr->type;
+
+	if ((ret = ntfs_inode_badclus_bad(inode, resize->ctx->attr)) != 0) {
+		if (ret == -1)
+			perr_exit("Bad sector list check failed");
+		return;
+	}
+
+	if (inode == FILE_Bitmap) {
+		llcn = &resize->last_lcn;
+		if (atype == AT_DATA && NInoAttrList(resize->ni))
+		    err_exit("Highly fragmented $Bitmap isn't supported yet.");
+
+		supported = 1;
+
+	} else if (NInoAttrList(resize->ni)) {
+		llcn = &resize->last_multi_mft;
+
+		if (inode != FILE_MFTMirr)
+			supported = 1;
+
+	} else if (flags & ATTR_IS_SPARSE) {
+		llcn = &resize->last_sparse;
+		supported = 1;
+
+	} else if (flags & ATTR_IS_COMPRESSED) {
+		llcn = &resize->last_compressed;
+		supported = 1;
+
+	} else if (inode == FILE_MFTMirr) {
+		llcn = &resize->last_mftmir;
+		supported = 1;
+
+		/* Fragmented $MFTMirr DATA attribute isn't supported yet */
+		if (atype == AT_DATA)
+			if (rl[1].length != 0 || rl->vcn)
+				supported = 0;
+	} else {
+		llcn = &resize->last_lcn;
+		supported = 1;
+	}
+
+	if (llcn->lcn < last_lcn) {
+		llcn->lcn = last_lcn;
+		llcn->inode = inode;
+	}
+
+	if (supported)
+		return;
+
+	if (resize->last_unsupp < last_lcn)
+		resize->last_unsupp = last_lcn;
+}
+
+
+static void collect_relocation_info(ntfs_resize_t *resize, runlist *rl)
+{
+	s64 lcn, lcn_length, start, len, inode;
+	s64 new_vol_size;	/* (last LCN on the volume) + 1 */
+
+	lcn = rl->lcn;
+	lcn_length = rl->length;
+	inode = resize->ni->mft_no;
+	new_vol_size = resize->new_volume_size;
+
+	if (lcn + lcn_length <= new_vol_size)
+		return;
+
+	if (inode == FILE_Bitmap && resize->ctx->attr->type == AT_DATA)
+		return;
+
+	start = lcn;
+	len = lcn_length;
+
+	if (lcn < new_vol_size) {
+		start = new_vol_size;
+		len = lcn_length - (new_vol_size - lcn);
+
+		if ((!opt.info && !opt.infombonly) && (inode == FILE_MFTMirr)) {
+			err_printf("$MFTMirr can't be split up yet. Please try "
+				   "a different size.\n");
+			print_advise(resize->vol, lcn + lcn_length - 1);
+			exit(1);
+		}
+	}
+
+	resize->relocations += len;
+
+	if ((!opt.info && !opt.infombonly) || !resize->new_volume_size)
+		return;
+
+	printf("Relocation needed for inode %8lld attr 0x%x LCN 0x%08llx "
+			"length %6lld\n", (long long)inode,
+			(unsigned int)le32_to_cpu(resize->ctx->attr->type),
+			(unsigned long long)start, (long long)len);
+}
+
+/**
+ * build_lcn_usage_bitmap
+ *
+ * lcn_bitmap has one bit for each cluster on the disk.  Initially, lcn_bitmap
+ * has no bits set.  As each attribute record is read the bits in lcn_bitmap are
+ * checked to ensure that no other file already references that cluster.
+ *
+ * This serves as a rudimentary "chkdsk" operation.
+ */
+static void build_lcn_usage_bitmap(ntfs_volume *vol, ntfsck_t *fsck)
+{
+	s64 inode;
+	ATTR_RECORD *a;
+	runlist *rl;
+	int i, j;
+	struct bitmap *lcn_bitmap = &fsck->lcn_bitmap;
+
+	a = fsck->ctx->attr;
+	inode = fsck->ni->mft_no;
+
+	if (!a->non_resident)
+		return;
+
+	if (!(rl = ntfs_mapping_pairs_decompress(vol, a, NULL))) {
+		int err = errno;
+		perr_printf("ntfs_decompress_mapping_pairs");
+		if (err == EIO)
+			printf("%s", corrupt_volume_msg);
+		exit(1);
+	}
+
+
+	for (i = 0; rl[i].length; i++) {
+		s64 lcn = rl[i].lcn;
+		s64 lcn_length = rl[i].length;
+
+		/* CHECKME: LCN_RL_NOT_MAPPED check isn't needed */
+		if (lcn == LCN_HOLE || lcn == LCN_RL_NOT_MAPPED)
+			continue;
+
+		/* FIXME: ntfs_mapping_pairs_decompress should return error */
+		if (lcn < 0 || lcn_length <= 0)
+			err_exit("Corrupt runlist in inode %lld attr %x LCN "
+				 "%llx length %llx\n", (long long)inode,
+				 (unsigned int)le32_to_cpu(a->type),
+				 (long long)lcn, (long long)lcn_length);
+
+		for (j = 0; j < lcn_length; j++) {
+			u64 k = (u64)lcn + j;
+
+			if (k >= (u64)vol->nr_clusters) {
+				long long outsiders = lcn_length - j;
+
+				fsck->outsider += outsiders;
+
+				if (++fsck->show_outsider <= 10 || opt.verbose)
+					printf("Outside of the volume reference"
+					       " for inode %lld at %lld:%lld\n",
+					       (long long)inode, (long long)k,
+					       (long long)outsiders);
+
+				break;
+			}
+
+			if (ntfs_bit_get_and_set(lcn_bitmap->bm, k, 1)) {
+				if (++fsck->multi_ref <= 10 || opt.verbose)
+					printf("Cluster %lld is referenced "
+					       "multiple times!\n",
+					       (long long)k);
+				continue;
+			}
+		}
+		fsck->inuse += lcn_length;
+	}
+	free(rl);
+}
+
+
+static ntfs_attr_search_ctx *attr_get_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec)
+{
+	ntfs_attr_search_ctx *ret;
+
+	if ((ret = ntfs_attr_get_search_ctx(ni, mrec)) == NULL)
+		perr_printf("ntfs_attr_get_search_ctx");
+
+	return ret;
+}
+
+/**
+ * walk_attributes
+ *
+ * For a given MFT Record, iterate through all its attributes.  Any non-resident
+ * data runs will be marked in lcn_bitmap.
+ */
+static int walk_attributes(ntfs_volume *vol, ntfsck_t *fsck)
+{
+	if (!(fsck->ctx = attr_get_search_ctx(fsck->ni, NULL)))
+		return -1;
+
+	while (!ntfs_attrs_walk(fsck->ctx)) {
+		if (fsck->ctx->attr->type == AT_END)
+			break;
+		build_lcn_usage_bitmap(vol, fsck);
+	}
+
+	ntfs_attr_put_search_ctx(fsck->ctx);
+	return 0;
+}
+
+/**
+ * compare_bitmaps
+ *
+ * Compare two bitmaps.  In this case, $Bitmap as read from the disk and
+ * lcn_bitmap which we built from the MFT Records.
+ */
+static void compare_bitmaps(ntfs_volume *vol, struct bitmap *a)
+{
+	s64 i, pos, count;
+	int mismatch = 0;
+	int backup_boot = 0;
+	u8 bm[NTFS_BUF_SIZE];
+
+        if (!opt.infombonly)
+		printf("Accounting clusters ...\n");
+
+	pos = 0;
+	while (1) {
+		count = ntfs_attr_pread(vol->lcnbmp_na, pos, NTFS_BUF_SIZE, bm);
+		if (count == -1)
+			perr_exit("Couldn't get $Bitmap $DATA");
+
+		if (count == 0) {
+			if (a->size > pos)
+				err_exit("$Bitmap size is smaller than expected"
+					 " (%lld != %lld)\n",
+					 (long long)a->size, (long long)pos);
+			break;
+		}
+
+		for (i = 0; i < count; i++, pos++) {
+			s64 cl;  /* current cluster */
+
+			if (a->size <= pos)
+				goto done;
+
+			if (a->bm[pos] == bm[i])
+				continue;
+
+			for (cl = pos * 8; cl < (pos + 1) * 8; cl++) {
+				char bit;
+
+				bit = ntfs_bit_get(a->bm, cl);
+				if (bit == ntfs_bit_get(bm, i * 8 + cl % 8))
+					continue;
+
+				if (!mismatch && !bit && !backup_boot &&
+						cl == vol->nr_clusters / 2) {
+					/* FIXME: call also boot sector check */
+					backup_boot = 1;
+					printf("Found backup boot sector in "
+					       "the middle of the volume.\n");
+					continue;
+				}
+
+				if (++mismatch > 10 && !opt.verbose)
+					continue;
+
+				printf("Cluster accounting failed at %lld "
+						"(0x%llx): %s cluster in "
+						"$Bitmap\n", (long long)cl,
+						(unsigned long long)cl,
+						bit ? "missing" : "extra");
+			}
+		}
+	}
+done:
+	if (mismatch) {
+		printf("Filesystem check failed! Totally %d cluster "
+		       "accounting mismatches.\n", mismatch);
+		err_printf("%s", corrupt_volume_msg);
+		exit(1);
+	}
+}
+
+/**
+ * progress_init
+ *
+ * Create and scale our progress bar.
+ */
+static void progress_init(struct progress_bar *p, u64 start, u64 stop, int flags)
+{
+	p->start = start;
+	p->stop = stop;
+	p->unit = 100.0 / (stop - start);
+	p->resolution = 100;
+	p->flags = flags;
+}
+
+/**
+ * progress_update
+ *
+ * Update the progress bar and tell the user.
+ */
+static void progress_update(struct progress_bar *p, u64 current)
+{
+	float percent;
+
+	if (!(p->flags & NTFS_PROGBAR))
+		return;
+	if (p->flags & NTFS_PROGBAR_SUPPRESS)
+		return;
+
+	/* WARNING: don't modify the texts, external tools grep for them */
+	percent = p->unit * current;
+	if (current != p->stop) {
+		if ((current - p->start) % p->resolution)
+			return;
+		printf("%6.2f percent completed\r", percent);
+	} else
+		printf("100.00 percent completed\n");
+	fflush(stdout);
+}
+
+static int inode_close(ntfs_inode *ni)
+{
+	if (ntfs_inode_close(ni)) {
+		perr_printf("ntfs_inode_close for inode %llu",
+			    (unsigned long long)ni->mft_no);
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * walk_inodes
+ *
+ * Read each record in the MFT, skipping the unused ones, and build up a bitmap
+ * from all the non-resident attributes.
+ */
+static int build_allocation_bitmap(ntfs_volume *vol, ntfsck_t *fsck)
+{
+	s64 nr_mft_records, inode = 0;
+	ntfs_inode *ni;
+	struct progress_bar progress;
+	int pb_flags = 0;	/* progress bar flags */
+
+	/* WARNING: don't modify the text, external tools grep for it */
+        if (!opt.infombonly)
+		printf("Checking filesystem consistency ...\n");
+
+	if (fsck->flags & NTFSCK_PROGBAR)
+		pb_flags |= NTFS_PROGBAR;
+
+	nr_mft_records = vol->mft_na->initialized_size >>
+			vol->mft_record_size_bits;
+
+	progress_init(&progress, inode, nr_mft_records - 1, pb_flags);
+
+	for (; inode < nr_mft_records; inode++) {
+        	if (!opt.infombonly)
+			progress_update(&progress, inode);
+
+		if ((ni = ntfs_inode_open(vol, (MFT_REF)inode)) == NULL) {
+			/* FIXME: continue only if it make sense, e.g.
+			   MFT record not in use based on $MFT bitmap */
+			if (errno == EIO || errno == ENOENT)
+				continue;
+			perr_printf("Reading inode %lld failed",
+					(long long)inode);
+			return -1;
+		}
+
+		if (ni->mrec->base_mft_record)
+			goto close_inode;
+
+		fsck->ni = ni;
+		if (walk_attributes(vol, fsck) != 0) {
+			inode_close(ni);
+			return -1;
+		}
+close_inode:
+		if (inode_close(ni) != 0)
+			return -1;
+	}
+	return 0;
+}
+
+static void build_resize_constraints(ntfs_resize_t *resize)
+{
+	s64 i;
+	runlist *rl;
+
+	if (!resize->ctx->attr->non_resident)
+		return;
+
+	if (!(rl = ntfs_mapping_pairs_decompress(resize->vol,
+						 resize->ctx->attr, NULL)))
+		perr_exit("ntfs_decompress_mapping_pairs");
+
+	for (i = 0; rl[i].length; i++) {
+		/* CHECKME: LCN_RL_NOT_MAPPED check isn't needed */
+		if (rl[i].lcn == LCN_HOLE || rl[i].lcn == LCN_RL_NOT_MAPPED)
+			continue;
+
+		collect_resize_constraints(resize, rl + i);
+		if (resize->shrink)
+			collect_relocation_info(resize, rl + i);
+	}
+	free(rl);
+}
+
+static void resize_constraints_by_attributes(ntfs_resize_t *resize)
+{
+	if (!(resize->ctx = attr_get_search_ctx(resize->ni, NULL)))
+		exit(1);
+
+	while (!ntfs_attrs_walk(resize->ctx)) {
+		if (resize->ctx->attr->type == AT_END)
+			break;
+		build_resize_constraints(resize);
+	}
+
+	ntfs_attr_put_search_ctx(resize->ctx);
+}
+
+static void set_resize_constraints(ntfs_resize_t *resize)
+{
+	s64 nr_mft_records, inode;
+	ntfs_inode *ni;
+
+        if (!opt.infombonly)
+		printf("Collecting resizing constraints ...\n");
+
+	nr_mft_records = resize->vol->mft_na->initialized_size >>
+			resize->vol->mft_record_size_bits;
+
+	for (inode = 0; inode < nr_mft_records; inode++) {
+
+		ni = ntfs_inode_open(resize->vol, (MFT_REF)inode);
+		if (ni == NULL) {
+			if (errno == EIO || errno == ENOENT)
+				continue;
+			perr_exit("Reading inode %lld failed",
+					(long long)inode);
+		}
+
+		if (ni->mrec->base_mft_record)
+			goto close_inode;
+
+		resize->ni = ni;
+		resize_constraints_by_attributes(resize);
+close_inode:
+		if (inode_close(ni) != 0)
+			exit(1);
+	}
+}
+
+static void rl_fixup(runlist **rl)
+{
+	runlist *tmp = *rl;
+
+	if (tmp->lcn == LCN_RL_NOT_MAPPED) {
+		s64 unmapped_len = tmp->length;
+
+		ntfs_log_verbose("Skip unmapped run at the beginning ...\n");
+
+		if (!tmp->length)
+			err_exit("Empty unmapped runlist! Please report!\n");
+		(*rl)++;
+		for (tmp = *rl; tmp->length; tmp++)
+			tmp->vcn -= unmapped_len;
+	}
+
+	for (tmp = *rl; tmp->length; tmp++) {
+		if (tmp->lcn == LCN_RL_NOT_MAPPED) {
+			ntfs_log_verbose("Skip unmapped run at the end  ...\n");
+
+			if (tmp[1].length)
+				err_exit("Unmapped runlist in the middle! "
+					 "Please report!\n");
+			tmp->lcn = LCN_ENOENT;
+			tmp->length = 0;
+		}
+	}
+}
+
+/*
+ *		Plug a replacement (partial) runlist into full runlist
+ *
+ *	Returns 0 if successful
+ *		-1 if failed
+ */
+
+static int replace_runlist(ntfs_attr *na, const runlist_element *reprl,
+				VCN lowest_vcn)
+{
+	const runlist_element *prep;
+	const runlist_element *pold;
+	runlist_element *pnew;
+	runlist_element *newrl;
+	VCN nextvcn;
+	s32 oldcnt, newcnt;
+	s32 newsize;
+	int r;
+
+	r = -1; /* default return */
+		/* allocate a new runlist able to hold both */
+	oldcnt = 0;
+	while (na->rl[oldcnt].length)
+		oldcnt++;
+	newcnt = 0;
+	while (reprl[newcnt].length)
+		newcnt++;
+	newsize = ((oldcnt + newcnt)*sizeof(runlist_element) + 4095) & -4096;
+	newrl = (runlist_element*)malloc(newsize);
+	if (newrl) {
+		/* copy old runs until reaching replaced ones */
+		pnew = newrl;
+		pold = na->rl;
+		while (pold->length
+		    && ((pold->vcn + pold->length)
+				 <= (reprl[0].vcn + lowest_vcn))) {
+			*pnew = *pold;
+			pnew++;
+			pold++;
+		}
+		/* split a possible old run partially overlapped */
+		if (pold->length
+		    && (pold->vcn < (reprl[0].vcn + lowest_vcn))) {
+			pnew->vcn = pold->vcn;
+			pnew->lcn = pold->lcn;
+			pnew->length = reprl[0].vcn + lowest_vcn - pold->vcn;
+			pnew++;
+		}
+		/* copy new runs */
+		prep = reprl;
+		nextvcn = prep->vcn + lowest_vcn;
+		while (prep->length) {
+			pnew->vcn = prep->vcn + lowest_vcn;
+			pnew->lcn = prep->lcn;
+			pnew->length = prep->length;
+			nextvcn = pnew->vcn + pnew->length;
+			pnew++;
+			prep++;
+		}
+		/* locate the first fully replaced old run */
+		while (pold->length
+		    && ((pold->vcn + pold->length) <= nextvcn)) {
+			pold++;
+		}
+		/* split a possible old run partially overlapped */
+		if (pold->length
+		    && (pold->vcn < nextvcn)) {
+			pnew->vcn = nextvcn;
+			pnew->lcn = pold->lcn + nextvcn - pold->vcn;
+			pnew->length = pold->length - nextvcn + pold->vcn;
+			pnew++;
+		}
+		/* copy old runs beyond replaced ones */
+		while (pold->length) {
+			*pnew = *pold;
+			pnew++;
+			pold++;
+		}
+		/* the terminator is same as the old one */
+		*pnew = *pold;
+		/* deallocate the old runlist and replace */
+		free(na->rl);
+		na->rl = newrl;
+		r = 0;
+	}
+	return (r);
+}
+
+/*
+ *		Expand the new runlist in new extent(s)
+ *
+ *	This implies allocating inode extents and, generally, creating
+ *	an attribute list and allocating clusters for the list, and
+ *	shuffle the existing attributes accordingly.
+ *
+ *	Sometimes the runlist being reallocated is within an extent,
+ *	so we have a partial runlist to plug into an existing one
+ *	whose other parts have already been processed or will have
+ *	to be processed later, and we must not interfere with the
+ *	processing of these parts.
+ *
+ *	This cannot be done on the runlist part stored in a single
+ *	extent, it has to be done globally for the file.
+ *
+ *	We use the standard library functions, so we must wait until
+ *	the new global bitmap and the new MFT bitmap are saved to
+ *	disk and usable for the allocation of a new extent and creation
+ *	of an attribute list.
+ *
+ *	Aborts if something goes wrong. There should be no data damage,
+ *	because the old runlist is still in use and the bootsector has
+ *	not been updated yet, so the initial clusters can be accessed.
+ */
+
+static void expand_attribute_runlist(ntfs_volume *vol, struct DELAYED *delayed)
+{
+	ntfs_inode *ni;
+	ntfs_attr *na;
+	ATTR_TYPES type;
+	MFT_REF mref;
+	runlist_element *rl;
+
+		/* open the inode */
+	mref = delayed->mref;
+#ifndef BAN_NEW_TEXT
+	ntfs_log_verbose("Processing a delayed update for inode %lld\n",
+					(long long)mref);
+#endif
+	type = delayed->type;
+	rl = delayed->rl;
+	ni = ntfs_inode_open(vol,mref);
+	if (ni) {
+		na = ntfs_attr_open(ni, type,
+					delayed->attr_name, delayed->name_len);
+		if (na) {
+			if (!ntfs_attr_map_whole_runlist(na)) {
+				if (replace_runlist(na,rl,delayed->lowest_vcn)
+				    || ntfs_attr_update_mapping_pairs(na,0))
+					perr_exit("Could not update runlist "
+						"for attribute 0x%lx in inode %lld",
+						(long)le32_to_cpu(type),(long long)mref);
+			} else
+				perr_exit("Could not map attribute 0x%lx in inode %lld",
+					(long)le32_to_cpu(type),(long long)mref);
+			ntfs_attr_close(na);
+		} else
+			perr_exit("Could not open attribute 0x%lx in inode %lld",
+				(long)le32_to_cpu(type),(long long)mref);
+		ntfs_inode_mark_dirty(ni);
+		if (ntfs_inode_close(ni))
+			perr_exit("Failed to close inode %lld through the library",
+				(long long)mref);
+	} else
+		perr_exit("Could not open inode %lld through the library",
+			(long long)mref);
+}
+
+/*
+ *		Process delayed runlist updates
+ */
+
+static void delayed_updates(ntfs_resize_t *resize)
+{
+	struct DELAYED *delayed;
+
+	if (ntfs_volume_get_free_space(resize->vol))
+		err_exit("Failed to determine free space\n");
+
+	while (resize->delayed_runlists) {
+		delayed = resize->delayed_runlists;
+		expand_attribute_runlist(resize->vol, delayed);
+		resize->delayed_runlists = resize->delayed_runlists->next;
+		if (delayed->attr_name)
+			free(delayed->attr_name);
+		free(delayed->head_rl);
+		free(delayed);
+	}
+}
+
+/*
+ *		Queue a runlist replacement for later update
+ *
+ *	Store the attribute identification relative to base inode
+ */
+
+static void replace_later(ntfs_resize_t *resize, runlist *rl, runlist *head_rl)
+{
+	struct DELAYED *delayed;
+	ATTR_RECORD *a;
+	MFT_REF mref;
+	leMFT_REF lemref;
+	int name_len;
+	ntfschar *attr_name;
+
+		/* save the attribute parameters, to be able to find it later */
+	a = resize->ctx->attr;
+	name_len = a->name_length;
+	attr_name = (ntfschar*)NULL;
+	if (name_len) {
+		attr_name = (ntfschar*)ntfs_malloc(name_len*sizeof(ntfschar));
+		if (attr_name)
+			memcpy(attr_name,(u8*)a + le16_to_cpu(a->name_offset),
+					name_len*sizeof(ntfschar));
+	}
+	delayed = (struct DELAYED*)ntfs_malloc(sizeof(struct DELAYED));
+	if (delayed && (attr_name || !name_len)) {
+		lemref = resize->ctx->mrec->base_mft_record;
+		if (lemref)
+			mref = le64_to_cpu(lemref);
+		else
+			mref = resize->mref;
+		delayed->mref = MREF(mref);
+		delayed->type = a->type;
+		delayed->attr_name = attr_name;
+		delayed->name_len = name_len;
+		delayed->lowest_vcn = le64_to_cpu(a->lowest_vcn);
+		delayed->rl = rl;
+		delayed->head_rl = head_rl;
+		delayed->next = resize->delayed_runlists;
+		resize->delayed_runlists = delayed;
+	} else
+		perr_exit("Could not store delayed update data");
+}
+
+/*
+ *		Replace the runlist in an attribute
+ *
+ *	This sometimes requires expanding the runlist into another extent,
+ *	which has to be done globally on the attribute. Is so, the action
+ *	is put in a delay queue, and the caller must not free the runlist.
+ *
+ *	Returns 0 if the replacement could be done
+ *		1 when it has been put in the delay queue.
+ */
+
+static int replace_attribute_runlist(ntfs_resize_t *resize, runlist *rl)
+{
+	int mp_size, l;
+	int must_delay;
+	void *mp;
+	runlist *head_rl;
+	ntfs_volume *vol;
+	ntfs_attr_search_ctx *ctx;
+	ATTR_RECORD *a;
+
+	vol = resize->vol;
+	ctx = resize->ctx;
+	a = ctx->attr;
+	head_rl = rl;
+	rl_fixup(&rl);
+
+	if ((mp_size = ntfs_get_size_for_mapping_pairs(vol, rl, 0, INT_MAX)) == -1)
+		perr_exit("ntfs_get_size_for_mapping_pairs");
+
+	if (a->name_length) {
+		u16 name_offs = le16_to_cpu(a->name_offset);
+		u16 mp_offs = le16_to_cpu(a->mapping_pairs_offset);
+
+		if (name_offs >= mp_offs)
+			err_exit("Attribute name is after mapping pairs! "
+				 "Please report!\n");
+	}
+
+	/* CHECKME: don't trust mapping_pairs is always the last item in the
+	   attribute, instead check for the real size/space */
+	l = (int)le32_to_cpu(a->length) - le16_to_cpu(a->mapping_pairs_offset);
+	must_delay = 0;
+	if (mp_size > l) {
+		s32 remains_size;
+		char *next_attr;
+
+		ntfs_log_verbose("Enlarging attribute header ...\n");
+
+		mp_size = (mp_size + 7) & ~7;
+
+		ntfs_log_verbose("Old mp size      : %d\n", l);
+		ntfs_log_verbose("New mp size      : %d\n", mp_size);
+		ntfs_log_verbose("Bytes in use     : %u\n", (unsigned int)
+				 le32_to_cpu(ctx->mrec->bytes_in_use));
+
+		next_attr = (char *)a + le32_to_cpu(a->length);
+		l = mp_size - l;
+
+		ntfs_log_verbose("Bytes in use new : %u\n", l + (unsigned int)
+				 le32_to_cpu(ctx->mrec->bytes_in_use));
+		ntfs_log_verbose("Bytes allocated  : %u\n", (unsigned int)
+				 le32_to_cpu(ctx->mrec->bytes_allocated));
+
+		remains_size = le32_to_cpu(ctx->mrec->bytes_in_use);
+		remains_size -= (next_attr - (char *)ctx->mrec);
+
+		ntfs_log_verbose("increase         : %d\n", l);
+		ntfs_log_verbose("shift            : %lld\n",
+				 (long long)remains_size);
+		if (le32_to_cpu(ctx->mrec->bytes_in_use) + l >
+				le32_to_cpu(ctx->mrec->bytes_allocated)) {
+#ifndef BAN_NEW_TEXT
+			ntfs_log_verbose("Queuing expansion for later processing\n");
+#endif
+			must_delay = 1;
+			replace_later(resize,rl,head_rl);
+		} else {
+			memmove(next_attr + l, next_attr, remains_size);
+			ctx->mrec->bytes_in_use = cpu_to_le32(l +
+					le32_to_cpu(ctx->mrec->bytes_in_use));
+			a->length = cpu_to_le32(le32_to_cpu(a->length) + l);
+		}
+	}
+
+	if (!must_delay) {
+		mp = ntfs_calloc(mp_size);
+		if (!mp)
+			perr_exit("ntfsc_calloc couldn't get memory");
+
+		if (ntfs_mapping_pairs_build(vol, (u8*)mp, mp_size, rl, 0, NULL))
+			perr_exit("ntfs_mapping_pairs_build");
+
+		memmove((u8*)a + le16_to_cpu(a->mapping_pairs_offset), mp, mp_size);
+
+		free(mp);
+	}
+	return (must_delay);
+}
+
+static void set_bitmap_range(struct bitmap *bm, s64 pos, s64 length, u8 bit)
+{
+	while (length--)
+		ntfs_bit_set(bm->bm, pos++, bit);
+}
+
+static void set_bitmap_clusters(struct bitmap *bm, runlist *rl, u8 bit)
+{
+	for (; rl->length; rl++)
+		set_bitmap_range(bm, rl->lcn, rl->length, bit);
+}
+
+static void release_bitmap_clusters(struct bitmap *bm, runlist *rl)
+{
+	max_free_cluster_range = 0;
+	set_bitmap_clusters(bm, rl, 0);
+}
+
+static void set_max_free_zone(s64 length, s64 end, runlist_element *rle)
+{
+	if (length > rle->length) {
+		rle->lcn = end - length;
+		rle->length = length;
+	}
+}
+
+static int find_free_cluster(struct bitmap *bm,
+			     runlist_element *rle,
+			     s64 nr_vol_clusters,
+			     int hint)
+{
+	/* FIXME: get rid of this 'static' variable */
+	static s64 pos = 0;
+	s64 i, items = rle->length;
+	s64 free_zone = 0;
+
+	if (pos >= nr_vol_clusters)
+		pos = 0;
+	if (!max_free_cluster_range)
+		max_free_cluster_range = nr_vol_clusters;
+	rle->lcn = rle->length = 0;
+	if (hint)
+		pos = nr_vol_clusters / 2;
+	i = pos;
+
+	do {
+		if (!ntfs_bit_get(bm->bm, i)) {
+			if (++free_zone == items) {
+				set_max_free_zone(free_zone, i + 1, rle);
+				break;
+			}
+		} else {
+			set_max_free_zone(free_zone, i, rle);
+			free_zone = 0;
+		}
+		if (++i == nr_vol_clusters) {
+			set_max_free_zone(free_zone, i, rle);
+			i = free_zone = 0;
+		}
+		if (rle->length == max_free_cluster_range)
+			break;
+	} while (i != pos);
+
+	if (i)
+		set_max_free_zone(free_zone, i, rle);
+
+	if (!rle->lcn) {
+		errno = ENOSPC;
+		return -1;
+	}
+	if (rle->length < items && rle->length < max_free_cluster_range) {
+		max_free_cluster_range = rle->length;
+		ntfs_log_verbose("Max free range: %7lld     \n",
+				 (long long)max_free_cluster_range);
+	}
+	pos = rle->lcn + items;
+	if (pos == nr_vol_clusters)
+		pos = 0;
+
+	set_bitmap_range(bm, rle->lcn, rle->length, 1);
+	return 0;
+}
+
+static runlist *alloc_cluster(struct bitmap *bm,
+			      s64 items,
+			      s64 nr_vol_clusters,
+			      int hint)
+{
+	runlist_element rle;
+	runlist *rl = NULL;
+	int rl_size, runs = 0;
+	s64 vcn = 0;
+
+	if (items <= 0) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	while (items > 0) {
+
+		if (runs)
+			hint = 0;
+		rle.length = items;
+		if (find_free_cluster(bm, &rle, nr_vol_clusters, hint) == -1)
+			return NULL;
+
+		rl_size = (runs + 2) * sizeof(runlist_element);
+		if (!(rl = (runlist *)realloc(rl, rl_size)))
+			return NULL;
+
+		rl_set(rl + runs, vcn, rle.lcn, rle.length);
+
+		vcn += rle.length;
+		items -= rle.length;
+		runs++;
+	}
+
+	rl_set(rl + runs, vcn, -1LL, 0LL);
+
+	if (runs > 1) {
+		ntfs_log_verbose("Multi-run allocation:    \n");
+		dump_runlist(rl);
+	}
+	return rl;
+}
+
+static int read_all(struct ntfs_device *dev, void *buf, int count)
+{
+	int i;
+
+	while (count > 0) {
+
+		i = count;
+		if (!NDevReadOnly(dev))
+			i = dev->d_ops->read(dev, buf, count);
+
+		if (i < 0) {
+			if (errno != EAGAIN && errno != EINTR)
+				return -1;
+		} else if (i > 0) {
+			count -= i;
+			buf = i + (char *)buf;
+		} else
+			err_exit("Unexpected end of file!\n");
+	}
+	return 0;
+}
+
+static int write_all(struct ntfs_device *dev, void *buf, int count)
+{
+	int i;
+
+	while (count > 0) {
+
+		i = count;
+		if (!NDevReadOnly(dev))
+			i = dev->d_ops->write(dev, buf, count);
+
+		if (i < 0) {
+			if (errno != EAGAIN && errno != EINTR)
+				return -1;
+		} else {
+			count -= i;
+			buf = i + (char *)buf;
+		}
+	}
+	return 0;
+}
+
+/**
+ * write_mft_record
+ *
+ * Write an MFT Record back to the disk.  If the read-only command line option
+ * was given, this function will do nothing.
+ */
+static int write_mft_record(ntfs_volume *v, const MFT_REF mref, MFT_RECORD *buf)
+{
+	if (ntfs_mft_record_write(v, mref, buf))
+		perr_exit("ntfs_mft_record_write");
+
+//	if (v->dev->d_ops->sync(v->dev) == -1)
+//		perr_exit("Failed to sync device");
+
+	return 0;
+}
+
+static void lseek_to_cluster(ntfs_volume *vol, s64 lcn)
+{
+	off_t pos;
+
+	pos = (off_t)(lcn * vol->cluster_size);
+
+	if (vol->dev->d_ops->seek(vol->dev, pos, SEEK_SET) == (off_t)-1)
+		perr_exit("seek failed to position %lld", (long long)lcn);
+}
+
+static void copy_clusters(ntfs_resize_t *resize, s64 dest, s64 src, s64 len)
+{
+	s64 i;
+	char buff[NTFS_MAX_CLUSTER_SIZE]; /* overflow checked at mount time */
+	ntfs_volume *vol = resize->vol;
+
+	for (i = 0; i < len; i++) {
+
+		lseek_to_cluster(vol, src + i);
+
+		if (read_all(vol->dev, buff, vol->cluster_size) == -1) {
+			perr_printf("Failed to read from the disk");
+			if (errno == EIO)
+				printf("%s", bad_sectors_warning_msg);
+			exit(1);
+		}
+
+		lseek_to_cluster(vol, dest + i);
+
+		if (write_all(vol->dev, buff, vol->cluster_size) == -1) {
+			perr_printf("Failed to write to the disk");
+			if (errno == EIO)
+				printf("%s", bad_sectors_warning_msg);
+			exit(1);
+		}
+
+		resize->relocations++;
+		progress_update(&resize->progress, resize->relocations);
+	}
+}
+
+static void relocate_clusters(ntfs_resize_t *r, runlist *dest_rl, s64 src_lcn)
+{
+	/* collect_shrink_constraints() ensured $MFTMir DATA is one run */
+	if (r->mref == FILE_MFTMirr && r->ctx->attr->type == AT_DATA) {
+		if (!r->mftmir_old) {
+			r->mftmir_rl.lcn = dest_rl->lcn;
+			r->mftmir_rl.length = dest_rl->length;
+			r->mftmir_old = src_lcn;
+		} else
+			err_exit("Multi-run $MFTMirr. Please report!\n");
+	}
+
+	for (; dest_rl->length; src_lcn += dest_rl->length, dest_rl++)
+		copy_clusters(r, dest_rl->lcn, src_lcn, dest_rl->length);
+}
+
+static void rl_split_run(runlist **rl, int run, s64 pos)
+{
+	runlist *rl_new, *rle_new, *rle;
+	int items, new_size, size_head, size_tail;
+	s64 len_head, len_tail;
+
+	items = rl_items(*rl);
+	new_size = (items + 1) * sizeof(runlist_element);
+	size_head = run * sizeof(runlist_element);
+	size_tail = (items - run - 1) * sizeof(runlist_element);
+
+	rl_new = ntfs_malloc(new_size);
+	if (!rl_new)
+		perr_exit("ntfs_malloc");
+
+	rle_new = rl_new + run;
+	rle = *rl + run;
+
+	memmove(rl_new, *rl, size_head);
+	memmove(rle_new + 2, rle + 1, size_tail);
+
+	len_tail = rle->length - (pos - rle->lcn);
+	len_head = rle->length - len_tail;
+
+	rl_set(rle_new, rle->vcn, rle->lcn, len_head);
+	rl_set(rle_new + 1, rle->vcn + len_head, rle->lcn + len_head, len_tail);
+
+	ntfs_log_verbose("Splitting run at cluster %lld:\n", (long long)pos);
+	dump_run(rle); dump_run(rle_new); dump_run(rle_new + 1);
+
+	free(*rl);
+	*rl = rl_new;
+}
+
+static void rl_insert_at_run(runlist **rl, int run, runlist *ins)
+{
+	int items, ins_items;
+	int new_size, size_tail;
+	runlist *rle;
+	s64 vcn;
+
+	items  = rl_items(*rl);
+	ins_items = rl_items(ins) - 1;
+	new_size = ((items - 1) + ins_items) * sizeof(runlist_element);
+	size_tail = (items - run - 1) * sizeof(runlist_element);
+
+	if (!(*rl = (runlist *)realloc(*rl, new_size)))
+		perr_exit("realloc");
+
+	rle = *rl + run;
+
+	memmove(rle + ins_items, rle + 1, size_tail);
+
+	for (vcn = rle->vcn; ins->length; rle++, vcn += ins->length, ins++) {
+		rl_set(rle, vcn, ins->lcn, ins->length);
+//		dump_run(rle);
+	}
+
+	return;
+
+	/* FIXME: fast path if ins_items = 1 */
+//	(*rl + run)->lcn = ins->lcn;
+}
+
+static void relocate_run(ntfs_resize_t *resize, runlist **rl, int run)
+{
+	s64 lcn, lcn_length;
+	s64 new_vol_size;	/* (last LCN on the volume) + 1 */
+	runlist *relocate_rl;	/* relocate runlist to relocate_rl */
+	int hint;
+
+	lcn = (*rl + run)->lcn;
+	lcn_length = (*rl + run)->length;
+	new_vol_size = resize->new_volume_size;
+
+	if (lcn + lcn_length <= new_vol_size)
+		return;
+
+	if (lcn < new_vol_size) {
+		rl_split_run(rl, run, new_vol_size);
+		return;
+	}
+
+	hint = (resize->mref == FILE_MFTMirr) ? 1 : 0;
+	if ((resize->mref == FILE_MFT)
+	    && (resize->ctx->attr->type == AT_DATA)
+	    && !run
+	    && resize->new_mft_start) {
+		relocate_rl = resize->new_mft_start;
+	} else
+		if (!(relocate_rl = alloc_cluster(&resize->lcn_bitmap,
+					lcn_length, new_vol_size, hint)))
+			perr_exit("Cluster allocation failed for %llu:%lld",
+				  (unsigned long long)resize->mref,
+				  (long long)lcn_length);
+
+	/* FIXME: check $MFTMirr DATA isn't multi-run (or support it) */
+	ntfs_log_verbose("Relocate record %7llu:0x%x:%08lld:0x%08llx:0x%08llx "
+			 "--> 0x%08llx\n", (unsigned long long)resize->mref,
+			 (unsigned int)le32_to_cpu(resize->ctx->attr->type),
+			 (long long)lcn_length,
+			 (unsigned long long)(*rl + run)->vcn,
+			 (unsigned long long)lcn,
+			 (unsigned long long)relocate_rl->lcn);
+
+	relocate_clusters(resize, relocate_rl, lcn);
+	rl_insert_at_run(rl, run, relocate_rl);
+
+	/* We don't release old clusters in the bitmap, that area isn't
+	   used by the allocator and will be truncated later on */
+
+		/* Do not free the relocated MFT start */
+	if ((resize->mref != FILE_MFT)
+	    || (resize->ctx->attr->type != AT_DATA)
+	    || run
+	    || !resize->new_mft_start)
+		free(relocate_rl);
+
+	resize->dirty_inode = DIRTY_ATTRIB;
+}
+
+static void relocate_attribute(ntfs_resize_t *resize)
+{
+	ATTR_RECORD *a;
+	runlist *rl;
+	int i;
+
+	a = resize->ctx->attr;
+
+	if (!a->non_resident)
+		return;
+
+	if (!(rl = ntfs_mapping_pairs_decompress(resize->vol, a, NULL)))
+		perr_exit("ntfs_decompress_mapping_pairs");
+
+	for (i = 0; rl[i].length; i++) {
+		s64 lcn = rl[i].lcn;
+		s64 lcn_length = rl[i].length;
+
+		if (lcn == LCN_HOLE || lcn == LCN_RL_NOT_MAPPED)
+			continue;
+
+		/* FIXME: ntfs_mapping_pairs_decompress should return error */
+		if (lcn < 0 || lcn_length <= 0)
+			err_exit("Corrupt runlist in MTF %llu attr %x LCN "
+				 "%llx length %llx\n",
+				 (unsigned long long)resize->mref,
+				 (unsigned int)le32_to_cpu(a->type),
+				 (long long)lcn, (long long)lcn_length);
+
+		relocate_run(resize, &rl, i);
+	}
+
+	if (resize->dirty_inode == DIRTY_ATTRIB) {
+		if (!replace_attribute_runlist(resize, rl))
+			free(rl);
+		resize->dirty_inode = DIRTY_INODE;
+	} else
+		free(rl);
+}
+
+static int is_mftdata(ntfs_resize_t *resize)
+{
+	/*
+	 * We must update the MFT own DATA record at the end of the second
+	 * step, because the old MFT must be kept available for processing
+	 * the other files.
+	 */
+
+	if (resize->ctx->attr->type != AT_DATA)
+		return 0;
+
+	if (resize->mref == 0)
+		return 1;
+
+	if (MREF_LE(resize->mrec->base_mft_record) == 0 &&
+	    MSEQNO_LE(resize->mrec->base_mft_record) != 0)
+		return 1;
+
+	return 0;
+}
+
+static int handle_mftdata(ntfs_resize_t *resize, int do_mftdata)
+{
+	ATTR_RECORD *attr = resize->ctx->attr;
+	VCN highest_vcn, lowest_vcn;
+
+	if (do_mftdata) {
+
+		if (!is_mftdata(resize))
+			return 0;
+
+		highest_vcn = sle64_to_cpu(attr->highest_vcn);
+		lowest_vcn  = sle64_to_cpu(attr->lowest_vcn);
+
+		if (resize->mft_highest_vcn != highest_vcn)
+			return 0;
+
+		if (lowest_vcn == 0)
+			resize->mft_highest_vcn = lowest_vcn;
+		else
+			resize->mft_highest_vcn = lowest_vcn - 1;
+
+	} else if (is_mftdata(resize)) {
+
+		highest_vcn = sle64_to_cpu(attr->highest_vcn);
+
+		if (resize->mft_highest_vcn < highest_vcn)
+			resize->mft_highest_vcn = highest_vcn;
+
+		return 0;
+	}
+
+	return 1;
+}
+
+static void relocate_attributes(ntfs_resize_t *resize, int do_mftdata)
+{
+	int ret;
+
+	if (!(resize->ctx = attr_get_search_ctx(NULL, resize->mrec)))
+		exit(1);
+
+	while (!ntfs_attrs_walk(resize->ctx)) {
+		if (resize->ctx->attr->type == AT_END)
+			break;
+
+		if (handle_mftdata(resize, do_mftdata) == 0)
+			continue;
+
+		ret = ntfs_inode_badclus_bad(resize->mref, resize->ctx->attr);
+		if (ret == -1)
+			perr_exit("Bad sector list check failed");
+		else if (ret == 1)
+			continue;
+
+		if (resize->mref == FILE_Bitmap &&
+		    resize->ctx->attr->type == AT_DATA)
+			continue;
+
+		relocate_attribute(resize);
+	}
+
+	ntfs_attr_put_search_ctx(resize->ctx);
+}
+
+static void relocate_inode(ntfs_resize_t *resize, MFT_REF mref, int do_mftdata)
+{
+	ntfs_volume *vol = resize->vol;
+
+	if (ntfs_file_record_read(vol, mref, &resize->mrec, NULL)) {
+		/* FIXME: continue only if it make sense, e.g.
+		   MFT record not in use based on $MFT bitmap */
+		if (errno == EIO || errno == ENOENT)
+			return;
+		perr_exit("ntfs_file_record_record");
+	}
+
+	if (!(resize->mrec->flags & MFT_RECORD_IN_USE))
+		return;
+
+	resize->mref = mref;
+	resize->dirty_inode = DIRTY_NONE;
+
+	relocate_attributes(resize, do_mftdata);
+
+//		if (vol->dev->d_ops->sync(vol->dev) == -1)
+//			perr_exit("Failed to sync device");
+		/* relocate MFT during second step, even if not dirty */
+	if ((mref == FILE_MFT) && do_mftdata && resize->new_mft_start) {
+		s64 pos;
+
+			/* write the MFT own record at its new location */
+		pos = (resize->new_mft_start->lcn
+					<< vol->cluster_size_bits)
+			+ (FILE_MFT << vol->mft_record_size_bits);
+		if (!opt.ro_flag
+		    && (ntfs_mst_pwrite(vol->dev, pos, 1,
+				vol->mft_record_size, resize->mrec) != 1))
+			perr_exit("Couldn't update MFT own record");
+	} else {
+		if ((resize->dirty_inode == DIRTY_INODE)
+		   && write_mft_record(vol, mref, resize->mrec)) {
+			perr_exit("Couldn't update record %llu",
+						(unsigned long long)mref);
+		}
+	}
+}
+
+static void relocate_inodes(ntfs_resize_t *resize)
+{
+	s64 nr_mft_records;
+	MFT_REF mref;
+	VCN highest_vcn;
+	u64 length;
+
+	printf("Relocating needed data ...\n");
+
+	progress_init(&resize->progress, 0, resize->relocations, resize->progress.flags);
+	resize->relocations = 0;
+
+	resize->mrec = ntfs_malloc(resize->vol->mft_record_size);
+	if (!resize->mrec)
+		perr_exit("ntfs_malloc failed");
+
+	nr_mft_records = resize->vol->mft_na->initialized_size >>
+			resize->vol->mft_record_size_bits;
+
+		/*
+		 * If we need to relocate the first run of the MFT DATA,
+		 * do it now, to have a better chance of getting at least
+		 * 16 records in the first chunk. This is mandatory to be
+		 * later able to read an MFT extent in record 15.
+		 * Should this fail, we can stop with no damage, the volume
+		 * is still in its initial state.
+		 */
+	if (!resize->vol->mft_na->rl)
+		err_exit("Internal error : no runlist for $MFT\n");
+
+	if ((resize->vol->mft_na->rl->lcn + resize->vol->mft_na->rl->length)
+			>= resize->new_volume_size) {
+		/*
+		 * The length of the first run is normally found in
+		 * mft_na. However in some rare circumstance, this is
+		 * merged with the first run of an extent of MFT,
+		 * which implies there is a single run in the base record.
+		 * So we have to make sure not to overflow from the
+		 * runs present in the base extent.
+		 */
+		length = resize->vol->mft_na->rl->length;
+		if (ntfs_file_record_read(resize->vol, FILE_MFT,
+				&resize->mrec, NULL)
+		    || !(resize->ctx = attr_get_search_ctx(NULL,
+				resize->mrec))) {
+			err_exit("Could not read the base record of MFT\n");
+		}
+		while (!ntfs_attrs_walk(resize->ctx)
+		   && (resize->ctx->attr->type != AT_DATA)) { }
+		if (resize->ctx->attr->type == AT_DATA) {
+			le64 high_le;
+
+			high_le = resize->ctx->attr->highest_vcn;
+			if (le64_to_cpu(high_le) < length)
+				length = le64_to_cpu(high_le) + 1;
+		} else {
+			err_exit("Could not find the DATA of MFT\n");
+		}
+		ntfs_attr_put_search_ctx(resize->ctx);
+		resize->new_mft_start = alloc_cluster(&resize->lcn_bitmap,
+				length, resize->new_volume_size, 0);
+		if (!resize->new_mft_start
+		    || (((resize->new_mft_start->length
+			<< resize->vol->cluster_size_bits)
+			    >> resize->vol->mft_record_size_bits) < 16)) {
+			err_exit("Could not allocate 16 records in"
+					" the first MFT chunk\n");
+		}
+	}
+
+	for (mref = 0; mref < (MFT_REF)nr_mft_records; mref++)
+		relocate_inode(resize, mref, 0);
+
+	while (1) {
+		highest_vcn = resize->mft_highest_vcn;
+		mref = nr_mft_records;
+		do {
+			relocate_inode(resize, --mref, 1);
+			if (resize->mft_highest_vcn == 0)
+				goto done;
+		} while (mref);
+
+		if (highest_vcn == resize->mft_highest_vcn)
+			err_exit("Sanity check failed! Highest_vcn = %lld. "
+				 "Please report!\n", (long long)highest_vcn);
+	}
+done:
+	free(resize->mrec);
+}
+
+static void print_hint(ntfs_volume *vol, const char *s, struct llcn_t llcn)
+{
+	s64 runs_b, runs_mb;
+
+	if (llcn.lcn == 0)
+		return;
+
+	runs_b = llcn.lcn * vol->cluster_size;
+	runs_mb = rounded_up_division(runs_b, NTFS_MBYTE);
+	printf("%-19s: %9lld MB      %8lld\n", s, (long long)runs_mb,
+			(long long)llcn.inode);
+}
+
+/**
+ * advise_on_resize
+ *
+ * The metadata file $Bitmap has one bit for each cluster on disk.  This has
+ * already been read into lcn_bitmap.  By looking for the last used cluster on
+ * the disk, we can work out by how much we can shrink the volume.
+ */
+static void advise_on_resize(ntfs_resize_t *resize)
+{
+	ntfs_volume *vol = resize->vol;
+
+	if (opt.verbose) {
+		printf("Estimating smallest shrunken size supported ...\n");
+		printf("File feature         Last used at      By inode\n");
+		print_hint(vol, "$MFT",		resize->last_mft);
+		print_hint(vol, "Multi-Record", resize->last_multi_mft);
+		print_hint(vol, "$MFTMirr",	resize->last_mftmir);
+		print_hint(vol, "Compressed",	resize->last_compressed);
+		print_hint(vol, "Sparse",	resize->last_sparse);
+		print_hint(vol, "Ordinary",	resize->last_lcn);
+	}
+
+	print_advise(vol, resize->last_unsupp);
+}
+
+static void rl_expand(runlist **rl, const VCN last_vcn)
+{
+	int len;
+	runlist *p = *rl;
+
+	len = rl_items(p) - 1;
+	if (len <= 0)
+		err_exit("rl_expand: bad runlist length: %d\n", len);
+
+	if (p[len].vcn > last_vcn)
+		err_exit("rl_expand: length is already more than requested "
+			 "(%lld > %lld)\n",
+			 (long long)p[len].vcn, (long long)last_vcn);
+
+	if (p[len - 1].lcn == LCN_HOLE) {
+
+		p[len - 1].length += last_vcn - p[len].vcn;
+		p[len].vcn = last_vcn;
+
+	} else if (p[len - 1].lcn >= 0) {
+
+		p = realloc(*rl, (++len + 1) * sizeof(runlist_element));
+		if (!p)
+			perr_exit("rl_expand: realloc");
+
+		p[len - 1].lcn = LCN_HOLE;
+		p[len - 1].length = last_vcn - p[len - 1].vcn;
+		rl_set(p + len, last_vcn, LCN_ENOENT, 0LL);
+		*rl = p;
+
+	} else
+		err_exit("rl_expand: bad LCN: %lld\n",
+				(long long)p[len - 1].lcn);
+}
+
+static void rl_truncate(runlist **rl, const VCN last_vcn)
+{
+	int len;
+	VCN vcn;
+
+	len = rl_items(*rl) - 1;
+	if (len <= 0)
+		err_exit("rl_truncate: bad runlist length: %d\n", len);
+
+	vcn = (*rl)[len].vcn;
+
+	if (vcn < last_vcn)
+		rl_expand(rl, last_vcn);
+
+	else if (vcn > last_vcn)
+		if (ntfs_rl_truncate(rl, last_vcn) == -1)
+			perr_exit("ntfs_rl_truncate");
+}
+
+/**
+ * bitmap_file_data_fixup
+ *
+ * $Bitmap can overlap the end of the volume. Any bits in this region
+ * must be set. This region also encompasses the backup boot sector.
+ */
+static void bitmap_file_data_fixup(s64 cluster, struct bitmap *bm)
+{
+	for (; cluster < bm->size << 3; cluster++)
+		ntfs_bit_set(bm->bm, (u64)cluster, 1);
+}
+
+/**
+ * truncate_badclust_bad_attr
+ *
+ * The metadata file $BadClus needs to be shrunk.
+ *
+ * FIXME: this function should go away and instead using a generalized
+ * "truncate_bitmap_data_attr()"
+ */
+static void truncate_badclust_bad_attr(ntfs_resize_t *resize)
+{
+	ATTR_RECORD *a;
+	runlist *rl_bad;
+	s64 nr_clusters = resize->new_volume_size;
+	ntfs_volume *vol = resize->vol;
+
+	a = resize->ctx->attr;
+	if (!a->non_resident)
+		/* FIXME: handle resident attribute value */
+		err_exit("Resident attribute in $BadClust isn't supported!\n");
+
+	if (!(rl_bad = ntfs_mapping_pairs_decompress(vol, a, NULL)))
+		perr_exit("ntfs_mapping_pairs_decompress");
+
+	rl_truncate(&rl_bad, nr_clusters);
+
+	a->highest_vcn = cpu_to_sle64(nr_clusters - 1LL);
+	a->allocated_size = cpu_to_sle64(nr_clusters * vol->cluster_size);
+	a->data_size = cpu_to_sle64(nr_clusters * vol->cluster_size);
+
+	if (!replace_attribute_runlist(resize, rl_bad))
+		free(rl_bad);
+}
+
+/**
+ * realloc_bitmap_data_attr
+ *
+ * Reallocate the metadata file $Bitmap.  It must be large enough for one bit
+ * per cluster of the shrunken volume.  Also it must be a of 8 bytes in size.
+ */
+static void realloc_bitmap_data_attr(ntfs_resize_t *resize,
+				     runlist **rl,
+				     s64 nr_bm_clusters)
+{
+	s64 i;
+	ntfs_volume *vol = resize->vol;
+	ATTR_RECORD *a = resize->ctx->attr;
+	s64 new_size = resize->new_volume_size;
+	struct bitmap *bm = &resize->lcn_bitmap;
+
+	if (!(*rl = ntfs_mapping_pairs_decompress(vol, a, NULL)))
+		perr_exit("ntfs_mapping_pairs_decompress");
+
+	release_bitmap_clusters(bm, *rl);
+	free(*rl);
+
+	for (i = vol->nr_clusters; i < new_size; i++)
+		ntfs_bit_set(bm->bm, i, 0);
+
+	if (!(*rl = alloc_cluster(bm, nr_bm_clusters, new_size, 0)))
+		perr_exit("Couldn't allocate $Bitmap clusters");
+}
+
+static void realloc_lcn_bitmap(ntfs_resize_t *resize, s64 bm_bsize)
+{
+	u8 *tmp;
+
+	if (!(tmp = realloc(resize->lcn_bitmap.bm, bm_bsize)))
+		perr_exit("realloc");
+
+	resize->lcn_bitmap.bm = tmp;
+	resize->lcn_bitmap.size = bm_bsize;
+	bitmap_file_data_fixup(resize->new_volume_size, &resize->lcn_bitmap);
+}
+
+/**
+ * truncate_bitmap_data_attr
+ */
+static void truncate_bitmap_data_attr(ntfs_resize_t *resize)
+{
+	ATTR_RECORD *a;
+	runlist *rl;
+	ntfs_attr *lcnbmp_na;
+	s64 bm_bsize, size;
+	s64 nr_bm_clusters;
+	int truncated;
+	ntfs_volume *vol = resize->vol;
+
+	a = resize->ctx->attr;
+	if (!a->non_resident)
+		/* FIXME: handle resident attribute value */
+		err_exit("Resident attribute in $Bitmap isn't supported!\n");
+
+	bm_bsize = nr_clusters_to_bitmap_byte_size(resize->new_volume_size);
+	nr_bm_clusters = rounded_up_division(bm_bsize, vol->cluster_size);
+
+	if (resize->shrink) {
+		realloc_bitmap_data_attr(resize, &rl, nr_bm_clusters);
+		realloc_lcn_bitmap(resize, bm_bsize);
+	} else {
+		realloc_lcn_bitmap(resize, bm_bsize);
+		realloc_bitmap_data_attr(resize, &rl, nr_bm_clusters);
+	}
+		/*
+		 * Delayed relocations may require cluster allocations
+		 * through the library, to hold added attribute lists,
+		 * be sure they will be within the new limits.
+		 */
+	lcnbmp_na = resize->vol->lcnbmp_na;
+	lcnbmp_na->data_size = bm_bsize;
+	lcnbmp_na->initialized_size = bm_bsize;
+	lcnbmp_na->allocated_size = nr_bm_clusters << vol->cluster_size_bits;
+	vol->lcnbmp_ni->data_size = bm_bsize;
+	vol->lcnbmp_ni->allocated_size = lcnbmp_na->allocated_size;
+	a->highest_vcn = cpu_to_sle64(nr_bm_clusters - 1LL);
+	a->allocated_size = cpu_to_sle64(nr_bm_clusters * vol->cluster_size);
+	a->data_size = cpu_to_sle64(bm_bsize);
+	a->initialized_size = cpu_to_sle64(bm_bsize);
+
+	truncated = !replace_attribute_runlist(resize, rl);
+
+	/*
+	 * FIXME: update allocated/data sizes and timestamps in $FILE_NAME
+	 * attribute too, for now chkdsk will do this for us.
+	 */
+
+	size = ntfs_rl_pwrite(vol, rl, 0, 0, bm_bsize, resize->lcn_bitmap.bm);
+	if (bm_bsize != size) {
+		if (size == -1)
+			perr_exit("Couldn't write $Bitmap");
+		err_exit("Couldn't write full $Bitmap file (%lld from %lld)\n",
+				(long long)size, (long long)bm_bsize);
+	}
+
+	if (truncated) {
+			/* switch to the new bitmap runlist */
+		free(lcnbmp_na->rl);
+		lcnbmp_na->rl = rl;
+	}
+}
+
+/**
+ * lookup_data_attr
+ *
+ * Find the $DATA attribute (with or without a name) for the given MFT reference
+ * (inode number).
+ */
+static void lookup_data_attr(ntfs_volume *vol,
+			     MFT_REF mref,
+			     const char *aname,
+			     ntfs_attr_search_ctx **ctx)
+{
+	ntfs_inode *ni;
+	ntfschar *ustr;
+	int len = 0;
+
+	if (!(ni = ntfs_inode_open(vol, mref)))
+		perr_exit("ntfs_open_inode");
+
+	if (!(*ctx = attr_get_search_ctx(ni, NULL)))
+		exit(1);
+
+	if ((ustr = ntfs_str2ucs(aname, &len)) == NULL) {
+		perr_printf("Couldn't convert '%s' to Unicode", aname);
+		exit(1);
+	}
+
+	if (ntfs_attr_lookup(AT_DATA, ustr, len, CASE_SENSITIVE,
+			 0, NULL, 0, *ctx))
+		perr_exit("ntfs_lookup_attr");
+
+	ntfs_ucsfree(ustr);
+}
+
+#if CLEAN_EXIT
+
+static void close_inode_and_context(ntfs_attr_search_ctx *ctx)
+{
+	ntfs_inode *ni;
+
+	ni = ctx->base_ntfs_ino;
+	if (!ni)
+		ni = ctx->ntfs_ino;
+	ntfs_attr_put_search_ctx(ctx);
+	if (ni)
+		ntfs_inode_close(ni);
+}
+
+#endif /* CLEAN_EXIT */
+
+static int check_bad_sectors(ntfs_volume *vol)
+{
+	ntfs_attr_search_ctx *ctx;
+	ntfs_inode *base_ni;
+	runlist *rl;
+	s64 i, badclusters = 0;
+
+	ntfs_log_verbose("Checking for bad sectors ...\n");
+
+	lookup_data_attr(vol, FILE_BadClus, "$Bad", &ctx);
+
+	base_ni = ctx->base_ntfs_ino;
+	if (!base_ni)
+		base_ni = ctx->ntfs_ino;
+
+	if (NInoAttrList(base_ni)) {
+		err_printf("Too many bad sectors have been detected!\n");
+		printf("%s", many_bad_sectors_msg);
+		exit(1);
+	}
+
+	if (!ctx->attr->non_resident)
+		err_exit("Resident attribute in $BadClust! Please report to "
+			 "%s\n", NTFS_DEV_LIST);
+	/*
+	 * FIXME: The below would be partial for non-base records in the
+	 * not yet supported multi-record case. Alternatively use audited
+	 * ntfs_attr_truncate after an umount & mount.
+	 */
+	if (!(rl = ntfs_mapping_pairs_decompress(vol, ctx->attr, NULL)))
+		perr_exit("Decompressing $BadClust:$Bad mapping pairs failed");
+
+	for (i = 0; rl[i].length; i++) {
+		/* CHECKME: LCN_RL_NOT_MAPPED check isn't needed */
+		if (rl[i].lcn == LCN_HOLE || rl[i].lcn == LCN_RL_NOT_MAPPED)
+			continue;
+
+		badclusters += rl[i].length;
+		ntfs_log_verbose("Bad cluster: %#8llx - %#llx    (%lld)\n",
+				 (long long)rl[i].lcn,
+				 (long long)rl[i].lcn + rl[i].length - 1,
+				 (long long)rl[i].length);
+	}
+
+	if (badclusters) {
+		printf("%sThis software has detected that the disk has at least"
+		       " %lld bad sector%s.\n",
+		       !opt.badsectors ? NERR_PREFIX : "WARNING: ",
+		       (long long)badclusters, badclusters - 1 ? "s" : "");
+		if (!opt.badsectors) {
+			printf("%s", bad_sectors_warning_msg);
+			exit(1);
+		} else
+			printf("WARNING: Bad sectors can cause reliability "
+			       "problems and massive data loss!!!\n");
+	}
+
+	free(rl);
+#if CLEAN_EXIT
+	close_inode_and_context(ctx);
+#else
+	ntfs_attr_put_search_ctx(ctx);
+#endif
+
+	return badclusters;
+}
+
+/**
+ * truncate_badclust_file
+ *
+ * Shrink the $BadClus file to match the new volume size.
+ */
+static void truncate_badclust_file(ntfs_resize_t *resize)
+{
+	printf("Updating $BadClust file ...\n");
+
+	lookup_data_attr(resize->vol, FILE_BadClus, "$Bad", &resize->ctx);
+	/* FIXME: sanity_check_attr(ctx->attr); */
+	truncate_badclust_bad_attr(resize);
+
+	if (write_mft_record(resize->vol, resize->ctx->ntfs_ino->mft_no,
+			     resize->ctx->mrec))
+		perr_exit("Couldn't update $BadClust");
+
+#if CLEAN_EXIT
+	close_inode_and_context(resize->ctx);
+#else
+	ntfs_attr_put_search_ctx(resize->ctx);
+#endif
+}
+
+/**
+ * truncate_bitmap_file
+ *
+ * Shrink the $Bitmap file to match the new volume size.
+ */
+static void truncate_bitmap_file(ntfs_resize_t *resize)
+{
+	ntfs_volume *vol = resize->vol;
+
+	printf("Updating $Bitmap file ...\n");
+
+	lookup_data_attr(resize->vol, FILE_Bitmap, NULL, &resize->ctx);
+	truncate_bitmap_data_attr(resize);
+
+	if (resize->new_mft_start) {
+		s64 pos;
+
+			/* write the MFT record at its new location */
+		pos = (resize->new_mft_start->lcn << vol->cluster_size_bits)
+			+ (FILE_Bitmap << vol->mft_record_size_bits);
+		if (!opt.ro_flag
+		    && (ntfs_mst_pwrite(vol->dev, pos, 1,
+				vol->mft_record_size, resize->ctx->mrec) != 1))
+			perr_exit("Couldn't update $Bitmap at new location");
+	} else {
+		if (write_mft_record(vol, resize->ctx->ntfs_ino->mft_no,
+			     resize->ctx->mrec))
+			perr_exit("Couldn't update $Bitmap");
+	}
+
+		/* If successful, update cache and sync $Bitmap */
+	memcpy(vol->lcnbmp_ni->mrec,resize->ctx->mrec,vol->mft_record_size);
+	ntfs_inode_mark_dirty(vol->lcnbmp_ni);
+	NInoFileNameSetDirty(vol->lcnbmp_ni);
+	ntfs_inode_sync(vol->lcnbmp_ni);
+
+#if CLEAN_EXIT
+	close_inode_and_context(resize->ctx);
+#else
+	ntfs_attr_put_search_ctx(resize->ctx);
+#endif
+}
+
+/**
+ * setup_lcn_bitmap
+ *
+ * Allocate a block of memory with one bit for each cluster of the disk.
+ * All the bits are set to 0, except those representing the region beyond the
+ * end of the disk.
+ */
+static int setup_lcn_bitmap(struct bitmap *bm, s64 nr_clusters)
+{
+	/* Determine lcn bitmap byte size and allocate it. */
+	bm->size = rounded_up_division(nr_clusters, 8);
+
+	bm->bm = ntfs_calloc(bm->size);
+	if (!bm->bm)
+		return -1;
+
+	bitmap_file_data_fixup(nr_clusters, bm);
+	return 0;
+}
+
+/**
+ * update_bootsector
+ *
+ * FIXME: should be done using ntfs_* functions
+ */
+static void update_bootsector(ntfs_resize_t *r)
+{
+	NTFS_BOOT_SECTOR *bs;
+	ntfs_volume *vol = r->vol;
+	s64  bs_size = vol->sector_size;
+
+	printf("Updating Boot record ...\n");
+
+	bs = (NTFS_BOOT_SECTOR*)ntfs_malloc(vol->sector_size);
+	if (!bs)
+		perr_exit("ntfs_malloc");
+
+	if (vol->dev->d_ops->seek(vol->dev, 0, SEEK_SET) == (off_t)-1)
+		perr_exit("lseek");
+
+	if (vol->dev->d_ops->read(vol->dev, bs, bs_size) == -1)
+		perr_exit("read() error");
+
+	bs->number_of_sectors = cpu_to_sle64(r->new_volume_size *
+			bs->bpb.sectors_per_cluster);
+
+	if (r->mftmir_old) {
+		r->progress.flags |= NTFS_PROGBAR_SUPPRESS;
+		/* Be sure the MFTMirr holds the updated MFT runlist */
+		if (r->new_mft_start)
+			copy_clusters(r, r->mftmir_rl.lcn,
+				 r->new_mft_start->lcn, r->mftmir_rl.length);
+		else
+			copy_clusters(r, r->mftmir_rl.lcn, r->mftmir_old,
+				      r->mftmir_rl.length);
+		bs->mftmirr_lcn = cpu_to_sle64(r->mftmir_rl.lcn);
+		r->progress.flags &= ~NTFS_PROGBAR_SUPPRESS;
+	}
+		/* Set the start of the relocated MFT */
+	if (r->new_mft_start) {
+		bs->mft_lcn = cpu_to_sle64(r->new_mft_start->lcn);
+			/* no more need for the new MFT start */
+		free(r->new_mft_start);
+		r->new_mft_start = (runlist_element*)NULL;
+	}
+
+	if (vol->dev->d_ops->seek(vol->dev, 0, SEEK_SET) == (off_t)-1)
+		perr_exit("lseek");
+
+	if (!opt.ro_flag)
+		if (vol->dev->d_ops->write(vol->dev, bs, bs_size) == -1)
+			perr_exit("write() error");
+		/*
+		 * Set the backup boot sector, if the target size is
+		 * either not defined or is defined with no multiplier
+		 * suffix and is a multiple of the sector size.
+		 * With these conditions we can be confident enough that
+		 * the partition size is already defined or it will be
+		 * later defined with the same exact value.
+		 */
+	if (!opt.ro_flag && opt.reliable_size
+	    && !(opt.bytes % vol->sector_size)) {
+		if (vol->dev->d_ops->seek(vol->dev, opt.bytes
+				- vol->sector_size, SEEK_SET) == (off_t)-1)
+			perr_exit("lseek");
+		if (vol->dev->d_ops->write(vol->dev, bs, bs_size) == -1)
+			perr_exit("write() error");
+	}
+	free(bs);
+}
+
+/**
+ * vol_size
+ */
+static s64 vol_size(ntfs_volume *v, s64 nr_clusters)
+{
+	/* add one sector_size for the backup boot sector */
+	return nr_clusters * v->cluster_size + v->sector_size;
+}
+
+/**
+ * print_vol_size
+ *
+ * Print the volume size in bytes and decimal megabytes.
+ */
+static void print_vol_size(const char *str, s64 bytes)
+{
+	printf("%s: %lld bytes (%lld MB)\n", str, (long long)bytes,
+			(long long)rounded_up_division(bytes, NTFS_MBYTE));
+}
+
+/**
+ * print_disk_usage
+ *
+ * Display the amount of disk space in use.
+ */
+static void print_disk_usage(ntfs_volume *vol, s64 nr_used_clusters)
+{
+	s64 total, used;
+
+	total = vol->nr_clusters * vol->cluster_size;
+	used = nr_used_clusters * vol->cluster_size;
+
+	/* WARNING: don't modify the text, external tools grep for it */
+        if (!opt.infombonly) {
+		printf("Space in use       : %lld MB (%.1f%%)\n",
+	        	(long long)rounded_up_division(used, NTFS_MBYTE),
+	        	100.0 * ((float)used / total));
+	}
+}
+
+static void print_num_of_relocations(ntfs_resize_t *resize)
+{
+	s64 relocations = resize->relocations * resize->vol->cluster_size;
+
+	printf("Needed relocations : %lld (%lld MB)\n",
+			(long long)resize->relocations, (long long)
+			rounded_up_division(relocations, NTFS_MBYTE));
+}
+
+static ntfs_volume *check_volume(void)
+{
+	ntfs_volume *myvol = NULL;
+
+	/*
+	 * Pass NTFS_MNT_FORENSIC so that the mount process does not modify the
+	 * volume at all.  We will do the logfile emptying and dirty setting
+	 * later if needed.
+	 */
+	if (!(myvol = ntfs_mount(opt.volume, opt.ro_flag | NTFS_MNT_FORENSIC)))
+	{
+		int err = errno;
+
+		perr_printf("Opening '%s' as NTFS failed", opt.volume);
+		switch (err) {
+		case EINVAL :
+			printf(invalid_ntfs_msg, opt.volume);
+			break;
+		case EIO :
+			printf("%s", corrupt_volume_msg);
+			break;
+		case EPERM :
+			printf("%s", hibernated_volume_msg);
+			break;
+		case EOPNOTSUPP :
+			printf("%s", unclean_journal_msg);
+			break;
+		case EBUSY :
+			printf("%s", opened_volume_msg);
+			break;
+		default :
+			break;
+		}
+		exit(1);
+	}
+	return myvol;
+}
+
+
+/**
+ * mount_volume
+ *
+ * First perform some checks to determine if the volume is already mounted, or
+ * is dirty (Windows wasn't shutdown properly).  If everything is OK, then mount
+ * the volume (load the metadata into memory).
+ */
+static ntfs_volume *mount_volume(void)
+{
+	unsigned long mntflag;
+	ntfs_volume *vol = NULL;
+
+	if (ntfs_check_if_mounted(opt.volume, &mntflag)) {
+		perr_printf("Failed to check '%s' mount state", opt.volume);
+		printf("Probably /etc/mtab is missing. It's too risky to "
+		       "continue. You might try\nan another Linux distro.\n");
+		exit(1);
+	}
+	if (mntflag & NTFS_MF_MOUNTED) {
+		if (!(mntflag & NTFS_MF_READONLY))
+			err_exit("Device '%s' is mounted read-write. "
+				 "You must 'umount' it first.\n", opt.volume);
+		if (!opt.ro_flag)
+			err_exit("Device '%s' is mounted. "
+				 "You must 'umount' it first.\n", opt.volume);
+	}
+	vol = check_volume();
+
+	if (vol->flags & VOLUME_IS_DIRTY)
+		if (opt.force-- <= 0)
+			err_exit("Volume is scheduled for check.\nRun chkdsk /f"
+				 " and please try again, or see option -f.\n");
+
+	if (NTFS_MAX_CLUSTER_SIZE < vol->cluster_size)
+		err_exit("Cluster size %u is too large!\n",
+			(unsigned int)vol->cluster_size);
+
+	if (ntfs_volume_get_free_space(vol))
+		err_exit("Failed to update the free space\n");
+
+	if (!opt.infombonly) {
+		printf("Device name        : %s\n", opt.volume);
+		printf("NTFS volume version: %d.%d\n",
+				vol->major_ver, vol->minor_ver);
+	}
+	if (ntfs_version_is_supported(vol))
+		perr_exit("Unknown NTFS version");
+
+	if (!opt.infombonly) {
+		printf("Cluster size       : %u bytes\n",
+			(unsigned int)vol->cluster_size);
+		print_vol_size("Current volume size",
+			vol_size(vol, vol->nr_clusters));
+	}
+
+	return vol;
+}
+
+/**
+ * prepare_volume_fixup
+ *
+ * Set the volume's dirty flag and wipe the filesystem journal.  When Windows
+ * boots it will automatically run chkdsk to check for any problems.  If the
+ * read-only command line option was given, this function will do nothing.
+ */
+static void prepare_volume_fixup(ntfs_volume *vol)
+{
+	printf("Schedule chkdsk for NTFS consistency check at Windows boot "
+			"time ...\n");
+	vol->flags |= VOLUME_IS_DIRTY;
+	if (ntfs_volume_write_flags(vol, vol->flags))
+		perr_exit("Failed to set the volume dirty");
+
+	/* Porting note: This flag does not exist in libntfs-3g. The dirty flag
+	 * is never modified by libntfs-3g on unmount and we set it above. We
+	 * can safely comment out this statement. */
+	/* NVolSetWasDirty(vol); */
+
+	if (vol->dev->d_ops->sync(vol->dev) == -1)
+		perr_exit("Failed to sync device");
+	printf("Resetting $LogFile ... (this might take a while)\n");
+	if (ntfs_logfile_reset(vol))
+		perr_exit("Failed to reset $LogFile");
+	if (vol->dev->d_ops->sync(vol->dev) == -1)
+		perr_exit("Failed to sync device");
+}
+
+static void set_disk_usage_constraint(ntfs_resize_t *resize)
+{
+	/* last lcn for a filled up volume (no empty space) */
+	s64 last = resize->inuse - 1;
+
+	if (resize->last_unsupp < last)
+		resize->last_unsupp = last;
+}
+
+static void check_resize_constraints(ntfs_resize_t *resize)
+{
+	s64 new_size = resize->new_volume_size;
+
+	/* FIXME: resize.shrink true also if only -i is used */
+	if (!resize->shrink)
+		return;
+
+	if (resize->inuse == resize->vol->nr_clusters)
+		err_exit("Volume is full. To shrink it, "
+			 "delete unused files.\n");
+
+	if (opt.info || opt.infombonly)
+		return;
+
+	/* FIXME: reserve some extra space so Windows can boot ... */
+	if (new_size < resize->inuse)
+		err_exit("New size can't be less than the space already"
+			 " occupied by data.\nYou either need to delete unused"
+			 " files or see the -i option.\n");
+
+	if (new_size <= resize->last_unsupp)
+		err_exit("The fragmentation type, you have, isn't "
+			 "supported yet. Rerun ntfsresize\nwith "
+			 "the -i option to estimate the smallest "
+			 "shrunken volume size supported.\n");
+
+	print_num_of_relocations(resize);
+}
+
+static void check_cluster_allocation(ntfs_volume *vol, ntfsck_t *fsck)
+{
+	memset(fsck, 0, sizeof(ntfsck_t));
+
+	if (opt.show_progress)
+		fsck->flags |= NTFSCK_PROGBAR;
+
+	if (setup_lcn_bitmap(&fsck->lcn_bitmap, vol->nr_clusters) != 0)
+		perr_exit("Failed to setup allocation bitmap");
+	if (build_allocation_bitmap(vol, fsck) != 0)
+		exit(1);
+	if (fsck->outsider || fsck->multi_ref) {
+		err_printf("Filesystem check failed!\n");
+		if (fsck->outsider)
+			err_printf("%d clusters are referenced outside "
+				   "of the volume.\n", fsck->outsider);
+		if (fsck->multi_ref)
+			err_printf("%d clusters are referenced multiple"
+				   " times.\n", fsck->multi_ref);
+		printf("%s", corrupt_volume_msg);
+		exit(1);
+	}
+
+	compare_bitmaps(vol, &fsck->lcn_bitmap);
+}
+
+/*
+ *		Following are functions to expand an NTFS file system
+ *	to the beginning of a partition. The old metadata can be
+ *	located according to the backup bootsector, provided it can
+ *	still be found at the end of the partition.
+ *
+ *	The data itself is kept in place, and this is only possible
+ *	if the expanded size is a multiple of cluster size, and big
+ *	enough to hold the new $Boot, $Bitmap and $MFT
+ *
+ *	The volume cannot be mounted because the layout of data does
+ *	not match the volume parameters. The alignments of MFT entries
+ *	and index blocks may be different in the new volume and the old
+ *	one. The "ntfs_volume" structure is only partially usable,
+ *	"ntfs_inode" and "search_context" cannot be used until the
+ *	metadata has been moved and the volume is opened.
+ *
+ *	Currently, no part of this new code is called from old code,
+ *	and the only change in old code is the processing of options.
+ *	Deduplication of code should be done later when the code is
+ *	proved safe.
+ *
+ */
+
+typedef struct EXPAND {
+	ntfs_volume *vol;
+	u64 original_sectors;
+	u64 new_sectors;
+	u64 bitmap_allocated;
+	u64 bitmap_size;
+	u64 boot_size;
+	u64 mft_size;
+	LCN mft_lcn;
+	s64 byte_increment;
+	s64 sector_increment;
+	s64 cluster_increment;
+	u8 *bitmap;
+	u8 *mft_bitmap;
+	char *bootsector;
+	MFT_RECORD *mrec;
+	struct progress_bar *progress;
+	struct DELAYED *delayed_runlists; /* runlists to process later */
+} expand_t;
+
+/*
+ *		Locate an attribute in an MFT record
+ *
+ *	Returns NULL if not found (with no error message)
+ */
+
+static ATTR_RECORD *find_attr(MFT_RECORD *mrec, ATTR_TYPES type,
+					ntfschar *name, int namelen)
+{
+	ATTR_RECORD *a;
+	u32 offset;
+	ntfschar *attrname;
+
+			/* fetch the requested attribute */
+	offset = le16_to_cpu(mrec->attrs_offset);
+	a = (ATTR_RECORD*)((char*)mrec + offset);
+	attrname = (ntfschar*)((char*)a + le16_to_cpu(a->name_offset));
+	while ((a->type != AT_END)
+	    && ((a->type != type)
+		|| (a->name_length != namelen)
+		|| (namelen && memcmp(attrname,name,2*namelen)))
+	    && (offset < le32_to_cpu(mrec->bytes_in_use))) {
+		offset += le32_to_cpu(a->length);
+		a = (ATTR_RECORD*)((char*)mrec + offset);
+		if (namelen)
+			attrname = (ntfschar*)((char*)a
+				+ le16_to_cpu(a->name_offset));
+	}
+	if ((a->type != type)
+	    || (a->name_length != namelen)
+	    || (namelen && memcmp(attrname,name,2*namelen)))
+		a = (ATTR_RECORD*)NULL;
+	return (a);
+}
+
+/*
+ *		Read an MFT record and find an unnamed attribute
+ *
+ *	Returns NULL if fails to read or attribute is not found
+ */
+
+static ATTR_RECORD *get_unnamed_attr(expand_t *expand, ATTR_TYPES type,
+							s64 inum)
+{
+	ntfs_volume *vol;
+	ATTR_RECORD *a;
+	MFT_RECORD *mrec;
+	s64 pos;
+	BOOL found;
+	int got;
+
+	found = FALSE;
+	a = (ATTR_RECORD*)NULL;
+	mrec = expand->mrec;
+	vol = expand->vol;
+	pos = (vol->mft_lcn << vol->cluster_size_bits)
+		+ (inum << vol->mft_record_size_bits)
+		+ expand->byte_increment;
+	got = ntfs_mst_pread(vol->dev, pos, 1, vol->mft_record_size, mrec);
+	if ((got == 1) && (mrec->flags & MFT_RECORD_IN_USE)) {
+		a = find_attr(expand->mrec, type, NULL, 0);
+		found = a && (a->type == type) && !a->name_length;
+	}
+		/* not finding the attribute list is not an error */
+	if (!found && (type != AT_ATTRIBUTE_LIST)) {
+		err_printf("Could not find attribute 0x%lx in inode %lld\n",
+				(long)le32_to_cpu(type), (long long)inum);
+		a = (ATTR_RECORD*)NULL;
+	}
+	return (a);
+}
+
+/*
+ *		Read an MFT record and find an unnamed attribute
+ *
+ *	Returns NULL if fails
+ */
+
+static ATTR_RECORD *read_and_get_attr(expand_t *expand, ATTR_TYPES type,
+				s64 inum, ntfschar *name, int namelen)
+{
+	ntfs_volume *vol;
+	ATTR_RECORD *a;
+	MFT_RECORD *mrec;
+	s64 pos;
+	int got;
+
+	a = (ATTR_RECORD*)NULL;
+	mrec = expand->mrec;
+	vol = expand->vol;
+	pos = (vol->mft_lcn << vol->cluster_size_bits)
+		+ (inum << vol->mft_record_size_bits)
+		+ expand->byte_increment;
+	got = ntfs_mst_pread(vol->dev, pos, 1, vol->mft_record_size, mrec);
+	if ((got == 1) && (mrec->flags & MFT_RECORD_IN_USE)) {
+		a = find_attr(expand->mrec, type, name, namelen);
+	}
+	if (!a) {
+		err_printf("Could not find attribute 0x%lx in inode %lld\n",
+				(long)le32_to_cpu(type), (long long)inum);
+	}
+	return (a);
+}
+
+/*
+ *		Get the size allocated to the unnamed data of some inode
+ *
+ *	Returns zero if fails.
+ */
+
+static s64 get_data_size(expand_t *expand, s64 inum)
+{
+	ATTR_RECORD *a;
+	s64 size;
+
+	size = 0;
+			/* get the size of unnamed $DATA */
+	a = get_unnamed_attr(expand, AT_DATA, inum);
+	if (a && a->non_resident)
+		size = le64_to_cpu(a->allocated_size);
+	if (!size) {
+		err_printf("Bad record %lld, could not get its size\n",
+					(long long)inum);
+	}
+	return (size);
+}
+
+/*
+ *		Get the MFT bitmap
+ *
+ *	Returns NULL if fails.
+ */
+
+static u8 *get_mft_bitmap(expand_t *expand)
+{
+	ATTR_RECORD *a;
+	ntfs_volume *vol;
+	runlist_element *rl;
+	runlist_element *prl;
+	u32 bitmap_size;
+	BOOL ok;
+
+	expand->mft_bitmap = (u8*)NULL;
+	vol = expand->vol;
+			/* get the runlist of unnamed bitmap */
+	a = get_unnamed_attr(expand, AT_BITMAP, FILE_MFT);
+	ok = TRUE;
+	bitmap_size = le64_to_cpu(a->allocated_size);
+	if (a
+	    && a->non_resident
+	    && ((bitmap_size << (vol->mft_record_size_bits + 3))
+			>= expand->mft_size)) {
+// rl in extent not implemented
+		rl = ntfs_mapping_pairs_decompress(expand->vol, a,
+						(runlist_element*)NULL);
+		expand->mft_bitmap = (u8*)ntfs_calloc(bitmap_size);
+		if (rl && expand->mft_bitmap) {
+			for (prl=rl; prl->length && ok; prl++) {
+				lseek_to_cluster(vol,
+					prl->lcn + expand->cluster_increment);
+				ok = !read_all(vol->dev, expand->mft_bitmap
+					+ (prl->vcn << vol->cluster_size_bits),
+					prl->length << vol->cluster_size_bits);
+			}
+			if (!ok) {
+				err_printf("Could not read the MFT bitmap\n");
+				free(expand->mft_bitmap);
+				expand->mft_bitmap = (u8*)NULL;
+			}
+			free(rl);
+		} else {
+			err_printf("Could not get the MFT bitmap\n");
+		}
+	} else
+		err_printf("Invalid MFT bitmap\n");
+	return (expand->mft_bitmap);
+}
+
+/*
+ *		Check for bad sectors
+ *
+ *	Deduplication to be done when proved safe
+ */
+
+static int check_expand_bad_sectors(expand_t *expand, ATTR_RECORD *a)
+{
+	runlist *rl;
+	int res;
+	s64 i, badclusters = 0;
+
+	res = 0;
+	ntfs_log_verbose("Checking for bad sectors ...\n");
+
+	if (find_attr(expand->mrec, AT_ATTRIBUTE_LIST, NULL, 0)) {
+		err_printf("Hopelessly many bad sectors have been detected!\n");
+		err_printf("%s", many_bad_sectors_msg);
+		res = -1;
+	} else {
+
+	/*
+	 * FIXME: The below would be partial for non-base records in the
+	 * not yet supported multi-record case. Alternatively use audited
+	 * ntfs_attr_truncate after an umount & mount.
+	 */
+		rl = ntfs_mapping_pairs_decompress(expand->vol, a, NULL);
+		if (!rl) {
+			perr_printf("Decompressing $BadClust:"
+					"$Bad mapping pairs failed");
+			res = -1;
+		} else {
+			for (i = 0; rl[i].length; i++) {
+		/* CHECKME: LCN_RL_NOT_MAPPED check isn't needed */
+				if (rl[i].lcn == LCN_HOLE
+				    || rl[i].lcn == LCN_RL_NOT_MAPPED)
+					continue;
+
+				badclusters += rl[i].length;
+				ntfs_log_verbose("Bad cluster: %#8llx - %#llx"
+						"    (%lld)\n",
+						(long long)rl[i].lcn,
+						(long long)rl[i].lcn
+							+ rl[i].length - 1,
+						(long long)rl[i].length);
+			}
+
+			if (badclusters) {
+				err_printf("%sThis software has detected that"
+					" the disk has at least"
+					" %lld bad sector%s.\n",
+					!opt.badsectors ? NERR_PREFIX
+							: "WARNING: ",
+					(long long)badclusters,
+					badclusters - 1 ? "s" : "");
+				if (!opt.badsectors) {
+					err_printf("%s", bad_sectors_warning_msg);
+					res = -1;
+				} else
+					err_printf("WARNING: Bad sectors can cause"
+						" reliability problems"
+						" and massive data loss!!!\n");
+			}
+		free(rl);
+		}
+	}
+	return (res);
+}
+
+/*
+ *		Check miscellaneous expansion constraints
+ */
+
+static int check_expand_constraints(expand_t *expand)
+{
+	static ntfschar bad[] = {
+			const_cpu_to_le16('$'), const_cpu_to_le16('B'),
+			const_cpu_to_le16('a'), const_cpu_to_le16('d')
+	} ;
+	ATTR_RECORD *a;
+	runlist_element *rl;
+	VOLUME_INFORMATION *volinfo;
+	VOLUME_FLAGS flags;
+	int res;
+
+	if (opt.verbose)
+		ntfs_log_verbose("Checking for expansion constraints...\n");
+	res = 0;
+		/* extents for $MFT are not supported */
+	if (get_unnamed_attr(expand, AT_ATTRIBUTE_LIST, FILE_MFT)) {
+		err_printf("The $MFT is too much fragmented\n");
+		res = -1;
+	}
+		/* fragmented $MFTMirr is not supported */
+	a = get_unnamed_attr(expand, AT_DATA, FILE_MFTMirr);
+	if (a) {
+		rl = ntfs_mapping_pairs_decompress(expand->vol, a, NULL);
+		if (!rl || !rl[0].length || rl[1].length) {
+			err_printf("$MFTMirr is bad or fragmented\n");
+			res = -1;
+		}
+		free(rl);
+	}
+		/* fragmented $Boot is not supported */
+	a = get_unnamed_attr(expand, AT_DATA, FILE_Boot);
+	if (a) {
+		rl = ntfs_mapping_pairs_decompress(expand->vol, a, NULL);
+		if (!rl || !rl[0].length || rl[1].length) {
+			err_printf("$Boot is bad or fragmented\n");
+			res = -1;
+		}
+		free(rl);
+	}
+		/* Volume should not be marked dirty */
+	a = get_unnamed_attr(expand, AT_VOLUME_INFORMATION, FILE_Volume);
+	if (a) {
+		volinfo = (VOLUME_INFORMATION*)
+				(le16_to_cpu(a->value_offset) + (char*)a);
+		flags = volinfo->flags;
+		if ((flags & VOLUME_IS_DIRTY) && (opt.force-- <= 0)) {
+			err_printf("Volume is scheduled for check.\nRun chkdsk /f"
+			 " and please try again, or see option -f.\n");
+			res = -1;
+		}
+	} else {
+		err_printf("Could not get Volume flags\n");
+		res = -1;
+	}
+
+		/* There should not be too many bad clusters */
+	a = read_and_get_attr(expand, AT_DATA, FILE_BadClus, bad, 4);
+	if (!a || !a->non_resident) {
+		err_printf("Resident attribute in $BadClust! Please report to "
+			 	"%s\n", NTFS_DEV_LIST);
+		res = -1;
+	} else
+		if (check_expand_bad_sectors(expand,a))
+			res = -1;
+	return (res);
+}
+
+/*
+ *		Compute the new sizes and check whether the NTFS file
+ *	system can be expanded
+ *
+ *	The partition has to have been expanded,
+ *	the extra space must be able to hold the $MFT, $Boot, and $Bitmap
+ *	the extra space must be a multiple of cluster size
+ *
+ *	Returns TRUE if the partition can be expanded,
+ *		FALSE if it canno be expanded or option --info was set
+ */
+
+static BOOL can_expand(expand_t *expand, ntfs_volume *vol)
+{
+	s64 old_sector_count;
+	s64 sectors_needed;
+	s64 clusters;
+	s64 minimum_size;
+	s64 got;
+	s64 advice;
+	s64 bitmap_bits;
+	BOOL ok;
+
+	ok = TRUE;
+	old_sector_count = vol->nr_clusters
+			<< (vol->cluster_size_bits - vol->sector_size_bits);
+		/* do not include the space lost near the end */
+	expand->cluster_increment = (expand->new_sectors
+			 >> (vol->cluster_size_bits - vol->sector_size_bits))
+				- vol->nr_clusters;
+	expand->byte_increment = expand->cluster_increment
+					<< vol->cluster_size_bits;
+	expand->sector_increment = expand->byte_increment
+					>> vol->sector_size_bits;
+	printf("Sectors allocated to volume :  old %lld current %lld difference %lld\n",
+			(long long)old_sector_count,
+			(long long)(old_sector_count + expand->sector_increment),
+			(long long)expand->sector_increment);
+	printf("Clusters allocated to volume : old %lld current %lld difference %lld\n",
+			(long long)vol->nr_clusters,
+			(long long)(vol->nr_clusters
+					+ expand->cluster_increment),
+			(long long)expand->cluster_increment);
+		/* the new size must be bigger */
+	if ((expand->sector_increment < 0)
+	    || (!expand->sector_increment && !opt.info)) {
+		err_printf("Cannot expand volume : the partition has not been expanded\n");
+		ok = FALSE;
+	}
+			/* the old bootsector must match the backup */
+	got = ntfs_pread(expand->vol->dev, expand->byte_increment,
+				vol->sector_size, expand->mrec);
+	if ((got != vol->sector_size)
+	    || memcmp(expand->bootsector,expand->mrec,vol->sector_size)) {
+		err_printf("The backup bootsector does not match the old bootsector\n");
+		ok = FALSE;
+	}
+	if (ok) {
+			/* read the first MFT record, to get the MFT size */
+		expand->mft_size = get_data_size(expand, FILE_MFT);
+			/* read the 6th MFT record, to get the $Boot size */
+		expand->boot_size = get_data_size(expand, FILE_Boot);
+		if (!expand->mft_size || !expand->boot_size) {
+			ok = FALSE;
+		} else {
+			/*
+			 * The bitmap is one bit per full cluster,
+			 * accounting for the backup bootsector.
+			 * When evaluating the minimal size, the bitmap
+			 * size must be adapted to the minimal size :
+			 *  bits = clusters + ceil(clusters/clustersize)
+			 */
+			if (opt.info) {
+				clusters = (((expand->original_sectors + 1)
+						<< vol->sector_size_bits)
+						+ expand->mft_size
+						+ expand->boot_size)
+						    >> vol->cluster_size_bits;
+				bitmap_bits = ((clusters + 1)
+						    << vol->cluster_size_bits)
+						/ (vol->cluster_size + 1);
+			} else {
+				bitmap_bits = (expand->new_sectors + 1)
+			    		>> (vol->cluster_size_bits
+						- vol->sector_size_bits);
+			}
+			/* byte size must be a multiple of 8 */
+			expand->bitmap_size = ((bitmap_bits + 63) >> 3) & -8;
+			expand->bitmap_allocated = ((expand->bitmap_size - 1)
+				| (vol->cluster_size - 1)) + 1;
+			expand->mft_lcn = (expand->boot_size
+					+ expand->bitmap_allocated)
+						>> vol->cluster_size_bits;
+			/*
+			 * Check whether $Boot, $Bitmap and $MFT can fit
+			 * into the expanded space.
+			 */
+			sectors_needed = (expand->boot_size + expand->mft_size
+					 + expand->bitmap_allocated)
+						>> vol->sector_size_bits;
+			if (!opt.info
+			    && (sectors_needed >= expand->sector_increment)) {
+				err_printf("The expanded space cannot hold the new metadata\n");
+				err_printf("   expanded space %lld sectors\n",
+					(long long)expand->sector_increment);
+				err_printf("   needed space %lld sectors\n",
+					(long long)sectors_needed);
+				ok = FALSE;
+			}
+		}
+	}
+	if (ok) {
+		advice = expand->byte_increment;
+		/* the increment must be an integral number of clusters */
+		if (expand->byte_increment & (vol->cluster_size - 1)) {
+			err_printf("Cannot expand volume without copying the data :\n");
+			err_printf("There are %d sectors in a cluster,\n",
+				(int)(vol->cluster_size/vol->sector_size));
+			err_printf("  and the sector difference is not a multiple of %d\n",
+				(int)(vol->cluster_size/vol->sector_size));
+			advice = expand->byte_increment & ~vol->cluster_size;
+			ok = FALSE;
+		}
+		if (!ok)
+			err_printf("You should increase the beginning of partition by %d sectors\n",
+				(int)((expand->byte_increment - advice)
+					>> vol->sector_size_bits));
+	}
+	if (ok)
+		ok = !check_expand_constraints(expand);
+	if (ok && opt.info) {
+		minimum_size = (expand->original_sectors
+						<< vol->sector_size_bits)
+					+ expand->boot_size
+					+ expand->mft_size
+					+ expand->bitmap_allocated;
+
+		printf("You must expand the partition to at least %lld bytes,\n",
+			(long long)(minimum_size + vol->sector_size));
+		printf("and you may add a multiple of %ld bytes to this size.\n",
+			(long)vol->cluster_size);
+		printf("The minimum NTFS volume size is %lld bytes\n",
+			(long long)minimum_size);
+		ok = FALSE;
+	}
+	return (ok);
+}
+
+static int set_bitmap(expand_t *expand, runlist_element *rl)
+{
+	int res;
+	s64 lcn;
+	s64 lcn_end;
+	BOOL reallocated;
+
+	res = -1;
+	reallocated = FALSE;
+	if ((rl->lcn >= 0)
+	    && (rl->length > 0)
+	    && ((rl->lcn + rl->length)
+		    <= (expand->vol->nr_clusters + expand->cluster_increment))) {
+		lcn = rl->lcn;
+		lcn_end = lcn + rl->length;
+		while ((lcn & 7) && (lcn < lcn_end)) {
+			if (expand->bitmap[lcn >> 3] & 1 << (lcn & 7))
+				reallocated = TRUE;
+			expand->bitmap[lcn >> 3] |= 1 << (lcn & 7);
+			lcn++;
+		}
+		while ((lcn_end - lcn) >= 8) {
+			if (expand->bitmap[lcn >> 3])
+				reallocated = TRUE;
+			expand->bitmap[lcn >> 3] = 255;
+			lcn += 8;
+		}
+		while (lcn < lcn_end) {
+			if (expand->bitmap[lcn >> 3] & 1 << (lcn & 7))
+				reallocated = TRUE;
+			expand->bitmap[lcn >> 3] |= 1 << (lcn & 7);
+			lcn++;
+		}
+		if (reallocated)
+			err_printf("Reallocated cluster found in run"
+				" lcn 0x%llx length %lld\n",
+				(long long)rl->lcn,(long long)rl->length);
+		else
+			res = 0;
+	} else {
+		err_printf("Bad run : lcn 0x%llx length %lld\n",
+			(long long)rl->lcn,(long long)rl->length);
+	}
+	return (res);
+}
+
+/*
+ *		Write the backup bootsector
+ *
+ *	When this has been done, the resizing cannot be done again
+ */
+
+static int write_bootsector(expand_t *expand)
+{
+	ntfs_volume *vol;
+	s64 bw;
+	int res;
+
+	res = -1;
+	vol = expand->vol;
+	if (opt.verbose)
+		ntfs_log_verbose("Rewriting the backup bootsector\n");
+	if (opt.ro_flag)
+		bw = vol->sector_size;
+	else 
+		bw = ntfs_pwrite(vol->dev,
+				expand->new_sectors*vol->sector_size,
+				vol->sector_size, expand->bootsector);
+	if (bw == vol->sector_size)
+		res = 0;
+	else {
+		if (bw != -1)
+			errno = EINVAL;
+		if (!bw)
+			err_printf("Failed to rewrite the bootsector (size=0)\n");
+		else
+			err_printf("Error rewriting the bootsector");
+	}
+	return (res);
+}
+
+/*
+ *		Write the new main bitmap
+ */
+
+static int write_bitmap(expand_t *expand)
+{
+	ntfs_volume *vol;
+	s64 bw;
+	u64 cluster;
+	int res;
+
+	res = -1;
+	vol = expand->vol;
+	cluster = vol->nr_clusters + expand->cluster_increment;
+	while (cluster < (expand->bitmap_size << 3)) {
+		expand->bitmap[cluster >> 3] |= 1 << (cluster & 7);
+		cluster++;
+	}
+	if (opt.verbose)
+		ntfs_log_verbose("Writing the new bitmap...\n");
+		/* write the full allocation (to avoid having to read) */
+	if (opt.ro_flag)
+		bw = expand->bitmap_allocated;
+	else
+		bw = ntfs_pwrite(vol->dev, expand->boot_size,
+					expand->bitmap_allocated, expand->bitmap);
+	if (bw == (s64)expand->bitmap_allocated)
+		res = 0;
+	else {
+		if (bw != -1)
+			errno = EINVAL;
+		if (!bw)
+			err_printf("Failed to write the bitmap (size=0)\n");
+		else
+			err_printf("Error rewriting the bitmap");
+	}
+	return (res);
+}
+
+/*
+ *		Copy the $MFT to $MFTMirr
+ *
+ *	The $MFTMirr is not relocated as it should be kept away from $MFT.
+ *	Apart from the backup bootsector, this is the only part which is
+ *	overwritten. This has no effect on being able to redo the resizing
+ *	if something goes wrong, as the $MFTMirr is never read. However
+ *	this is done near the end of the resizing.
+ */
+
+static int copy_mftmirr(expand_t *expand)
+{
+	ntfs_volume *vol;
+	s64 pos;
+	s64 inum;
+	int res;
+	u16 usa_ofs;
+	le16 *pusn;
+	u16 usn;
+
+	if (opt.verbose)
+		ntfs_log_verbose("Copying $MFT to $MFTMirr...\n");
+	vol = expand->vol;
+	res = 0;
+	for (inum=FILE_MFT; !res && (inum<=FILE_Volume); inum++) {
+			/* read the new $MFT */
+		pos = (expand->mft_lcn << vol->cluster_size_bits)
+			+ (inum << vol->mft_record_size_bits);
+		if (ntfs_mst_pread(vol->dev, pos, 1, vol->mft_record_size,
+				expand->mrec) == 1) {
+				/* overwrite the old $MFTMirr */
+			pos = (vol->mftmirr_lcn << vol->cluster_size_bits)
+				+ (inum << vol->mft_record_size_bits)
+				+ expand->byte_increment;
+			usa_ofs = le16_to_cpu(expand->mrec->usa_ofs);
+			pusn = (le16*)((u8*)expand->mrec + usa_ofs);
+			usn = le16_to_cpu(*pusn) - 1;
+			if (!usn || (usn == 0xffff))
+				usn = -2;
+			*pusn = cpu_to_le16(usn);
+			if (!opt.ro_flag
+			    && (ntfs_mst_pwrite(vol->dev, pos, 1,
+				    vol->mft_record_size, expand->mrec) != 1)) {
+				err_printf("Failed to overwrite the old $MFTMirr\n");
+				res = -1;
+			}
+		} else {
+			err_printf("Failed to write the new $MFT\n");
+			res = -1;
+		}
+	}
+	return (res);
+}
+
+/*
+ *		Copy the $Boot, including the bootsector
+ *
+ *	When the bootsector has been copied, repair tools are able to
+ *	fix things, but this is dangerous if the other metadata do
+ *	not point to actual user data. So this must be done near the end
+ *	of resizing.
+ */
+
+static int copy_boot(expand_t *expand)
+{
+	NTFS_BOOT_SECTOR *bs;
+	char *buf;
+	ntfs_volume *vol;
+	s64 mftmirr_lcn;
+	s64 written;
+	u32 boot_cnt;
+	u32 hidden_sectors;
+	le32 hidden_sectors_le;
+	int res;
+
+	if (opt.verbose)
+		ntfs_log_verbose("Copying $Boot...\n");
+	vol = expand->vol;
+	res = 0;
+	buf = (char*)ntfs_malloc(vol->cluster_size);
+	if (buf) {
+			/* set the new volume parameters in the bootsector */
+		bs = (NTFS_BOOT_SECTOR*)expand->bootsector;
+		bs->number_of_sectors = cpu_to_le64(expand->new_sectors);
+		bs->mft_lcn = cpu_to_le64(expand->mft_lcn);
+		mftmirr_lcn = vol->mftmirr_lcn + expand->cluster_increment;
+		bs->mftmirr_lcn = cpu_to_le64(mftmirr_lcn);
+			/* the hidden sectors are needed to boot into windows */
+		memcpy(&hidden_sectors_le,&bs->bpb.hidden_sectors,4);
+				/* alignment messed up on the Sparc */
+		if (hidden_sectors_le) {
+			hidden_sectors = le32_to_cpu(hidden_sectors_le);
+			if (hidden_sectors >= expand->sector_increment)
+				hidden_sectors -= expand->sector_increment;
+			else
+				hidden_sectors = 0;
+			hidden_sectors_le = cpu_to_le32(hidden_sectors);
+			memcpy(&bs->bpb.hidden_sectors,&hidden_sectors_le,4);
+		}
+		written = 0;
+		boot_cnt = expand->boot_size >> vol->cluster_size_bits;
+		while (!res && (written < boot_cnt)) {
+			lseek_to_cluster(vol, expand->cluster_increment + written);
+			if (!read_all(vol->dev, buf, vol->cluster_size)) {
+				if (!written)
+					memcpy(buf, expand->bootsector, vol->sector_size);
+				lseek_to_cluster(vol, written);
+				if (!opt.ro_flag
+				    && write_all(vol->dev, buf, vol->cluster_size)) {
+					err_printf("Failed to write the new $Boot\n");
+					res = -1;
+				} else
+					written++;
+			} else {
+				err_printf("Failed to read the old $Boot\n");
+				res = -1;
+			}
+		}
+		free(buf);
+	} else {
+		err_printf("Failed to allocate buffer\n");
+		res = -1;
+	}
+	return (res);
+}
+
+/*
+ *		Process delayed runlist updates
+ *
+ *	This is derived from delayed_updates() and they should
+ *	both be merged when the new code is considered safe.
+ */
+
+static void delayed_expand(ntfs_volume *vol, struct DELAYED *delayed,
+			struct progress_bar *progress)
+{
+	unsigned long count;
+	struct DELAYED *current;
+	int step = 100;
+
+	if (delayed) {
+		if (opt.verbose)
+			ntfs_log_verbose("Delayed updating of overflowing runlists...\n");
+		count = 0;
+			/* count by steps because of inappropriate resolution */
+		for (current=delayed; current; current=current->next)
+			count += step;
+		progress_init(progress, 0, count,
+					(opt.show_progress ? NTFS_PROGBAR : 0));
+		current = delayed;
+		count = 0;
+		while (current) {
+			delayed = current;
+			if (!opt.ro_flag)
+				expand_attribute_runlist(vol, delayed);
+			count += step;
+			progress_update(progress, count);
+			current = current->next;
+			if (delayed->attr_name)
+				free(delayed->attr_name);
+			free(delayed->head_rl);
+			free(delayed);
+		}
+	}
+}
+
+/*
+ *		Expand the sizes in indexes for inodes which were expanded
+ *
+ *	Only the new $Bitmap sizes are identified as needed to be
+ *	adjusted in index. The $BadClus is only expanded in an
+ *	alternate data stream, whose sizes are not present in the index.
+ *
+ *	This is modifying the initial data, and can only be done when
+ *	the volume has been reopened after expanding.
+ */
+
+static int expand_index_sizes(expand_t *expand)
+{
+	ntfs_inode *ni;
+	int res;
+
+	res = -1;
+	ni = ntfs_inode_open(expand->vol, FILE_Bitmap);
+	if (ni) {
+		NInoSetDirty(ni);
+		NInoFileNameSetDirty(ni);
+		ntfs_inode_close(ni);
+		res = 0;
+	}
+	return (res);
+}
+
+/*
+ *		Update a runlist into an attribute
+ *
+ *	This is derived from replace_attribute_runlist() and they should
+ *	both be merged when the new code is considered safe.
+ */
+
+static int update_runlist(expand_t *expand, s64 inum,
+				ATTR_RECORD *a, runlist_element *rl)
+{
+	ntfs_resize_t resize;
+	ntfs_attr_search_ctx ctx;
+	ntfs_volume *vol;
+	MFT_RECORD *mrec;
+	runlist *head_rl;
+	int mp_size;
+	int l;
+	int must_delay;
+	void *mp;
+
+	vol = expand->vol;
+	mrec = expand->mrec;
+	head_rl = rl;
+	rl_fixup(&rl);
+	if ((mp_size = ntfs_get_size_for_mapping_pairs(vol, rl,
+				0, INT_MAX)) == -1)
+		perr_exit("ntfs_get_size_for_mapping_pairs");
+
+	if (a->name_length) {
+		u16 name_offs = le16_to_cpu(a->name_offset);
+		u16 mp_offs = le16_to_cpu(a->mapping_pairs_offset);
+
+		if (name_offs >= mp_offs)
+			err_exit("Attribute name is after mapping pairs! "
+				 "Please report!\n");
+	}
+
+	/* CHECKME: don't trust mapping_pairs is always the last item in the
+	   attribute, instead check for the real size/space */
+	l = (int)le32_to_cpu(a->length) - le16_to_cpu(a->mapping_pairs_offset);
+	must_delay = 0;
+	if (mp_size > l) {
+		s32 remains_size;
+		char *next_attr;
+
+		ntfs_log_verbose("Enlarging attribute header ...\n");
+
+		mp_size = (mp_size + 7) & ~7;
+
+		ntfs_log_verbose("Old mp size      : %d\n", l);
+		ntfs_log_verbose("New mp size      : %d\n", mp_size);
+		ntfs_log_verbose("Bytes in use     : %u\n", (unsigned int)
+				 le32_to_cpu(mrec->bytes_in_use));
+
+		next_attr = (char *)a + le32_to_cpu(a->length);
+		l = mp_size - l;
+
+		ntfs_log_verbose("Bytes in use new : %u\n", l + (unsigned int)
+				 le32_to_cpu(mrec->bytes_in_use));
+		ntfs_log_verbose("Bytes allocated  : %u\n", (unsigned int)
+				 le32_to_cpu(mrec->bytes_allocated));
+
+		remains_size = le32_to_cpu(mrec->bytes_in_use);
+		remains_size -= (next_attr - (char *)mrec);
+
+		ntfs_log_verbose("increase         : %d\n", l);
+		ntfs_log_verbose("shift            : %lld\n",
+				 (long long)remains_size);
+		if (le32_to_cpu(mrec->bytes_in_use) + l >
+				le32_to_cpu(mrec->bytes_allocated)) {
+			ntfs_log_verbose("Queuing expansion for later processing\n");
+				/* hack for reusing unmodified old code ! */
+			resize.ctx = &ctx;
+			ctx.attr = a;
+			ctx.mrec = mrec;
+			resize.mref = inum;
+			resize.delayed_runlists = expand->delayed_runlists;
+			must_delay = 1;
+			replace_later(&resize,rl,head_rl);
+			expand->delayed_runlists = resize.delayed_runlists;
+		} else {
+			memmove(next_attr + l, next_attr, remains_size);
+			mrec->bytes_in_use = cpu_to_le32(l +
+					le32_to_cpu(mrec->bytes_in_use));
+			a->length = cpu_to_le32(le32_to_cpu(a->length) + l);
+		}
+	}
+
+	if (!must_delay) {
+		mp = ntfs_calloc(mp_size);
+		if (!mp)
+			perr_exit("ntfsc_calloc couldn't get memory");
+
+		if (ntfs_mapping_pairs_build(vol, (u8*)mp, mp_size, rl, 0, NULL))
+			perr_exit("ntfs_mapping_pairs_build");
+
+		memmove((u8*)a + le16_to_cpu(a->mapping_pairs_offset), mp, mp_size);
+
+		free(mp);
+	}
+	return (must_delay);
+}
+
+/*
+ *		Create a minimal valid MFT record
+ */
+
+static int minimal_record(expand_t *expand, MFT_RECORD *mrec)
+{
+	int usa_count;
+	u32 bytes_in_use;
+
+	memset(mrec,0,expand->vol->mft_record_size);
+	mrec->magic = magic_FILE;
+	mrec->usa_ofs = const_cpu_to_le16(sizeof(MFT_RECORD));
+	usa_count = expand->vol->mft_record_size / NTFS_BLOCK_SIZE + 1;
+	mrec->usa_count = cpu_to_le16(usa_count);
+	bytes_in_use = (sizeof(MFT_RECORD) + 2*usa_count + 7) & -8;
+	memset(((char*)mrec) + bytes_in_use, 255, 4);  /* AT_END */
+	bytes_in_use += 8;
+	mrec->bytes_in_use = cpu_to_le32(bytes_in_use);
+	mrec->bytes_allocated = cpu_to_le32(expand->vol->mft_record_size);
+	return (0);
+}
+
+/*
+ *		Rebase all runlists of an MFT record
+ *
+ *	Iterate through all its attributes and offset the non resident ones
+ */
+
+static int rebase_runlists(expand_t *expand, s64 inum)
+{
+	MFT_RECORD *mrec;
+	ATTR_RECORD *a;
+	runlist_element *rl;
+	runlist_element *prl;
+	u32 offset;
+	int res;
+
+	res = 0;
+	mrec = expand->mrec;
+	offset = le16_to_cpu(mrec->attrs_offset);
+	a = (ATTR_RECORD*)((char*)mrec + offset);
+	while (!res && (a->type != AT_END)
+			&& (offset < le32_to_cpu(mrec->bytes_in_use))) {
+		if (a->non_resident) {
+			rl = ntfs_mapping_pairs_decompress(expand->vol, a,
+						(runlist_element*)NULL);
+			if (rl) {
+				for (prl=rl; prl->length; prl++)
+					if (prl->lcn >= 0) {
+						prl->lcn += expand->cluster_increment;
+						if (set_bitmap(expand,prl))
+							res = -1;
+						}
+				if (update_runlist(expand,inum,a,rl)) {
+					ntfs_log_verbose("Runlist updating has to be delayed\n");
+				} else
+					free(rl);
+			} else {
+				err_printf("Could not get a runlist of inode %lld\n",
+						(long long)inum);
+				res = -1;
+			}
+		}
+		offset += le32_to_cpu(a->length);
+		a = (ATTR_RECORD*)((char*)mrec + offset);
+	}
+	return (res);
+}
+
+/*
+ *		Rebase the runlists present in records with relocated $DATA
+ *
+ *	The returned runlist is the old rebased runlist for $DATA,
+ *	which is generally different from the new computed runlist.
+ */
+
+static runlist_element *rebase_runlists_meta(expand_t *expand, s64 inum)
+{
+	MFT_RECORD *mrec;
+	ATTR_RECORD *a;
+	ntfs_volume *vol;
+	runlist_element *rl;
+	runlist_element *old_rl;
+	runlist_element *prl;
+	runlist_element new_rl[2];
+	s64 data_size;
+	s64 allocated_size;
+	s64 lcn;
+	u64 lth;
+	u32 offset;
+	BOOL keeprl;
+	int res;
+
+	res = 0;
+	old_rl = (runlist_element*)NULL;
+	vol = expand->vol;
+	mrec = expand->mrec;
+	switch (inum) {
+	case FILE_Boot :
+		lcn = 0;
+		lth = expand->boot_size >> vol->cluster_size_bits;
+		data_size = expand->boot_size;
+		break;
+	case FILE_Bitmap :
+		lcn = expand->boot_size >> vol->cluster_size_bits;
+		lth = expand->bitmap_allocated >> vol->cluster_size_bits;
+		data_size = expand->bitmap_size;
+		break;
+	case FILE_MFT :
+		lcn = (expand->boot_size + expand->bitmap_allocated)
+				>> vol->cluster_size_bits;
+		lth = expand->mft_size >> vol->cluster_size_bits;
+		data_size = expand->mft_size;
+		break;
+	case FILE_BadClus :
+		lcn = 0; /* not used */
+		lth = vol->nr_clusters + expand->cluster_increment;
+		data_size = lth << vol->cluster_size_bits;
+		break;
+	default :
+		lcn = lth = data_size = 0;
+		res = -1;
+	}
+	allocated_size = lth << vol->cluster_size_bits;
+	offset = le16_to_cpu(mrec->attrs_offset);
+	a = (ATTR_RECORD*)((char*)mrec + offset);
+	while (!res && (a->type != AT_END)
+			&& (offset < le32_to_cpu(mrec->bytes_in_use))) {
+		if (a->non_resident) {
+			keeprl = FALSE;
+			rl = ntfs_mapping_pairs_decompress(vol, a,
+						(runlist_element*)NULL);
+			if (rl) {
+				/* rebase the old runlist */
+				for (prl=rl; prl->length; prl++)
+					if (prl->lcn >= 0) {
+						prl->lcn += expand->cluster_increment;
+						if ((a->type != AT_DATA)
+						    && set_bitmap(expand,prl))
+							res = -1;
+					}
+				/* relocated unnamed data (not $BadClus) */
+				if ((a->type == AT_DATA)
+				    && !a->name_length
+				    && (inum != FILE_BadClus)) {
+					old_rl = rl;
+					rl = new_rl;
+					keeprl = TRUE;
+					rl[0].vcn = 0;
+					rl[0].lcn = lcn;
+					rl[0].length = lth;
+					rl[1].vcn = lth;
+					rl[1].lcn = LCN_ENOENT;
+					rl[1].length = 0;
+					if (set_bitmap(expand,rl))
+						res = -1;
+					a->data_size = cpu_to_le64(data_size);
+					a->initialized_size = a->data_size;
+					a->allocated_size
+						= cpu_to_le64(allocated_size);
+					a->highest_vcn = cpu_to_le64(lth - 1);
+				}
+				/* expand the named data for $BadClus */
+				if ((a->type == AT_DATA)
+				    && a->name_length
+				    && (inum == FILE_BadClus)) {
+					old_rl = rl;
+					keeprl = TRUE;
+					prl = rl;
+					if (prl->length) {
+						while (prl[1].length)
+							prl++;
+						prl->length = lth - prl->vcn;
+						prl[1].vcn = lth;
+					} else
+						prl->vcn = lth;
+					a->data_size = cpu_to_le64(data_size);
+					/* do not change the initialized size */
+					a->allocated_size
+						= cpu_to_le64(allocated_size);
+					a->highest_vcn = cpu_to_le64(lth - 1);
+				}
+				if (!res && update_runlist(expand,inum,a,rl))
+					res = -1;
+				if (!keeprl)
+					free(rl);
+			} else {
+				err_printf("Could not get the data runlist of inode %lld\n",
+						(long long)inum);
+				res = -1;
+			}
+		}
+		offset += le32_to_cpu(a->length);
+		a = (ATTR_RECORD*)((char*)mrec + offset);
+	}
+	if (res && old_rl) {
+		free(old_rl);
+		old_rl = (runlist_element*)NULL;
+	}
+	return (old_rl);
+}
+
+/*
+ *		Rebase all runlists in an MFT record
+ *
+ *	Read from the old $MFT, rebase the runlists,
+ *	and write to the new $MFT
+ */
+
+static int rebase_inode(expand_t *expand, const runlist_element *prl,
+		s64 inum, s64 jnum)
+{
+	MFT_RECORD *mrec;
+	runlist_element *rl;
+	ntfs_volume *vol;
+	s64 pos;
+	int res;
+
+	res = 0;
+	vol = expand->vol;
+	mrec = expand->mrec;
+	if (expand->mft_bitmap[inum >> 3] & (1 << (inum & 7))) {
+		pos = (prl->lcn << vol->cluster_size_bits)
+			+ ((inum - jnum) << vol->mft_record_size_bits);
+		if ((ntfs_mst_pread(vol->dev, pos, 1,
+					vol->mft_record_size, mrec) == 1)
+		    && (mrec->flags & MFT_RECORD_IN_USE)) {
+			switch (inum) {
+			case FILE_Bitmap :
+			case FILE_Boot :
+			case FILE_BadClus :
+				rl = rebase_runlists_meta(expand, inum);
+				if (rl)
+					free(rl);
+				else
+					res = -1;
+				break;
+			default :
+			   	res = rebase_runlists(expand, inum);
+				break;
+			}
+		} else {
+			err_printf("Could not read the $MFT entry %lld\n",
+					(long long)inum);
+			res = -1;
+		}
+	} else {
+			/*
+			 * Replace unused records (possibly uninitialized)
+			 * by minimal valid records, not marked in use
+			 */
+		res = minimal_record(expand,mrec);
+	}
+	if (!res) {
+		pos = (expand->mft_lcn << vol->cluster_size_bits)
+			+ (inum << vol->mft_record_size_bits);
+		if (opt.verbose)
+			ntfs_log_verbose("Rebasing inode %lld cluster 0x%llx\n",
+				(long long)inum,
+				(long long)(pos >> vol->cluster_size_bits));
+		if (!opt.ro_flag
+		    && (ntfs_mst_pwrite(vol->dev, pos, 1,
+				vol->mft_record_size, mrec) != 1)) {
+			err_printf("Could not write the $MFT entry %lld\n",
+					(long long)inum);
+			res = -1;
+		}
+	}
+	return (res);
+}
+
+/*
+ *		Rebase all runlists
+ *
+ *	First get the $MFT and define its location in the expanded space,
+ *	then rebase the other inodes and write them to the new $MFT
+ */
+
+static int rebase_all_inodes(expand_t *expand)
+{
+	ntfs_volume *vol;
+	MFT_RECORD *mrec;
+	s64 inum;
+	s64 jnum;
+	s64 inodecnt;
+	s64 pos;
+	s64 got;
+	int res;
+	runlist_element *mft_rl;
+	runlist_element *prl;
+
+	res = 0;
+	mft_rl = (runlist_element*)NULL;
+	vol = expand->vol;
+	mrec = expand->mrec;
+	inum = 0;
+	pos = (vol->mft_lcn + expand->cluster_increment)
+				<< vol->cluster_size_bits;
+	got = ntfs_mst_pread(vol->dev, pos, 1,
+			vol->mft_record_size, mrec);
+	if ((got == 1) && (mrec->flags & MFT_RECORD_IN_USE)) {
+		pos = expand->mft_lcn << vol->cluster_size_bits;
+		if (opt.verbose)
+			ntfs_log_verbose("Rebasing inode %lld cluster 0x%llx\n",
+				(long long)inum,
+				(long long)(pos >> vol->cluster_size_bits));
+		mft_rl = rebase_runlists_meta(expand, FILE_MFT);
+		if (!mft_rl
+		    || (!opt.ro_flag
+			&& (ntfs_mst_pwrite(vol->dev, pos, 1,
+				vol->mft_record_size, mrec) != 1)))
+			res = -1;
+		else {
+			for (prl=mft_rl; prl->length; prl++) { }
+			inodecnt = (prl->vcn << vol->cluster_size_bits)
+				>> vol->mft_record_size_bits;
+			progress_init(expand->progress, 0, inodecnt,
+				(opt.show_progress ? NTFS_PROGBAR : 0));
+			prl = mft_rl;
+			jnum = 0;
+			do {
+				inum++;
+				while (prl->length
+				    && ((inum << vol->mft_record_size_bits)
+					>= ((prl->vcn + prl->length)
+						<< vol->cluster_size_bits))) {
+					prl++;
+					jnum = inum;
+				}
+				progress_update(expand->progress, inum);
+				if (prl->length) {
+					res = rebase_inode(expand,
+						prl,inum,jnum);
+				}
+			} while (!res && prl->length);
+			free(mft_rl);
+		}
+	} else {
+		err_printf("Could not read the old $MFT\n");
+		res = -1;
+	}
+	return (res);
+}
+
+
+
+/*
+ *		Get the old volume parameters from the backup bootsector
+ *
+ */
+
+static ntfs_volume *get_volume_data(expand_t *expand, struct ntfs_device *dev,
+			s32 sector_size)
+{
+	s64 br;
+	ntfs_volume *vol;
+	le16 sector_size_le;
+	NTFS_BOOT_SECTOR *bs;
+	BOOL ok;
+
+	ok = FALSE;
+	vol = (ntfs_volume*)ntfs_malloc(sizeof(ntfs_volume));
+	expand->bootsector = (char*)ntfs_malloc(sector_size);
+	if (vol && expand->bootsector) {
+		expand->vol = vol;
+		vol->dev = dev;
+		br = ntfs_pread(dev, expand->new_sectors*sector_size,
+				 sector_size, expand->bootsector);
+		if (br != sector_size) {
+			if (br != -1)
+				errno = EINVAL;
+			if (!br)
+				err_printf("Failed to read the backup bootsector (size=0)\n");
+			else
+				err_printf("Error reading the backup bootsector");
+		} else {
+			bs = (NTFS_BOOT_SECTOR*)expand->bootsector;
+		/* alignment problem on Sparc, even doing memcpy() */
+			sector_size_le = cpu_to_le16(sector_size);
+			if (!memcmp(&sector_size_le,
+						&bs->bpb.bytes_per_sector,2)
+			    && ntfs_boot_sector_is_ntfs(bs)
+			    && !ntfs_boot_sector_parse(vol, bs)) {
+				expand->original_sectors
+				    = le64_to_cpu(bs->number_of_sectors);
+				expand->mrec = (MFT_RECORD*)
+					ntfs_malloc(vol->mft_record_size);
+				if (expand->mrec
+				    && can_expand(expand,vol)) {
+					ntfs_log_verbose("Resizing is possible\n");
+					ok = TRUE;
+				}
+			} else
+				err_printf("Could not get the old volume parameters "
+					"from the backup bootsector\n");
+		}
+		if (!ok) {
+			free(vol);
+			free(expand->bootsector);
+		}
+	}
+	return (ok ? vol : (ntfs_volume*)NULL);
+}
+
+static int really_expand(expand_t *expand)
+{
+	ntfs_volume *vol;
+	struct ntfs_device *dev;
+	int res;
+
+	res = -1;
+
+	expand->bitmap = (u8*)ntfs_calloc(expand->bitmap_allocated);
+	if (expand->bitmap
+	    && get_mft_bitmap(expand)) {
+		printf("\n*** WARNING ***\n\n");
+		printf("Expanding a volume is an experimental new feature\n");
+		if (!opt.ro_flag)
+			printf("A first check with option -n is recommended\n");
+		printf("\nShould something go wrong during the actual"
+			 " resizing (power outage, etc.),\n");
+		printf("just restart the procedure, but DO NOT TRY to repair"
+			" with chkdsk or similar,\n");
+		printf("until the resizing is over,"
+			" you would LOSE YOUR DATA !\n");
+		printf("\nYou have been warned !\n\n");
+		if (!opt.ro_flag && (opt.force-- <= 0))
+			proceed_question();
+		if (!rebase_all_inodes(expand)
+		    && !write_bitmap(expand)
+		    && !copy_mftmirr(expand)
+		    && !copy_boot(expand)) {
+			free(expand->vol);
+			expand->vol = (ntfs_volume*)NULL;
+			free(expand->mft_bitmap);
+			expand->mft_bitmap = (u8*)NULL;
+			if (!opt.ro_flag) {
+				/* the volume must be dirty, do not check */
+				opt.force++;
+				vol = mount_volume();
+				if (vol) {
+					dev = vol->dev;
+					ntfs_log_verbose("Remounting the updated volume\n");
+					expand->vol = vol;
+					ntfs_log_verbose("Delayed runlist updatings\n");
+					delayed_expand(vol, expand->delayed_runlists,
+						expand->progress);
+					expand->delayed_runlists
+						= (struct DELAYED*)NULL;
+					expand_index_sizes(expand);
+		/* rewriting the backup bootsector, no return ticket now ! */
+					res = write_bootsector(expand);
+					if (dev->d_ops->sync(dev) == -1) {
+						printf("Could not sync\n");
+						res = -1;
+					}
+					ntfs_umount(vol,0);
+					if (!res)
+						printf("\nResizing completed successfully\n");
+				}
+			} else {
+				ntfs_log_verbose("Delayed runlist updatings\n");
+				delayed_expand(expand->vol,
+						expand->delayed_runlists,
+						expand->progress);
+				expand->delayed_runlists
+						= (struct DELAYED*)NULL;
+				printf("\nAll checks have been completed successfully\n");
+				printf("Cannot check further in no-action mode\n");
+			}
+			free(expand->bootsector);
+			free(expand->mrec);
+		}
+		free(expand->bitmap);
+	} else {
+		err_printf("Failed to allocate memory\n");
+	}
+	return (res);
+}
+
+/*
+ *		Expand a volume to beginning of partition
+ *
+ *	We rely on the backup bootsector to determine the original
+ *	volume size and metadata.
+ */
+
+static int expand_to_beginning(void)
+{
+	expand_t expand;
+	struct progress_bar progress;
+	int ret;
+	ntfs_volume *vol;
+	struct ntfs_device *dev;
+	int sector_size;
+	s64 new_sectors;
+	        
+	ret = -1;
+	dev = ntfs_device_alloc(opt.volume, 0, &ntfs_device_default_io_ops,
+			NULL);
+	if (dev) {
+	        if (!(*dev->d_ops->open)(dev,
+				(opt.ro_flag ? O_RDONLY : O_RDWR))) {
+			sector_size = ntfs_device_sector_size_get(dev);
+			if (sector_size <= 0) {
+				sector_size = 512;
+				new_sectors = ntfs_device_size_get(dev,
+								sector_size);
+				if (!new_sectors) {
+					sector_size = 4096;
+					new_sectors = ntfs_device_size_get(dev,
+								sector_size);
+				}
+			} else
+				new_sectors = ntfs_device_size_get(dev,
+								sector_size);
+			if (new_sectors) {
+				new_sectors--; /* last sector not counted */
+				expand.new_sectors = new_sectors;
+				expand.progress = &progress;
+				expand.delayed_runlists = (struct DELAYED*)NULL;
+				vol = get_volume_data(&expand,dev,sector_size);
+				if (vol) {
+					expand.vol = vol;
+					ret = really_expand(&expand);
+				}
+			}
+			(*dev->d_ops->close)(dev);
+		} else {
+			err_exit("Couldn't open volume '%s'!\n", opt.volume);
+		}
+		ntfs_device_free(dev);
+	}
+	return (ret);
+}
+
+
+int main(int argc, char **argv)
+{
+	ntfsck_t fsck;
+	ntfs_resize_t resize;
+	s64 new_size = 0;	/* in clusters; 0 = --info w/o --size */
+	s64 device_size;        /* in bytes */
+	ntfs_volume *vol = NULL;
+	int res;
+
+	ntfs_log_set_handler(ntfs_log_handler_outerr);
+
+	printf("%s v%s (libntfs-3g)\n", EXEC_NAME, VERSION);
+
+	res = parse_options(argc, argv);
+	if (res >= 0)
+		return (res);
+
+	utils_set_locale();
+
+		/*
+		 * If we're just checking the device, we'll do it first,
+		 * and exit out, no matter what we find.
+		 */
+	if (opt.check) {
+		vol = check_volume();
+#if CLEAN_EXIT
+		if (vol)
+			ntfs_umount(vol,0);
+#endif
+		exit(0);
+	} else {
+		if (opt.expand) {
+			/*
+			 * If we are to expand to beginning of partition, do
+			 * not try to mount : when merging two partitions,
+			 * the beginning of the partition would contain an
+			 * old filesystem which is not the one to expand.
+			 */
+			if (expand_to_beginning() && !opt.info)
+				exit(1);
+			return (0);
+		}
+	}
+
+	if (!(vol = mount_volume()))
+		err_exit("Couldn't open volume '%s'!\n", opt.volume);
+
+	device_size = ntfs_device_size_get(vol->dev, vol->sector_size);
+	device_size *= vol->sector_size;
+	if (device_size <= 0)
+		err_exit("Couldn't get device size (%lld)!\n",
+			(long long)device_size);
+
+	if (!opt.infombonly)
+		print_vol_size("Current device size", device_size);
+
+	if (device_size < vol->nr_clusters * vol->cluster_size)
+		err_exit("Current NTFS volume size is bigger than the device "
+			 "size!\nCorrupt partition table or incorrect device "
+			 "partitioning?\n");
+
+	if (!opt.bytes && !opt.info && !opt.infombonly) {
+		opt.bytes = device_size;
+		opt.reliable_size = 1;
+	}
+
+	/* Backup boot sector at the end of device isn't counted in NTFS
+	   volume size thus we have to reserve space for it. */
+	if (opt.bytes > vol->sector_size)
+		new_size = (opt.bytes - vol->sector_size) / vol->cluster_size;
+	else
+		new_size = 0;
+
+	if (!opt.info && !opt.infombonly) {
+		print_vol_size("New volume size    ", vol_size(vol, new_size));
+		if (device_size < opt.bytes)
+			err_exit("New size can't be bigger than the device size"
+				 ".\nIf you want to enlarge NTFS then first "
+				 "enlarge the device size by e.g. fdisk.\n");
+	}
+
+	if (!opt.info && !opt.infombonly && (new_size == vol->nr_clusters ||
+			  (opt.bytes == device_size &&
+			   new_size == vol->nr_clusters - 1))) {
+		printf("Nothing to do: NTFS volume size is already OK.\n");
+		exit(0);
+	}
+
+	memset(&resize, 0, sizeof(resize));
+	resize.vol = vol;
+	resize.new_volume_size = new_size;
+	/* This is also true if --info was used w/o --size (new_size = 0) */
+	if (new_size < vol->nr_clusters)
+		resize.shrink = 1;
+	if (opt.show_progress)
+		resize.progress.flags |= NTFS_PROGBAR;
+	/*
+	 * Checking and __reporting__ of bad sectors must be done before cluster
+	 * allocation check because chkdsk doesn't fix $Bitmap's w/ bad sectors
+	 * thus users would (were) quite confused why chkdsk doesn't work.
+	 */
+	resize.badclusters = check_bad_sectors(vol);
+
+	NVolSetNoFixupWarn(vol);
+	check_cluster_allocation(vol, &fsck);
+
+	print_disk_usage(vol, fsck.inuse);
+
+	resize.inuse = fsck.inuse;
+	resize.lcn_bitmap = fsck.lcn_bitmap;
+
+	set_resize_constraints(&resize);
+	set_disk_usage_constraint(&resize);
+	check_resize_constraints(&resize);
+
+	if (opt.info || opt.infombonly) {
+		advise_on_resize(&resize);
+		exit(0);
+	}
+
+	if (opt.force-- <= 0 && !opt.ro_flag) {
+		printf("%s", resize_warning_msg);
+		proceed_question();
+	}
+
+	/* FIXME: performance - relocate logfile here if it's needed */
+	prepare_volume_fixup(vol);
+
+	if (resize.relocations)
+		relocate_inodes(&resize);
+
+	truncate_badclust_file(&resize);
+	truncate_bitmap_file(&resize);
+	delayed_updates(&resize);
+	update_bootsector(&resize);
+
+	/* We don't create backup boot sector because we don't know where the
+	   partition will be split. The scheduled chkdsk will fix it */
+
+	if (opt.ro_flag) {
+		printf("The read-only test run ended successfully.\n");
+		exit(0);
+	}
+
+	/* WARNING: don't modify the texts, external tools grep for them */
+	printf("Syncing device ...\n");
+	if (vol->dev->d_ops->sync(vol->dev) == -1)
+		perr_exit("fsync");
+
+	printf("Successfully resized NTFS on device '%s'.\n", vol->dev->d_name);
+	if (resize.shrink)
+		printf("%s", resize_important_msg);
+#if CLEAN_EXIT
+	if (resize.lcn_bitmap.bm)
+		free(resize.lcn_bitmap.bm);
+	if (vol)
+		ntfs_umount(vol,0);
+#endif
+	return 0;
+}
diff --git a/ntfsprogs/ntfstruncate.8 b/ntfsprogs/ntfstruncate.8
new file mode 100755
index 0000000000000000000000000000000000000000..9a75d538bc9c970049fe2147257b69083706fb94
--- /dev/null
+++ b/ntfsprogs/ntfstruncate.8
@@ -0,0 +1,124 @@
+.\" Copyright (c) 2014 Jean-Pierre Andre
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSTRUNCATE 8 "June 2014" "ntfs-3g 2015.3.14"
+.SH NAME
+ntfstruncate \- truncate a file on an NTFS volume
+.SH SYNOPSIS
+\fBntfstruncate\fR [\fIoptions\fR] \fIdevice\fR \fIfile\fR \fI[attr-type\fR [\fIattr-name\fR]] \fInew-length\fR
+.SH DESCRIPTION
+.B ntfstruncate
+truncates (or extends) a specified attribute belonging to a
+file or directory, to a specified length.
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfstruncate
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+This will override some sensible defaults, such as not using a mounted volume.
+Use this option with caution.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.TP
+\fB\-l\fR
+Display licensing information.
+.TP
+\fB\-n\fR, \fB\-\-no-action\fR
+Simulate the truncation without actually write to device.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Suppress some debug/warning/error messages.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Display more debug/warning/error messages.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Show the version number, copyright and license of
+.BR ntfstruncate .
+.TP
+\fBattr-type\fR
+Define a particular attribute type to be truncated (advanced use only).
+By default, the unnamed $DATA attribute (the contents of a plain file) will
+be truncated. The attribute has to be specified by a number in decimal
+or hexadecimal :
+.TS
+box;
+lB lB lB
+l l l.
+Hex	Decimal	Name
+0x10	16	"$STANDARD_INFORMATION"
+0x20	32	"$ATTRIBUTE_LIST"
+0x30	48	"$FILE_NAME"
+0x40	64	"$OBJECT_ID"
+0x50	80	"$SECURITY_DESCRIPTOR"
+0x60	96	"$VOLUME_NAME"
+0x70	112	"$VOLUME_INFORMATION"
+0x80	128	"$DATA"
+0x90	144	"$INDEX_ROOT"
+0xA0	160	"$INDEX_ALLOCATION"
+0xB0	176	"$BITMAP"
+0xC0	192	"$REPARSE_POINT"
+0xD0	208	"$EA_INFORMATION"
+0xE0	224	"$EA"
+0xF0	240	"$PROPERTY_SET"
+0x100	256	"$LOGGED_UTILITY_STREAM"
+.TE
+.sp
+.TP
+\fBattr-name\fR
+Define the name of the particular attribute type to be truncated
+(advanced use only).
+.sp
+.TP
+\fBnew-length\fR
+Specify the target size of the file.
+It will be rounded up to a multiple of the cluster size.
+A suffix of K, M, G, T, P or E may be appended to
+mean a multiplicative factor of a power of 1000. Similarly a suffix of
+Ki, Mi, Gi, Ti, Pi or Ei may be appended to mean a multiplicative factor
+of a power of 1024.
+.SH EXAMPLES
+Resize to 100MB the file database.db located in the Data directory
+which is at the root of an NTFS file system.
+.RS
+.sp
+.B ntfstruncate /dev/sda1 Data/database.db 100M
+.sp
+.RE
+.SH BUGS
+There are no known problems with
+.BR ntfstruncate .
+If you find a bug, please send an email
+describing the problem to the development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+.B ntfstruncate
+was written by Anton Altaparmakov.
+.SH AVAILABILITY
+.B ntfstruncate
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR ntfs-3g (8),
+.BR ntfsfallocate (8),
+.BR ntfsprogs (8).
diff --git a/ntfsprogs/ntfstruncate.8.in b/ntfsprogs/ntfstruncate.8.in
new file mode 100755
index 0000000000000000000000000000000000000000..e793f649526f1262544cbaf03e89c2b337a41ab9
--- /dev/null
+++ b/ntfsprogs/ntfstruncate.8.in
@@ -0,0 +1,124 @@
+.\" Copyright (c) 2014 Jean-Pierre Andre
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSTRUNCATE 8 "June 2014" "ntfs-3g @VERSION@"
+.SH NAME
+ntfstruncate \- truncate a file on an NTFS volume
+.SH SYNOPSIS
+\fBntfstruncate\fR [\fIoptions\fR] \fIdevice\fR \fIfile\fR \fI[attr-type\fR [\fIattr-name\fR]] \fInew-length\fR
+.SH DESCRIPTION
+.B ntfstruncate
+truncates (or extends) a specified attribute belonging to a
+file or directory, to a specified length.
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfstruncate
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+This will override some sensible defaults, such as not using a mounted volume.
+Use this option with caution.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.TP
+\fB\-l\fR
+Display licensing information.
+.TP
+\fB\-n\fR, \fB\-\-no-action\fR
+Simulate the truncation without actually write to device.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Suppress some debug/warning/error messages.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Display more debug/warning/error messages.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Show the version number, copyright and license of
+.BR ntfstruncate .
+.TP
+\fBattr-type\fR
+Define a particular attribute type to be truncated (advanced use only).
+By default, the unnamed $DATA attribute (the contents of a plain file) will
+be truncated. The attribute has to be specified by a number in decimal
+or hexadecimal :
+.TS
+box;
+lB lB lB
+l l l.
+Hex	Decimal	Name
+0x10	16	"$STANDARD_INFORMATION"
+0x20	32	"$ATTRIBUTE_LIST"
+0x30	48	"$FILE_NAME"
+0x40	64	"$OBJECT_ID"
+0x50	80	"$SECURITY_DESCRIPTOR"
+0x60	96	"$VOLUME_NAME"
+0x70	112	"$VOLUME_INFORMATION"
+0x80	128	"$DATA"
+0x90	144	"$INDEX_ROOT"
+0xA0	160	"$INDEX_ALLOCATION"
+0xB0	176	"$BITMAP"
+0xC0	192	"$REPARSE_POINT"
+0xD0	208	"$EA_INFORMATION"
+0xE0	224	"$EA"
+0xF0	240	"$PROPERTY_SET"
+0x100	256	"$LOGGED_UTILITY_STREAM"
+.TE
+.sp
+.TP
+\fBattr-name\fR
+Define the name of the particular attribute type to be truncated
+(advanced use only).
+.sp
+.TP
+\fBnew-length\fR
+Specify the target size of the file.
+It will be rounded up to a multiple of the cluster size.
+A suffix of K, M, G, T, P or E may be appended to
+mean a multiplicative factor of a power of 1000. Similarly a suffix of
+Ki, Mi, Gi, Ti, Pi or Ei may be appended to mean a multiplicative factor
+of a power of 1024.
+.SH EXAMPLES
+Resize to 100MB the file database.db located in the Data directory
+which is at the root of an NTFS file system.
+.RS
+.sp
+.B ntfstruncate /dev/sda1 Data/database.db 100M
+.sp
+.RE
+.SH BUGS
+There are no known problems with
+.BR ntfstruncate .
+If you find a bug, please send an email
+describing the problem to the development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+.B ntfstruncate
+was written by Anton Altaparmakov.
+.SH AVAILABILITY
+.B ntfstruncate
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR ntfs-3g (8),
+.BR ntfsfallocate (8),
+.BR ntfsprogs (8).
diff --git a/ntfsprogs/ntfstruncate.c b/ntfsprogs/ntfstruncate.c
new file mode 100755
index 0000000000000000000000000000000000000000..f561690fc206168c1d3d47b31db61ad0b0dfafd0
--- /dev/null
+++ b/ntfsprogs/ntfstruncate.c
@@ -0,0 +1,810 @@
+/**
+ * ntfstruncate - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2002-2005 Anton Altaparmakov
+ *
+ * This utility will truncate a specified attribute belonging to a
+ * specified inode, i.e. file or directory, to a specified length.
+ *
+ * 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 Linux-NTFS source
+ * 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_UNISTD_H
+#	include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#	include <stdlib.h>
+#endif
+#ifdef HAVE_STDIO_H
+#	include <stdio.h>
+#endif
+#ifdef HAVE_STDARG_H
+#	include <stdarg.h>
+#endif
+#ifdef HAVE_STRING_H
+#	include <string.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#	include <errno.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_GETOPT_H
+#	include <getopt.h>
+#else
+	extern char *optarg;
+	extern int optind;
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifndef LLONG_MAX
+#	define LLONG_MAX 9223372036854775807LL
+#endif
+
+#include "types.h"
+#include "attrib.h"
+#include "inode.h"
+#include "layout.h"
+#include "volume.h"
+#include "utils.h"
+#include "attrdef.h"
+/* #include "version.h" */
+#include "logging.h"
+
+const char *EXEC_NAME = "ntfstruncate";
+
+/* Need these global so ntfstruncate_exit can access them. */
+BOOL success = FALSE;
+
+char *dev_name;
+s64 inode;
+u32 attr_type;
+ntfschar *attr_name = NULL;
+u32 attr_name_len;
+s64 new_len;
+
+ntfs_volume *vol;
+ntfs_inode *ni;
+ntfs_attr *na = NULL;
+
+ATTR_DEF *attr_defs;
+
+struct {
+				/* -h, print usage and exit. */
+	int no_action;		/* -n, do not write to device, only display
+				       what would be done. */
+	int quiet;		/* -q, quiet execution. */
+	int verbose;		/* -v, verbose execution, given twice, really
+				       verbose execution (debug mode). */
+	int force;		/* -f, force truncation. */
+				/* -V, print version and exit. */
+} opts;
+
+/**
+ * err_exit - error output and terminate; ignores quiet (-q)
+ */
+__attribute__((noreturn))
+__attribute__((format(printf, 1, 2)))
+static void err_exit(const char *fmt, ...)
+{
+	va_list ap;
+
+	fprintf(stderr, "ERROR: ");
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	fprintf(stderr, "Aborting...\n");
+	exit(1);
+}
+
+/**
+ * copyright - print copyright statements
+ */
+static void copyright(void)
+{
+	fprintf(stderr, "Copyright (c) 2002-2005 Anton Altaparmakov\n"
+			"Copyright (c) 2003 Richard Russon\n"
+			"Truncate a specified attribute of a specified "
+			"inode.\n");
+}
+
+/**
+ * license - print license statement
+ */
+static void license(void)
+{
+	fprintf(stderr, "%s", ntfs_gpl);
+}
+
+/**
+ * usage - print a list of the parameters to the program
+ */
+__attribute__((noreturn))
+static void usage(int ret)
+{
+	copyright();
+	fprintf(stderr, "Usage: %s [options] device inode [attr-type "
+			"[attr-name]] new-length\n"
+			"    If attr-type is not specified, 0x80 (i.e. $DATA) "
+			"is assumed.\n"
+			"    If attr-name is not specified, an unnamed "
+			"attribute is assumed.\n"
+			"    -n    Do not write to disk\n"
+			"    -f    Force execution despite errors\n"
+			"    -q    Quiet execution\n"
+			"    -v    Verbose execution\n"
+			"    -vv   Very verbose execution\n"
+			"    -V    Display version information\n"
+			"    -l    Display licensing information\n"
+			"    -h    Display this help\n", EXEC_NAME);
+	fprintf(stderr, "%s%s", ntfs_bugs, ntfs_home);
+	exit(ret);
+}
+
+/**
+ * parse_options
+ */
+static void parse_options(int argc, char *argv[])
+{
+	long long ll;
+	char *s, *s2;
+	int c;
+
+	if (argc && *argv)
+		EXEC_NAME = *argv;
+	fprintf(stderr, "%s v%s (libntfs-3g)\n", EXEC_NAME, VERSION);
+	while ((c = getopt(argc, argv, "fh?nqvVl")) != EOF)
+		switch (c) {
+		case 'f':
+			opts.force = 1;
+			break;
+		case 'n':
+			opts.no_action = 1;
+			break;
+		case 'q':
+			opts.quiet = 1;
+			ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
+			break;
+		case 'v':
+			opts.verbose++;
+			ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
+			break;
+		case 'V':
+			/* Version number already printed, so just exit. */
+			exit(0);
+		case 'l':
+			copyright();
+			license();
+			exit(0);
+		case 'h':
+			usage(0);
+		case '?':
+		default:
+			usage(1);
+		}
+	if (optind == argc)
+		usage(1);
+
+	if (opts.verbose > 1)
+		ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG | NTFS_LOG_LEVEL_TRACE |
+			NTFS_LOG_LEVEL_VERBOSE | NTFS_LOG_LEVEL_QUIET);
+
+	/* Get the device. */
+	dev_name = argv[optind++];
+	ntfs_log_verbose("device name = %s\n", dev_name);
+
+	if (optind == argc)
+		usage(1);
+
+	/* Get the inode. */
+	ll = strtoll(argv[optind++], &s, 0);
+	if (*s || !ll || (ll >= LLONG_MAX && errno == ERANGE))
+		err_exit("Invalid inode number: %s\n", argv[optind - 1]);
+	inode = ll;
+	ntfs_log_verbose("inode = %lli\n", (long long)inode);
+
+	if (optind == argc)
+		usage(1);
+
+	/* Get the attribute type, if specified. */
+	s = argv[optind++];
+	if (optind == argc) {
+		attr_type = AT_DATA;
+		attr_name = AT_UNNAMED;
+		attr_name_len = 0;
+	} else {
+		unsigned long ul;
+
+		ul = strtoul(s, &s2, 0);
+		if (*s2 || !ul || (ul >= ULONG_MAX && errno == ERANGE))
+			err_exit("Invalid attribute type %s: %s\n", s,
+					strerror(errno));
+		attr_type = ul;
+
+		/* Get the attribute name, if specified. */
+		s = argv[optind++];
+		if (optind != argc) {
+			/* Convert the string to little endian Unicode. */
+			attr_name_len = ntfs_mbstoucs(s, &attr_name);
+			if ((int)attr_name_len < 0)
+				err_exit("Invalid attribute name \"%s\": %s\n",
+						s, strerror(errno));
+
+			/* Keep hold of the original string. */
+			s2 = s;
+
+			s = argv[optind++];
+			if (optind != argc)
+				usage(1);
+		} else {
+			attr_name = AT_UNNAMED;
+			attr_name_len = 0;
+		}
+	}
+	ntfs_log_verbose("attribute type = 0x%x\n", (unsigned int)attr_type);
+	if (attr_name == AT_UNNAMED)
+		ntfs_log_verbose("attribute name = \"\" (UNNAMED)\n");
+	else
+		ntfs_log_verbose("attribute name = \"%s\" (length %u Unicode "
+				"characters)\n", s2,
+				(unsigned int)attr_name_len);
+
+	/* Get the new length. */
+	ll = strtoll(s, &s2, 0);
+	if (*s2 || ll < 0 || (ll >= LLONG_MAX && errno == ERANGE))
+		err_exit("Invalid new length: %s\n", s);
+	new_len = ll;
+	ntfs_log_verbose("new length = %lli\n", (long long)new_len);
+}
+
+/**
+ * ucstos - convert unicode-character string to ASCII
+ * @dest:	points to buffer to receive the converted string
+ * @src:	points to string to convert
+ * @maxlen:	size of @dest buffer in bytes
+ *
+ * Return the number of characters written to @dest, not including the
+ * terminating null byte. If a unicode character was encountered which could
+ * not be converted -1 is returned.
+ */
+static int ucstos(char *dest, const ntfschar *src, int maxlen)
+{
+	ntfschar u;
+	int i;
+
+	/* Need one byte for null terminator. */
+	maxlen--;
+	for (i = 0; i < maxlen; i++) {
+		u = le16_to_cpu(src[i]);
+		if (!u)
+			break;
+		if (u & 0xff00)
+			return -1;
+		dest[i] = u & 0xff;
+	}
+	dest[i] = 0;
+	return i;
+}
+
+/**
+ * dump_resident_attr_val
+ */
+static void dump_resident_attr_val(ATTR_TYPES type, char *val, u32 val_len)
+{
+	const char *don_t_know = "Don't know what to do with this attribute "
+			"type yet.";
+	const char *skip = "Skipping display of $%s attribute value.\n";
+	const char *todo = "This is still work in progress.";
+	char *buf;
+	int i, j;
+	u32 u;
+
+	switch (type) {
+	case AT_STANDARD_INFORMATION:
+		// TODO
+		printf("%s\n", todo);
+		return;
+	case AT_ATTRIBUTE_LIST:
+		// TODO
+		printf("%s\n", todo);
+		return;
+	case AT_FILE_NAME:
+		// TODO
+		printf("%s\n", todo);
+		return;
+	case AT_OBJECT_ID:
+		// TODO
+		printf("%s\n", todo);
+		return;
+	case AT_SECURITY_DESCRIPTOR:
+		// TODO
+		printf("%s\n", todo);
+		return;
+	case AT_VOLUME_NAME:
+		printf("Volume name length = %u\n", (unsigned int)val_len);
+		if (val_len) {
+			buf = calloc(1, val_len);
+			if (!buf)
+				err_exit("Failed to allocate internal buffer: "
+						"%s\n", strerror(errno));
+			i = ucstos(buf, (ntfschar*)val, val_len);
+			if (i == -1)
+				printf("Volume name contains non-displayable "
+						"Unicode characters.\n");
+			printf("Volume name = %s\n", buf);
+			free(buf);
+		}
+		return;
+	case AT_VOLUME_INFORMATION:
+#define VOL_INF(x) ((VOLUME_INFORMATION *)(x))
+		printf("NTFS version %i.%i\n", VOL_INF(val)->major_ver,
+				VOL_INF(val)->minor_ver);
+		i = VOL_INF(val)->flags;
+#undef VOL_INF
+		printf("Volume flags = 0x%x: ", i);
+		if (!i) {
+			printf("NONE\n");
+			return;
+		}
+		j = 0;
+		if (i & VOLUME_MODIFIED_BY_CHKDSK) {
+			j = 1;
+			printf("VOLUME_MODIFIED_BY_CHKDSK");
+		}
+		if (i & VOLUME_REPAIR_OBJECT_ID) {
+			if (j)
+				printf(" | ");
+			else
+				j = 0;
+			printf("VOLUME_REPAIR_OBJECT_ID");
+		}
+		if (i & VOLUME_DELETE_USN_UNDERWAY) {
+			if (j)
+				printf(" | ");
+			else
+				j = 0;
+			printf("VOLUME_DELETE_USN_UNDERWAY");
+		}
+		if (i & VOLUME_MOUNTED_ON_NT4) {
+			if (j)
+				printf(" | ");
+			else
+				j = 0;
+			printf("VOLUME_MOUNTED_ON_NT4");
+		}
+		if (i & VOLUME_UPGRADE_ON_MOUNT) {
+			if (j)
+				printf(" | ");
+			else
+				j = 0;
+			printf("VOLUME_UPGRADE_ON_MOUNT");
+		}
+		if (i & VOLUME_RESIZE_LOG_FILE) {
+			if (j)
+				printf(" | ");
+			else
+				j = 0;
+			printf("VOLUME_RESIZE_LOG_FILE");
+		}
+		if (i & VOLUME_IS_DIRTY) {
+			if (j)
+				printf(" | ");
+			else
+				j = 0;
+			printf("VOLUME_IS_DIRTY");
+		}
+		printf("\n");
+		return;
+	case AT_DATA:
+		printf(skip, "DATA");
+		return;
+	case AT_INDEX_ROOT:
+		// TODO
+		printf("%s\n", todo);
+		return;
+	case AT_INDEX_ALLOCATION:
+		// TODO
+		printf("%s\n", todo);
+		return;
+	case AT_BITMAP:
+		printf(skip, "BITMAP");
+		return;
+	case AT_REPARSE_POINT:
+		// TODO
+		printf("%s\n", todo);
+		return;
+	case AT_EA_INFORMATION:
+		// TODO
+		printf("%s\n", don_t_know);
+		return;
+	case AT_EA:
+		// TODO
+		printf("%s\n", don_t_know);
+		return;
+	case AT_LOGGED_UTILITY_STREAM:
+		// TODO
+		printf("%s\n", don_t_know);
+		return;
+	default:
+		u = le32_to_cpu(type);
+		printf("Cannot display unknown %s defined attribute type 0x%x"
+				".\n", u >=
+				le32_to_cpu(AT_FIRST_USER_DEFINED_ATTRIBUTE) ?
+				"user" : "system", (unsigned int)u);
+	}
+}
+
+/**
+ * dump_resident_attr
+ */
+static void dump_resident_attr(ATTR_RECORD *a)
+{
+	int i;
+
+	i = le32_to_cpu(a->value_length);
+	printf("Attribute value length = %u (0x%x)\n", i, i);
+	i = le16_to_cpu(a->value_offset);
+	printf("Attribute value offset = %u (0x%x)\n", i, i);
+	i = a->resident_flags;
+	printf("Resident flags = 0x%x: ", i);
+	if (!i)
+		printf("NONE\n");
+	else if (i & ~RESIDENT_ATTR_IS_INDEXED)
+		printf("UNKNOWN FLAG(S)\n");
+	else
+		printf("RESIDENT_ATTR_IS_INDEXED\n");
+	dump_resident_attr_val(a->type, (char*)a + le16_to_cpu(a->value_offset),
+			le32_to_cpu(a->value_length));
+}
+
+/**
+ * dump_mapping_pairs_array
+ */
+static void dump_mapping_pairs_array(char *b __attribute__((unused)),
+	unsigned int max_len __attribute__((unused)))
+{
+	// TODO
+	return;
+}
+
+/**
+ * dump_non_resident_attr
+ */
+static void dump_non_resident_attr(ATTR_RECORD *a)
+{
+	s64 l;
+	int i;
+
+	l = sle64_to_cpu(a->lowest_vcn);
+	printf("Lowest VCN = %lli (0x%llx)\n", (long long)l,
+			(unsigned long long)l);
+	l = sle64_to_cpu(a->highest_vcn);
+	printf("Highest VCN = %lli (0x%llx)\n", (long long)l,
+			(unsigned long long)l);
+	printf("Mapping pairs array offset = 0x%x\n",
+			le16_to_cpu(a->mapping_pairs_offset));
+	printf("Compression unit = 0x%x: %sCOMPRESSED\n", a->compression_unit,
+			a->compression_unit ? "" : "NOT ");
+	if (sle64_to_cpu(a->lowest_vcn))
+		printf("Attribute is not the first extent. The following "
+				"sizes are meaningless:\n");
+	l = sle64_to_cpu(a->allocated_size);
+	printf("Allocated size = %lli (0x%llx)\n", (long long)l,
+			(unsigned long long)l);
+	l = sle64_to_cpu(a->data_size);
+	printf("Data size = %lli (0x%llx)\n", (long long)l,
+			(unsigned long long)l);
+	l = sle64_to_cpu(a->initialized_size);
+	printf("Initialized size = %lli (0x%llx)\n", (long long)l,
+			(unsigned long long)l);
+	if (a->flags & ATTR_COMPRESSION_MASK) {
+		l = sle64_to_cpu(a->compressed_size);
+		printf("Compressed size = %lli (0x%llx)\n", (long long)l,
+				(unsigned long long)l);
+	}
+	i = le16_to_cpu(a->mapping_pairs_offset);
+	dump_mapping_pairs_array((char*)a + i, le32_to_cpu(a->length) - i);
+}
+
+/**
+ * dump_attr_record
+ */
+static void dump_attr_record(MFT_RECORD *m, ATTR_RECORD *a)
+{
+	unsigned int u;
+	char s[0x200];
+	int i;
+
+	printf("-- Beginning dump of attribute record at offset 0x%x. --\n",
+			(unsigned)((u8*)a - (u8*)m));
+	if (a->type == AT_END) {
+		printf("Attribute type = 0x%x ($END)\n",
+				(unsigned int)le32_to_cpu(AT_END));
+		u = le32_to_cpu(a->length);
+		printf("Length of resident part = %u (0x%x)\n", u, u);
+		return;
+	}
+	u = le32_to_cpu(a->type);
+	for (i = 0; attr_defs[i].type; i++)
+		if (le32_to_cpu(attr_defs[i].type) >= u)
+			break;
+	if (attr_defs[i].type) {
+//		printf("type = 0x%x\n", le32_to_cpu(attr_defs[i].type));
+//		{ char *p = (char*)attr_defs[i].name;
+//		printf("name = %c%c%c%c%c\n", *p, p[1], p[2], p[3], p[4]);
+//		}
+		if (ucstos(s, attr_defs[i].name, sizeof(s)) == -1) {
+			ntfs_log_error("Could not convert Unicode string to single "
+				"byte string in current locale.\n");
+			strncpy(s, "Error converting Unicode string",
+					sizeof(s));
+		}
+	} else
+		strncpy(s, "UNKNOWN_TYPE", sizeof(s));
+	printf("Attribute type = 0x%x (%s)\n", u, s);
+	u = le32_to_cpu(a->length);
+	printf("Length of resident part = %u (0x%x)\n", u, u);
+	printf("Attribute is %sresident\n", a->non_resident ? "non-" : "");
+	printf("Name length = %u unicode characters\n", a->name_length);
+	printf("Name offset = %u (0x%x)\n", cpu_to_le16(a->name_offset),
+			cpu_to_le16(a->name_offset));
+	u = a->flags;
+	if (a->name_length) {
+		if (ucstos(s, (ntfschar*)((char*)a +
+				cpu_to_le16(a->name_offset)),
+				min((int)sizeof(s),
+						a->name_length + 1)) == -1) {
+			ntfs_log_error("Could not convert Unicode string to single "
+				"byte string in current locale.\n");
+			strncpy(s, "Error converting Unicode string",
+					sizeof(s));
+
+		}
+		printf("Name = %s\n", s);
+	}
+	printf("Attribute flags = 0x%x: ", le16_to_cpu(u));
+	if (!u)
+		printf("NONE");
+	else {
+		int first = TRUE;
+		if (u & ATTR_COMPRESSION_MASK) {
+			if (u & ATTR_IS_COMPRESSED) {
+				printf("ATTR_IS_COMPRESSED");
+				first = FALSE;
+			}
+			if ((u & ATTR_COMPRESSION_MASK) & ~ATTR_IS_COMPRESSED) {
+				if (!first)
+					printf(" | ");
+				else
+					first = FALSE;
+				printf("ATTR_UNKNOWN_COMPRESSION");
+			}
+		}
+		if (u & ATTR_IS_ENCRYPTED) {
+			if (!first)
+				printf(" | ");
+			else
+				first = FALSE;
+			printf("ATTR_IS_ENCRYPTED");
+		}
+		if (u & ATTR_IS_SPARSE) {
+			if (!first)
+				printf(" | ");
+			else
+				first = FALSE;
+			printf("ATTR_IS_SPARSE");
+		}
+	}
+	printf("\n");
+	printf("Attribute instance = %u\n", le16_to_cpu(a->instance));
+	if (a->non_resident) {
+		dump_non_resident_attr(a);
+	} else {
+		dump_resident_attr(a);
+	}
+}
+
+/**
+ * dump_mft_record
+ */
+static void dump_mft_record(MFT_RECORD *m)
+{
+	ATTR_RECORD *a;
+	unsigned int u;
+	MFT_REF r;
+
+	printf("-- Beginning dump of mft record. --\n");
+	u = le32_to_cpu(m->magic);
+	printf("Mft record signature (magic) = %c%c%c%c\n", u & 0xff,
+			u >> 8 & 0xff, u >> 16 & 0xff, u >> 24 & 0xff);
+	u = le16_to_cpu(m->usa_ofs);
+	printf("Update sequence array offset = %u (0x%x)\n", u, u);
+	printf("Update sequence array size = %u\n", le16_to_cpu(m->usa_count));
+	printf("$LogFile sequence number (lsn) = %llu\n",
+			(unsigned long long)le64_to_cpu(m->lsn));
+	printf("Sequence number = %u\n", le16_to_cpu(m->sequence_number));
+	printf("Reference (hard link) count = %u\n",
+						le16_to_cpu(m->link_count));
+	u = le16_to_cpu(m->attrs_offset);
+	printf("First attribute offset = %u (0x%x)\n", u, u);
+	printf("Flags = %u: ", le16_to_cpu(m->flags));
+	if (m->flags & MFT_RECORD_IN_USE)
+		printf("MFT_RECORD_IN_USE");
+	else
+		printf("MFT_RECORD_NOT_IN_USE");
+	if (m->flags & MFT_RECORD_IS_DIRECTORY)
+		printf(" | MFT_RECORD_IS_DIRECTORY");
+	printf("\n");
+	u = le32_to_cpu(m->bytes_in_use);
+	printf("Bytes in use = %u (0x%x)\n", u, u);
+	u = le32_to_cpu(m->bytes_allocated);
+	printf("Bytes allocated = %u (0x%x)\n", u, u);
+	r = le64_to_cpu(m->base_mft_record);
+	printf("Base mft record reference:\n\tMft record number = %llu\n\t"
+			"Sequence number = %u\n",
+			(unsigned long long)MREF(r), MSEQNO(r));
+	printf("Next attribute instance = %u\n",
+			le16_to_cpu(m->next_attr_instance));
+	a = (ATTR_RECORD*)((char*)m + le16_to_cpu(m->attrs_offset));
+	printf("-- Beginning dump of attributes within mft record. --\n");
+	while ((char*)a < (char*)m + le32_to_cpu(m->bytes_in_use)) {
+		if (a->type == cpu_to_le32(attr_type))
+			dump_attr_record(m, a);
+		if (a->type == AT_END)
+			break;
+		a = (ATTR_RECORD*)((char*)a + le32_to_cpu(a->length));
+	};
+	printf("-- End of attributes. --\n");
+}
+
+/**
+ * ntfstruncate_exit
+ */
+static void ntfstruncate_exit(void)
+{
+	int err;
+
+	if (success)
+		return;
+	/* Close the attribute. */
+	if (na)
+		ntfs_attr_close(na);
+	/* Close the inode. */
+	if (ni && ntfs_inode_close(ni)) {
+		ntfs_log_perror("Warning: Failed to close inode %lli",
+				(long long)inode);
+	}
+	/* Unmount the volume. */
+	err = ntfs_umount(vol, 0);
+	if (err == -1)
+		ntfs_log_perror("Warning: Could not umount %s", dev_name);
+	/* Free the attribute name if it exists. */
+	ntfs_ucsfree(attr_name);
+}
+
+/**
+ * main
+ */
+int main(int argc, char **argv)
+{
+	unsigned long mnt_flags, ul;
+	int err;
+
+	ntfs_log_set_handler(ntfs_log_handler_outerr);
+
+	/* Initialize opts to zero / required values. */
+	memset(&opts, 0, sizeof(opts));
+
+	/*
+	 * Setup a default $AttrDef. FIXME: Should be reading this from the
+	 * volume itself, at ntfs_mount() time.
+	 */
+	attr_defs = (ATTR_DEF*)&attrdef_ntfs3x_array;
+
+	/* Parse command line options. */
+	parse_options(argc, argv);
+
+	utils_set_locale();
+
+	/* Make sure the file system is not mounted. */
+	if (ntfs_check_if_mounted(dev_name, &mnt_flags))
+		ntfs_log_perror("Failed to determine whether %s is mounted",
+				dev_name);
+	else if (mnt_flags & NTFS_MF_MOUNTED) {
+		ntfs_log_error("%s is mounted.\n", dev_name);
+		if (!opts.force)
+			err_exit("Refusing to run!\n");
+		fprintf(stderr, "ntfstruncate forced anyway. Hope /etc/mtab "
+				"is incorrect.\n");
+	}
+
+	/* Mount the device. */
+	if (opts.no_action) {
+		ntfs_log_quiet("Running in READ-ONLY mode!\n");
+		ul = NTFS_MNT_RDONLY;
+	} else
+		ul = 0;
+	vol = ntfs_mount(dev_name, ul);
+	if (!vol)
+		err_exit("Failed to mount %s: %s\n", dev_name, strerror(errno));
+
+	/* Register our exit function which will unlock and close the device. */
+	err = atexit(&ntfstruncate_exit);
+	if (err == -1) {
+		ntfs_log_error("Could not set up exit() function because atexit() "
+				"failed: %s Aborting...\n", strerror(errno));
+		ntfstruncate_exit();
+		exit(1);
+	}
+
+	/* Open the specified inode. */
+	ni = ntfs_inode_open(vol, inode);
+	if (!ni)
+		err_exit("Failed to open inode %lli: %s\n", (long long)inode,
+				strerror(errno));
+
+	/* Open the specified attribute. */
+	na = ntfs_attr_open(ni, attr_type, attr_name, attr_name_len);
+	if (!na)
+		err_exit("Failed to open attribute 0x%x: %s\n",
+				(unsigned int)attr_type, strerror(errno));
+
+	if (!opts.quiet && opts.verbose > 1) {
+		ntfs_log_verbose("Dumping mft record before calling "
+				"ntfs_attr_truncate():\n");
+		dump_mft_record(ni->mrec);
+	}
+
+	/* Truncate the attribute. */
+	err = ntfs_attr_truncate(na, new_len);
+	if (err)
+		err_exit("Failed to truncate attribute 0x%x: %s\n",
+				(unsigned int)attr_type, strerror(errno));
+
+	if (!opts.quiet && opts.verbose > 1) {
+		ntfs_log_verbose("Dumping mft record after calling "
+				"ntfs_attr_truncate():\n");
+		dump_mft_record(ni->mrec);
+	}
+
+	/* Close the attribute. */
+	ntfs_attr_close(na);
+	na = NULL;
+
+	/* Close the inode. */
+	err = ntfs_inode_close(ni);
+	if (err)
+		err_exit("Failed to close inode %lli: %s\n", (long long)inode,
+				strerror(errno));
+
+	/* Unmount the volume. */
+	err = ntfs_umount(vol, 0);
+	if (err == -1)
+		ntfs_log_perror("Warning: Failed to umount %s", dev_name);
+
+	/* Free the attribute name if it exists. */
+	ntfs_ucsfree(attr_name);
+
+	/* Finally, disable our ntfstruncate_exit() handler. */
+	success = TRUE;
+
+	ntfs_log_quiet("ntfstruncate completed successfully. Have a nice day.\n");
+	return 0;
+}
diff --git a/ntfsprogs/ntfsundelete.8 b/ntfsprogs/ntfsundelete.8
new file mode 100755
index 0000000000000000000000000000000000000000..91df57e87c27fcee7ecc4c2cbd5355581b42b9ce
--- /dev/null
+++ b/ntfsprogs/ntfsundelete.8
@@ -0,0 +1,324 @@
+.\" Copyright (c) 2002\-2005 Richard Russon.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSUNDELETE 8 "November 2005" "ntfs-3g 2015.3.14"
+.SH NAME
+ntfsundelete \- recover a deleted file from an NTFS volume.
+.SH SYNOPSIS
+.B ntfsundelete
+[\fIoptions\fR] \fIdevice\fR
+.SH DESCRIPTION
+.B ntfsundelete
+has three modes of operation:
+.IR scan ,
+.I undelete
+and
+.IR copy .
+.SS Scan
+.PP
+The default mode,
+.I scan
+simply reads an NTFS Volume and looks for files that have been deleted.  Then it
+will print a list giving the inode number, name and size.
+.SS Undelete
+.PP
+The
+.I undelete
+mode takes the files either matching the regular expression (option \-m)
+or  specified by the inode\-expressions and recovers as much of the data
+as possible.   It saves the result to another location.  Partly for
+safety, but mostly because NTFS write support isn't finished.
+.SS Copy
+.PP
+This is a wizard's option.  It will save a portion of the MFT to a file.  This
+probably only be useful when debugging
+.I ntfsundelete
+.SS Notes
+.B ntfsundelete
+only ever
+.B reads
+from the NTFS Volume.
+.B ntfsundelete
+will never change the volume.
+.SH CAVEATS
+.SS Miracles
+.B ntfsundelete
+cannot perform the impossible.
+.PP
+When a file is deleted the MFT Record is marked as not in use and the bitmap
+representing the disk usage is updated.  If the power isn't turned off
+immediately, the free space, where the file used to live, may become
+overwritten.  Worse, the MFT Record may be reused for another file.  If this
+happens it is impossible to tell where the file was on disk.
+.PP
+Even if all the clusters of a file are not in use, there is no guarantee that
+they haven't been overwritten by some short\-lived file.
+.SS Locale
+In NTFS all the filenames are stored as Unicode.  They will be converted into
+the current locale for display by
+.BR ntfsundelete .
+The utility has successfully displayed some Chinese pictogram filenames and then
+correctly recovered them.
+.SS Extended MFT Records
+In rare circumstances, a single MFT Record will not be large enough to hold the
+metadata describing a file (a file would have to be in hundreds of fragments
+for this to happen).  In these cases one MFT record may hold the filename, but
+another will hold the information about the data.
+.B ntfsundelete
+will not try and piece together such records.  It will simply show unnamed files
+with data.
+.SS Compressed and Encrypted Files
+.B ntfsundelete
+cannot recover compressed or encrypted files.  When scanning for them, it will
+display as being 0% recoverable.
+.SS The Recovered File's Size and Date
+To recover a file
+.B ntfsundelete
+has to read the file's metadata.  Unfortunately, this isn't always intact.
+When a file is deleted, the metadata can be left in an inconsistent state. e.g.
+the file size may be zero; the dates of the file may be set to the time it was
+deleted, or random.
+.br
+To be safe
+.B ntfsundelete
+will pick the largest file size it finds and write that to disk.  It will also
+try and set the file's date to the last modified date.  This date may be the
+correct last modified date, or something unexpected.
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfsundelete
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-b\fR, \fB\-\-byte\fR NUM
+If any clusters of the file cannot be recovered, the missing parts will be
+filled with this byte.  The default is zeros.
+.TP
+\fB\-C\fR, \fB\-\-case\fR
+When scanning an NTFS volume, any filename matching (using the
+.B \-\-match
+option) is case\-insensitive.  This option makes the matching case\-sensitive.
+.TP
+\fB\-c\fR, \fB\-\-copy\fR RANGE
+This wizard's option will write a block of MFT FILE records to a file.  The
+default file is
+.I mft
+which will be created in the current directory.  This option can be combined
+with the
+.B \-\-output
+and
+.B \-\-destination
+options.
+.TP
+\fB\-d\fR, \fB\-\-destination\fR DIR
+This option controls where to put the output file of the
+.B \-\-undelete
+and
+.B \-\-copy
+options.
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+This will override some sensible defaults, such as not overwriting an existing
+file.  Use this option with caution.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.TP
+\fB\-i\fR, \fB\-\-inodes\fR RANGE
+Recover the files with these inode numbers.
+.I RANGE
+can be a single inode number, several numbers separated by commas "," or a
+range separated by a dash "\-".
+.TP
+\fB\-m\fR, \fB\-\-match\fR PATTERN
+Filter the output by only looking for matching filenames.  The pattern can
+include the wildcards '?', match exactly one character or '*', match zero or
+more characters.  By default the matching is case\-insensitive.  To make the
+search case sensitive, use the
+.B \-\-case
+option.
+.TP
+\fB\-O\fR, \fB\-\-optimistic\fR
+Recover parts of the file even if they are currently marked as in use.
+.TP
+\fB\-o\fR, \fB\-\-output\fR FILE
+Use this option to set name of output file that
+.B \-\-undelete
+or
+.B \-\-copy
+will create.
+.TP
+\fB\-P\fR, \fB\-\-parent\fR
+Display the parent directory of a deleted file.
+.TP
+\fB\-p\fR, \fB\-\-percentage\fR NUM
+Filter the output of the
+.B \-\-scan
+option, by only matching files with a certain amount of recoverable content.
+.B Please read the caveats section for more details.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Reduce the amount of output to a minimum.  Naturally, it doesn't make sense to
+combine this option with
+.BR \-\-scan .
+.TP
+\fB\-s\fR, \fB\-\-scan\fR
+Search through an NTFS volume and print a list of files that could be recovered.
+This is the default action of
+.BR ntfsundelete .
+This list can be filtered by filename, size, percentage recoverable or last
+modification time, using the
+.BR \-\-match ,
+.BR \-\-size ,
+.B \-\-percent
+and
+.B \-\-time
+options, respectively.
+.sp
+The output of scan will be:
+.sp
+.nf
+Inode  Flags  %age     Date    Time    Size  Filename
+ 6038  FN..    93%  2002\-07\-17 13:42  26629  thesis.doc
+.fi
+.TS
+box;
+lB lB
+l l.
+Flag	Description
+F/D	File/Directory
+N/R	(Non\-)Resident data stream
+C/E	Compressed/Encrypted data stream
+!	Missing attributes
+.TE
+.sp
+.sp
+The percentage field shows how much of the file can potentially be recovered.
+.TP
+\fB\-S\fR, \fB\-\-size\fR RANGE
+Filter the output of the
+.B \-\-scan
+option, by looking for a particular range of file sizes.  The range may be
+specified as two numbers separated by a '\-'.  The sizes may be abbreviated
+using the suffixes k, m, g, t, for kilobytes, megabytes, gigabytes and terabytes
+respectively.
+.TP
+\fB\-t\fR, \fB\-\-time\fR SINCE
+Filter the output of the
+.B \-\-scan
+option.  Only match files that have been altered since this time.  The time must
+be given as number using a suffix of d, w, m, y for days, weeks, months or years
+ago.
+.TP
+\fB\-T\fR, \fB\-\-truncate\fR
+If
+.B ntfsundelete
+is confident about the size of a deleted file, then it will restore the file to
+exactly that size.  The default behaviour is to round up the size to the nearest
+cluster (which will be a multiple of 512 bytes).
+.TP
+\fB\-u\fR, \fB\-\-undelete\fR
+Select
+.B undelete
+mode.  You can specify the files to be recovered using by using
+.B \-\-match
+or
+.B \-\-inodes
+options.  This option can be combined with
+.BR \-\-output ,
+.BR \-\-destination ,
+and
+.BR \-\-byte .
+.sp
+When the file is recovered it will be given its original name, unless the
+.B \-\-output
+option is used.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Increase the amount of output that
+.B ntfsundelete
+prints.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Show the version number, copyright and license for
+.BR ntfsundelete .
+.SH EXAMPLES
+Look for deleted files on /dev/hda1.
+.RS
+.sp
+.B ntfsundelete /dev/hda1
+.sp
+.RE
+Look for deleted documents on /dev/hda1.
+.RS
+.sp
+.B ntfsundelete /dev/hda1 \-s \-m '*.doc'
+.sp
+.RE
+Look for deleted files between 5000 and 6000000 bytes, with at least 90% of the
+data recoverable, on /dev/hda1.
+.RS
+.sp
+.B ntfsundelete /dev/hda1 \-S 5k\-6m \-p 90
+.sp
+.RE
+Look for deleted files altered in the last two days
+.RS
+.sp
+.B ntfsundelete /dev/hda1 \-t 2d
+.sp
+.RE
+Undelete inodes 2, 5 and 100 to 131 of device /dev/sda1
+.RS
+.sp
+.B ntfsundelete /dev/sda1 \-u \-i 2,5,100\-131
+.sp
+.RE
+Undelete inode number 3689, call the file 'work.doc', set it to recovered
+size and put it in the user's home directory.
+.RS
+.sp
+.B ntfsundelete /dev/hda1 \-u \-T \-i 3689 \-o work.doc \-d ~
+.sp
+.RE
+Save MFT Records 3689 to 3690 to a file 'debug'
+.RS
+.sp
+.B ntfsundelete /dev/hda1 \-c 3689\-3690 \-o debug
+.sp
+.RE
+.SH BUGS
+There are some small limitations to
+.BR ntfsundelete ,
+but currently no known bugs.  If you find a bug please send an email describing
+the problem to the development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+.B ntfsundelete
+was written by Richard Russon and Holger Ohmacht, with contributions from Anton
+Altaparmakov.
+It was ported to ntfs-3g by Erik Larsson and Jean-Pierre Andre.
+.SH AVAILABILITY
+.B ntfsundelete
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR ntfsinfo (8),
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/ntfsundelete.8.in b/ntfsprogs/ntfsundelete.8.in
new file mode 100755
index 0000000000000000000000000000000000000000..f80a4d75fec6554722ab98632360c6654d18c6b7
--- /dev/null
+++ b/ntfsprogs/ntfsundelete.8.in
@@ -0,0 +1,324 @@
+.\" Copyright (c) 2002\-2005 Richard Russon.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSUNDELETE 8 "November 2005" "ntfs-3g @VERSION@"
+.SH NAME
+ntfsundelete \- recover a deleted file from an NTFS volume.
+.SH SYNOPSIS
+.B ntfsundelete
+[\fIoptions\fR] \fIdevice\fR
+.SH DESCRIPTION
+.B ntfsundelete
+has three modes of operation:
+.IR scan ,
+.I undelete
+and
+.IR copy .
+.SS Scan
+.PP
+The default mode,
+.I scan
+simply reads an NTFS Volume and looks for files that have been deleted.  Then it
+will print a list giving the inode number, name and size.
+.SS Undelete
+.PP
+The
+.I undelete
+mode takes the files either matching the regular expression (option \-m)
+or  specified by the inode\-expressions and recovers as much of the data
+as possible.   It saves the result to another location.  Partly for
+safety, but mostly because NTFS write support isn't finished.
+.SS Copy
+.PP
+This is a wizard's option.  It will save a portion of the MFT to a file.  This
+probably only be useful when debugging
+.I ntfsundelete
+.SS Notes
+.B ntfsundelete
+only ever
+.B reads
+from the NTFS Volume.
+.B ntfsundelete
+will never change the volume.
+.SH CAVEATS
+.SS Miracles
+.B ntfsundelete
+cannot perform the impossible.
+.PP
+When a file is deleted the MFT Record is marked as not in use and the bitmap
+representing the disk usage is updated.  If the power isn't turned off
+immediately, the free space, where the file used to live, may become
+overwritten.  Worse, the MFT Record may be reused for another file.  If this
+happens it is impossible to tell where the file was on disk.
+.PP
+Even if all the clusters of a file are not in use, there is no guarantee that
+they haven't been overwritten by some short\-lived file.
+.SS Locale
+In NTFS all the filenames are stored as Unicode.  They will be converted into
+the current locale for display by
+.BR ntfsundelete .
+The utility has successfully displayed some Chinese pictogram filenames and then
+correctly recovered them.
+.SS Extended MFT Records
+In rare circumstances, a single MFT Record will not be large enough to hold the
+metadata describing a file (a file would have to be in hundreds of fragments
+for this to happen).  In these cases one MFT record may hold the filename, but
+another will hold the information about the data.
+.B ntfsundelete
+will not try and piece together such records.  It will simply show unnamed files
+with data.
+.SS Compressed and Encrypted Files
+.B ntfsundelete
+cannot recover compressed or encrypted files.  When scanning for them, it will
+display as being 0% recoverable.
+.SS The Recovered File's Size and Date
+To recover a file
+.B ntfsundelete
+has to read the file's metadata.  Unfortunately, this isn't always intact.
+When a file is deleted, the metadata can be left in an inconsistent state. e.g.
+the file size may be zero; the dates of the file may be set to the time it was
+deleted, or random.
+.br
+To be safe
+.B ntfsundelete
+will pick the largest file size it finds and write that to disk.  It will also
+try and set the file's date to the last modified date.  This date may be the
+correct last modified date, or something unexpected.
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfsundelete
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-b\fR, \fB\-\-byte\fR NUM
+If any clusters of the file cannot be recovered, the missing parts will be
+filled with this byte.  The default is zeros.
+.TP
+\fB\-C\fR, \fB\-\-case\fR
+When scanning an NTFS volume, any filename matching (using the
+.B \-\-match
+option) is case\-insensitive.  This option makes the matching case\-sensitive.
+.TP
+\fB\-c\fR, \fB\-\-copy\fR RANGE
+This wizard's option will write a block of MFT FILE records to a file.  The
+default file is
+.I mft
+which will be created in the current directory.  This option can be combined
+with the
+.B \-\-output
+and
+.B \-\-destination
+options.
+.TP
+\fB\-d\fR, \fB\-\-destination\fR DIR
+This option controls where to put the output file of the
+.B \-\-undelete
+and
+.B \-\-copy
+options.
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+This will override some sensible defaults, such as not overwriting an existing
+file.  Use this option with caution.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.TP
+\fB\-i\fR, \fB\-\-inodes\fR RANGE
+Recover the files with these inode numbers.
+.I RANGE
+can be a single inode number, several numbers separated by commas "," or a
+range separated by a dash "\-".
+.TP
+\fB\-m\fR, \fB\-\-match\fR PATTERN
+Filter the output by only looking for matching filenames.  The pattern can
+include the wildcards '?', match exactly one character or '*', match zero or
+more characters.  By default the matching is case\-insensitive.  To make the
+search case sensitive, use the
+.B \-\-case
+option.
+.TP
+\fB\-O\fR, \fB\-\-optimistic\fR
+Recover parts of the file even if they are currently marked as in use.
+.TP
+\fB\-o\fR, \fB\-\-output\fR FILE
+Use this option to set name of output file that
+.B \-\-undelete
+or
+.B \-\-copy
+will create.
+.TP
+\fB\-P\fR, \fB\-\-parent\fR
+Display the parent directory of a deleted file.
+.TP
+\fB\-p\fR, \fB\-\-percentage\fR NUM
+Filter the output of the
+.B \-\-scan
+option, by only matching files with a certain amount of recoverable content.
+.B Please read the caveats section for more details.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Reduce the amount of output to a minimum.  Naturally, it doesn't make sense to
+combine this option with
+.BR \-\-scan .
+.TP
+\fB\-s\fR, \fB\-\-scan\fR
+Search through an NTFS volume and print a list of files that could be recovered.
+This is the default action of
+.BR ntfsundelete .
+This list can be filtered by filename, size, percentage recoverable or last
+modification time, using the
+.BR \-\-match ,
+.BR \-\-size ,
+.B \-\-percent
+and
+.B \-\-time
+options, respectively.
+.sp
+The output of scan will be:
+.sp
+.nf
+Inode  Flags  %age     Date    Time    Size  Filename
+ 6038  FN..    93%  2002\-07\-17 13:42  26629  thesis.doc
+.fi
+.TS
+box;
+lB lB
+l l.
+Flag	Description
+F/D	File/Directory
+N/R	(Non\-)Resident data stream
+C/E	Compressed/Encrypted data stream
+!	Missing attributes
+.TE
+.sp
+.sp
+The percentage field shows how much of the file can potentially be recovered.
+.TP
+\fB\-S\fR, \fB\-\-size\fR RANGE
+Filter the output of the
+.B \-\-scan
+option, by looking for a particular range of file sizes.  The range may be
+specified as two numbers separated by a '\-'.  The sizes may be abbreviated
+using the suffixes k, m, g, t, for kilobytes, megabytes, gigabytes and terabytes
+respectively.
+.TP
+\fB\-t\fR, \fB\-\-time\fR SINCE
+Filter the output of the
+.B \-\-scan
+option.  Only match files that have been altered since this time.  The time must
+be given as number using a suffix of d, w, m, y for days, weeks, months or years
+ago.
+.TP
+\fB\-T\fR, \fB\-\-truncate\fR
+If
+.B ntfsundelete
+is confident about the size of a deleted file, then it will restore the file to
+exactly that size.  The default behaviour is to round up the size to the nearest
+cluster (which will be a multiple of 512 bytes).
+.TP
+\fB\-u\fR, \fB\-\-undelete\fR
+Select
+.B undelete
+mode.  You can specify the files to be recovered using by using
+.B \-\-match
+or
+.B \-\-inodes
+options.  This option can be combined with
+.BR \-\-output ,
+.BR \-\-destination ,
+and
+.BR \-\-byte .
+.sp
+When the file is recovered it will be given its original name, unless the
+.B \-\-output
+option is used.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Increase the amount of output that
+.B ntfsundelete
+prints.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Show the version number, copyright and license for
+.BR ntfsundelete .
+.SH EXAMPLES
+Look for deleted files on /dev/hda1.
+.RS
+.sp
+.B ntfsundelete /dev/hda1
+.sp
+.RE
+Look for deleted documents on /dev/hda1.
+.RS
+.sp
+.B ntfsundelete /dev/hda1 \-s \-m '*.doc'
+.sp
+.RE
+Look for deleted files between 5000 and 6000000 bytes, with at least 90% of the
+data recoverable, on /dev/hda1.
+.RS
+.sp
+.B ntfsundelete /dev/hda1 \-S 5k\-6m \-p 90
+.sp
+.RE
+Look for deleted files altered in the last two days
+.RS
+.sp
+.B ntfsundelete /dev/hda1 \-t 2d
+.sp
+.RE
+Undelete inodes 2, 5 and 100 to 131 of device /dev/sda1
+.RS
+.sp
+.B ntfsundelete /dev/sda1 \-u \-i 2,5,100\-131
+.sp
+.RE
+Undelete inode number 3689, call the file 'work.doc', set it to recovered
+size and put it in the user's home directory.
+.RS
+.sp
+.B ntfsundelete /dev/hda1 \-u \-T \-i 3689 \-o work.doc \-d ~
+.sp
+.RE
+Save MFT Records 3689 to 3690 to a file 'debug'
+.RS
+.sp
+.B ntfsundelete /dev/hda1 \-c 3689\-3690 \-o debug
+.sp
+.RE
+.SH BUGS
+There are some small limitations to
+.BR ntfsundelete ,
+but currently no known bugs.  If you find a bug please send an email describing
+the problem to the development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+.B ntfsundelete
+was written by Richard Russon and Holger Ohmacht, with contributions from Anton
+Altaparmakov.
+It was ported to ntfs-3g by Erik Larsson and Jean-Pierre Andre.
+.SH AVAILABILITY
+.B ntfsundelete
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR ntfsinfo (8),
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/ntfsundelete.c b/ntfsprogs/ntfsundelete.c
new file mode 100755
index 0000000000000000000000000000000000000000..7340dc5053f56e7ee7c1b37119c23cd343c9c2b3
--- /dev/null
+++ b/ntfsprogs/ntfsundelete.c
@@ -0,0 +1,2495 @@
+/**
+ * ntfsundelete - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2002-2005 Richard Russon
+ * Copyright (c) 2004-2005 Holger Ohmacht
+ * Copyright (c) 2005      Anton Altaparmakov
+ * Copyright (c) 2007      Yura Pakhuchiy
+ * Copyright (c) 2013-2014 Jean-Pierre Andre
+ *
+ * This utility will recover deleted files from an NTFS volume.
+ *
+ * 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 Linux-NTFS
+ * 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_FEATURES_H
+#include <features.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_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+#ifdef HAVE_UTIME_H
+#include <utime.h>
+#endif
+#ifdef HAVE_REGEX_H
+#include <regex.h>
+#endif
+
+#if !defined(REG_NOERROR) || (REG_NOERROR != 0)
+#define REG_NOERROR 0
+#endif
+
+#ifndef REG_NOMATCH
+#define REG_NOMATCH 1
+#endif
+
+#include "ntfsundelete.h"
+#include "bootsect.h"
+#include "mft.h"
+#include "attrib.h"
+#include "layout.h"
+#include "inode.h"
+#include "device.h"
+#include "utils.h"
+#include "debug.h"
+#include "ntfstime.h"
+/* #include "version.h" */
+#include "logging.h"
+#include "misc.h"
+
+#ifdef HAVE_WINDOWS_H
+/*
+ *		Replacements for functions which do not exist on Windows
+ */
+#define ftruncate(fd, size) ntfs_win32_ftruncate(fd, size)
+#endif
+
+static const char *EXEC_NAME = "ntfsundelete";
+static const char *MFTFILE   = "mft";
+static const char *UNNAMED   = "<unnamed>";
+static const char *NONE      = "<none>";
+static const char *UNKNOWN   = "unknown";
+static struct options opts;
+
+typedef struct
+{
+	u32 begin;
+	u32 end;
+} range;
+
+static short	with_regex;			/* Flag  Regular expression available */
+static short	avoid_duplicate_printing;	/* Flag  No duplicate printing of file infos */
+static range	*ranges;			/* Array containing all Inode-Ranges for undelete */
+static long	nr_entries;			/* Number of range entries */
+
+#ifdef HAVE_WINDOWS_H
+/*
+ *		Replacement for strftime() on Windows
+ *
+ *	strftime() on Windows uses format codes different from those
+ *	defined in C99 sect. 7.23.3.5
+ *	Use snprintf() instead.
+ */
+static int win32_strftime(char *buffer, int size, const char *format,
+					const struct tm *ptm)
+{
+	int ret;
+
+	if (!strcmp(format, "%F %R"))
+		ret = snprintf(buffer, size, "%4d-%02d-%02d %02d:%02d",
+			ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday,
+			ptm->tm_hour, ptm->tm_min);
+	else
+		ret = snprintf(buffer, size, "%4d-%02d-%02d",
+			ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday);
+	return (ret);
+}
+#define strftime(buf, sz, fmt, ptm) win32_strftime(buf, sz, fmt, ptm)
+#endif
+
+#ifndef HAVE_REGEX_H
+
+/*
+ *		Pattern matching routing for systems with no regex.
+ */
+
+typedef struct REGEX {
+	ntfschar *upcase;
+	u32 upcase_len;
+	int flags;
+	int pattern_len;
+	ntfschar pattern[1];
+} *regex_t;
+
+enum { REG_NOSUB = 1, REG_ICASE = 2 };
+
+static BOOL patmatch(regex_t *re, const ntfschar *f, int flen,
+			const ntfschar *p, int plen, BOOL dot)
+{
+	regex_t pre;
+	BOOL ok;
+	BOOL anyextens;
+	int i;
+	unsigned int c;
+
+	pre = *re;
+	if (pre->flags & REG_ICASE) {
+		while ((flen > 0) && (plen > 0)
+		    && ((*f == *p)
+			|| (*p == const_cpu_to_le16('?'))
+			|| ((c = le16_to_cpu(*f)) < pre->upcase_len
+				? pre->upcase[c] : *f) == *p)) {
+			flen--;
+			if (*f++ == const_cpu_to_le16('.'))
+				dot = TRUE;
+			plen--;
+			p++;
+		}
+	} else {
+		while ((flen > 0) && (plen > 0)
+		    && ((*f == *p) || (*p == const_cpu_to_le16('?')))) {
+			flen--;
+			if (*f++ == const_cpu_to_le16('.'))
+				dot = TRUE;
+			plen--;
+			p++;
+		}
+	}
+	if ((flen <= 0) && (plen <= 0))
+		ok = TRUE;
+	else {
+		ok = FALSE;
+		plen--;
+		if (*p++ == const_cpu_to_le16('*')) {
+			/* special case "*.*" requires the end or a dot */
+			anyextens = FALSE;
+			if ((plen == 2)
+			    && (p[0] == const_cpu_to_le16('.'))
+			    && (p[1] == const_cpu_to_le16('*'))
+			    && !dot) {
+				for (i=0; (i<flen) && !anyextens; i++)
+					if (f[i] == const_cpu_to_le16('.'))
+						anyextens = TRUE;
+			}
+			if (!plen || anyextens)
+				ok = TRUE;
+			else
+				while ((flen > 0) && !ok)
+					if (patmatch(re,f,flen,p,plen,dot))
+						ok = TRUE;
+					else {
+						flen--;
+						f++;
+					}
+		}
+	}
+	return (ok);
+}
+
+static int regcomp(regex_t *re, const char *pattern, int flags)
+{
+	regex_t pre;
+	ntfschar *rp;
+	ntfschar *p;
+	unsigned int c;
+	int lth;
+	int i;
+
+	pre = (regex_t)malloc(sizeof(struct REGEX)
+			+ strlen(pattern)*sizeof(ntfschar));
+	*re = pre;
+	if (pre) {
+		pre->flags = flags;
+		pre->upcase_len = 0;
+		rp = pre->pattern;
+		lth = ntfs_mbstoucs(pattern, &rp);
+		pre->pattern_len = lth;
+		p = pre->pattern;
+		if (flags & REG_ICASE) {
+			for (i=0; i<lth; i++) {
+				c = le16_to_cpu(*p);
+				if (c < pre->upcase_len)
+					*p = pre->upcase[c];
+				p++;
+			}
+		}
+	}
+	return (*re && (lth > 0) ? 0 : -1);
+}
+
+static int regexec(regex_t *re, const ntfschar *uname, int len,
+		char *q __attribute__((unused)), int r __attribute__((unused)))
+{
+	BOOL m;
+
+	m = patmatch(re, uname, len, (*re)->pattern, (*re)->pattern_len, FALSE);
+	return (m ? REG_NOERROR : REG_NOMATCH);
+}
+
+static void regfree(regex_t *re)
+{
+	free(*re);
+}
+
+#endif
+
+/**
+ * parse_inode_arg - parses the inode expression
+ *
+ * Parses the optarg after parameter -u for valid ranges
+ *
+ * Return: Number of correct inode specifications or -1 for error
+ */
+static int parse_inode_arg(void)
+{
+	int p;
+	u32 range_begin;
+	u32 range_end;
+	u32 range_temp;
+	u32 inode;
+	char *opt_arg_ptr;
+	char *opt_arg_temp;
+	char *opt_arg_end1;
+	char *opt_arg_end2;
+
+	/* Check whether optarg is available or not */
+	nr_entries = 0;
+	if (optarg == NULL)
+		return (0);	/* bailout if no optarg */
+
+	/* init variables */
+	p = strlen(optarg);
+	opt_arg_ptr = optarg;
+	opt_arg_end1 = optarg;
+	opt_arg_end2 = &(optarg[p]);
+
+	/* alloc mem for range table */
+	ranges = (range *) malloc((p + 1) * sizeof(range));
+	if (ranges == NULL) {
+		ntfs_log_error("ERROR: Couldn't alloc mem for parsing inodes!\n");
+		return (-1);
+	}
+
+	/* loop */
+	while ((opt_arg_end1 != opt_arg_end2) && (p > 0)) {
+		/* Try to get inode */
+		inode = strtoul(opt_arg_ptr, &opt_arg_end1, 0);
+		p--;
+
+		/* invalid char at begin */
+		if ((opt_arg_ptr == opt_arg_end1) || (opt_arg_ptr == opt_arg_end2)) {
+			ntfs_log_error("ERROR: Invalid Number: %s\n", opt_arg_ptr);
+			return (-1);
+		}
+
+		/* RANGE - Check for range */
+		if (opt_arg_end1[0] == '-') {
+			/* get range end */
+			opt_arg_temp = opt_arg_end1;
+			opt_arg_end1 = & (opt_arg_temp[1]);
+			if (opt_arg_temp >= opt_arg_end2) {
+				ntfs_log_error("ERROR: Missing range end!\n");
+				return (-1);
+			}
+			range_begin = inode;
+
+			/* get count */
+			range_end = strtoul(opt_arg_end1, &opt_arg_temp, 0);
+			if (opt_arg_temp == opt_arg_end1) {
+				ntfs_log_error("ERROR: Invalid Number: %s\n", opt_arg_temp);
+				return (-1);
+			}
+
+			/* check for correct values */
+			if (range_begin > range_end) {
+				range_temp = range_end;
+				range_end = range_begin;
+				range_begin = range_temp;
+			}
+
+			/* put into struct */
+			ranges[nr_entries].begin = range_begin;
+			ranges[nr_entries].end = range_end;
+			nr_entries++;
+
+			/* Last check */
+			opt_arg_ptr = & (opt_arg_temp[1]);
+			if (opt_arg_ptr >= opt_arg_end2)
+				break;
+		} else if (opt_arg_end1[0] == ',') {
+			/* SINGLE VALUE, BUT CONTINUING */
+			/* put inode into range list */
+			ranges[nr_entries].begin = inode;
+			ranges[nr_entries].end = inode;
+			nr_entries++;
+
+			/* Next inode */
+			opt_arg_ptr = & (opt_arg_end1[1]);
+			if (opt_arg_ptr >= opt_arg_end2) {
+				ntfs_log_error("ERROR: Missing new value at end of input!\n");
+				return (-1);
+			}
+			continue;
+		} else { /* SINGLE VALUE, END */
+			ranges[nr_entries].begin = inode;
+			ranges[nr_entries].end = inode;
+			nr_entries++;
+		}
+	}
+	return (nr_entries);
+}
+
+/**
+ * version - Print version information about the program
+ *
+ * Print a copyright statement and a brief description of the program.
+ *
+ * Return:  none
+ */
+static void version(void)
+{
+	ntfs_log_info("\n%s v%s (libntfs-3g) - Recover deleted files from an "
+			"NTFS Volume.\n\n", EXEC_NAME, VERSION);
+	ntfs_log_info("Copyright (c) 2002-2005 Richard Russon\n"
+			"Copyright (c) 2004-2005 Holger Ohmacht\n"
+			"Copyright (c) 2005      Anton Altaparmakov\n"
+			"Copyright (c) 2007      Yura Pakhuchiy\n"
+			"Copyright (c) 2013-2014 Jean-Pierre Andre\n");
+	ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
+}
+
+/**
+ * usage - Print a list of the parameters to the program
+ *
+ * Print a list of the parameters and options for the program.
+ *
+ * Return:  none
+ */
+static void usage(void)
+{
+	ntfs_log_info("\nUsage: %s [options] device\n"
+		"    -s, --scan             Scan for files (default)\n"
+		"    -p, --percentage NUM   Minimum percentage recoverable\n"
+		"    -m, --match PATTERN    Only work on files with matching names\n"
+		"    -C, --case             Case sensitive matching\n"
+		"    -S, --size RANGE       Match files of this size\n"
+		"    -t, --time SINCE       Last referenced since this time\n"
+		"\n"
+		"    -u, --undelete         Undelete mode\n"
+		"    -i, --inodes RANGE     Recover these inodes\n"
+		//"    -I, --interactive      Interactive mode\n"
+		"    -o, --output FILE      Save with this filename\n"
+		"    -O, --optimistic       Undelete in-use clusters as well\n"
+		"    -d, --destination DIR  Destination directory\n"
+		"    -b, --byte NUM         Fill missing parts with this byte\n"
+		"    -T, --truncate         Truncate 100%% recoverable file to exact size.\n"
+		"    -P, --parent           Show parent directory\n"
+		"\n"
+		"    -c, --copy RANGE       Write a range of MFT records to a file\n"
+		"\n"
+		"    -f, --force            Use less caution\n"
+		"    -q, --quiet            Less output\n"
+		"    -v, --verbose          More output\n"
+		"    -V, --version          Display version information\n"
+		"    -h, --help             Display this help\n\n",
+		EXEC_NAME);
+	ntfs_log_info("%s%s\n", ntfs_bugs, ntfs_home);
+}
+
+/**
+ * transform - Convert a shell style pattern to a regex
+ * @pattern:  String to be converted
+ * @regex:    Resulting regular expression is put here
+ *
+ * This will transform patterns, such as "*.doc" to true regular expressions.
+ * The function will also place '^' and '$' around the expression to make it
+ * behave as the user would expect
+ *
+ * Before  After
+ *   .       \.
+ *   *       .*
+ *   ?       .
+ *
+ * Notes:
+ *     The returned string must be freed by the caller.
+ *     If transform fails, @regex will not be changed.
+ *
+ * Return:  1, Success, the string was transformed
+ *	    0, An error occurred
+ */
+static int transform(const char *pattern, char **regex)
+{
+	char *result;
+	int length, i;
+#ifdef HAVE_REGEX_H
+	int j;
+#endif
+
+	if (!pattern || !regex)
+		return 0;
+
+	length = strlen(pattern);
+	if (length < 1) {
+		ntfs_log_error("Pattern to transform is empty\n");
+		return 0;
+	}
+
+	for (i = 0; pattern[i]; i++) {
+		if ((pattern[i] == '*') || (pattern[i] == '.'))
+			length++;
+	}
+
+	result = malloc(length + 3);
+	if (!result) {
+		ntfs_log_error("Couldn't allocate memory in transform()\n");
+		return 0;
+	}
+
+#ifdef HAVE_REGEX_H
+	result[0] = '^';
+
+	for (i = 0, j = 1; pattern[i]; i++, j++) {
+		if (pattern[i] == '*') {
+			result[j] = '.';
+			j++;
+			result[j] = '*';
+		} else if (pattern[i] == '.') {
+			result[j] = '\\';
+			j++;
+			result[j] = '.';
+		} else if (pattern[i] == '?') {
+			result[j] = '.';
+		} else {
+			result[j] = pattern[i];
+		}
+	}
+
+	result[j]   = '$';
+	result[j+1] = 0;
+	ntfs_log_debug("Pattern '%s' replaced with regex '%s'.\n", pattern,
+			result);
+#else
+	strcpy(result, pattern);
+#endif
+
+	*regex = result;
+	return 1;
+}
+
+/**
+ * parse_time - Convert a time abbreviation to seconds
+ * @string:  The string to be converted
+ * @since:   The absolute time referred to
+ *
+ * Strings representing times will be converted into a time_t.  The numbers will
+ * be regarded as seconds unless suffixed.
+ *
+ * Suffix  Description
+ *  [yY]      Year
+ *  [mM]      Month
+ *  [wW]      Week
+ *  [dD]      Day
+ *  [sS]      Second
+ *
+ * Therefore, passing "1W" will return the time_t representing 1 week ago.
+ *
+ * Notes:
+ *     Only the first character of the suffix is read.
+ *     If parse_time fails, @since will not be changed
+ *
+ * Return:  1  Success
+ *	    0  Error, the string was malformed
+ */
+static int parse_time(const char *value, time_t *since)
+{
+	long long result;
+	time_t now;
+	char *suffix = NULL;
+
+	if (!value || !since)
+		return -1;
+
+	ntfs_log_trace("Parsing time '%s' ago.\n", value);
+
+	result = strtoll(value, &suffix, 10);
+	if (result < 0 || errno == ERANGE) {
+		ntfs_log_error("Invalid time '%s'.\n", value);
+		return 0;
+	}
+
+	if (!suffix) {
+		ntfs_log_error("Internal error, strtoll didn't return a suffix.\n");
+		return 0;
+	}
+
+	if (strlen(suffix) > 1) {
+		ntfs_log_error("Invalid time suffix '%s'.  Use Y, M, W, D or H.\n", suffix);
+		return 0;
+	}
+
+	switch (suffix[0]) {
+		case 'y': case 'Y': result *=   12;
+		case 'm': case 'M': result *=    4;
+		case 'w': case 'W': result *=    7;
+		case 'd': case 'D': result *=   24;
+		case 'h': case 'H': result *= 3600;
+		case 0:
+		    break;
+
+		default:
+			ntfs_log_error("Invalid time suffix '%s'.  Use Y, M, W, D or H.\n", suffix);
+			return 0;
+	}
+
+	now = time(NULL);
+
+	ntfs_log_debug("Time now = %lld, Time then = %lld.\n", (long long) now,
+			(long long) result);
+	*since = now - result;
+	return 1;
+}
+
+/**
+ * parse_options - Read and validate the programs command line
+ *
+ * Read the command line, verify the syntax and parse the options.
+ * This function is very long, but quite simple.
+ *
+ * Return:  1 Success
+ *	    0 Error, one or more problems
+ */
+static int parse_options(int argc, char *argv[])
+{
+	static const char *sopt = "-b:Cc:d:fh?i:m:o:OPp:sS:t:TuqvV";
+	static const struct option lopt[] = {
+		{ "byte",	 required_argument,	NULL, 'b' },
+		{ "case",	 no_argument,		NULL, 'C' },
+		{ "copy",	 required_argument,	NULL, 'c' },
+		{ "destination", required_argument,	NULL, 'd' },
+		{ "force",	 no_argument,		NULL, 'f' },
+		{ "help",	 no_argument,		NULL, 'h' },
+		{ "inodes",	 required_argument,	NULL, 'i' },
+		//{ "interactive", no_argument,		NULL, 'I' },
+		{ "match",	 required_argument,	NULL, 'm' },
+		{ "optimistic",  no_argument,		NULL, 'O' },
+		{ "output",	 required_argument,	NULL, 'o' },
+		{ "parent",	 no_argument,		NULL, 'P' },
+		{ "percentage",  required_argument,	NULL, 'p' },
+		{ "quiet",	 no_argument,		NULL, 'q' },
+		{ "scan",	 no_argument,		NULL, 's' },
+		{ "size",	 required_argument,	NULL, 'S' },
+		{ "time",	 required_argument,	NULL, 't' },
+		{ "truncate",	 no_argument,		NULL, 'T' },
+		{ "undelete",	 no_argument,		NULL, 'u' },
+		{ "verbose",	 no_argument,		NULL, 'v' },
+		{ "version",	 no_argument,		NULL, 'V' },
+		{ NULL, 0, NULL, 0 }
+	};
+
+	int c = -1;
+	char *end = NULL;
+	int err  = 0;
+	int ver  = 0;
+	int help = 0;
+	int levels = 0;
+
+	opterr = 0; /* We'll handle the errors, thank you. */
+
+	opts.mode     = MODE_NONE;
+	opts.uinode   = -1;
+	opts.percent  = -1;
+	opts.fillbyte = -1;
+	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
+		switch (c) {
+		case 1:	/* A non-option argument */
+			if (!opts.device) {
+				opts.device = argv[optind-1];
+			} else {
+				opts.device = NULL;
+				err++;
+			}
+			break;
+		case 'b':
+			if (opts.fillbyte == (char)-1) {
+				end = NULL;
+				opts.fillbyte = strtol(optarg, &end, 0);
+				if (end && *end)
+					err++;
+			} else {
+				err++;
+			}
+			break;
+		case 'C':
+			opts.match_case++;
+			break;
+		case 'c':
+			if (opts.mode == MODE_NONE) {
+				if (!utils_parse_range(optarg,
+				    &opts.mft_begin, &opts.mft_end, TRUE))
+					err++;
+				opts.mode = MODE_COPY;
+			} else {
+				opts.mode = MODE_ERROR;
+			}
+			break;
+		case 'd':
+			if (!opts.dest)
+				opts.dest = optarg;
+			else
+				err++;
+			break;
+		case 'f':
+			opts.force++;
+			break;
+		case 'h':
+			help++;
+			break;
+		case '?':
+			if (ntfs_log_parse_option (argv[optind-1]))
+				break;
+			ntfs_log_error("Unknown option '%s'.\n", argv[optind-1]);
+			err++;
+			break;
+		case 'i':
+			end = NULL;
+			/* parse inodes */
+			if (parse_inode_arg() == -1)
+				err++;
+			if (end && *end)
+				err++;
+			break;
+		case 'm':
+			if (!opts.match) {
+				if (!transform(optarg, &opts.match)) {
+					err++;
+				} else {
+					/* set regex-flag on true ;) */
+					with_regex= 1;
+				}
+			} else {
+				err++;
+			}
+			break;
+		case 'o':
+			if (!opts.output) {
+				opts.output = optarg;
+			} else {
+				err++;
+			}
+			break;
+		case 'O':
+			if (!opts.optimistic) {
+				opts.optimistic++;
+			} else {
+				err++;
+			}
+			break;
+		case 'P':
+			if (!opts.parent) {
+				opts.parent++;
+			} else {
+				err++;
+			}
+			break;
+		case 'p':
+			if (opts.percent == -1) {
+				end = NULL;
+				opts.percent = strtol(optarg, &end, 0);
+				if (end && ((*end != '%') && (*end != 0)))
+					err++;
+			} else {
+				err++;
+			}
+			break;
+		case 'q':
+			opts.quiet++;
+			ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
+			break;
+		case 's':
+			if (opts.mode == MODE_NONE)
+				opts.mode = MODE_SCAN;
+			else
+				opts.mode = MODE_ERROR;
+			break;
+		case 'S':
+			if ((opts.size_begin > 0) || (opts.size_end > 0) ||
+			    !utils_parse_range(optarg, &opts.size_begin,
+			     &opts.size_end, TRUE)) {
+			    err++;
+			}
+			break;
+		case 't':
+			if (opts.since == 0) {
+				if (!parse_time(optarg, &opts.since))
+					err++;
+			} else {
+			    err++;
+			}
+			break;
+		case 'T':
+			opts.truncate++;
+			break;
+		case 'u':
+			if (opts.mode == MODE_NONE) {
+				opts.mode = MODE_UNDELETE;
+			} else {
+				opts.mode = MODE_ERROR;
+			}
+			break;
+		case 'v':
+			opts.verbose++;
+			ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
+			break;
+		case 'V':
+			ver++;
+			break;
+		default:
+			if (((optopt == 'b') || (optopt == 'c') ||
+			     (optopt == 'd') || (optopt == 'm') ||
+			     (optopt == 'o') || (optopt == 'p') ||
+			     (optopt == 'S') || (optopt == 't') ||
+			     (optopt == 'u')) && (!optarg)) {
+				ntfs_log_error("Option '%s' requires an argument.\n", argv[optind-1]);
+			} else {
+				ntfs_log_error("Unknown option '%s'.\n", argv[optind-1]);
+			}
+			err++;
+			break;
+		}
+	}
+
+	/* Make sure we're in sync with the log levels */
+	levels = ntfs_log_get_levels();
+	if (levels & NTFS_LOG_LEVEL_VERBOSE)
+		opts.verbose++;
+	if (!(levels & NTFS_LOG_LEVEL_QUIET))
+		opts.quiet++;
+
+	if (help || ver) {
+		opts.quiet = 0;
+	} else {
+		if (opts.device == NULL) {
+			if (argc > 1)
+				ntfs_log_error("You must specify exactly one device.\n");
+			err++;
+		}
+
+		if (opts.mode == MODE_NONE) {
+			opts.mode = MODE_SCAN;
+		}
+
+		switch (opts.mode) {
+		case MODE_SCAN:
+			if (opts.output || opts.dest || opts.truncate ||
+					(opts.fillbyte != (char)-1)) {
+				ntfs_log_error("Scan can only be used with --percent, "
+					"--match, --ignore-case, --size and --time.\n");
+				err++;
+			}
+			if (opts.match_case && !opts.match) {
+				ntfs_log_error("The --case option doesn't make sense without the --match option\n");
+				err++;
+			}
+			break;
+
+		case MODE_UNDELETE:
+			/*if ((opts.percent != -1) || (opts.size_begin > 0) || (opts.size_end > 0)) {
+				ntfs_log_error("Undelete can only be used with "
+					"--output, --destination, --byte and --truncate.\n");
+				err++;
+			}*/
+			break;
+		case MODE_COPY:
+			if ((opts.fillbyte != (char)-1) || opts.truncate ||
+			    (opts.percent != -1) ||
+			    opts.match || opts.match_case ||
+			    (opts.size_begin > 0) ||
+			    (opts.size_end > 0)) {
+				ntfs_log_error("Copy can only be used with --output and --destination.\n");
+				err++;
+			}
+			break;
+		default:
+			ntfs_log_error("You can only select one of Scan, Undelete or Copy.\n");
+			err++;
+		}
+
+		if ((opts.percent < -1) || (opts.percent > 100)) {
+			ntfs_log_error("Percentage value must be in the range 0 - 100.\n");
+			err++;
+		}
+
+		if (opts.quiet) {
+			if (opts.verbose) {
+				ntfs_log_error("You may not use --quiet and --verbose at the same time.\n");
+				err++;
+			} else if (opts.mode == MODE_SCAN) {
+				ntfs_log_error("You may not use --quiet when scanning a volume.\n");
+				err++;
+			}
+		}
+
+		if (opts.parent && !opts.verbose) {
+			ntfs_log_error("To use --parent, you must also use --verbose.\n");
+			err++;
+		}
+	}
+
+	if (opts.fillbyte == (char)-1)
+		opts.fillbyte = 0;
+
+	if (ver)
+		version();
+	if (help || err)
+		usage();
+
+		/* tri-state 0 : done, 1 : error, -1 : proceed */
+	return (err ? 1 : (help || ver ? 0 : -1));
+}
+
+/**
+ * free_file - Release the resources used by a file object
+ * @file:  The unwanted file object
+ *
+ * This will free up the memory used by a file object and iterate through the
+ * object's children, freeing their resources too.
+ *
+ * Return:  none
+ */
+static void free_file(struct ufile *file)
+{
+	struct ntfs_list_head *item, *tmp;
+
+	if (!file)
+		return;
+
+	ntfs_list_for_each_safe(item, tmp, &file->name) {
+		/* List of filenames */
+		struct filename *f = ntfs_list_entry(item, struct filename, list);
+		ntfs_log_debug("freeing filename '%s'", f->name ? f->name :
+				NONE);
+		if (f->name)
+			free(f->name);
+		if (f->parent_name) {
+			ntfs_log_debug(" and parent filename '%s'",
+					f->parent_name);
+			free(f->parent_name);
+		}
+		ntfs_log_debug(".\n");
+		free(f);
+	}
+
+	ntfs_list_for_each_safe(item, tmp, &file->data) {
+		/* List of data streams */
+		struct data *d = ntfs_list_entry(item, struct data, list);
+		ntfs_log_debug("Freeing data stream '%s'.\n", d->name ?
+				d->name : UNNAMED);
+		if (d->name)
+			free(d->name);
+		if (d->runlist)
+			free(d->runlist);
+		free(d);
+	}
+
+	free(file->mft);
+	free(file);
+}
+
+/**
+ * verify_parent - confirm a record is parent of a file
+ * @name:	a filename of the file
+ * @rec:	the mft record of the possible parent
+ *
+ * Check that @rec is the parent of the file represented by @name.
+ * If @rec is a directory, but it is created after @name, then we
+ * can't determine whether @rec is really @name's parent.
+ *
+ * Return:	@rec's filename, either same name space as @name or lowest space.
+ *		NULL if can't determine parenthood or on error.
+ */
+static FILE_NAME_ATTR* verify_parent(struct filename* name, MFT_RECORD* rec)
+{
+	ATTR_RECORD *attr30;
+	FILE_NAME_ATTR *filename_attr = NULL, *lowest_space_name = NULL;
+	ntfs_attr_search_ctx *ctx;
+	int found_same_space = 1;
+
+	if (!name || !rec)
+		return NULL;
+
+	if (!(rec->flags & MFT_RECORD_IS_DIRECTORY)) {
+		return NULL;
+	}
+
+	ctx = ntfs_attr_get_search_ctx(NULL, rec);
+	if (!ctx) {
+		ntfs_log_error("ERROR: Couldn't create a search context.\n");
+		return NULL;
+	}
+
+	attr30 = find_attribute(AT_FILE_NAME, ctx);
+	if (!attr30) {
+		return NULL;
+	}
+
+	filename_attr = (FILE_NAME_ATTR*)((char*)attr30 + le16_to_cpu(attr30->value_offset));
+	/* if name is older than this dir -> can't determine */
+	if (ntfs2timespec(filename_attr->creation_time).tv_sec > name->date_c) {
+		return NULL;
+	}
+
+	if (filename_attr->file_name_type != name->name_space) {
+		found_same_space = 0;
+		lowest_space_name = filename_attr;
+
+		while (!found_same_space && (attr30 = find_attribute(AT_FILE_NAME, ctx))) {
+			filename_attr = (FILE_NAME_ATTR*)((char*)attr30 + le16_to_cpu(attr30->value_offset));
+
+			if (filename_attr->file_name_type == name->name_space) {
+				found_same_space = 1;
+			} else {
+				if (filename_attr->file_name_type < lowest_space_name->file_name_type) {
+					lowest_space_name = filename_attr;
+				}
+			}
+		}
+	}
+
+	ntfs_attr_put_search_ctx(ctx);
+
+	return (found_same_space ? filename_attr : lowest_space_name);
+}
+
+/**
+ * get_parent_name - Find the name of a file's parent.
+ * @name:	the filename whose parent's name to find
+ */
+static void get_parent_name(struct filename* name, ntfs_volume* vol)
+{
+	ntfs_attr* mft_data;
+	MFT_RECORD* rec;
+	FILE_NAME_ATTR* filename_attr;
+	long long inode_num;
+
+	if (!name || !vol)
+		return;
+
+	rec = calloc(1, vol->mft_record_size);
+	if (!rec) {
+		ntfs_log_error("ERROR: Couldn't allocate memory in "
+				"get_parent_name()\n");
+		return;
+	}
+
+	mft_data = ntfs_attr_open(vol->mft_ni, AT_DATA, AT_UNNAMED, 0);
+	if (!mft_data) {
+		ntfs_log_perror("ERROR: Couldn't open $MFT/$DATA");
+	} else {
+		inode_num = MREF_LE(name->parent_mref);
+
+		if (ntfs_attr_pread(mft_data, vol->mft_record_size * inode_num,
+					vol->mft_record_size, rec) < 1) {
+			ntfs_log_error("ERROR: Couldn't read MFT Record %lld"
+					".\n", inode_num);
+		} else if ((filename_attr = verify_parent(name, rec))) {
+			if (ntfs_ucstombs(filename_attr->file_name,
+					filename_attr->file_name_length,
+					&name->parent_name, 0) < 0) {
+				ntfs_log_debug("ERROR: Couldn't translate "
+						"filename to current "
+						"locale.\n");
+				name->parent_name = NULL;
+			}
+		}
+	}
+
+	if (mft_data) {
+		ntfs_attr_close(mft_data);
+	}
+
+	if (rec) {
+		free(rec);
+	}
+
+	return;
+}
+
+/*
+ *		Rescue the last deleted name of a file
+ *
+ *	Under some conditions, when a name is deleted and the MFT
+ *	record is shifted to reclaim the space, the name is still
+ *	present beyond the end of record.
+ *
+ *	For this to be possible, the data record has to be small (less
+ *	than 80 bytes), and there must be no other attributes.
+ *	So only the names of plain unfragmented files can be rescued.
+ *
+ *	Returns NULL when the name cannot be recovered.
+ */
+
+static struct filename *rescue_name(MFT_RECORD *mft, ntfs_attr_search_ctx *ctx)
+{
+	ATTR_RECORD *rec;
+	struct filename *name;
+	int off_name;
+	int length;
+	int type;
+
+	name = (struct filename*)NULL;
+	ntfs_attr_reinit_search_ctx(ctx);
+	rec = find_attribute(AT_DATA, ctx);
+	if (rec) {
+		/*
+		 * If the data attribute replaced the name attribute,
+		 * the name itself is at offset 0x58 from the data attr.
+		 * First be sure this location is within the unused part
+		 * of the MFT record, then make extra checks.
+		 */
+		off_name = (long)rec - (long)mft + 0x58;
+		if ((off_name >= (int)le32_to_cpu(mft->bytes_in_use))
+		    && ((off_name + 4)
+				 <= (int)le32_to_cpu(mft->bytes_allocated))) {
+			length = *((char*)mft + off_name);
+			type = *((char*)mft + off_name + 1);
+			/* check whether the name is fully allocated */
+			if ((type <= 3)
+			   && (length > 0)
+			   && ((off_name + 2*length + 2) 
+				<= (int)le32_to_cpu(mft->bytes_allocated))) {
+				/* create a (partial) name record */
+				name = (struct filename*)
+						ntfs_calloc(sizeof(*name));
+				if (name) {
+					name->uname = (ntfschar*)
+						((char*)mft + off_name + 2);
+					name->uname_len = length;
+					name->name_space = type;
+					if (ntfs_ucstombs(name->uname, length,
+							&name->name, 0) < 0) {
+						free(name);
+						name = (struct filename*)NULL;
+					}
+				}
+			if (name && name->name)
+				ntfs_log_verbose("Recovered file name %s\n",
+						name->name);
+			}
+		}
+	}
+	return (name);
+}
+
+
+
+/**
+ * get_filenames - Read an MFT Record's $FILENAME attributes
+ * @file:  The file object to work with
+ *
+ * A single file may have more than one filename.  This is quite common.
+ * Windows creates a short DOS name for each long name, e.g. LONGFI~1.XYZ,
+ * LongFiLeName.xyZ.
+ *
+ * The filenames that are found are put in filename objects and added to a
+ * linked list of filenames in the file object.  For convenience, the unicode
+ * filename is converted into the current locale and stored in the filename
+ * object.
+ *
+ * One of the filenames is picked (the one with the lowest numbered namespace)
+ * and its locale friendly name is put in pref_name.
+ *
+ * Return:  n  The number of $FILENAME attributes found
+ *	   -1  Error
+ */
+static int get_filenames(struct ufile *file, ntfs_volume* vol)
+{
+	ATTR_RECORD *rec;
+	FILE_NAME_ATTR *attr;
+	ntfs_attr_search_ctx *ctx;
+	struct filename *name;
+	int count = 0;
+	int space = 4;
+
+	if (!file)
+		return -1;
+
+	ctx = ntfs_attr_get_search_ctx(NULL, file->mft);
+	if (!ctx)
+		return -1;
+
+	while ((rec = find_attribute(AT_FILE_NAME, ctx))) {
+		/* We know this will always be resident. */
+		attr = (FILE_NAME_ATTR *)((char *)rec +
+				le16_to_cpu(rec->value_offset));
+
+		name = calloc(1, sizeof(*name));
+		if (!name) {
+			ntfs_log_error("ERROR: Couldn't allocate memory in "
+					"get_filenames().\n");
+			count = -1;
+			break;
+		}
+
+		name->uname      = attr->file_name;
+		name->uname_len  = attr->file_name_length;
+		name->name_space = attr->file_name_type;
+		name->size_alloc = sle64_to_cpu(attr->allocated_size);
+		name->size_data  = sle64_to_cpu(attr->data_size);
+		name->flags      = attr->file_attributes;
+
+		name->date_c     = ntfs2timespec(attr->creation_time).tv_sec;
+		name->date_a     = ntfs2timespec(attr->last_data_change_time).tv_sec;
+		name->date_m     = ntfs2timespec(attr->last_mft_change_time).tv_sec;
+		name->date_r     = ntfs2timespec(attr->last_access_time).tv_sec;
+
+		if (ntfs_ucstombs(name->uname, name->uname_len, &name->name,
+				0) < 0) {
+			ntfs_log_debug("ERROR: Couldn't translate filename to "
+					"current locale.\n");
+		}
+
+		name->parent_name = NULL;
+
+		if (opts.parent) {
+			name->parent_mref = attr->parent_directory;
+			get_parent_name(name, vol);
+		}
+
+		if (name->name_space < space) {
+			file->pref_name = name->name;
+			file->pref_pname = name->parent_name;
+			space = name->name_space;
+		}
+
+		file->max_size = max(file->max_size, name->size_alloc);
+		file->max_size = max(file->max_size, name->size_data);
+
+		ntfs_list_add_tail(&name->list, &file->name);
+		count++;
+	}
+
+	if (!count) {
+		name = rescue_name(file->mft,ctx);
+		if (name) {
+			/* a name was recovered, get missing attributes */
+			file->pref_name = name->name;
+			ntfs_attr_reinit_search_ctx(ctx);
+			rec = find_attribute(AT_STANDARD_INFORMATION, ctx);
+			if (rec) {
+				attr = (FILE_NAME_ATTR *)((char *)rec +
+						le16_to_cpu(rec->value_offset));
+				name->flags      = attr->file_attributes;
+
+				name->date_c     = ntfs2timespec(attr->creation_time).tv_sec;
+				name->date_a     = ntfs2timespec(attr->last_data_change_time).tv_sec;
+				name->date_m     = ntfs2timespec(attr->last_mft_change_time).tv_sec;
+				name->date_r     = ntfs2timespec(attr->last_access_time).tv_sec;
+			}
+			rec = find_attribute(AT_DATA, ctx);
+			if (rec) {
+				attr = (FILE_NAME_ATTR *)((char *)rec +
+						le16_to_cpu(rec->value_offset));
+				name->size_alloc = sle64_to_cpu(attr->allocated_size);
+				name->size_data  = sle64_to_cpu(attr->data_size);
+			}
+		ntfs_list_add_tail(&name->list, &file->name);
+		count++;
+		}
+	}
+	ntfs_attr_put_search_ctx(ctx);
+	ntfs_log_debug("File has %d names.\n", count);
+	return count;
+}
+
+/**
+ * get_data - Read an MFT Record's $DATA attributes
+ * @file:  The file object to work with
+ * @vol:  An ntfs volume obtained from ntfs_mount
+ *
+ * A file may have more than one data stream.  All files will have an unnamed
+ * data stream which contains the file's data.  Some Windows applications store
+ * extra information in a separate stream.
+ *
+ * The streams that are found are put in data objects and added to a linked
+ * list of data streams in the file object.
+ *
+ * Return:  n  The number of $FILENAME attributes found
+ *	   -1  Error
+ */
+static int get_data(struct ufile *file, ntfs_volume *vol)
+{
+	ATTR_RECORD *rec;
+	ntfs_attr_search_ctx *ctx;
+	int count = 0;
+	struct data *data;
+
+	if (!file)
+		return -1;
+
+	ctx = ntfs_attr_get_search_ctx(NULL, file->mft);
+	if (!ctx)
+		return -1;
+
+	while ((rec = find_attribute(AT_DATA, ctx))) {
+		data = calloc(1, sizeof(*data));
+		if (!data) {
+			ntfs_log_error("ERROR: Couldn't allocate memory in "
+					"get_data().\n");
+			count = -1;
+			break;
+		}
+
+		data->resident   = !rec->non_resident;
+		data->compressed = (rec->flags & ATTR_IS_COMPRESSED) ? 1 : 0;
+		data->encrypted  = (rec->flags & ATTR_IS_ENCRYPTED) ? 1 : 0;
+
+		if (rec->name_length) {
+			data->uname = (ntfschar *)((char *)rec +
+					le16_to_cpu(rec->name_offset));
+			data->uname_len = rec->name_length;
+
+			if (ntfs_ucstombs(data->uname, data->uname_len,
+						&data->name, 0) < 0) {
+				ntfs_log_error("ERROR: Cannot translate name "
+						"into current locale.\n");
+			}
+		}
+
+		if (data->resident) {
+			data->size_data = le32_to_cpu(rec->value_length);
+			data->data = (char*)rec +
+				le16_to_cpu(rec->value_offset);
+		} else {
+			data->size_alloc = sle64_to_cpu(rec->allocated_size);
+			data->size_data  = sle64_to_cpu(rec->data_size);
+			data->size_init  = sle64_to_cpu(rec->initialized_size);
+			data->size_vcn   = sle64_to_cpu(rec->highest_vcn) + 1;
+		}
+
+		data->runlist = ntfs_mapping_pairs_decompress(vol, rec, NULL);
+		if (!data->runlist) {
+			ntfs_log_debug("Couldn't decompress the data runs.\n");
+		}
+
+		file->max_size = max(file->max_size, data->size_data);
+		file->max_size = max(file->max_size, data->size_init);
+
+		ntfs_list_add_tail(&data->list, &file->data);
+		count++;
+	}
+
+	ntfs_attr_put_search_ctx(ctx);
+	ntfs_log_debug("File has %d data streams.\n", count);
+	return count;
+}
+
+/**
+ * read_record - Read an MFT record into memory
+ * @vol:     An ntfs volume obtained from ntfs_mount
+ * @record:  The record number to read
+ *
+ * Read the specified MFT record and gather as much information about it as
+ * possible.
+ *
+ * Return:  Pointer  A ufile object containing the results
+ *	    NULL     Error
+ */
+static struct ufile * read_record(ntfs_volume *vol, long long record)
+{
+	ATTR_RECORD *attr10, *attr20, *attr90;
+	struct ufile *file;
+	ntfs_attr *mft;
+	u32 log_levels;
+
+	if (!vol)
+		return NULL;
+
+	file = calloc(1, sizeof(*file));
+	if (!file) {
+		ntfs_log_error("ERROR: Couldn't allocate memory in read_record()\n");
+		return NULL;
+	}
+
+	NTFS_INIT_LIST_HEAD(&file->name);
+	NTFS_INIT_LIST_HEAD(&file->data);
+	file->inode = record;
+
+	file->mft = malloc(vol->mft_record_size);
+	if (!file->mft) {
+		ntfs_log_error("ERROR: Couldn't allocate memory in read_record()\n");
+		free_file(file);
+		return NULL;
+	}
+
+	mft = ntfs_attr_open(vol->mft_ni, AT_DATA, AT_UNNAMED, 0);
+	if (!mft) {
+		ntfs_log_perror("ERROR: Couldn't open $MFT/$DATA");
+		free_file(file);
+		return NULL;
+	}
+
+	if (ntfs_attr_mst_pread(mft, vol->mft_record_size * record, 1, vol->mft_record_size, file->mft) < 1) {
+		ntfs_log_error("ERROR: Couldn't read MFT Record %lld.\n", record);
+		ntfs_attr_close(mft);
+		free_file(file);
+		return NULL;
+	}
+
+	ntfs_attr_close(mft);
+	mft = NULL;
+
+	/* disable errors logging, while examining suspicious records */
+	log_levels = ntfs_log_clear_levels(NTFS_LOG_LEVEL_PERROR);
+	attr10 = find_first_attribute(AT_STANDARD_INFORMATION,	file->mft);
+	attr20 = find_first_attribute(AT_ATTRIBUTE_LIST,	file->mft);
+	attr90 = find_first_attribute(AT_INDEX_ROOT,		file->mft);
+
+	ntfs_log_debug("Attributes present: %s %s %s.\n", attr10?"0x10":"",
+			attr20?"0x20":"", attr90?"0x90":"");
+
+	if (attr10) {
+		STANDARD_INFORMATION *si;
+		si = (STANDARD_INFORMATION *) ((char *) attr10 + le16_to_cpu(attr10->value_offset));
+		file->date = ntfs2timespec(si->last_data_change_time).tv_sec;
+	}
+
+	if (attr20 || !attr10)
+		file->attr_list = 1;
+	if (attr90)
+		file->directory = 1;
+
+	if (get_filenames(file, vol) < 0) {
+		ntfs_log_error("ERROR: Couldn't get filenames.\n");
+	}
+	if (get_data(file, vol) < 0) {
+		ntfs_log_error("ERROR: Couldn't get data streams.\n");
+	}
+	/* restore errors logging */
+	ntfs_log_set_levels(log_levels);
+
+	return file;
+}
+
+/**
+ * calc_percentage - Calculate how much of the file is recoverable
+ * @file:  The file object to work with
+ * @vol:   An ntfs volume obtained from ntfs_mount
+ *
+ * Read through all the $DATA streams and determine if each cluster in each
+ * stream is still free disk space.  This is just measuring the potential for
+ * recovery.  The data may have still been overwritten by a another file which
+ * was then deleted.
+ *
+ * Files with a resident $DATA stream will have a 100% potential.
+ *
+ * N.B.  If $DATA attribute spans more than one MFT record (i.e. badly
+ *       fragmented) then only the data in this segment will be used for the
+ *       calculation.
+ *
+ * N.B.  Currently, compressed and encrypted files cannot be recovered, so they
+ *       will return 0%.
+ *
+ * Return:  n  The percentage of the file that _could_ be recovered
+ *	   -1  Error
+ */
+static int calc_percentage(struct ufile *file, ntfs_volume *vol)
+{
+	runlist_element *rl = NULL;
+	struct ntfs_list_head *pos;
+	struct data *data;
+	long long i, j;
+	long long start, end;
+	int clusters_inuse, clusters_free;
+	int percent = 0;
+
+	if (!file || !vol)
+		return -1;
+
+	if (file->directory) {
+		ntfs_log_debug("Found a directory: not recoverable.\n");
+		return 0;
+	}
+
+	if (ntfs_list_empty(&file->data)) {
+		ntfs_log_verbose("File has no data streams.\n");
+		return 0;
+	}
+
+	ntfs_list_for_each(pos, &file->data) {
+		data  = ntfs_list_entry(pos, struct data, list);
+		clusters_inuse = 0;
+		clusters_free  = 0;
+
+		if (data->encrypted) {
+			ntfs_log_verbose("File is encrypted, recovery is "
+					"impossible.\n");
+			continue;
+		}
+
+		if (data->compressed) {
+			ntfs_log_verbose("File is compressed, recovery not yet "
+					"implemented.\n");
+			continue;
+		}
+
+		if (data->resident) {
+			ntfs_log_verbose("File is resident, therefore "
+					"recoverable.\n");
+			percent = 100;
+			data->percent = 100;
+			continue;
+		}
+
+		rl = data->runlist;
+		if (!rl) {
+			ntfs_log_verbose("File has no runlist, hence no data."
+					"\n");
+			continue;
+		}
+
+		if (rl[0].length <= 0) {
+			ntfs_log_verbose("File has an empty runlist, hence no "
+					"data.\n");
+			continue;
+		}
+
+		if (rl[0].lcn == LCN_RL_NOT_MAPPED) { /* extended mft record */
+			ntfs_log_verbose("Missing segment at beginning, %lld "
+					"clusters\n", (long long)rl[0].length);
+			clusters_inuse += rl[0].length;
+			rl++;
+		}
+
+		for (i = 0; rl[i].length > 0; i++) {
+			if (rl[i].lcn == LCN_RL_NOT_MAPPED) {
+				ntfs_log_verbose("Missing segment at end, %lld "
+						"clusters\n",
+						(long long)rl[i].length);
+				clusters_inuse += rl[i].length;
+				continue;
+			}
+
+			if (rl[i].lcn == LCN_HOLE) {
+				clusters_free += rl[i].length;
+				continue;
+			}
+
+			start = rl[i].lcn;
+			end   = rl[i].lcn + rl[i].length;
+
+			for (j = start; j < end; j++) {
+				if (utils_cluster_in_use(vol, j))
+					clusters_inuse++;
+				else
+					clusters_free++;
+			}
+		}
+
+		if ((clusters_inuse + clusters_free) == 0) {
+			ntfs_log_error("ERROR: Unexpected error whilst "
+				"calculating percentage for inode %lld\n",
+				file->inode);
+			continue;
+		}
+
+		data->percent = (clusters_free * 100) /
+				(clusters_inuse + clusters_free);
+
+		percent = max(percent, data->percent);
+	}
+
+	ntfs_log_verbose("File is %d%% recoverable\n", percent);
+	return percent;
+}
+
+/**
+ * dump_record - Print everything we know about an MFT record
+ * @file:  The file to work with
+ *
+ * Output the contents of the file object.  This will print everything that has
+ * been read from the MFT record, or implied by various means.
+ *
+ * Because of the redundant nature of NTFS, there will be some duplication of
+ * information, though it will have been read from different sources.
+ *
+ * N.B.  If the filename is missing, or couldn't be converted to the current
+ *       locale, "<none>" will be displayed.
+ *
+ * Return:  none
+ */
+static void dump_record(struct ufile *file)
+{
+	char buffer[20];
+	struct ntfs_list_head *item;
+	int i;
+
+	if (!file)
+		return;
+
+	ntfs_log_quiet("MFT Record %lld\n", file->inode);
+	ntfs_log_quiet("Type: %s\n", (file->directory) ? "Directory" : "File");
+	strftime(buffer, sizeof(buffer), "%F %R", localtime(&file->date));
+	ntfs_log_quiet("Date: %s\n", buffer);
+
+	if (file->attr_list)
+		ntfs_log_quiet("Metadata may span more than one MFT record\n");
+
+	ntfs_list_for_each(item, &file->name) {
+		struct filename *f =
+			ntfs_list_entry(item, struct filename, list);
+
+		ntfs_log_quiet("Filename: (%d) %s\n", f->name_space, f->name);
+		ntfs_log_quiet("File Flags: ");
+		if (f->flags & FILE_ATTR_SYSTEM)
+			ntfs_log_quiet("System ");
+		if (f->flags & FILE_ATTR_DIRECTORY)
+			ntfs_log_quiet("Directory ");
+		if (f->flags & FILE_ATTR_SPARSE_FILE)
+			ntfs_log_quiet("Sparse ");
+		if (f->flags & FILE_ATTR_REPARSE_POINT)
+			ntfs_log_quiet("Reparse ");
+		if (f->flags & FILE_ATTR_COMPRESSED)
+			ntfs_log_quiet("Compressed ");
+		if (f->flags & FILE_ATTR_ENCRYPTED)
+			ntfs_log_quiet("Encrypted ");
+		if (!(f->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_DIRECTORY |
+		    FILE_ATTR_SPARSE_FILE | FILE_ATTR_REPARSE_POINT |
+		    FILE_ATTR_COMPRESSED | FILE_ATTR_ENCRYPTED))) {
+			ntfs_log_quiet("%s", NONE);
+		}
+
+		ntfs_log_quiet("\n");
+
+		if (opts.parent) {
+			ntfs_log_quiet("Parent: %s\n", f->parent_name ?
+				f->parent_name : "<non-determined>");
+		}
+
+		ntfs_log_quiet("Size alloc: %lld\n", f->size_alloc);
+		ntfs_log_quiet("Size data: %lld\n", f->size_data);
+
+		strftime(buffer, sizeof(buffer), "%F %R",
+				localtime(&f->date_c));
+		ntfs_log_quiet("Date C: %s\n", buffer);
+		strftime(buffer, sizeof(buffer), "%F %R",
+				localtime(&f->date_a));
+		ntfs_log_quiet("Date A: %s\n", buffer);
+		strftime(buffer, sizeof(buffer), "%F %R",
+				localtime(&f->date_m));
+		ntfs_log_quiet("Date M: %s\n", buffer);
+		strftime(buffer, sizeof(buffer), "%F %R",
+				localtime(&f->date_r));
+		ntfs_log_quiet("Date R: %s\n", buffer);
+	}
+
+	ntfs_log_quiet("Data Streams:\n");
+	ntfs_list_for_each(item, &file->data) {
+		struct data *d = ntfs_list_entry(item, struct data, list);
+		ntfs_log_quiet("Name: %s\n", (d->name) ? d->name : UNNAMED);
+		ntfs_log_quiet("Flags: ");
+		if (d->resident)   ntfs_log_quiet("Resident\n");
+		if (d->compressed) ntfs_log_quiet("Compressed\n");
+		if (d->encrypted)  ntfs_log_quiet("Encrypted\n");
+		if (!d->resident && !d->compressed && !d->encrypted)
+			ntfs_log_quiet("None\n");
+		else
+			ntfs_log_quiet("\n");
+
+		ntfs_log_quiet("Size alloc: %lld\n", d->size_alloc);
+		ntfs_log_quiet("Size data: %lld\n", d->size_data);
+		ntfs_log_quiet("Size init: %lld\n", d->size_init);
+		ntfs_log_quiet("Size vcn: %lld\n", d->size_vcn);
+
+		ntfs_log_quiet("Data runs:\n");
+		if ((!d->runlist) || (d->runlist[0].length <= 0)) {
+			ntfs_log_quiet("    None\n");
+		} else {
+			for (i = 0; d->runlist[i].length > 0; i++) {
+				ntfs_log_quiet("    %lld @ %lld\n",
+						(long long)d->runlist[i].length,
+						(long long)d->runlist[i].lcn);
+			}
+		}
+
+		ntfs_log_quiet("Amount potentially recoverable %d%%\n",
+				d->percent);
+	}
+
+	ntfs_log_quiet("________________________________________\n\n");
+}
+
+/**
+ * list_record - Print a one line summary of the file
+ * @file:  The file to work with
+ *
+ * Print a one line description of a file.
+ *
+ *   Inode    Flags  %age     Date  Time        Size  Filename
+ *
+ * The output will contain the file's inode number (MFT Record), some flags,
+ * the percentage of the file that is recoverable, the last modification date,
+ * the size and the filename.
+ *
+ * The flags are F/D = File/Directory, N/R = Data is (Non-)Resident,
+ * C = Compressed, E = Encrypted, ! = Metadata may span multiple records.
+ *
+ * N.B.  The file size is stored in many forms in several attributes.   This
+ *       display the largest it finds.
+ *
+ * N.B.  If the filename is missing, or couldn't be converted to the current
+ *       locale, "<none>" will be displayed.
+ *
+ * Return:  none
+ */
+static void list_record(struct ufile *file)
+{
+	char buffer[20];
+	struct ntfs_list_head *item;
+	const char *name = NULL;
+	long long size = 0;
+	int percent = 0;
+
+	char flagd = '.', flagr = '.', flagc = '.', flagx = '.';
+
+	strftime(buffer, sizeof(buffer), "%F %R", localtime(&file->date));
+
+	if (file->attr_list)
+		flagx = '!';
+
+	if (file->directory)
+		flagd = 'D';
+	else
+		flagd = 'F';
+
+	ntfs_list_for_each(item, &file->data) {
+		struct data *d = ntfs_list_entry(item, struct data, list);
+
+		if (!d->name) {
+			if (d->resident)
+				flagr = 'R';
+			else
+				flagr = 'N';
+			if (d->compressed)
+				flagc = 'C';
+			if (d->encrypted)
+				flagc = 'E';
+
+			percent = max(percent, d->percent);
+		}
+
+		size = max(size, d->size_data);
+		size = max(size, d->size_init);
+	}
+
+	if (file->pref_name)
+		name = file->pref_name;
+	else
+		name = NONE;
+
+	ntfs_log_quiet("%-8lld %c%c%c%c   %3d%%  %s %9lld  %s\n",
+		file->inode, flagd, flagr, flagc, flagx,
+		percent, buffer, size, name);
+
+}
+
+/**
+ * name_match - Does a file have a name matching a regex
+ * @re:    The regular expression object
+ * @file:  The file to be tested
+ *
+ * Iterate through the file's $FILENAME attributes and compare them against the
+ * regular expression, created with regcomp.
+ *
+ * Return:  1  There is a matching filename.
+ *	    0  There is no match.
+ */
+static int name_match(regex_t *re, struct ufile *file)
+{
+	struct ntfs_list_head *item;
+	int result;
+
+	if (!re || !file)
+		return 0;
+
+	ntfs_list_for_each(item, &file->name) {
+		struct filename *f =
+			ntfs_list_entry(item, struct filename, list);
+
+		if (!f->name)
+			continue;
+#ifdef HAVE_REGEX_H
+		result = regexec(re, f->name, 0, NULL, 0);
+#else
+		result = regexec(re, f->uname, f->uname_len, NULL, 0);
+#endif
+		if (result < 0) {
+			ntfs_log_perror("Couldn't compare filename with regex");
+			return 0;
+		} else if (result == REG_NOERROR) {
+			ntfs_log_debug("Found a matching filename.\n");
+			return 1;
+		}
+	}
+
+	ntfs_log_debug("Filename '%s' doesn't match regex.\n", file->pref_name);
+	return 0;
+}
+
+/**
+ * write_data - Write out a block of data
+ * @fd:       File descriptor to write to
+ * @buffer:   Data to write
+ * @bufsize:  Amount of data to write
+ *
+ * Write a block of data to a file descriptor.
+ *
+ * Return:  -1  Error, something went wrong
+ *	     0  Success, all the data was written
+ */
+static unsigned int write_data(int fd, const char *buffer,
+	unsigned int bufsize)
+{
+	ssize_t result1, result2;
+
+	if (!buffer) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	result1 = write(fd, buffer, bufsize);
+	if ((result1 == (ssize_t) bufsize) || (result1 < 0))
+		return result1;
+
+	/* Try again with the rest of the buffer */
+	buffer  += result1;
+	bufsize -= result1;
+
+	result2 = write(fd, buffer, bufsize);
+	if (result2 < 0)
+		return result1;
+
+	return result1 + result2;
+}
+
+/**
+ * create_pathname - Create a path/file from some components
+ * @dir:      Directory in which to create the file (optional)
+ * @name:     Filename to give the file (optional)
+ * @stream:   Name of the stream (optional)
+ * @buffer:   Store the result here
+ * @bufsize:  Size of buffer
+ *
+ * Create a filename from various pieces.  The output will be of the form:
+ *	dir/file
+ *	dir/file:stream
+ *	file
+ *	file:stream
+ *
+ * All the components are optional.  If the name is missing, "unknown" will be
+ * used.  If the directory is missing the file will be created in the current
+ * directory.  If the stream name is present it will be appended to the
+ * filename, delimited by a colon.
+ *
+ * N.B. If the buffer isn't large enough the name will be truncated.
+ *
+ * Return:  n  Length of the allocated name
+ */
+static int create_pathname(const char *dir, const char *name,
+	const char *stream, char *buffer, int bufsize)
+{
+	if (!name)
+		name = UNKNOWN;
+
+	if (dir)
+		if (stream)
+			snprintf(buffer, bufsize, "%s/%s:%s", dir, name, stream);
+		else
+			snprintf(buffer, bufsize, "%s/%s", dir, name);
+	else
+		if (stream)
+			snprintf(buffer, bufsize, "%s:%s", name, stream);
+		else
+			snprintf(buffer, bufsize, "%s", name);
+
+	return strlen(buffer);
+}
+
+/**
+ * open_file - Open a file to write to
+ * @pathname:  Path, name and stream of the file to open
+ *
+ * Create a file and return the file descriptor.
+ *
+ * N.B.  If option force is given and existing file will be overwritten.
+ *
+ * Return:  -1  Error, failed to create the file
+ *	     n  Success, this is the file descriptor
+ */
+static int open_file(const char *pathname)
+{
+	int flags;
+
+	ntfs_log_verbose("Creating file: %s\n", pathname);
+
+	if (opts.force)
+		flags = O_RDWR | O_CREAT | O_TRUNC;
+	else
+		flags = O_RDWR | O_CREAT | O_EXCL;
+#ifdef HAVE_WINDOWS_H
+	flags ^= O_BINARY | O_RDWR | O_WRONLY;
+#endif
+
+	return open(pathname, flags, S_IRUSR | S_IWUSR);
+}
+
+/**
+ * set_date - Set the file's date and time
+ * @pathname:  Path and name of the file to alter
+ * @date:      Date and time to set
+ *
+ * Give a file a particular date and time.
+ *
+ * Return:  1  Success, set the file's date and time
+ *	    0  Error, failed to change the file's date and time
+ */
+static int set_date(const char *pathname, time_t date)
+{
+	struct utimbuf ut;
+
+	if (!pathname)
+		return 0;
+
+	ut.actime  = date;
+	ut.modtime = date;
+	if (utime(pathname, &ut)) {
+		ntfs_log_error("ERROR: Couldn't set the file's date and time\n");
+		return 0;
+	}
+	return 1;
+}
+
+/**
+ * undelete_file - Recover a deleted file from an NTFS volume
+ * @vol:    An ntfs volume obtained from ntfs_mount
+ * @inode:  MFT Record number to be recovered
+ *
+ * Read an MFT Record and try an recover any data associated with it.  Some of
+ * the clusters may be in use; these will be filled with zeros or the fill byte
+ * supplied in the options.
+ *
+ * Each data stream will be recovered and saved to a file.  The file's name will
+ * be the original filename and it will be written to the current directory.
+ * Any named data stream will be saved as filename:streamname.
+ *
+ * The output file's name and location can be altered by using the command line
+ * options.
+ *
+ * N.B.  We cannot tell if someone has overwritten some of the data since the
+ *       file was deleted.
+ *
+ * Return:  0  Error, something went wrong
+ *	    1  Success, the data was recovered
+ */
+static int undelete_file(ntfs_volume *vol, long long inode)
+{
+	char pathname[256];
+	char *buffer = NULL;
+	unsigned int bufsize;
+	struct ufile *file;
+	int i, j;
+	long long start, end;
+	runlist_element *rl;
+	struct ntfs_list_head *item;
+	int fd = -1;
+	long long k;
+	int result = 0;
+	char *name;
+	long long cluster_count;	/* I'll need this variable (see below). +mabs */
+
+	if (!vol)
+		return 0;
+
+	/* try to get record */
+	file = read_record(vol, inode);
+	if (!file || !file->mft) {
+		ntfs_log_error("Can't read info from mft record %lld.\n", inode);
+		return 0;
+	}
+
+	/* if flag was not set, print file informations */
+	if (avoid_duplicate_printing == 0) {
+		if (opts.verbose) {
+			dump_record(file);
+		} else {
+			list_record(file);
+			//ntfs_log_quiet("\n");
+		}
+	}
+
+	bufsize = vol->cluster_size;
+	buffer = malloc(bufsize);
+	if (!buffer)
+		goto free;
+
+	/* calc_percentage() must be called before dump_record() or
+	 * list_record(). Otherwise, when undeleting, a file will always be
+	 * listed as 0% recoverable even if successfully undeleted. +mabs
+	 */
+	if (file->mft->flags & MFT_RECORD_IN_USE) {
+		ntfs_log_error("Record is in use by the mft\n");
+		if (!opts.force) {
+			free(buffer);
+			free_file(file);
+			return 0;
+		}
+		ntfs_log_verbose("Forced to continue.\n");
+	}
+
+	if (calc_percentage(file, vol) == 0) {
+		ntfs_log_quiet("File has no recoverable data.\n");
+		goto free;
+	}
+
+	if (ntfs_list_empty(&file->data)) {
+		ntfs_log_quiet("File has no data.  There is nothing to recover.\n");
+		goto free;
+	}
+
+	ntfs_list_for_each(item, &file->data) {
+		struct data *d = ntfs_list_entry(item, struct data, list);
+		char defname[sizeof(UNKNOWN) + 25];
+
+		if (opts.output)
+			name = opts.output;
+		else
+			if (file->pref_name)
+				name = file->pref_name;
+			else {
+				sprintf(defname,"%s%lld",UNKNOWN,
+						(long long)file->inode);
+				name = defname;
+			}
+
+		create_pathname(opts.dest, name, d->name, pathname, sizeof(pathname));
+		if (d->resident) {
+			fd = open_file(pathname);
+			if (fd < 0) {
+				ntfs_log_perror("Couldn't create file");
+				goto free;
+			}
+
+			ntfs_log_verbose("File has resident data.\n");
+			if (write_data(fd, d->data, d->size_data) < d->size_data) {
+				ntfs_log_perror("Write failed");
+				close(fd);
+				goto free;
+			}
+
+			if (close(fd) < 0) {
+				ntfs_log_perror("Close failed");
+			}
+			fd = -1;
+		} else {
+			rl = d->runlist;
+			if (!rl) {
+				ntfs_log_verbose("File has no runlist, hence no data.\n");
+				continue;
+			}
+
+			if (rl[0].length <= 0) {
+				ntfs_log_verbose("File has an empty runlist, hence no data.\n");
+				continue;
+			}
+
+			fd = open_file(pathname);
+			if (fd < 0) {
+				ntfs_log_perror("Couldn't create output file");
+				goto free;
+			}
+
+			if (rl[0].lcn == LCN_RL_NOT_MAPPED) {	/* extended mft record */
+				ntfs_log_verbose("Missing segment at beginning, %lld "
+						"clusters.\n",
+						(long long)rl[0].length);
+				memset(buffer, opts.fillbyte, bufsize);
+				for (k = 0; k < rl[0].length * vol->cluster_size; k += bufsize) {
+					if (write_data(fd, buffer, bufsize) < bufsize) {
+						ntfs_log_perror("Write failed");
+						close(fd);
+						goto free;
+					}
+				}
+			}
+
+			cluster_count = 0LL;
+			for (i = 0; rl[i].length > 0; i++) {
+
+				if (rl[i].lcn == LCN_RL_NOT_MAPPED) {
+					ntfs_log_verbose("Missing segment at end, "
+							"%lld clusters.\n",
+							(long long)rl[i].length);
+					memset(buffer, opts.fillbyte, bufsize);
+					for (k = 0; k < rl[i].length * vol->cluster_size; k += bufsize) {
+						if (write_data(fd, buffer, bufsize) < bufsize) {
+							ntfs_log_perror("Write failed");
+							close(fd);
+							goto free;
+						}
+						cluster_count++;
+					}
+					continue;
+				}
+
+				if (rl[i].lcn == LCN_HOLE) {
+					ntfs_log_verbose("File has a sparse section.\n");
+					memset(buffer, 0, bufsize);
+					for (k = 0; k < rl[i].length * vol->cluster_size; k += bufsize) {
+						if (write_data(fd, buffer, bufsize) < bufsize) {
+							ntfs_log_perror("Write failed");
+							close(fd);
+							goto free;
+						}
+					}
+					continue;
+				}
+
+				start = rl[i].lcn;
+				end   = rl[i].lcn + rl[i].length;
+
+				for (j = start; j < end; j++) {
+					if (utils_cluster_in_use(vol, j) && !opts.optimistic) {
+						memset(buffer, opts.fillbyte, bufsize);
+						if (write_data(fd, buffer, bufsize) < bufsize) {
+							ntfs_log_perror("Write failed");
+							close(fd);
+							goto free;
+						}
+					} else {
+						if (ntfs_cluster_read(vol, j, 1, buffer) < 1) {
+							ntfs_log_perror("Read failed");
+							close(fd);
+							goto free;
+						}
+						if (write_data(fd, buffer, bufsize) < bufsize) {
+							ntfs_log_perror("Write failed");
+							close(fd);
+							goto free;
+						}
+						cluster_count++;
+					}
+				}
+			}
+			ntfs_log_quiet("\n");
+
+			/*
+			 * The following block of code implements the --truncate option.
+			 * Its semantics are as follows:
+			 * IF opts.truncate is set AND data stream currently being recovered is
+			 * non-resident AND data stream has no holes (100% recoverability) AND
+			 * 0 <= (data->size_alloc - data->size_data) <= vol->cluster_size AND
+			 * cluster_count * vol->cluster_size == data->size_alloc THEN file
+			 * currently being written is truncated to data->size_data bytes before
+			 * it's closed.
+			 * This multiple checks try to ensure that only files with consistent
+			 * values of size/occupied clusters are eligible for truncation. Note
+			 * that resident streams need not be truncated, since the original code
+			 * already recovers their exact length.                           +mabs
+			 */
+			if (opts.truncate) {
+				if (d->percent == 100 && d->size_alloc >= d->size_data &&
+					(d->size_alloc - d->size_data) <= (long long)vol->cluster_size &&
+					cluster_count * (long long)vol->cluster_size == d->size_alloc) {
+					if (ftruncate(fd, (off_t)d->size_data))
+						ntfs_log_perror("Truncation failed");
+				} else ntfs_log_quiet("Truncation not performed because file has an "
+					"inconsistent $MFT record.\n");
+			}
+
+			if (close(fd) < 0) {
+				ntfs_log_perror("Close failed");
+			}
+			fd = -1;
+
+		}
+		set_date(pathname, file->date);
+		if (d->name)
+			ntfs_log_quiet("Undeleted '%s:%s' successfully.\n", file->pref_name, d->name);
+		else
+			ntfs_log_quiet("Undeleted '%s' successfully.\n", file->pref_name);
+	}
+	result = 1;
+free:
+	if (buffer)
+		free(buffer);
+	free_file(file);
+	return result;
+}
+
+/**
+ * scan_disk - Search an NTFS volume for files that could be undeleted
+ * @vol:  An ntfs volume obtained from ntfs_mount
+ *
+ * Read through all the MFT entries looking for deleted files.  For each one
+ * determine how much of the data lies in unused disk space.
+ *
+ * The list can be filtered by name, size and date, using command line options.
+ *
+ * Return:  -1  Error, something went wrong
+ *	     n  Success, the number of recoverable files
+ */
+static int scan_disk(ntfs_volume *vol)
+{
+	s64 nr_mft_records;
+	const int BUFSIZE = 8192;
+	char *buffer = NULL;
+	int results = 0;
+	ntfs_attr *attr;
+	long long size;
+	long long bmpsize;
+	long long i;
+	int j, k, b;
+	int percent;
+	struct ufile *file;
+	regex_t re;
+
+	if (!vol)
+		return -1;
+
+	attr = ntfs_attr_open(vol->mft_ni, AT_BITMAP, AT_UNNAMED, 0);
+	if (!attr) {
+		ntfs_log_perror("ERROR: Couldn't open $MFT/$BITMAP");
+		return -1;
+	}
+	NVolSetNoFixupWarn(vol);
+	bmpsize = attr->initialized_size;
+
+	buffer = malloc(BUFSIZE);
+	if (!buffer) {
+		ntfs_log_error("ERROR: Couldn't allocate memory in scan_disk()\n");
+		results = -1;
+		goto out;
+	}
+
+	if (opts.match) {
+		int flags = REG_NOSUB;
+
+		if (!opts.match_case)
+			flags |= REG_ICASE;
+		if (regcomp(&re, opts.match, flags)) {
+			ntfs_log_error("ERROR: Couldn't create a regex.\n");
+			goto out;
+		}
+#ifndef HAVE_REGEX_H
+		re->upcase = vol->upcase;
+		re->upcase_len = vol->upcase_len;
+#endif
+	}
+
+	nr_mft_records = vol->mft_na->initialized_size >>
+			vol->mft_record_size_bits;
+
+	ntfs_log_quiet("Inode    Flags  %%age     Date    Time       Size  Filename\n");
+	ntfs_log_quiet("-----------------------------------------------------------------------\n");
+	for (i = 0; i < bmpsize; i += BUFSIZE) {
+		long long read_count = min((bmpsize - i), BUFSIZE);
+		size = ntfs_attr_pread(attr, i, read_count, buffer);
+		if (size < 0)
+			break;
+
+		for (j = 0; j < size; j++) {
+			b = buffer[j];
+			for (k = 0; k < 8; k++, b>>=1) {
+				if (((i+j)*8+k) >= nr_mft_records)
+					goto done;
+				if (b & 1)
+					continue;
+				file = read_record(vol, (i+j)*8+k);
+				if (!file) {
+					ntfs_log_error("Couldn't read MFT Record %lld.\n",
+							(long long)(i+j)*8+k);
+					continue;
+				}
+
+				if ((opts.since > 0) && (file->date <= opts.since))
+					goto skip;
+				if (opts.match && !name_match(&re, file))
+					goto skip;
+				if (opts.size_begin && (opts.size_begin > file->max_size))
+					goto skip;
+				if (opts.size_end && (opts.size_end < file->max_size))
+					goto skip;
+
+				percent = calc_percentage(file, vol);
+				if ((opts.percent == -1) || (percent >= opts.percent)) {
+					if (opts.verbose)
+						dump_record(file);
+					else
+						list_record(file);
+
+					/* Was -u specified with no inode
+					   so undelete file by regex */
+					if (opts.mode == MODE_UNDELETE) {
+						if  (!undelete_file(vol, file->inode))
+							ntfs_log_verbose("ERROR: Failed to undelete "
+								  "inode %lli\n!",
+								  file->inode);
+						ntfs_log_info("\n");
+					}
+				}
+				if (((opts.percent == -1) && (percent > 0)) ||
+				    ((opts.percent > 0)  && (percent >= opts.percent))) {
+					results++;
+				}
+skip:
+				free_file(file);
+			}
+		}
+	}
+done:
+	ntfs_log_quiet("\nFiles with potentially recoverable content: %d\n",
+		results);
+out:
+	if (opts.match)
+		regfree(&re);
+	free(buffer);
+	NVolClearNoFixupWarn(vol);
+	if (attr)
+		ntfs_attr_close(attr);
+	return results;
+}
+
+/**
+ * copy_mft - Write a range of MFT Records to a file
+ * @vol:	An ntfs volume obtained from ntfs_mount
+ * @mft_begin:	First MFT Record to save
+ * @mft_end:	Last MFT Record to save
+ *
+ * Read a number of MFT Records and write them to a file.
+ *
+ * Return:  0  Success, all the records were written
+ *	    1  Error, something went wrong
+ */
+static int copy_mft(ntfs_volume *vol, long long mft_begin, long long mft_end)
+{
+	s64 nr_mft_records;
+	char pathname[256];
+	ntfs_attr *mft;
+	char *buffer;
+	const char *name;
+	long long i;
+	int result = 1;
+	int fd;
+
+	if (!vol)
+		return 1;
+
+	if (mft_end < mft_begin) {
+		ntfs_log_error("Range to copy is backwards.\n");
+		return 1;
+	}
+
+	buffer = malloc(vol->mft_record_size);
+	if (!buffer) {
+		ntfs_log_error("Couldn't allocate memory in copy_mft()\n");
+		return 1;
+	}
+
+	mft = ntfs_attr_open(vol->mft_ni, AT_DATA, AT_UNNAMED, 0);
+	if (!mft) {
+		ntfs_log_perror("Couldn't open $MFT/$DATA");
+		goto free;
+	}
+
+	name = opts.output;
+	if (!name) {
+		name = MFTFILE;
+		ntfs_log_debug("No output filename, defaulting to '%s'.\n",
+				name);
+	}
+
+	create_pathname(opts.dest, name, NULL, pathname, sizeof(pathname));
+	fd = open_file(pathname);
+	if (fd < 0) {
+		ntfs_log_perror("Couldn't open output file '%s'", name);
+		goto attr;
+	}
+
+	nr_mft_records = vol->mft_na->initialized_size >>
+			vol->mft_record_size_bits;
+
+	mft_end = min(mft_end, nr_mft_records - 1);
+
+	ntfs_log_debug("MFT records:\n");
+	ntfs_log_debug("\tTotal: %8lld\n", nr_mft_records);
+	ntfs_log_debug("\tBegin: %8lld\n", mft_begin);
+	ntfs_log_debug("\tEnd:   %8lld\n", mft_end);
+
+	for (i = mft_begin; i <= mft_end; i++) {
+		if (ntfs_attr_pread(mft, vol->mft_record_size * i,
+		    vol->mft_record_size, buffer) < vol->mft_record_size) {
+			ntfs_log_perror("Couldn't read MFT Record %lld", i);
+			goto close;
+		}
+
+		if (write_data(fd, buffer, vol->mft_record_size) < vol->mft_record_size) {
+			ntfs_log_perror("Write failed");
+			goto close;
+		}
+	}
+
+	ntfs_log_verbose("Read %lld MFT Records\n", mft_end - mft_begin + 1);
+	result = 0;
+close:
+	close(fd);
+attr:
+	ntfs_attr_close(mft);
+free:
+	free(buffer);
+	return result;
+}
+
+/**
+ * handle_undelete
+ *
+ * Handles the undelete
+ */
+static int handle_undelete(ntfs_volume *vol)
+{
+	int result = 1;
+	int i;
+	unsigned long long	inode;
+
+	/* Check whether (an) inode(s) was specified or at least a regex! */
+	if (nr_entries == 0) {
+		if (with_regex == 0) {
+			ntfs_log_error("ERROR: NO inode(s) AND NO match-regex "
+				"specified!\n");
+		} else {
+			avoid_duplicate_printing= 1;
+			result = !scan_disk(vol);
+			if (result)
+				ntfs_log_verbose("ERROR: Failed to scan device "
+					"'%s'.\n", opts.device);
+		}
+	} else {
+		/* Normal undelete by specifying inode(s) */
+		ntfs_log_quiet("Inode    Flags  %%age  Date            Size  Filename\n");
+		ntfs_log_quiet("---------------------------------------------------------------\n");
+
+		/* loop all given inodes */
+		for (i = 0; i < nr_entries; i++) {
+			for (inode = ranges[i].begin; inode <= ranges[i].end; inode ++) {
+				/* Now undelete file */
+				result = !undelete_file(vol, inode);
+				if (result)
+					ntfs_log_verbose("ERROR: Failed to "
+						"undelete inode %lli\n!", inode);
+			}
+		}
+	}
+	return (result);
+}
+
+/**
+ * main - Begin here
+ *
+ * Start from here.
+ *
+ * Return:  0  Success, the program worked
+ *	    1  Error, something went wrong
+ */
+int main(int argc, char *argv[])
+{
+	ntfs_volume *vol;
+	int result = 1;
+
+	ntfs_log_set_handler(ntfs_log_handler_outerr);
+
+	with_regex = 0;
+	avoid_duplicate_printing = 0;
+
+	result = parse_options(argc, argv);
+	if (result >= 0)
+		goto free;
+
+	utils_set_locale();
+
+	vol = utils_mount_volume(opts.device, NTFS_MNT_RDONLY |
+			(opts.force ? NTFS_MNT_RECOVER : 0));
+	if (!vol)
+		return 1;
+
+	/* handling of the different modes */
+	switch (opts.mode) {
+	/* Scanning */
+	case MODE_SCAN:
+		result = !scan_disk(vol);
+		if (result)
+			ntfs_log_verbose("ERROR: Failed to scan device '%s'.\n",
+				opts.device);
+		break;
+
+	/* Undelete-handling */
+	case MODE_UNDELETE:
+		result= handle_undelete(vol);
+		break;
+
+	/* Handling of copy mft */
+	case MODE_COPY:
+		result = !copy_mft(vol, opts.mft_begin, opts.mft_end);
+		if (result)
+			ntfs_log_verbose("ERROR: Failed to read MFT blocks "
+				"%lld-%lld.\n", (long long)opts.mft_begin,
+				(long long)min((vol->mft_na->initialized_size >>
+				vol->mft_record_size_bits) , opts.mft_end));
+		break;
+	default:
+		; /* Cannot happen */
+	}
+
+	ntfs_umount(vol, FALSE);
+free:
+	if (opts.match)
+		free(opts.match);
+
+	return result;
+}
+
diff --git a/ntfsprogs/ntfsundelete.h b/ntfsprogs/ntfsundelete.h
new file mode 100755
index 0000000000000000000000000000000000000000..dd462f2c313c7179f177c7e9afb6a4ebabc8ee30
--- /dev/null
+++ b/ntfsprogs/ntfsundelete.h
@@ -0,0 +1,112 @@
+/*
+ * ntfsundelete - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2002 Richard Russon
+ * Copyright (c) 2007 Yura Pakhuchiy
+ *
+ * This utility will recover deleted files from an NTFS volume.
+ *
+ * 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 Linux-NTFS
+ * 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 _NTFSUNDELETE_H_
+#define _NTFSUNDELETE_H_
+
+#include "types.h"
+#include "list.h"
+#include "runlist.h"
+#include "utils.h"
+
+enum optmode {
+	MODE_NONE = 0,
+	MODE_SCAN,
+	MODE_UNDELETE,
+	MODE_COPY,
+	MODE_ERROR
+};
+
+struct options {
+	char		*device;	/* Device/File to work with */
+	enum optmode	 mode;		/* Scan / Undelete / Copy */
+	int		 percent;	/* Minimum recoverability */
+	int		 uinode;	/* Undelete this inode */
+	char		*dest;		/* Save file to this directory */
+	char		*output;	/* With this filename */
+	char		*match;		/* Pattern for filename matching */
+	int		 match_case;	/* Case sensitive matching */
+	int		 truncate;	/* Truncate files to exact size. */
+	int		 quiet;		/* Less output */
+	int		 verbose;	/* Extra output */
+	int		 force;		/* Override common sense */
+	int              optimistic;    /* Undelete in-use clusters as well */
+	int		 parent;	/* Show parent directory */
+	time_t		 since;		/* Since this time */
+	s64		 size_begin;	/* Range for file size */
+	s64		 size_end;
+	s64		 mft_begin;	/* Range for mft copy */
+	s64		 mft_end;
+	char		 fillbyte;	/* Use for unrecoverable sections */
+};
+
+struct filename {
+	struct ntfs_list_head list;	/* Previous/Next links */
+	ntfschar	*uname;		/* Filename in unicode */
+	int		 uname_len;	/* and its length */
+	long long	 size_alloc;	/* Allocated size (multiple of cluster size) */
+	long long	 size_data;	/* Actual size of data */
+	FILE_ATTR_FLAGS	 flags;
+	time_t		 date_c;	/* Time created */
+	time_t		 date_a;	/*	altered */
+	time_t		 date_m;	/*	mft record changed */
+	time_t		 date_r;	/*	read */
+	char		*name;		/* Filename in current locale */
+	FILE_NAME_TYPE_FLAGS name_space;
+	leMFT_REF	 parent_mref;
+	char		*parent_name;
+};
+
+struct data {
+	struct ntfs_list_head list;	/* Previous/Next links */
+	char		*name;		/* Stream name in current locale */
+	ntfschar	*uname;		/* Unicode stream name */
+	int		 uname_len;	/* and its length */
+	int		 resident;	/* Stream is resident */
+	int		 compressed;	/* Stream is compressed */
+	int		 encrypted;	/* Stream is encrypted */
+	long long	 size_alloc;	/* Allocated size (multiple of cluster size) */
+	long long	 size_data;	/* Actual size of data */
+	long long	 size_init;	/* Initialised size, may be less than data size */
+	long long	 size_vcn;	/* Highest VCN in the data runs */
+	runlist_element *runlist;	/* Decoded data runs */
+	int		 percent;	/* Amount potentially recoverable */
+	void		*data;		/* If resident, a pointer to the data */
+};
+
+struct ufile {
+	long long	 inode;		/* MFT record number */
+	time_t		 date;		/* Last modification date/time */
+	struct ntfs_list_head name;	/* A list of filenames */
+	struct ntfs_list_head data;	/* A list of data streams */
+	char		*pref_name;	/* Preferred filename */
+	char		*pref_pname;	/*	     parent filename */
+	long long	 max_size;	/* Largest size we find */
+	int		 attr_list;	/* MFT record may be one of many */
+	int		 directory;	/* MFT record represents a directory */
+	MFT_RECORD	*mft;		/* Raw MFT record */
+};
+
+#endif /* _NTFSUNDELETE_H_ */
+
diff --git a/ntfsprogs/ntfswipe.8 b/ntfsprogs/ntfswipe.8
new file mode 100755
index 0000000000000000000000000000000000000000..6912d3f12548f50964df45be999fa595b3a6aa4c
--- /dev/null
+++ b/ntfsprogs/ntfswipe.8
@@ -0,0 +1,128 @@
+.\" Copyright (c) 2014 Jean-Pierre Andre
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSWIPE 8 "June 2014" "ntfs-3g 2015.3.14"
+.SH NAME
+ntfswipe \- overwrite unused space on an NTFS volume
+.SH SYNOPSIS
+\fBntfswipe\fR [\fIoptions\fR] \fIdevice\fR
+.SH DESCRIPTION
+.B ntfswipe
+clears all or part of unused space on an NTFS volume by overwriting
+with zeroes or random bytes.
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfswipe
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-a\fR, \fB\-\-all\fR
+Wipe all unused space. This may take significant time.
+.TP
+\fB\-b\fR, \fB\-\-bytes\fR BYTE-LIST
+Define the allowed replacement bytes which are drawn randomly to overwrite
+the unused space. BYTE-LIST is a comma-separated list of values in
+range 0-255 expressed in octal, decimal or hexadecimal base.
+.TP
+\fB\-c\fR, \fB\-\-count\fR NUM
+Define the number of times the unused space is to be overwritten.
+.TP
+\fB\-d\fR, \fB\-\-directory\fR
+Wipe all the directory indexes, which may contain names of deleted files.
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+This will override some sensible defaults, such as not using a mounted volume.
+Use this option with caution.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.TP
+\fB\-i\fR, \fB\-\-info\fR
+Display details about unused space.
+.TP
+\fB\-l\fR, \fB\-\-logfile\fR
+Overwrite the logfile (update journal).
+.TP
+\fB\-m\fR, \fB\-\-mft\fR
+Overwrite the unused space in the MFT (main file table, which contains the
+file names, and the contents of short files).
+.TP
+\fB\-n\fR, \fB\-\-no-action\fR
+Executes the wiping process without writing to device.
+.TP
+\fB\-p\fR, \fB\-\-pagefile\fR
+Overwrite the Windows swap space.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Suppress some debug/warning/error messages.
+.TP
+\fB\-s\fR, \fB\-\-undel\fR
+Overwrite the space which had been allocated to a file which has been deleted
+recently and is still undeletable.
+.TP
+\fB\-t\fR, \fB\-\-tails\fR
+Overwrite the space at the end of files which is unused, but allocated
+because the allocations are always done by full clusters.
+.TP
+\fB\-u\fR, \fB\-\-unused\fR
+Overwrite the space which is currently not allocated to any file (but
+may have been used in the past).
+.TP
+\fB\-U\fR, \fB\-\-unused-fast\fR
+Overwrite the space which is currently not allocated to any file, trying
+not to overwrite the space not written to since the previous wiping.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Display more debug/warning/error messages.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Show the version number, copyright and license of
+.BR ntfswipe .
+.SH EXAMPLES
+Wipe out all unused space in an NTFS volume.
+.RS
+.sp
+.B ntfswipe -a /dev/sda1
+.sp
+.RE
+Wipe out all deleted file names from an NTFS volume.
+.RS
+.sp
+.B ntfswipe -dms /dev/sda1
+.sp
+.RE
+.SH BUGS
+There are no known problems with
+.BR ntfswipe .
+If you find a bug please send an email describing the problem to the
+development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+.B ntfswipe
+was written by Richard Russon, Anton Altaparmakov and Yura Pakhuchiy.
+It was ported to ntfs-3g by Erik Larsson.
+.SH AVAILABILITY
+.B ntfswipe
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR ntfs-3g (8),
+.BR ntfsls (8),
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/ntfswipe.8.in b/ntfsprogs/ntfswipe.8.in
new file mode 100755
index 0000000000000000000000000000000000000000..08192580500a50199c7c62adf6f6db51f21c0691
--- /dev/null
+++ b/ntfsprogs/ntfswipe.8.in
@@ -0,0 +1,128 @@
+.\" Copyright (c) 2014 Jean-Pierre Andre
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFSWIPE 8 "June 2014" "ntfs-3g @VERSION@"
+.SH NAME
+ntfswipe \- overwrite unused space on an NTFS volume
+.SH SYNOPSIS
+\fBntfswipe\fR [\fIoptions\fR] \fIdevice\fR
+.SH DESCRIPTION
+.B ntfswipe
+clears all or part of unused space on an NTFS volume by overwriting
+with zeroes or random bytes.
+.SH OPTIONS
+Below is a summary of all the options that
+.B ntfswipe
+accepts.  Nearly all options have two equivalent names.  The short name is
+preceded by
+.B \-
+and the long name is preceded by
+.BR \-\- .
+Any single letter options, that don't take an argument, can be combined into a
+single command, e.g.
+.B \-fv
+is equivalent to
+.BR "\-f \-v" .
+Long named options can be abbreviated to any unique prefix of their name.
+.TP
+\fB\-a\fR, \fB\-\-all\fR
+Wipe all unused space. This may take significant time.
+.TP
+\fB\-b\fR, \fB\-\-bytes\fR BYTE-LIST
+Define the allowed replacement bytes which are drawn randomly to overwrite
+the unused space. BYTE-LIST is a comma-separated list of values in
+range 0-255 expressed in octal, decimal or hexadecimal base.
+.TP
+\fB\-c\fR, \fB\-\-count\fR NUM
+Define the number of times the unused space is to be overwritten.
+.TP
+\fB\-d\fR, \fB\-\-directory\fR
+Wipe all the directory indexes, which may contain names of deleted files.
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+This will override some sensible defaults, such as not using a mounted volume.
+Use this option with caution.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show a list of options with a brief description of each one.
+.TP
+\fB\-i\fR, \fB\-\-info\fR
+Display details about unused space.
+.TP
+\fB\-l\fR, \fB\-\-logfile\fR
+Overwrite the logfile (update journal).
+.TP
+\fB\-m\fR, \fB\-\-mft\fR
+Overwrite the unused space in the MFT (main file table, which contains the
+file names, and the contents of short files).
+.TP
+\fB\-n\fR, \fB\-\-no-action\fR
+Executes the wiping process without writing to device.
+.TP
+\fB\-p\fR, \fB\-\-pagefile\fR
+Overwrite the Windows swap space.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Suppress some debug/warning/error messages.
+.TP
+\fB\-s\fR, \fB\-\-undel\fR
+Overwrite the space which had been allocated to a file which has been deleted
+recently and is still undeletable.
+.TP
+\fB\-t\fR, \fB\-\-tails\fR
+Overwrite the space at the end of files which is unused, but allocated
+because the allocations are always done by full clusters.
+.TP
+\fB\-u\fR, \fB\-\-unused\fR
+Overwrite the space which is currently not allocated to any file (but
+may have been used in the past).
+.TP
+\fB\-U\fR, \fB\-\-unused-fast\fR
+Overwrite the space which is currently not allocated to any file, trying
+not to overwrite the space not written to since the previous wiping.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Display more debug/warning/error messages.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Show the version number, copyright and license of
+.BR ntfswipe .
+.SH EXAMPLES
+Wipe out all unused space in an NTFS volume.
+.RS
+.sp
+.B ntfswipe -a /dev/sda1
+.sp
+.RE
+Wipe out all deleted file names from an NTFS volume.
+.RS
+.sp
+.B ntfswipe -dms /dev/sda1
+.sp
+.RE
+.SH BUGS
+There are no known problems with
+.BR ntfswipe .
+If you find a bug please send an email describing the problem to the
+development team:
+.br
+.nh
+ntfs\-3g\-devel@lists.sf.net
+.hy
+.SH AUTHORS
+.B ntfswipe
+was written by Richard Russon, Anton Altaparmakov and Yura Pakhuchiy.
+It was ported to ntfs-3g by Erik Larsson.
+.SH AVAILABILITY
+.B ntfswipe
+is part of the
+.B ntfs-3g
+package and is available from:
+.br
+.nh
+http://www.tuxera.com/community/
+.hy
+.SH SEE ALSO
+.BR ntfs-3g (8),
+.BR ntfsls (8),
+.BR ntfsprogs (8)
diff --git a/ntfsprogs/ntfswipe.c b/ntfsprogs/ntfswipe.c
new file mode 100755
index 0000000000000000000000000000000000000000..658aaac08b4d86f15516c06c4d7dd88a0645e946
--- /dev/null
+++ b/ntfsprogs/ntfswipe.c
@@ -0,0 +1,2260 @@
+/**
+ * ntfswipe - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2005 Anton Altaparmakov
+ * Copyright (c) 2002-2005 Richard Russon
+ * Copyright (c) 2004 Yura Pakhuchiy
+ *
+ * This utility will overwrite unused space on an NTFS volume.
+ *
+ * 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 Linux-NTFS
+ * 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_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#else
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+#include "ntfswipe.h"
+#include "types.h"
+#include "volume.h"
+#include "utils.h"
+#include "debug.h"
+#include "dir.h"
+#include "mst.h"
+/* #include "version.h" */
+#include "logging.h"
+#include "list.h"
+#include "mft.h"
+
+static const char *EXEC_NAME = "ntfswipe";
+static struct options opts;
+static unsigned long int npasses = 0;
+
+struct filename {
+	char		*parent_name;
+	struct ntfs_list_head list;	/* Previous/Next links */
+	ntfschar	*uname;		/* Filename in unicode */
+	int		 uname_len;	/* and its length */
+		/* Allocated size (multiple of cluster size) */
+	s64		 size_alloc;
+	s64		 size_data;	/* Actual size of data */
+	long long	 parent_mref;
+	FILE_ATTR_FLAGS	 flags;
+	time_t		 date_c;	/* Time created */
+	time_t		 date_a;	/*	altered */
+	time_t		 date_m;	/*	mft record changed */
+	time_t		 date_r;	/*	read */
+	char		*name;		/* Filename in current locale */
+	FILE_NAME_TYPE_FLAGS name_space;
+	char		 padding[7];	/* Unused: padding to 64 bit. */
+};
+
+struct data {
+	struct ntfs_list_head list;	/* Previous/Next links */
+	char		*name;		/* Stream name in current locale */
+	ntfschar	*uname;		/* Unicode stream name */
+	int		 uname_len;	/* and its length */
+	int		 resident;	/* Stream is resident */
+	int		 compressed;	/* Stream is compressed */
+	int		 encrypted;	/* Stream is encrypted */
+		/* Allocated size (multiple of cluster size) */
+	s64		 size_alloc;
+	s64		 size_data;	/* Actual size of data */
+		/* Initialised size, may be less than data size */
+	s64		 size_init;
+	VCN		 size_vcn;	/* Highest VCN in the data runs */
+	runlist_element *runlist;	/* Decoded data runs */
+	int		 percent;	/* Amount potentially recoverable */
+	void		*data;	       /* If resident, a pointer to the data */
+	char		 padding[4];	/* Unused: padding to 64 bit. */
+};
+
+struct ufile {
+	s64		 inode;		/* MFT record number */
+	time_t		 date;		/* Last modification date/time */
+	struct ntfs_list_head name;		/* A list of filenames */
+	struct ntfs_list_head data;		/* A list of data streams */
+	char		*pref_name;	/* Preferred filename */
+	char		*pref_pname;	/*	     parent filename */
+	s64		 max_size;	/* Largest size we find */
+	int		 attr_list;	/* MFT record may be one of many */
+	int		 directory;	/* MFT record represents a directory */
+	MFT_RECORD	*mft;		/* Raw MFT record */
+	char		 padding[4];	/* Unused: padding to 64 bit. */
+};
+
+#define NPAT 22
+
+/* Taken from `shred' source */
+static const unsigned int patterns[NPAT] = {
+	0x000, 0xFFF,					/* 1-bit */
+	0x555, 0xAAA,					/* 2-bit */
+	0x249, 0x492, 0x6DB, 0x924, 0xB6D, 0xDB6,	/* 3-bit */
+	0x111, 0x222, 0x333, 0x444, 0x666, 0x777,
+	0x888, 0x999, 0xBBB, 0xCCC, 0xDDD, 0xEEE	/* 4-bit */
+};
+
+
+/**
+ * version - Print version information about the program
+ *
+ * Print a copyright statement and a brief description of the program.
+ *
+ * Return:  none
+ */
+static void version(void)
+{
+	ntfs_log_info("\n%s v%s (libntfs-3g) - Overwrite the unused space on an NTFS "
+			"Volume.\n\n", EXEC_NAME, VERSION);
+	ntfs_log_info("Copyright (c) 2002-2005 Richard Russon\n");
+	ntfs_log_info("Copyright (c) 2004 Yura Pakhuchiy\n");
+	ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
+}
+
+/**
+ * usage - Print a list of the parameters to the program
+ *
+ * Print a list of the parameters and options for the program.
+ *
+ * Return:  none
+ */
+static void usage(void)
+{
+	ntfs_log_info("\nUsage: %s [options] device\n"
+		"    -i       --info        Show volume information (default)\n"
+		"\n"
+		"    -d       --directory   Wipe directory indexes\n"
+		"    -l       --logfile     Wipe the logfile (journal)\n"
+		"    -m       --mft         Wipe mft space\n"
+		"    -p       --pagefile    Wipe pagefile (swap space)\n"
+		"    -t       --tails       Wipe file tails\n"
+		"    -u       --unused      Wipe unused clusters\n"
+		"    -U       --unused-fast Wipe unused clusters (fast)\n"
+		"    -s       --undel       Wipe undelete data\n"
+		"\n"
+		"    -a       --all         Wipe all unused space\n"
+		"\n"
+		"    -c num   --count num   Number of times to write(default = 1)\n"
+		"    -b list  --bytes list  List of values to write(default = 0)\n"
+		"\n"
+		"    -n       --no-action   Do not write to disk\n"
+		"    -f       --force       Use less caution\n"
+		"    -q       --quiet       Less output\n"
+		"    -v       --verbose     More output\n"
+		"    -V       --version     Version information\n"
+		"    -h       --help        Print this help\n\n",
+		EXEC_NAME);
+	ntfs_log_info("%s%s\n", ntfs_bugs, ntfs_home);
+}
+
+/**
+ * parse_list - Read a comma-separated list of numbers
+ * @list:    The comma-separated list of numbers
+ * @result:  Store the parsed list here (must be freed by caller)
+ *
+ * Read a comma-separated list of numbers and allocate an array of ints to store
+ * them in.  The numbers can be in decimal, octal or hex.
+ *
+ * N.B.  The caller must free the memory returned in @result.
+ * N.B.  If the function fails, @result is not changed.
+ *
+ * Return:  0  Error, invalid string
+ *	    n  Success, the count of numbers parsed
+ */
+static int parse_list(char *list, int **result)
+{
+	char *ptr;
+	char *end;
+	int i;
+	int count;
+	int *mem = NULL;
+
+	if (!list || !result)
+		return 0;
+
+	for (count = 0, ptr = list; ptr; ptr = strchr(ptr+1, ','))
+		count++;
+
+	mem = malloc((count+1) * sizeof(int));
+	if (!mem) {
+		ntfs_log_error("Couldn't allocate memory in parse_list().\n");
+		return 0;
+	}
+
+	memset(mem, 0xFF, (count+1) * sizeof(int));
+
+	for (ptr = list, i = 0; i < count; i++) {
+
+		end = NULL;
+		mem[i] = strtol(ptr, &end, 0);
+
+		if (!end || (end == ptr) || ((*end != ',') && (*end != 0))) {
+			ntfs_log_error("Invalid list '%s'\n", list);
+			free(mem);
+			return 0;
+		}
+
+		if ((mem[i] < 0) || (mem[i] > 255)) {
+			ntfs_log_error("Bytes must be in range 0-255.\n");
+			free(mem);
+			return 0;
+		}
+
+		ptr = end + 1;
+	}
+
+	ntfs_log_debug("Parsing list '%s' - ", list);
+	for (i = 0; i <= count; i++)
+		ntfs_log_debug("0x%02x ", mem[i]);
+	ntfs_log_debug("\n");
+
+	*result = mem;
+	return count;
+}
+
+/**
+ * parse_options - Read and validate the programs command line
+ *
+ * Read the command line, verify the syntax and parse the options.
+ * This function is very long, but quite simple.
+ *
+ * Return:  1 Success
+ *	    0 Error, one or more problems
+ */
+static int parse_options(int argc, char *argv[])
+{
+	static const char *sopt = "-ab:c:dfh?ilmnpqtuUvVs";
+	static struct option lopt[] = {
+		{ "all",	no_argument,		NULL, 'a' },
+		{ "bytes",	required_argument,	NULL, 'b' },
+		{ "count",	required_argument,	NULL, 'c' },
+		{ "directory",	no_argument,		NULL, 'd' },
+		{ "force",	no_argument,		NULL, 'f' },
+		{ "help",	no_argument,		NULL, 'h' },
+		{ "info",	no_argument,		NULL, 'i' },
+		{ "logfile",	no_argument,		NULL, 'l' },
+		{ "mft",	no_argument,		NULL, 'm' },
+		{ "no-action",	no_argument,		NULL, 'n' },
+		//{ "no-wait",	no_argument,		NULL, 0   },
+		{ "pagefile",	no_argument,		NULL, 'p' },
+		{ "quiet",	no_argument,		NULL, 'q' },
+		{ "tails",	no_argument,		NULL, 't' },
+		{ "unused",	no_argument,		NULL, 'u' },
+		{ "unused-fast",no_argument,		NULL, 'U' },
+		{ "undel",	no_argument,		NULL, 's' },
+		{ "verbose",	no_argument,		NULL, 'v' },
+		{ "version",	no_argument,		NULL, 'V' },
+		{ NULL,		0,			NULL, 0   }
+	};
+
+	int c = -1;
+	char *end;
+	int err  = 0;
+	int ver  = 0;
+	int help = 0;
+	int levels = 0;
+
+	opterr = 0; /* We'll handle the errors, thank you. */
+
+	opts.count = 1;
+
+	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
+		switch (c) {
+		case 1:	/* A non-option argument */
+			if (!opts.device) {
+				opts.device = argv[optind-1];
+			} else {
+				opts.device = NULL;
+				err++;
+			}
+			break;
+
+		case 'i':
+			opts.info++;		/* and fall through */
+		case 'a':
+			opts.directory++;
+			opts.logfile++;
+			opts.mft++;
+			opts.pagefile++;
+			opts.tails++;
+			opts.unused++;
+			opts.undel++;
+			break;
+		case 'b':
+			if (!opts.bytes) {
+				if (!parse_list(optarg, &opts.bytes))
+					err++;
+			} else {
+				err++;
+			}
+			break;
+		case 'c':
+			if (opts.count == 1) {
+				end = NULL;
+				opts.count = strtol(optarg, &end, 0);
+				if (end && *end)
+					err++;
+			} else {
+				err++;
+			}
+			break;
+		case 'd':
+			opts.directory++;
+			break;
+		case 'f':
+			opts.force++;
+			break;
+		case 'h':
+			help++;
+			break;
+		case 'l':
+			opts.logfile++;
+			break;
+		case 'm':
+			opts.mft++;
+			break;
+		case 'n':
+			opts.noaction++;
+			break;
+		case 'p':
+			opts.pagefile++;
+			break;
+		case 'q':
+			opts.quiet++;
+			ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
+			break;
+		case 's':
+			opts.undel++;
+			break;
+		case 't':
+			opts.tails++;
+			break;
+		case 'u':
+			opts.unused++;
+			break;
+		case 'U':
+			opts.unused_fast++;
+			break;
+		case 'v':
+			opts.verbose++;
+			ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
+			break;
+		case 'V':
+			ver++;
+			break;
+		case '?':
+			if (strncmp (argv[optind-1], "--log-", 6) == 0) {
+				if (!ntfs_log_parse_option (argv[optind-1]))
+					err++;
+				break;
+			}
+			/* fall through */
+		default:
+			if ((optopt == 'b') || (optopt == 'c')) {
+				ntfs_log_error("Option '%s' requires an argument.\n", argv[optind-1]);
+			} else {
+				ntfs_log_error("Unknown option '%s'.\n", argv[optind-1]);
+			}
+			err++;
+			break;
+		}
+	}
+
+	/* Make sure we're in sync with the log levels */
+	levels = ntfs_log_get_levels();
+	if (levels & NTFS_LOG_LEVEL_VERBOSE)
+		opts.verbose++;
+	if (!(levels & NTFS_LOG_LEVEL_QUIET))
+		opts.quiet++;
+
+	if (help || ver) {
+		opts.quiet = 0;
+	} else {
+		if (opts.device == NULL) {
+			if (argc > 1)
+				ntfs_log_error("You must specify exactly one device.\n");
+			err++;
+		}
+
+		if (opts.quiet && opts.verbose) {
+			ntfs_log_error("You may not use --quiet and --verbose at the same time.\n");
+			err++;
+		}
+
+		/*
+		if (opts.info && (opts.unused || opts.tails || opts.mft || opts.directory)) {
+			ntfs_log_error("You may not use any other options with --info.\n");
+			err++;
+		}
+		*/
+
+		if ((opts.count < 1) || (opts.count > 100)) {
+			ntfs_log_error("The iteration count must be between 1 and 100.\n");
+			err++;
+		}
+
+		/* Create a default list */
+		if (!opts.bytes) {
+			opts.bytes = malloc(2 * sizeof(int));
+			if (opts.bytes) {
+				opts.bytes[0] =  0;
+				opts.bytes[1] = -1;
+			} else {
+				ntfs_log_error("Couldn't allocate memory for byte list.\n");
+				err++;
+			}
+		}
+
+		if (!opts.directory && !opts.logfile && !opts.mft &&
+		    !opts.pagefile && !opts.tails && !opts.unused &&
+		    !opts.unused_fast && !opts.undel) {
+			opts.info = 1;
+		}
+	}
+
+	if (ver)
+		version();
+	if (help || err)
+		usage();
+
+		/* tri-state 0 : done, 1 : error, -1 : proceed */
+	return (err ? 1 : (help || ver ? 0 : -1));
+}
+
+/**
+ * wipe_unused - Wipe unused clusters
+ * @vol:   An ntfs volume obtained from ntfs_mount
+ * @byte:  Overwrite with this value
+ * @act:   Wipe, test or info
+ *
+ * Read $Bitmap and wipe any clusters that are marked as not in use.
+ *
+ * Return: >0  Success, the attribute was wiped
+ *          0  Nothing to wipe
+ *         -1  Error, something went wrong
+ */
+static s64 wipe_unused(ntfs_volume *vol, int byte, enum action act)
+{
+	s64 i;
+	s64 total = 0;
+	s64 result = 0;
+	u8 *buffer = NULL;
+
+	if (!vol || (byte < 0))
+		return -1;
+
+	if (act != act_info) {
+		buffer = malloc(vol->cluster_size);
+		if (!buffer) {
+			ntfs_log_error("malloc failed\n");
+			return -1;
+		}
+		memset(buffer, byte, vol->cluster_size);
+	}
+
+	for (i = 0; i < vol->nr_clusters; i++) {
+		if (utils_cluster_in_use(vol, i)) {
+			//ntfs_log_verbose("cluster %lld is in use\n", i);
+			continue;
+		}
+
+		if (act == act_wipe) {
+			//ntfs_log_verbose("cluster %lld is not in use\n", i);
+			result = ntfs_pwrite(vol->dev, vol->cluster_size * i, vol->cluster_size, buffer);
+			if (result != vol->cluster_size) {
+				ntfs_log_error("write failed\n");
+				goto free;
+			}
+		}
+
+		total += vol->cluster_size;
+	}
+
+	ntfs_log_quiet("wipe_unused 0x%02x, %lld bytes\n", byte, (long long)total);
+free:
+	free(buffer);
+	return total;
+}
+
+/**
+ * wipe_unused_fast - Faster wipe unused clusters
+ * @vol:   An ntfs volume obtained from ntfs_mount
+ * @byte:  Overwrite with this value
+ * @act:   Wipe, test or info
+ *
+ * Read $Bitmap and wipe any clusters that are marked as not in use.
+ *
+ * - read/write on a block basis (64 clusters, arbitrary)
+ * - skip of fully used block
+ * - skip non-used block already wiped
+ *
+ * Return: >0  Success, the attribute was wiped
+ *          0  Nothing to wipe
+ *         -1  Error, something went wrong
+ */
+static s64 wipe_unused_fast(ntfs_volume *vol, int byte, enum action act)
+{
+	s64 i;
+	s64 total = 0;
+	s64 unused = 0;
+	s64 result;
+	u8 *buffer;
+	u8 *big_buffer;
+	u32 *u32_buffer;
+	u32 u32_bytes;
+	unsigned int blksize;
+	unsigned int j,k;
+	BOOL wipe_needed;
+
+	if (!vol || (byte < 0))
+		return -1;
+
+	big_buffer = (u8*)malloc(vol->cluster_size*64);
+	if (!big_buffer) {
+		ntfs_log_error("malloc failed\n");
+		return -1;
+	}
+
+	for (i = 0; i < vol->nr_clusters; i+=64) {
+		blksize = vol->nr_clusters - i;
+		if (blksize > 64)
+			blksize = 64;
+	   /* if all clusters in this block are used, ignore the block */
+		result = 0;
+		for (j = 0; j < blksize; j++) {
+			if (utils_cluster_in_use(vol, i+j))
+				result++;
+		}
+		unused += (blksize - result) * vol->cluster_size;
+
+		if (result == blksize) {
+			continue;
+		}
+		/*
+		 * if all unused clusters in this block are already wiped,
+		 * ignore the block
+		 */
+		if (ntfs_pread(vol->dev, vol->cluster_size * i,
+					vol->cluster_size * blksize, big_buffer)
+				!= vol->cluster_size * blksize) {
+			ntfs_log_error("Read failed at cluster %lld\n",
+					(long long)i);
+			goto free;
+		}
+
+		result = 0;
+		wipe_needed = FALSE;
+		u32_bytes = (byte & 255)*0x01010101;
+		buffer = big_buffer;
+		for (j = 0; (j < blksize) && !wipe_needed; j++) {
+			u32_buffer = (u32*)buffer;
+			if (!utils_cluster_in_use(vol, i+j)) {
+				for (k = 0; (k < vol->cluster_size)
+					&& (*u32_buffer++ == u32_bytes); k+=4) {
+				}
+				if (k < vol->cluster_size)
+					wipe_needed = TRUE;
+			}
+			buffer += vol->cluster_size;
+		}
+
+		if (!wipe_needed) { 
+			continue;
+		}
+			/* else wipe unused clusters in the block */
+		buffer = big_buffer;
+
+		for (j = 0; j < blksize; j++) {
+			if (!utils_cluster_in_use(vol, i+j)) {
+				memset(buffer, byte, vol->cluster_size);
+				total += vol->cluster_size;
+			}
+			buffer += vol->cluster_size;
+		}
+
+		if ((act == act_wipe)
+			&& (ntfs_pwrite(vol->dev, vol->cluster_size * i,
+				vol->cluster_size * blksize, big_buffer)
+					!= vol->cluster_size * blksize)) {
+			ntfs_log_error("Write failed at cluster %lld\n",
+					(long long)i);
+			goto free;
+		}
+	}
+
+	ntfs_log_quiet("wipe_unused_fast 0x%02x, %lld bytes"
+			" already wiped, %lld more bytes wiped\n",
+			byte, (long long)(unused - total), (long long)total);
+free:
+	free(big_buffer);
+	return total;
+}
+
+/**
+ * wipe_compressed_attribute - Wipe compressed $DATA attribute
+ * @vol:	An ntfs volume obtained from ntfs_mount
+ * @byte:	Overwrite with this value
+ * @act:	Wipe, test or info
+ * @na:		Opened ntfs attribute
+ *
+ * Return: >0  Success, the attribute was wiped
+ *          0  Nothing to wipe
+ *         -1  Error, something went wrong
+ */
+static s64 wipe_compressed_attribute(ntfs_volume *vol, int byte,
+						enum action act, ntfs_attr *na)
+{
+	unsigned char *buf;
+	s64 size, offset, ret, wiped = 0;
+	le16 block_size_le;
+	u16 block_size;
+	VCN cur_vcn = 0;
+	runlist_element *rlc = na->rl;
+	s64 cu_mask = na->compression_block_clusters - 1;
+	runlist_element *restart = na->rl;
+
+	while (rlc->length) {
+		cur_vcn += rlc->length;
+		if ((cur_vcn & cu_mask) ||
+			(((rlc + 1)->length) && (rlc->lcn != LCN_HOLE))) {
+			rlc++;
+			continue;
+		}
+
+		if (rlc->lcn == LCN_HOLE) {
+			runlist_element *rlt;
+
+			offset = cur_vcn - rlc->length;
+			if (offset == (offset & (~cu_mask))) {
+				restart = rlc + 1;
+				rlc++;
+				continue;
+			}
+			offset = (offset & (~cu_mask))
+						<< vol->cluster_size_bits;
+			rlt = rlc;
+			while ((rlt - 1)->lcn == LCN_HOLE) rlt--;
+			while (1) {
+				ret = ntfs_rl_pread(vol, restart,
+    					offset - (restart->vcn
+    					<< vol->cluster_size_bits),
+					2, &block_size_le);
+				block_size = le16_to_cpu(block_size_le);
+				if (ret != 2) {
+					ntfs_log_verbose("Internal error\n");
+					ntfs_log_error("ntfs_rl_pread failed");
+					return -1;
+				}
+				if (block_size == 0) {
+					offset += 2;
+					break;
+				}
+				block_size &= 0x0FFF;
+				block_size += 3;
+				offset += block_size;
+				if (offset >= (((rlt->vcn) <<
+						vol->cluster_size_bits) - 2))
+					goto next;
+			}
+			size = (rlt->vcn << vol->cluster_size_bits) - offset;
+		} else {
+			size = na->allocated_size - na->data_size;
+			offset = (cur_vcn << vol->cluster_size_bits) - size;
+		}
+
+		if (size < 0) {
+			ntfs_log_verbose("Internal error\n");
+			ntfs_log_error("bug or damaged fs: we want "
+				"allocate buffer size %lld bytes",
+				(long long)size);
+			return -1;
+		}
+
+		if ((act == act_info) || (!size)) {
+			wiped += size;
+			if (rlc->lcn == LCN_HOLE)
+				restart = rlc + 1;
+			rlc++;
+			continue;
+		}
+
+		buf = malloc(size);
+		if (!buf) {
+			ntfs_log_verbose("Not enough memory\n");
+			ntfs_log_error("Not enough memory to allocate "
+							"%lld bytes",
+							(long long)size);
+			return -1;
+		}
+		memset(buf, byte, size);
+
+		ret = ntfs_rl_pwrite(vol, restart,
+    			restart->vcn << vol->cluster_size_bits,
+			offset, size, buf);
+		free(buf);
+		if (ret != size) {
+			ntfs_log_verbose("Internal error\n");
+			ntfs_log_error("ntfs_rl_pwrite failed, offset %llu, "
+				"size %lld, vcn %lld",
+				(unsigned long long)offset,
+				(long long)size, (long long)rlc->vcn);
+			return -1;
+		}
+		wiped += ret;
+next:
+		if (rlc->lcn == LCN_HOLE)
+			restart = rlc + 1;
+		rlc++;
+	}
+
+	return wiped;
+}
+
+/**
+ * wipe_attribute - Wipe not compressed $DATA attribute
+ * @vol:	An ntfs volume obtained from ntfs_mount
+ * @byte:	Overwrite with this value
+ * @act:	Wipe, test or info
+ * @na:		Opened ntfs attribute
+ *
+ * Return: >0  Success, the attribute was wiped
+ *          0  Nothing to wipe
+ *         -1  Error, something went wrong
+ */
+static s64 wipe_attribute(ntfs_volume *vol, int byte, enum action act,
+								ntfs_attr *na)
+{
+	unsigned char *buf;
+	s64 wiped;
+	s64 size;
+	u64 offset = na->data_size;
+
+	if (!offset)
+		return 0;
+	if (na->data_flags & ATTR_IS_ENCRYPTED)
+		offset = (((offset - 1) >> 10) + 1) << 10;
+	size = (vol->cluster_size - offset) % vol->cluster_size;
+
+	if (act == act_info)
+		return size;
+
+	buf = malloc(size);
+	if (!buf) {
+		ntfs_log_verbose("Not enough memory\n");
+		ntfs_log_error("Not enough memory to allocate %lld bytes",
+					(long long)size);
+		return -1;
+	}
+	memset(buf, byte, size);
+
+	wiped = ntfs_rl_pwrite(vol, na->rl, 0, offset, size, buf);
+	if (wiped == -1) {
+		ntfs_log_verbose("Internal error\n");
+		ntfs_log_error("Couldn't wipe tail");
+	}
+
+	free(buf);
+	return wiped;
+}
+
+/*
+ *		Wipe a data attribute tail
+ *
+ * Return: >0  Success, the clusters were wiped
+ *          0  Nothing to wipe
+ *         -1  Error, something went wrong
+ */
+
+static s64 wipe_attr_tail(ntfs_inode *ni, ntfschar *name, int namelen,
+					int byte, enum action act)
+{
+	ntfs_attr *na;
+	ntfs_volume *vol = ni->vol;
+	s64 wiped;
+
+	wiped = -1;
+	na = ntfs_attr_open(ni, AT_DATA, name, namelen);
+	if (!na) {
+		ntfs_log_error("Couldn't open $DATA attribute\n");
+		goto close_attr;
+	}
+
+	if (!NAttrNonResident(na)) {
+		ntfs_log_verbose("Resident $DATA attribute. Skipping.\n");
+		goto close_attr;
+	}
+
+	if (ntfs_attr_map_whole_runlist(na)) {
+		ntfs_log_verbose("Internal error\n");
+		ntfs_log_error("Can't map runlist (inode %lld)\n",
+				(long long)ni->mft_no);
+		goto close_attr;
+	}
+
+	if (na->data_flags & ATTR_COMPRESSION_MASK)
+		wiped = wipe_compressed_attribute(vol, byte, act, na);
+	else
+		wiped = wipe_attribute(vol, byte, act, na);
+
+	if (wiped == -1) {
+		ntfs_log_error(" (inode %lld)\n", (long long)ni->mft_no);
+	}
+
+close_attr:
+	ntfs_attr_close(na);
+	return (wiped);
+}
+
+/**
+ * wipe_tails - Wipe the file tails in all its data attributes
+ * @vol:   An ntfs volume obtained from ntfs_mount
+ * @byte:  Overwrite with this value
+ * @act:   Wipe, test or info
+ *
+ * Disk space is allocated in clusters.  If a file isn't an exact multiple of
+ * the cluster size, there is some slack space at the end.  Wipe this space.
+ *
+ * Return: >0  Success, the clusters were wiped
+ *          0  Nothing to wipe
+ *         -1  Error, something went wrong
+ */
+static s64 wipe_tails(ntfs_volume *vol, int byte, enum action act)
+{
+	s64 total = 0;
+	s64 nr_mft_records, inode_num;
+	ntfs_attr_search_ctx *ctx;
+	ntfs_inode *ni;
+	ATTR_RECORD *a;
+	ntfschar *name;
+
+	if (!vol || (byte < 0))
+		return -1;
+
+	nr_mft_records = vol->mft_na->initialized_size >>
+			vol->mft_record_size_bits;
+
+	for (inode_num = FILE_first_user; inode_num < nr_mft_records;
+							inode_num++) {
+		s64 attr_wiped;
+		s64 wiped = 0;
+
+		ntfs_log_verbose("Inode %lld - ", (long long)inode_num);
+		ni = ntfs_inode_open(vol, inode_num);
+		if (!ni) {
+			ntfs_log_verbose("Could not open inode\n");
+			continue;
+		}
+
+		if (ni->mrec->base_mft_record) {
+			ntfs_log_verbose("Not base mft record. Skipping\n");
+			goto close_inode;
+		}
+
+		ctx = ntfs_attr_get_search_ctx(ni, (MFT_RECORD*)NULL);
+		if (!ctx) {
+			ntfs_log_error("Can't get a context, aborting\n");
+			ntfs_inode_close(ni);
+			goto close_abort;
+		}
+		while (!ntfs_attr_lookup(AT_DATA, NULL, 0, CASE_SENSITIVE, 0,
+							NULL, 0, ctx)) {
+			a = ctx->attr;
+
+			if (!ctx->al_entry || !ctx->al_entry->lowest_vcn) {
+				name = (ntfschar*)((u8*)a
+						+ le16_to_cpu(a->name_offset));
+				attr_wiped = wipe_attr_tail(ni, name,
+						a->name_length, byte, act);
+				if (attr_wiped > 0)
+					wiped += attr_wiped;
+			}
+		}
+		ntfs_attr_put_search_ctx(ctx);
+		if (wiped) {
+			ntfs_log_verbose("Wiped %llu bytes\n",
+					(unsigned long long)wiped);
+			total += wiped;
+		} else
+			ntfs_log_verbose("Nothing to wipe\n");
+close_inode:
+		ntfs_inode_close(ni);
+	}
+close_abort :
+	ntfs_log_quiet("wipe_tails 0x%02x, %lld bytes\n", byte,
+				(long long)total);
+	return total;
+}
+
+/**
+ * wipe_mft - Wipe the MFT slack space
+ * @vol:   An ntfs volume obtained from ntfs_mount
+ * @byte:  Overwrite with this value
+ * @act:   Wipe, test or info
+ *
+ * MFT Records are 1024 bytes long, but some of this space isn't used.  Wipe any
+ * unused space at the end of the record and wipe any unused records.
+ *
+ * Return: >0  Success, the clusters were wiped
+ *          0  Nothing to wipe
+ *         -1  Error, something went wrong
+ */
+static s64 wipe_mft(ntfs_volume *vol, int byte, enum action act)
+{
+	// by considering the individual attributes we might be able to
+	// wipe a few more bytes at the attr's tail.
+	s64 nr_mft_records, i;
+	s64 total = 0;
+	s64 result = 0;
+	int size = 0;
+	MFT_RECORD *rec = NULL;
+
+	if (!vol || (byte < 0))
+		return -1;
+
+	rec = (MFT_RECORD*)malloc(vol->mft_record_size);
+	if (!rec) {
+		ntfs_log_error("malloc failed\n");
+		return -1;
+	}
+
+	nr_mft_records = vol->mft_na->initialized_size >>
+			vol->mft_record_size_bits;
+
+	for (i = 0; i < nr_mft_records; i++) {
+		if (utils_mftrec_in_use(vol, i)) {
+			result = ntfs_attr_mst_pread(vol->mft_na, vol->mft_record_size * i,
+				1, vol->mft_record_size, rec);
+			if (result != 1) {
+				ntfs_log_error("error attr mst read %lld\n",
+						(long long)i);
+				total = -1;	// XXX just negate result?
+				goto free;
+			}
+
+			// We know that the end marker will only take 4 bytes
+			size = le32_to_cpu(rec->bytes_in_use) - 4;
+
+			if (act == act_info) {
+				//ntfs_log_info("mft %d\n", size);
+				total += size;
+				continue;
+			}
+
+			memset(((u8*) rec) + size, byte, vol->mft_record_size - size);
+		} else {
+			const u16 usa_offset =
+				(vol->major_ver == 3) ? 0x0030 : 0x002A;
+			const u32 usa_size = 1 +
+				(vol->mft_record_size >> NTFS_BLOCK_SIZE_BITS);
+			const u16 attrs_offset =
+				((usa_offset + usa_size) + 7) & ~((u16) 7);
+			const u32 bytes_in_use = attrs_offset + 8;
+
+			if(usa_size > 0xFFFF || (usa_offset + usa_size) >
+				(NTFS_BLOCK_SIZE - sizeof(u16)))
+			{
+				ntfs_log_error("%d: usa_size out of bounds "
+					"(%u)\n", __LINE__, usa_size);
+				total = -1;
+				goto free;
+			}
+
+			if (act == act_info) {
+				total += vol->mft_record_size;
+				continue;
+			}
+
+			// Build the record from scratch
+			memset(rec, 0, vol->mft_record_size);
+
+			// Common values
+			rec->magic = magic_FILE;
+			rec->usa_ofs = cpu_to_le16(usa_offset);
+			rec->usa_count = cpu_to_le16((u16) usa_size);
+			rec->sequence_number = cpu_to_le16(0x0001);
+			rec->attrs_offset = cpu_to_le16(attrs_offset);
+			rec->bytes_in_use = cpu_to_le32(bytes_in_use);
+			rec->bytes_allocated = cpu_to_le32(vol->mft_record_size);
+			rec->next_attr_instance = cpu_to_le16(0x0001);
+
+			// End marker.
+			*((le32*) (((u8*) rec) + attrs_offset)) = cpu_to_le32(0xFFFFFFFF);
+		}
+
+		result = ntfs_attr_mst_pwrite(vol->mft_na, vol->mft_record_size * i,
+			1, vol->mft_record_size, rec);
+		if (result != 1) {
+			ntfs_log_error("error attr mst write %lld\n",
+					(long long)i);
+			total = -1;
+			goto free;
+		}
+
+		if ((vol->mft_record_size * (i+1)) <= vol->mftmirr_na->allocated_size)
+		{
+			// We have to reduce the update sequence number, or else...
+			u16 offset;
+			le16 *usnp;
+			offset = le16_to_cpu(rec->usa_ofs);
+			usnp = (le16*) (((u8*) rec) + offset);
+			*usnp = cpu_to_le16(le16_to_cpu(*usnp) - 1);
+
+			result = ntfs_attr_mst_pwrite(vol->mftmirr_na, vol->mft_record_size * i,
+				1, vol->mft_record_size, rec);
+			if (result != 1) {
+				ntfs_log_error("error attr mst write %lld\n",
+						(long long)i);
+				total = -1;
+				goto free;
+			}
+		}
+
+		total += vol->mft_record_size;
+	}
+
+	ntfs_log_quiet("wipe_mft 0x%02x, %lld bytes\n", byte, (long long)total);
+free:
+	free(rec);
+	return total;
+}
+
+/**
+ * wipe_index_allocation - Wipe $INDEX_ALLOCATION attribute
+ * @vol:		An ntfs volume obtained from ntfs_mount
+ * @byte:		Overwrite with this value
+ * @act:		Wipe, test or info
+ * @naa:		Opened ntfs $INDEX_ALLOCATION attribute
+ * @nab:		Opened ntfs $BITMAP attribute
+ * @indx_record_size:	Size of INDX record
+ *
+ * Return: >0  Success, the clusters were wiped
+ *          0  Nothing to wipe
+ *         -1  Error, something went wrong
+ */
+static s64 wipe_index_allocation(ntfs_volume *vol, int byte, enum action act
+	__attribute__((unused)), ntfs_attr *naa, ntfs_attr *nab,
+	u32 indx_record_size)
+{
+	s64 total = 0;
+	s64 wiped = 0;
+	s64 offset = 0;
+	s64 obyte = 0;
+	u64 wipe_offset;
+	s64 wipe_size;
+	u8 obit = 0;
+	u8 mask;
+	u8 *bitmap;
+	u8 *buf;
+
+	bitmap = malloc(nab->data_size);
+	if (!bitmap) {
+		ntfs_log_verbose("malloc failed\n");
+		ntfs_log_error("Couldn't allocate %lld bytes",
+				(long long)nab->data_size);
+		return -1;
+	}
+
+	if (ntfs_attr_pread(nab, 0, nab->data_size, bitmap)
+						!= nab->data_size) {
+		ntfs_log_verbose("Internal error\n");
+		ntfs_log_error("Couldn't read $BITMAP");
+		total = -1;
+		goto free_bitmap;
+	}
+
+	buf = malloc(indx_record_size);
+	if (!buf) {
+		ntfs_log_verbose("malloc failed\n");
+		ntfs_log_error("Couldn't allocate %u bytes",
+				(unsigned int)indx_record_size);
+		total = -1;
+		goto free_bitmap;
+	}
+
+	while (offset < naa->allocated_size) {
+		mask = 1 << obit;
+		if (bitmap[obyte] & mask) {
+			INDEX_ALLOCATION *indx;
+
+			s64 ret = ntfs_rl_pread(vol, naa->rl,
+					offset, indx_record_size, buf);
+			if (ret != indx_record_size) {
+				ntfs_log_verbose("ntfs_rl_pread failed\n");
+				ntfs_log_error("Couldn't read INDX record");
+				total = -1;
+				goto free_buf;
+			}
+
+			indx = (INDEX_ALLOCATION *) buf;
+			if (ntfs_mst_post_read_fixup((NTFS_RECORD *)buf,
+								indx_record_size))
+				ntfs_log_error("damaged fs: mst_post_read_fixup failed");
+
+			if ((le32_to_cpu(indx->index.allocated_size) + 0x18) !=
+							indx_record_size) {
+				ntfs_log_verbose("Internal error\n");
+				ntfs_log_error("INDX record should be %u bytes",
+						(unsigned int)indx_record_size);
+				total = -1;
+				goto free_buf;
+			}
+
+			wipe_offset = le32_to_cpu(indx->index.index_length) + 0x18;
+			wipe_size = indx_record_size - wipe_offset;
+			memset(buf + wipe_offset, byte, wipe_size);
+			if (ntfs_mst_pre_write_fixup((NTFS_RECORD *)indx,
+								indx_record_size))
+				ntfs_log_error("damaged fs: mst_pre_write_protect failed");
+			if (opts.verbose > 1)
+				ntfs_log_verbose("+");
+		} else {
+			wipe_size = indx_record_size;
+			memset(buf, byte, wipe_size);
+			if (opts.verbose > 1)
+				ntfs_log_verbose("x");
+		}
+
+		wiped = ntfs_rl_pwrite(vol, naa->rl, 0, offset, indx_record_size, buf);
+		if (wiped != indx_record_size) {
+			ntfs_log_verbose("ntfs_rl_pwrite failed\n");
+			ntfs_log_error("Couldn't wipe tail of INDX record");
+			total = -1;
+			goto free_buf;
+		}
+		total += wipe_size;
+
+		offset += indx_record_size;
+		obit++;
+		if (obit > 7) {
+			obit = 0;
+			obyte++;
+		}
+	}
+	if ((opts.verbose > 1) && (wiped != -1))
+		ntfs_log_verbose("\n\t");
+free_buf:
+	free(buf);
+free_bitmap:
+	free(bitmap);
+	return total;
+}
+
+/**
+ * get_indx_record_size - determine size of INDX record from $INDEX_ROOT
+ * @nar:	Opened ntfs $INDEX_ROOT attribute
+ *
+ * Return: >0  Success, return INDX record size
+ *          0  Error, something went wrong
+ */
+static u32 get_indx_record_size(ntfs_attr *nar)
+{
+	u32 indx_record_size;
+	le32 indx_record_size_le;
+
+	if (ntfs_attr_pread(nar, 8, 4, &indx_record_size_le) != 4) {
+		ntfs_log_verbose("Couldn't determine size of INDX record\n");
+		ntfs_log_error("ntfs_attr_pread failed");
+		return 0;
+	}
+
+	indx_record_size = le32_to_cpu(indx_record_size_le);
+	if (!indx_record_size) {
+		ntfs_log_verbose("Internal error\n");
+		ntfs_log_error("INDX record should be 0");
+	}
+	return indx_record_size;
+}
+
+/**
+ * wipe_directory - Wipe the directory indexes
+ * @vol:	An ntfs volume obtained from ntfs_mount
+ * @byte:	Overwrite with this value
+ * @act:	Wipe, test or info
+ *
+ * Directories are kept in sorted B+ Trees.  Index blocks may not be full.  Wipe
+ * the unused space at the ends of these blocks.
+ *
+ * Return: >0  Success, the clusters were wiped
+ *          0  Nothing to wipe
+ *         -1  Error, something went wrong
+ */
+static s64 wipe_directory(ntfs_volume *vol, int byte, enum action act)
+{
+	s64 total = 0;
+	s64 nr_mft_records, inode_num;
+	ntfs_inode *ni;
+	ntfs_attr *naa;
+	ntfs_attr *nab;
+	ntfs_attr *nar;
+
+	if (!vol || (byte < 0))
+		return -1;
+
+	nr_mft_records = vol->mft_na->initialized_size >>
+			vol->mft_record_size_bits;
+
+	for (inode_num = 5; inode_num < nr_mft_records; inode_num++) {
+		u32 indx_record_size;
+		s64 wiped;
+
+		ntfs_log_verbose("Inode %lld - ", (long long)inode_num);
+		ni = ntfs_inode_open(vol, inode_num);
+		if (!ni) {
+			if (opts.verbose > 2)
+				ntfs_log_verbose("Could not open inode\n");
+			else
+				ntfs_log_verbose("\r");
+			continue;
+		}
+
+		if (ni->mrec->base_mft_record) {
+			if (opts.verbose > 2)
+				ntfs_log_verbose("Not base mft record. Skipping\n");
+			else
+				ntfs_log_verbose("\r");
+			goto close_inode;
+		}
+
+		naa = ntfs_attr_open(ni, AT_INDEX_ALLOCATION, NTFS_INDEX_I30, 4);
+		if (!naa) {
+			if (opts.verbose > 2)
+				ntfs_log_verbose("Couldn't open $INDEX_ALLOCATION\n");
+			else
+				ntfs_log_verbose("\r");
+			goto close_inode;
+		}
+
+		if (!NAttrNonResident(naa)) {
+			ntfs_log_verbose("Resident $INDEX_ALLOCATION\n");
+			ntfs_log_error("damaged fs: Resident $INDEX_ALLOCATION "
+					"(inode %lld)\n", (long long)inode_num);
+			goto close_attr_allocation;
+		}
+
+		if (ntfs_attr_map_whole_runlist(naa)) {
+			ntfs_log_verbose("Internal error\n");
+			ntfs_log_error("Can't map runlist for $INDEX_ALLOCATION "
+					"(inode %lld)\n", (long long)inode_num);
+			goto close_attr_allocation;
+		}
+
+		nab = ntfs_attr_open(ni, AT_BITMAP, NTFS_INDEX_I30, 4);
+		if (!nab) {
+			ntfs_log_verbose("Couldn't open $BITMAP\n");
+			ntfs_log_error("damaged fs: $INDEX_ALLOCATION is present, "
+					"but we can't open $BITMAP with same "
+					"name (inode %lld)\n", (long long)inode_num);
+			goto close_attr_allocation;
+		}
+
+		nar = ntfs_attr_open(ni, AT_INDEX_ROOT, NTFS_INDEX_I30, 4);
+		if (!nar) {
+			ntfs_log_verbose("Couldn't open $INDEX_ROOT\n");
+			ntfs_log_error("damaged fs: $INDEX_ALLOCATION is present, but "
+					"we can't open $INDEX_ROOT with same name"
+					" (inode %lld)\n", (long long)inode_num);
+			goto close_attr_bitmap;
+		}
+
+		if (NAttrNonResident(nar)) {
+			ntfs_log_verbose("Not resident $INDEX_ROOT\n");
+			ntfs_log_error("damaged fs: Not resident $INDEX_ROOT "
+					"(inode %lld)\n", (long long)inode_num);
+			goto close_attr_root;
+		}
+
+		indx_record_size = get_indx_record_size(nar);
+		if (!indx_record_size) {
+			ntfs_log_error(" (inode %lld)\n", (long long)inode_num);
+			goto close_attr_root;
+		}
+
+		wiped = wipe_index_allocation(vol, byte, act,
+						naa, nab, indx_record_size);
+		if (wiped == -1) {
+			ntfs_log_error(" (inode %lld)\n",
+					(long long)inode_num);
+			goto close_attr_root;
+		}
+
+		if (wiped) {
+			ntfs_log_verbose("Wiped %llu bytes\n",
+					(unsigned long long)wiped);
+			total += wiped;
+		} else
+			ntfs_log_verbose("Nothing to wipe\n");
+close_attr_root:
+		ntfs_attr_close(nar);
+close_attr_bitmap:
+		ntfs_attr_close(nab);
+close_attr_allocation:
+		ntfs_attr_close(naa);
+close_inode:
+		ntfs_inode_close(ni);
+	}
+
+	ntfs_log_quiet("wipe_directory 0x%02x, %lld bytes\n", byte,
+			(long long)total);
+	return total;
+}
+
+/**
+ * wipe_logfile - Wipe the logfile (journal)
+ * @vol:   An ntfs volume obtained from ntfs_mount
+ * @byte:  Overwrite with this value
+ * @act:   Wipe, test or info
+ *
+ * The logfile journals the metadata to give the volume fault-tolerance.  If the
+ * volume is in a consistent state, then this information can be erased.
+ *
+ * Return: >0  Success, the clusters were wiped
+ *          0  Nothing to wipe
+ *         -1  Error, something went wrong
+ */
+static s64 wipe_logfile(ntfs_volume *vol, int byte, enum action act
+	__attribute__((unused)))
+{
+	const int NTFS_BUF_SIZE2 = 8192;
+	//FIXME(?): We might need to zero the LSN field of every single mft
+	//record as well. (But, first try without doing that and see what
+	//happens, since chkdsk might pickup the pieces and do it for us...)
+	ntfs_inode *ni;
+	ntfs_attr *na;
+	s64 len, pos, count;
+	char buf[NTFS_BUF_SIZE2];
+	int eo;
+
+	/* We can wipe logfile only with 0xff. */
+	byte = 0xff;
+
+	if (!vol || (byte < 0))
+		return -1;
+
+	//ntfs_log_quiet("wipe_logfile(not implemented) 0x%02x\n", byte);
+
+	if ((ni = ntfs_inode_open(vol, FILE_LogFile)) == NULL) {
+		ntfs_log_debug("Failed to open inode FILE_LogFile.\n");
+		return -1;
+	}
+
+	if ((na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0)) == NULL) {
+		ntfs_log_debug("Failed to open $FILE_LogFile/$DATA.\n");
+		goto error_exit;
+	}
+
+	/* The $DATA attribute of the $LogFile has to be non-resident. */
+	if (!NAttrNonResident(na)) {
+		ntfs_log_debug("$LogFile $DATA attribute is resident!?!\n");
+		errno = EIO;
+		goto io_error_exit;
+	}
+
+	/* 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_SIZE2, buf)) > 0)
+		pos += count;
+
+	if (count == -1 || pos != len) {
+		ntfs_log_debug("Amount of $LogFile data read does not "
+			"correspond to expected length!\n");
+		if (count != -1)
+			errno = EIO;
+		goto io_error_exit;
+	}
+
+	/* Fill the buffer with @byte's. */
+	memset(buf, byte, NTFS_BUF_SIZE2);
+
+	/* Set the $DATA attribute. */
+	pos = 0;
+	while ((count = len - pos) > 0) {
+		if (count > NTFS_BUF_SIZE2)
+			count = NTFS_BUF_SIZE2;
+
+		if ((count = ntfs_attr_pwrite(na, pos, count, buf)) <= 0) {
+			ntfs_log_debug("Failed to set the $LogFile attribute "
+					"value.\n");
+			if (count != -1)
+				errno = EIO;
+			goto io_error_exit;
+		}
+
+		pos += count;
+	}
+
+	ntfs_attr_close(na);
+	ntfs_inode_close(ni);
+	ntfs_log_quiet("wipe_logfile 0x%02x, %lld bytes\n", byte,
+			(long long)pos);
+	return pos;
+
+io_error_exit:
+	eo = errno;
+	ntfs_attr_close(na);
+	errno = eo;
+error_exit:
+	eo = errno;
+	ntfs_inode_close(ni);
+	errno = eo;
+	return -1;
+}
+
+/**
+ * wipe_pagefile - Wipe the pagefile (swap space)
+ * @vol:   An ntfs volume obtained from ntfs_mount
+ * @byte:  Overwrite with this value
+ * @act:   Wipe, test or info
+ *
+ * pagefile.sys is used by Windows as extra virtual memory (swap space).
+ * Windows recreates the file at bootup, so it can be wiped without harm.
+ *
+ * Return: >0  Success, the clusters were wiped
+ *          0  Nothing to wipe
+ *         -1  Error, something went wrong
+ */
+static s64 wipe_pagefile(ntfs_volume *vol, int byte, enum action act
+	__attribute__((unused)))
+{
+	// wipe completely, chkdsk doesn't do anything, booting writes header
+	const int NTFS_BUF_SIZE2 = 4096;
+	ntfs_inode *ni;
+	ntfs_attr *na;
+	s64 len, pos, count;
+	char buf[NTFS_BUF_SIZE2];
+	int eo;
+
+	if (!vol || (byte < 0))
+		return -1;
+
+	//ntfs_log_quiet("wipe_pagefile(not implemented) 0x%02x\n", byte);
+
+	ni = ntfs_pathname_to_inode(vol, NULL, "pagefile.sys");
+	if (!ni) {
+		ntfs_log_debug("Failed to open inode of pagefile.sys.\n");
+		return 0;
+	}
+
+	if ((na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0)) == NULL) {
+		ntfs_log_debug("Failed to open pagefile.sys/$DATA.\n");
+		goto error_exit;
+	}
+
+	/* The $DATA attribute of the pagefile.sys has to be non-resident. */
+	if (!NAttrNonResident(na)) {
+		ntfs_log_debug("pagefile.sys $DATA attribute is resident!?!\n");
+		errno = EIO;
+		goto io_error_exit;
+	}
+
+	/* Get length of pagefile.sys contents. */
+	len = na->data_size;
+	if (!len) {
+		ntfs_log_debug("pagefile.sys has zero length, no disk write "
+				"needed.\n");
+		return 0;
+	}
+
+	memset(buf, byte, NTFS_BUF_SIZE2);
+
+	/* Set the $DATA attribute. */
+	pos = 0;
+	while ((count = len - pos) > 0) {
+		if (count > NTFS_BUF_SIZE2)
+			count = NTFS_BUF_SIZE2;
+
+		if ((count = ntfs_attr_pwrite(na, pos, count, buf)) <= 0) {
+			ntfs_log_debug("Failed to set the pagefile.sys "
+					"attribute value.\n");
+			if (count != -1)
+				errno = EIO;
+			goto io_error_exit;
+		}
+
+		pos += count;
+	}
+
+	ntfs_attr_close(na);
+	ntfs_inode_close(ni);
+	ntfs_log_quiet("wipe_pagefile 0x%02x, %lld bytes\n", byte,
+			(long long)pos);
+	return pos;
+
+io_error_exit:
+	eo = errno;
+	ntfs_attr_close(na);
+	errno = eo;
+error_exit:
+	eo = errno;
+	ntfs_inode_close(ni);
+	errno = eo;
+	return -1;
+}
+
+/**
+ * Part of ntfsprogs.
+ * Modified: removed logging, signal handling, removed data.
+ *
+ * free_file - Release the resources used by a file object
+ * \param file  The unwanted file object
+ *
+ * This will free up the memory used by a file object and iterate through the
+ * object's children, freeing their resources too.
+ *
+ * \return  none
+ */
+static void free_file (struct ufile *file)
+{
+	struct ntfs_list_head *item = NULL, *tmp = NULL;
+	struct filename *f = NULL;
+	struct data *d = NULL;
+
+	if (file == NULL)
+		return;
+
+	ntfs_list_for_each_safe(item, tmp, &(file->name)) {
+		/* List of filenames */
+
+		f = ntfs_list_entry(item, struct filename, list);
+		if (f->name != NULL)
+			free(f->name);
+		if (f->parent_name != NULL) {
+			free(f->parent_name);
+		}
+		free(f);
+	}
+
+	ntfs_list_for_each_safe(item, tmp, &(file->data)) {
+		/* List of data streams */
+
+		d = ntfs_list_entry(item, struct data, list);
+		if (d->name != NULL)
+			free(d->name);
+		if (d->runlist != NULL)
+			free(d->runlist);
+		free(d);
+	}
+
+
+	free(file->mft);
+	free(file);
+}
+
+/**
+ * Fills the given buffer with one of predefined patterns.
+ * \param pat_no Pass number.
+ * \param buffer Buffer to be filled.
+ * \param buflen Length of the buffer.
+ */
+static void fill_buffer (
+		unsigned long int 		pat_no,
+		unsigned char * const 		buffer,
+		const size_t 			buflen,
+		int * const			selected )
+		/*@requires notnull buffer @*/ /*@sets *buffer @*/
+{
+
+	size_t i;
+#if (!defined HAVE_MEMCPY) && (!defined HAVE_STRING_H)
+	size_t j;
+#endif
+	unsigned int bits;
+
+	if ((buffer == NULL) || (buflen == 0))
+		return;
+
+	/* De-select all patterns once every npasses calls. */
+	if (pat_no % npasses == 0) {
+		for (i = 0; i < NPAT; i++) {
+			selected[i] = 0;
+		}
+        }
+        pat_no %= npasses;
+	/* double check for npasses >= NPAT + 3: */
+        for (i = 0; i < NPAT; i++) {
+		if (selected[i] == 0)
+			break;
+	}
+	if (i >= NPAT) {
+		for (i = 0; i < NPAT; i++) {
+			selected[i] = 0;
+		}
+	}
+
+	/* The first, last and middle passess will be using a random pattern */
+	if ((pat_no == 0) || (pat_no == npasses-1) || (pat_no == npasses/2)) {
+#if (!defined __STRICT_ANSI__) && (defined HAVE_RANDOM)
+		bits = (unsigned int)(random() & 0xFFF);
+#else
+		bits = (unsigned int)(rand() & 0xFFF);
+#endif
+	} else {
+		/* For other passes, one of the fixed patterns is selected. */
+		do {
+#if (!defined __STRICT_ANSI__) && (defined HAVE_RANDOM)
+			i = (size_t)(random() % NPAT);
+#else
+			i = (size_t)(rand() % NPAT);
+#endif
+		} while (selected[i] == 1);
+		bits = 	opts.bytes[i];
+		selected[i] = 1;
+    	}
+
+	buffer[0] = (unsigned char) bits;
+	buffer[1] = (unsigned char) bits;
+	buffer[2] = (unsigned char) bits;
+	for (i = 3; i < buflen / 2; i *= 2) {
+#ifdef HAVE_MEMCPY
+		memcpy(buffer + i, buffer, i);
+#elif defined HAVE_STRING_H
+		strncpy((char *)(buffer + i), (char *)buffer, i);
+#else
+		for (j = 0; j < i; j++) {
+			buffer[i+j] = buffer[j];
+		}
+#endif
+	}
+	if (i < buflen) {
+#ifdef HAVE_MEMCPY
+		memcpy(buffer + i, buffer, buflen - i);
+#elif defined HAVE_STRING_H
+		strncpy((char *)(buffer + i), (char *)buffer, buflen - i);
+#else
+		for (j=0; j<buflen - i; j++) {
+			buffer[i+j] = buffer[j];
+		}
+#endif
+	}
+}
+
+/**
+ * Destroys the specified record's filenames and data.
+ *
+ * \param nv The filesystem.
+ * \param record The record (i-node number), which filenames & data
+ * to destroy.
+ * \return 0 in case of no errors, other values otherwise.
+ */
+static int destroy_record(ntfs_volume *nv, const s64 record,
+	unsigned char * const buf)
+{
+	struct ufile *file = NULL;
+	runlist_element *rl = NULL;
+	ntfs_attr *mft = NULL;
+
+	ntfs_attr_search_ctx *ctx = NULL;
+	int ret_wfs = 0;
+	unsigned long int pass, i;
+	s64 j;
+	unsigned char * a_offset;
+	int selected[NPAT];
+
+	file = (struct ufile *) malloc(sizeof(struct ufile));
+	if (file == NULL) {
+		return -1;
+	}
+
+	NTFS_INIT_LIST_HEAD(&(file->name));
+	NTFS_INIT_LIST_HEAD(&(file->data));
+	file->inode = record;
+
+	file->mft = (MFT_RECORD*)malloc(nv->mft_record_size);
+	if (file->mft == NULL) {
+		free_file (file);
+		return -1;
+	}
+
+	mft = ntfs_attr_open(nv->mft_ni, AT_DATA, AT_UNNAMED, 0);
+	if (mft == NULL) {
+		free_file(file);
+		return -2;
+	}
+
+	/* Read the MFT reocrd of the i-node */
+	if (ntfs_attr_mst_pread(mft, nv->mft_record_size * record, 1LL,
+		nv->mft_record_size, file->mft) < 1) {
+
+		ntfs_attr_close(mft);
+		free_file(file);
+		return -3;
+	}
+	ntfs_attr_close(mft);
+	mft = NULL;
+
+	ctx = ntfs_attr_get_search_ctx(NULL, file->mft);
+	if (ctx == NULL) {
+		free_file(file);
+		return -4;
+	}
+
+	/* Wiping file names */
+	while (1 == 1) {
+
+        	if (ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, CASE_SENSITIVE,
+			0LL, NULL, 0, ctx) != 0) {
+			break;	/* None / no more of that type */
+		}
+		if (ctx->attr == NULL)
+			break;
+
+		/* We know this will always be resident.
+		   Find the offset of the data, including the MFT record. */
+		a_offset = ((unsigned char *) ctx->attr
+			+ le16_to_cpu(ctx->attr->value_offset));
+
+		for (pass = 0; pass < npasses; pass++) {
+			fill_buffer(pass, a_offset,
+				le32_to_cpu(ctx->attr->value_length),
+				selected);
+
+			if ( !opts.noaction ) {
+				if (ntfs_mft_records_write(nv,
+					MK_MREF(record, 0), 1LL,
+					ctx->mrec) != 0) {
+					ret_wfs = -5;
+					break;
+				}
+				/* Flush after each writing, if more than
+				   1 overwriting needs to be done. Allow I/O
+				   bufferring (efficiency), if just one
+				   pass is needed. */
+				if (npasses > 1) {
+					nv->dev->d_ops->sync(nv->dev);
+				}
+			}
+
+		}
+
+		/* Wiping file name length */
+		for (pass = 0; pass < npasses; pass++) {
+
+			fill_buffer (pass, (unsigned char *)
+				&(ctx->attr->value_length), sizeof(u32),
+				selected);
+
+			if (!opts.noaction) {
+				if (ntfs_mft_records_write(nv,
+					MK_MREF(record, 0),
+					1LL, ctx->mrec) != 0) {
+					ret_wfs = -5;
+					break;
+				}
+
+				if (npasses > 1) {
+					nv->dev->d_ops->sync(nv->dev);
+				}
+			}
+		}
+		ctx->attr->value_length = cpu_to_le32(0);
+		if (!opts.noaction) {
+			if (ntfs_mft_records_write(nv, MK_MREF(record, 0),
+					1LL, ctx->mrec) != 0) {
+				ret_wfs = -5;
+				break;
+			}
+		}
+	}
+
+	ntfs_attr_reinit_search_ctx(ctx);
+
+	/* Wiping file data */
+	while (1 == 1) {
+        	if (ntfs_attr_lookup(AT_DATA, NULL, 0, CASE_SENSITIVE, 0LL,
+			NULL, 0, ctx) != 0) {
+			break;	/* None / no more of that type */
+		}
+		if (ctx->attr == NULL)
+			break;
+
+		if (ctx->attr->non_resident == 0) {
+			/* attribute is resident (part of MFT record) */
+			/* find the offset of the data, including the MFT record */
+			a_offset = ((unsigned char *) ctx->attr
+				+ le16_to_cpu(ctx->attr->value_offset));
+
+			/* Wiping the data itself */
+			for (pass = 0; pass < npasses; pass++) {
+
+				fill_buffer (pass, a_offset,
+					le32_to_cpu(ctx->attr->value_length),
+					selected);
+
+				if (!opts.noaction) {
+					if (ntfs_mft_records_write(nv,
+						MK_MREF(record, 0),
+						1LL, ctx->mrec) != 0) {
+						ret_wfs = -5;
+						break;
+					}
+
+					if (npasses > 1) {
+						nv->dev->d_ops->sync(nv->dev);
+					}
+				}
+			}
+
+			/* Wiping data length */
+			for (pass = 0; pass < npasses; pass++) {
+
+				fill_buffer(pass, (unsigned char *)
+					&(ctx->attr->value_length),
+					sizeof(u32), selected);
+
+				if (!opts.noaction) {
+					if (ntfs_mft_records_write(nv,
+						MK_MREF(record, 0),
+						1LL, ctx->mrec) != 0) {
+						ret_wfs = -5;
+						break;
+					}
+
+					if (npasses > 1) {
+						nv->dev->d_ops->sync(nv->dev);
+					}
+				}
+			}
+			ctx->attr->value_length = cpu_to_le32(0);
+			if ( !opts.noaction ) {
+				if (ntfs_mft_records_write(nv,
+					MK_MREF(record, 0),
+					1LL, ctx->mrec) != 0) {
+					ret_wfs = -5;
+					break;
+				}
+			}
+		} else {
+				/* Non-resident here */
+
+			rl = ntfs_mapping_pairs_decompress(nv,
+				ctx->attr, NULL);
+			if (rl == NULL)	{
+				continue;
+			}
+
+			if (rl[0].length <= 0) {
+				continue;
+			}
+
+			for (i = 0; (rl[i].length > 0) && (ret_wfs == 0); i++) {
+				if (rl[i].lcn == -1) {
+					continue;
+				}
+				for (j = rl[i].lcn;
+					(j < rl[i].lcn + rl[i].length)
+					&& (ret_wfs == 0); j++)	{
+
+					if (utils_cluster_in_use(nv, j) != 0)
+						continue;
+					for (pass = 0;
+						pass < npasses;
+						pass++)	{
+
+						fill_buffer(pass, buf,
+						 (size_t) nv->cluster_size,
+						 selected);
+						if (!opts.noaction) {
+							if (ntfs_cluster_write(
+								nv, j, 1LL,
+								buf) < 1) {
+								ret_wfs = -5;
+								break;
+							}
+
+							if (npasses > 1) {
+							 nv->dev->d_ops->sync
+							  (nv->dev);
+							}
+						}
+					}
+				}
+			}
+
+			/* Wipe the data length here */
+			for (pass = 0; pass < npasses; pass++) {
+				fill_buffer(pass, (unsigned char *)
+					&(ctx->attr->lowest_vcn),
+					sizeof(VCN), selected);
+				fill_buffer(pass, (unsigned char *)
+					&(ctx->attr->highest_vcn),
+					sizeof(VCN), selected);
+				fill_buffer(pass, (unsigned char *)
+					&(ctx->attr->allocated_size),
+					sizeof(s64), selected);
+				fill_buffer(pass, (unsigned char *)
+					&(ctx->attr->data_size),
+					sizeof(s64), selected);
+				fill_buffer(pass, (unsigned char *)
+					&(ctx->attr->initialized_size),
+					sizeof(s64), selected);
+				fill_buffer(pass, (unsigned char *)
+					&(ctx->attr->compressed_size),
+					sizeof(s64), selected);
+
+				if ( !opts.noaction ) {
+					if (ntfs_mft_records_write(nv,
+						MK_MREF (record, 0),
+						1LL, ctx->mrec) != 0) {
+						ret_wfs = -5;
+						break;
+					}
+
+					if (npasses > 1) {
+						nv->dev->d_ops->sync(nv->dev);
+					}
+				}
+			}
+			ctx->attr->lowest_vcn = cpu_to_le64(0);
+			ctx->attr->highest_vcn = cpu_to_le64(0);
+			ctx->attr->allocated_size = cpu_to_le64(0);
+			ctx->attr->data_size = cpu_to_le64(0);
+			ctx->attr->initialized_size = cpu_to_le64(0);
+			ctx->attr->compressed_size = cpu_to_le64(0);
+			if (!opts.noaction) {
+				if (ntfs_mft_records_write(nv,
+					MK_MREF (record, 0),
+					1LL, ctx->mrec) != 0) {
+					ret_wfs = -5;
+					break;
+				}
+			}
+		}	/* end of resident check */
+	} /* end of 'wiping file data' loop */
+
+	ntfs_attr_put_search_ctx(ctx);
+	free_file(file);
+
+	return ret_wfs;
+}
+
+/**
+ * Starts search for deleted inodes and undelete data on the given
+ * NTFS filesystem.
+ * \param FS The filesystem.
+ * \return 0 in case of no errors, other values otherwise.
+ */
+static int wipe_unrm(ntfs_volume *nv)
+{
+	int ret_wfs = 0, ret;
+	ntfs_attr *bitmapattr = NULL;
+	s64 bmpsize, size, nr_mft_records, i, j, k;
+	unsigned char b;
+	unsigned char * buf = NULL;
+
+#define MYBUF_SIZE 8192
+	unsigned char *mybuf;
+#define MINIM(x, y) ( ((x)<(y))?(x):(y) )
+
+	mybuf = (unsigned char *) malloc(MYBUF_SIZE);
+	if (mybuf == NULL) {
+		return -1;
+	}
+
+	buf = (unsigned char *) malloc(nv->cluster_size);
+	if (buf == NULL) {
+		free (mybuf);
+		return -1;
+	}
+
+	bitmapattr = ntfs_attr_open(nv->mft_ni, AT_BITMAP, AT_UNNAMED, 0);
+	if (bitmapattr == NULL) {
+		free (buf);
+		free (mybuf);
+		return -2;
+	}
+	bmpsize = bitmapattr->initialized_size;
+
+	nr_mft_records = nv->mft_na->initialized_size
+		>> nv->mft_record_size_bits;
+
+	/* just like ntfsundelete; detects i-node numbers fine */
+	for (i = 0; (i < bmpsize) && (ret_wfs==0); i += MYBUF_SIZE) {
+
+		/* read a part of the file bitmap */
+		size = ntfs_attr_pread(bitmapattr, i,
+			MINIM((bmpsize - i), MYBUF_SIZE), mybuf);
+		if (size < 0)
+			break;
+
+		/* parse each byte of the just-read part of the bitmap */
+		for (j = 0; (j < size) && (ret_wfs==0); j++) {
+			b = mybuf[j];
+			/* parse each bit of the byte Bit 1 means 'in use'. */
+			for (k = 0; (k < CHAR_BIT) && (ret_wfs==0);
+					k++, b>>=1) {
+				/* (i+j)*8+k is the i-node bit number */
+				if (((i+j)*CHAR_BIT+k) >= nr_mft_records) {
+					goto done;
+				}
+				if ((b & 1) != 0) {
+					/* i-node is in use, skip it */
+					continue;
+				}
+				/* wiping the i-node here: */
+				ret = destroy_record (nv,
+					(i+j)*CHAR_BIT+k, buf);
+				if (ret != 0) {
+					ret_wfs = ret;
+				}
+			}
+		}
+	}
+done:
+	ntfs_attr_close(bitmapattr);
+	free(buf);
+	free(mybuf);
+
+	ntfs_log_quiet("wipe_undelete\n");
+	return ret_wfs;
+}
+
+
+
+/**
+ * print_summary - Tell the user what we are about to do
+ *
+ * List the operations about to be performed.  The output will be silenced by
+ * the --quiet option.
+ *
+ * Return:  none
+ */
+static void print_summary(void)
+{
+	int i;
+
+	if (opts.noaction)
+		ntfs_log_quiet("%s is in 'no-action' mode, it will NOT write to disk."
+			 "\n\n", EXEC_NAME);
+
+	ntfs_log_quiet("%s is about to wipe:\n", EXEC_NAME);
+	if (opts.unused)
+		ntfs_log_quiet("\tunused disk space\n");
+	if (opts.unused_fast)
+		ntfs_log_quiet("\tunused disk space (fast)\n");
+	if (opts.tails)
+		ntfs_log_quiet("\tfile tails\n");
+	if (opts.mft)
+		ntfs_log_quiet("\tunused mft areas\n");
+	if (opts.directory)
+		ntfs_log_quiet("\tunused directory index space\n");
+	if (opts.logfile)
+		ntfs_log_quiet("\tthe logfile (journal)\n");
+	if (opts.pagefile)
+		ntfs_log_quiet("\tthe pagefile (swap space)\n");
+	if (opts.undel)
+		ntfs_log_quiet("\tundelete data\n");
+
+	ntfs_log_quiet("\n%s will overwrite these areas with: ", EXEC_NAME);
+	if (opts.bytes) {
+		for (i = 0; opts.bytes[i] >= 0; i++)
+			ntfs_log_quiet("0x%02x ", opts.bytes[i]);
+	}
+	ntfs_log_quiet("\n");
+
+	if (opts.count > 1)
+		ntfs_log_quiet("%s will repeat these operations %d times.\n", EXEC_NAME, opts.count);
+	ntfs_log_quiet("\n");
+}
+
+/**
+ * main - Begin here
+ *
+ * Start from here.
+ *
+ * Return:  0  Success, the program worked
+ *	    1  Error, something went wrong
+ */
+int main(int argc, char *argv[])
+{
+	ntfs_volume *vol;
+	int result = 1;
+	int flags = 0;
+	int res;
+	int i, j;
+	enum action act = act_info;
+
+	ntfs_log_set_handler(ntfs_log_handler_outerr);
+
+	res = parse_options(argc, argv);
+	if (res >= 0)
+		return (res);
+
+	utils_set_locale();
+
+	if (!opts.info)
+		print_summary();
+
+	if (opts.info || opts.noaction)
+		flags = NTFS_MNT_RDONLY;
+	if (opts.force)
+		flags |= NTFS_MNT_RECOVER;
+
+	vol = utils_mount_volume(opts.device, flags);
+	if (!vol)
+		goto free;
+
+	if ((vol->flags & VOLUME_IS_DIRTY) && !opts.force)
+		goto umount;
+
+	if (opts.info) {
+		act = act_info;
+		opts.count = 1;
+	} else if (opts.noaction) {
+		act = act_test;
+	} else {
+		act = act_wipe;
+	}
+
+	/* Even if the output it quieted, you still get 5 seconds to abort. */
+	if ((act == act_wipe) && !opts.force) {
+		ntfs_log_quiet("\n%s will begin in 5 seconds, press CTRL-C to abort.\n", EXEC_NAME);
+		sleep(5);
+	}
+
+	for (i = 0; opts.bytes[i] >= 0; i++) {
+		npasses = i+1;
+	}
+	if (npasses == 0) {
+		npasses = opts.count;
+	}
+#ifdef HAVE_TIME_H
+	srandom(time(NULL));
+#else
+	/* use a pointer as a pseudorandom value */
+	srandom((int)vol + npasses);
+#endif
+	ntfs_log_info("\n");
+	for (i = 0; i < opts.count; i++) {
+		int byte;
+		s64 total = 0;
+		s64 wiped = 0;
+
+		for (j = 0; byte = opts.bytes[j], byte >= 0; j++) {
+
+			if (opts.directory) {
+				wiped = wipe_directory(vol, byte, act);
+				if (wiped < 0)
+					goto umount;
+				else
+					total += wiped;
+			}
+
+			if (opts.tails) {
+				wiped = wipe_tails(vol, byte, act);
+				if (wiped < 0)
+					goto umount;
+				else
+					total += wiped;
+			}
+
+			if (opts.logfile) {
+				wiped = wipe_logfile(vol, byte, act);
+				if (wiped < 0)
+					goto umount;
+				else
+					total += wiped;
+			}
+
+			if (opts.mft) {
+				wiped = wipe_mft(vol, byte, act);
+				if (wiped < 0)
+					goto umount;
+				else
+					total += wiped;
+			}
+
+			if (opts.pagefile) {
+				wiped = wipe_pagefile(vol, byte, act);
+				if (wiped < 0)
+					goto umount;
+				else
+					total += wiped;
+			}
+
+			if (opts.unused || opts.unused_fast) {
+				if (opts.unused_fast)
+					wiped = wipe_unused_fast(vol, byte,
+								act);
+				else
+					wiped = wipe_unused(vol, byte, act);
+				if (wiped < 0)
+					goto umount;
+				else
+					total += wiped;
+			}
+
+			if (opts.undel) {
+				wiped = wipe_unrm(vol);
+				if (wiped != 0)
+					goto umount;
+				/*
+				else
+					total += wiped;
+				*/
+			}
+
+			if (act == act_info)
+				break;
+		}
+
+		ntfs_log_info(
+			"%lld bytes were wiped (excluding undelete data)\n",
+			(long long)total);
+	}
+	result = 0;
+umount:
+	ntfs_umount(vol, FALSE);
+free:
+	if (opts.bytes)
+		free(opts.bytes);
+	return result;
+}
diff --git a/ntfsprogs/ntfswipe.h b/ntfsprogs/ntfswipe.h
new file mode 100755
index 0000000000000000000000000000000000000000..08620e5ffbc706dd02a10fe43423cf49696cbc99
--- /dev/null
+++ b/ntfsprogs/ntfswipe.h
@@ -0,0 +1,55 @@
+/*
+ * ntfswipe - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2002 Richard Russon
+ *
+ * This utility will overwrite unused space on an NTFS volume.
+ *
+ * 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 Linux-NTFS
+ * 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 _NTFSWIPE_H_
+#define _NTFSWIPE_H_
+
+#include "types.h"
+
+enum action {
+	act_info,
+	act_test,
+	act_wipe,
+};
+
+struct options {
+	char	*device;	/* Device/File to work with */
+	int	 info;		/* Show volume info */
+	int	 force;		/* Override common sense */
+	int	 quiet;		/* Less output */
+	int	 verbose;	/* Extra output */
+	int	 noaction;	/* Do not write to disk */
+	int	 count;		/* Number of iterations */
+	int	*bytes;		/* List of overwrite characters */
+	int	 directory;	/* Wipe directory indexes */
+	int	 logfile;	/* Wipe the logfile (journal) */
+	int	 mft;		/* Wipe mft slack space */
+	int	 pagefile;	/* Wipe pagefile (swap space) */
+	int	 tails;		/* Wipe file tails */
+	int	 unused;	/* Wipe unused clusters */
+	int	 unused_fast;	/* Wipe unused clusters (fast) */
+	int	 undel;		/* Wipe undelete data */
+};
+
+#endif /* _NTFSWIPE_H_ */
+
diff --git a/ntfsprogs/sd.c b/ntfsprogs/sd.c
new file mode 100755
index 0000000000000000000000000000000000000000..4e3af97801bf5df8c93ea9d643d3ab8719f99eb1
--- /dev/null
+++ b/ntfsprogs/sd.c
@@ -0,0 +1,607 @@
+#include "types.h"
+#include "layout.h"
+#include "sd.h"
+
+/**
+ * init_system_file_sd -
+ *
+ * NTFS 3.1 - System files security decriptors
+ * =====================================================
+ *
+ * Create the security descriptor for system file number @sys_file_no and
+ * return a pointer to the descriptor.
+ *
+ * Note the root directory system file (".") is very different and handled by a
+ * different function.
+ *
+ * The sd is returned in *@sd_val and has length *@sd_val_len.
+ *
+ * Do NOT free *@sd_val as it is static memory. This also means that you can
+ * only use *@sd_val until the next call to this function.
+ */
+void init_system_file_sd(int sys_file_no, u8 **sd_val, int *sd_val_len)
+{
+	static u8 sd_array[0x68];
+	SECURITY_DESCRIPTOR_RELATIVE *sd;
+	ACL *acl;
+	ACCESS_ALLOWED_ACE *aa_ace;
+	SID *sid;
+	le32 *sub_authorities;
+
+	if (sys_file_no < 0) {
+		*sd_val = NULL;
+		*sd_val_len = 0;
+		return;
+	}
+	*sd_val = sd_array;
+	sd = (SECURITY_DESCRIPTOR_RELATIVE*)&sd_array;
+	sd->revision = 1;
+	sd->alignment = 0;
+	sd->control = SE_SELF_RELATIVE | SE_DACL_PRESENT;
+	*sd_val_len = 0x64;
+	sd->owner = const_cpu_to_le32(0x48);
+	sd->group = const_cpu_to_le32(0x54);
+	sd->sacl = const_cpu_to_le32(0);
+	sd->dacl = const_cpu_to_le32(0x14);
+	/*
+	 * Now at offset 0x14, as specified in the security descriptor, we have
+	 * the DACL.
+	 */
+	acl = (ACL*)((char*)sd + le32_to_cpu(sd->dacl));
+	acl->revision = 2;
+	acl->alignment1 = 0;
+	acl->size = const_cpu_to_le16(0x34);
+	acl->ace_count = const_cpu_to_le16(2);
+	acl->alignment2 = const_cpu_to_le16(0);
+	/*
+	 * Now at offset 0x1c, just after the DACL's ACL, we have the first
+	 * ACE of the DACL. The type of the ACE is access allowed.
+	 */
+	aa_ace = (ACCESS_ALLOWED_ACE*)((char*)acl + sizeof(ACL));
+	aa_ace->type = ACCESS_ALLOWED_ACE_TYPE;
+	aa_ace->flags = 0;
+	aa_ace->size = const_cpu_to_le16(0x14);
+	switch (sys_file_no) {
+	case FILE_AttrDef:
+	case FILE_Boot:
+		aa_ace->mask = SYNCHRONIZE | STANDARD_RIGHTS_READ |
+			FILE_READ_ATTRIBUTES | FILE_READ_EA | FILE_READ_DATA;
+		break;
+	default:
+		aa_ace->mask = SYNCHRONIZE | STANDARD_RIGHTS_WRITE |
+			FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES |
+			FILE_WRITE_EA | FILE_READ_EA | FILE_APPEND_DATA |
+			FILE_WRITE_DATA | FILE_READ_DATA;
+		break;
+	}
+	aa_ace->sid.revision = 1;
+	aa_ace->sid.sub_authority_count = 1;
+	aa_ace->sid.identifier_authority.value[0] = 0;
+	aa_ace->sid.identifier_authority.value[1] = 0;
+	aa_ace->sid.identifier_authority.value[2] = 0;
+	aa_ace->sid.identifier_authority.value[3] = 0;
+	aa_ace->sid.identifier_authority.value[4] = 0;
+	/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
+	aa_ace->sid.identifier_authority.value[5] = 5;
+	aa_ace->sid.sub_authority[0] =
+			const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID);
+	/*
+	 * Now at offset 0x30 within security descriptor, just after the first
+	 * ACE of the DACL. All system files, except the root directory, have
+	 * a second ACE.
+	 */
+	/* The second ACE of the DACL. Type is access allowed. */
+	aa_ace = (ACCESS_ALLOWED_ACE*)((char*)aa_ace +
+			le16_to_cpu(aa_ace->size));
+	aa_ace->type = ACCESS_ALLOWED_ACE_TYPE;
+	aa_ace->flags = 0;
+	aa_ace->size = const_cpu_to_le16(0x18);
+	/* Only $AttrDef and $Boot behave differently to everything else. */
+	switch (sys_file_no) {
+	case FILE_AttrDef:
+	case FILE_Boot:
+		aa_ace->mask = SYNCHRONIZE | STANDARD_RIGHTS_READ |
+				FILE_READ_ATTRIBUTES | FILE_READ_EA |
+				FILE_READ_DATA;
+		break;
+	default:
+		aa_ace->mask = SYNCHRONIZE | STANDARD_RIGHTS_READ |
+				FILE_WRITE_ATTRIBUTES |
+				FILE_READ_ATTRIBUTES | FILE_WRITE_EA |
+				FILE_READ_EA | FILE_APPEND_DATA |
+				FILE_WRITE_DATA | FILE_READ_DATA;
+		break;
+	}
+	aa_ace->sid.revision = 1;
+	aa_ace->sid.sub_authority_count = 2;
+	/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
+	aa_ace->sid.identifier_authority.value[0] = 0;
+	aa_ace->sid.identifier_authority.value[1] = 0;
+	aa_ace->sid.identifier_authority.value[2] = 0;
+	aa_ace->sid.identifier_authority.value[3] = 0;
+	aa_ace->sid.identifier_authority.value[4] = 0;
+	aa_ace->sid.identifier_authority.value[5] = 5;
+	sub_authorities = aa_ace->sid.sub_authority;
+	*sub_authorities++ =
+			const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
+	*sub_authorities =
+			const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
+	/*
+	 * Now at offset 0x48 into the security descriptor, as specified in the
+	 * security descriptor, we now have the owner SID.
+	 */
+	sid = (SID*)((char*)sd + le32_to_cpu(sd->owner));
+	sid->revision = 1;
+	sid->sub_authority_count = 1;
+	/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
+	sid->identifier_authority.value[0] = 0;
+	sid->identifier_authority.value[1] = 0;
+	sid->identifier_authority.value[2] = 0;
+	sid->identifier_authority.value[3] = 0;
+	sid->identifier_authority.value[4] = 0;
+	sid->identifier_authority.value[5] = 5;
+	sid->sub_authority[0] = const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID);
+	/*
+	 * Now at offset 0x54 into the security descriptor, as specified in the
+	 * security descriptor, we have the group SID.
+	 */
+	sid = (SID*)((char*)sd + le32_to_cpu(sd->group));
+	sid->revision = 1;
+	sid->sub_authority_count = 2;
+	/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
+	sid->identifier_authority.value[0] = 0;
+	sid->identifier_authority.value[1] = 0;
+	sid->identifier_authority.value[2] = 0;
+	sid->identifier_authority.value[3] = 0;
+	sid->identifier_authority.value[4] = 0;
+	sid->identifier_authority.value[5] = 5;
+	sub_authorities = sid->sub_authority;
+	*sub_authorities++ = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
+	*sub_authorities = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
+}
+
+/**
+ * init_root_sd -
+ *
+ * Creates the security_descriptor for the root folder on ntfs 3.1 as created
+ * by Windows Vista (when the format is done from the disk management MMC
+ * snap-in, note this is different from the format done from the disk
+ * properties in Windows Explorer).
+ */
+void init_root_sd(u8 **sd_val, int *sd_val_len)
+{
+	SECURITY_DESCRIPTOR_RELATIVE *sd;
+	ACL *acl;
+	ACCESS_ALLOWED_ACE *ace;
+	SID *sid;
+	le32 *sub_authorities;
+
+	static char sd_array[0x102c];
+	*sd_val_len = 0x102c;
+	*sd_val = (u8*)&sd_array;
+
+	//security descriptor relative
+	sd = (SECURITY_DESCRIPTOR_RELATIVE*)sd_array;
+	sd->revision = SECURITY_DESCRIPTOR_REVISION;
+	sd->alignment = 0;
+	sd->control = SE_SELF_RELATIVE | SE_DACL_PRESENT;
+	sd->owner = const_cpu_to_le32(0x1014);
+	sd->group = const_cpu_to_le32(0x1020);
+	sd->sacl = 0;
+	sd->dacl = const_cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE));
+
+	//acl
+	acl = (ACL*)((u8*)sd + sizeof(SECURITY_DESCRIPTOR_RELATIVE));
+	acl->revision = ACL_REVISION;
+	acl->alignment1 = 0;
+	acl->size = const_cpu_to_le16(0x1000);
+	acl->ace_count = const_cpu_to_le16(0x08);
+	acl->alignment2 = 0;
+
+	//ace1
+	ace = (ACCESS_ALLOWED_ACE*)((u8*)acl + sizeof(ACL));
+	ace->type = ACCESS_ALLOWED_ACE_TYPE;
+	ace->flags = 0;
+	ace->size = const_cpu_to_le16(0x18);
+	ace->mask = STANDARD_RIGHTS_ALL | FILE_WRITE_ATTRIBUTES |
+			 FILE_LIST_DIRECTORY | FILE_WRITE_DATA |
+			 FILE_ADD_SUBDIRECTORY | FILE_READ_EA | FILE_WRITE_EA |
+			 FILE_TRAVERSE | FILE_DELETE_CHILD |
+			 FILE_READ_ATTRIBUTES;
+	ace->sid.revision = SID_REVISION;
+	ace->sid.sub_authority_count = 0x02;
+	/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
+	ace->sid.identifier_authority.value[0] = 0;
+	ace->sid.identifier_authority.value[1] = 0;
+	ace->sid.identifier_authority.value[2] = 0;
+	ace->sid.identifier_authority.value[3] = 0;
+	ace->sid.identifier_authority.value[4] = 0;
+	ace->sid.identifier_authority.value[5] = 5;
+	sub_authorities = ace->sid.sub_authority;
+	*sub_authorities++ =
+			const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
+	*sub_authorities = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
+
+	//ace2
+	ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size));
+	ace->type = ACCESS_ALLOWED_ACE_TYPE;
+	ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE |
+			INHERIT_ONLY_ACE;
+	ace->size = const_cpu_to_le16(0x18);
+	ace->mask = GENERIC_ALL;
+	ace->sid.revision = SID_REVISION;
+	ace->sid.sub_authority_count = 0x02;
+	/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
+	ace->sid.identifier_authority.value[0] = 0;
+	ace->sid.identifier_authority.value[1] = 0;
+	ace->sid.identifier_authority.value[2] = 0;
+	ace->sid.identifier_authority.value[3] = 0;
+	ace->sid.identifier_authority.value[4] = 0;
+	ace->sid.identifier_authority.value[5] = 5;
+	sub_authorities = ace->sid.sub_authority;
+	*sub_authorities++ =
+			const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
+	*sub_authorities = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
+
+	//ace3
+	ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size));
+	ace->type = ACCESS_ALLOWED_ACE_TYPE;
+	ace->flags = 0;
+	ace->size = const_cpu_to_le16(0x14);
+	ace->mask = STANDARD_RIGHTS_ALL | FILE_WRITE_ATTRIBUTES |
+			 FILE_LIST_DIRECTORY | FILE_WRITE_DATA |
+			 FILE_ADD_SUBDIRECTORY | FILE_READ_EA | FILE_WRITE_EA |
+			 FILE_TRAVERSE | FILE_DELETE_CHILD |
+			 FILE_READ_ATTRIBUTES;
+	ace->sid.revision = SID_REVISION;
+	ace->sid.sub_authority_count = 0x01;
+	/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
+	ace->sid.identifier_authority.value[0] = 0;
+	ace->sid.identifier_authority.value[1] = 0;
+	ace->sid.identifier_authority.value[2] = 0;
+	ace->sid.identifier_authority.value[3] = 0;
+	ace->sid.identifier_authority.value[4] = 0;
+	ace->sid.identifier_authority.value[5] = 5;
+	ace->sid.sub_authority[0] =
+			const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID);
+
+	//ace4
+	ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size));
+	ace->type = ACCESS_ALLOWED_ACE_TYPE;
+	ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE |
+			INHERIT_ONLY_ACE;
+	ace->size = const_cpu_to_le16(0x14);
+	ace->mask = GENERIC_ALL;
+	ace->sid.revision = SID_REVISION;
+	ace->sid.sub_authority_count = 0x01;
+	/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
+	ace->sid.identifier_authority.value[0] = 0;
+	ace->sid.identifier_authority.value[1] = 0;
+	ace->sid.identifier_authority.value[2] = 0;
+	ace->sid.identifier_authority.value[3] = 0;
+	ace->sid.identifier_authority.value[4] = 0;
+	ace->sid.identifier_authority.value[5] = 5;
+	ace->sid.sub_authority[0] =
+			const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID);
+
+	//ace5
+	ace = (ACCESS_ALLOWED_ACE*)((char*)ace + le16_to_cpu(ace->size));
+	ace->type = ACCESS_ALLOWED_ACE_TYPE;
+	ace->flags = 0;
+	ace->size = const_cpu_to_le16(0x14);
+	ace->mask = SYNCHRONIZE | READ_CONTROL | DELETE |
+			FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES |
+			FILE_TRAVERSE | FILE_WRITE_EA | FILE_READ_EA |
+			FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE |
+			FILE_LIST_DIRECTORY;
+	ace->sid.revision = SID_REVISION;
+	ace->sid.sub_authority_count = 0x01;
+	/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
+	ace->sid.identifier_authority.value[0] = 0;
+	ace->sid.identifier_authority.value[1] = 0;
+	ace->sid.identifier_authority.value[2] = 0;
+	ace->sid.identifier_authority.value[3] = 0;
+	ace->sid.identifier_authority.value[4] = 0;
+	ace->sid.identifier_authority.value[5] = 5;
+	ace->sid.sub_authority[0] =
+			const_cpu_to_le32(SECURITY_AUTHENTICATED_USER_RID);
+
+	//ace6
+	ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size));
+	ace->type = ACCESS_ALLOWED_ACE_TYPE;
+	ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE |
+			INHERIT_ONLY_ACE;
+	ace->size = const_cpu_to_le16(0x14);
+	ace->mask = GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | DELETE;
+	ace->sid.revision = SID_REVISION;
+	ace->sid.sub_authority_count = 0x01;
+	/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
+	ace->sid.identifier_authority.value[0] = 0;
+	ace->sid.identifier_authority.value[1] = 0;
+	ace->sid.identifier_authority.value[2] = 0;
+	ace->sid.identifier_authority.value[3] = 0;
+	ace->sid.identifier_authority.value[4] = 0;
+	ace->sid.identifier_authority.value[5] = 5;
+	ace->sid.sub_authority[0] =
+			const_cpu_to_le32(SECURITY_AUTHENTICATED_USER_RID);
+
+	//ace7
+	ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size));
+	ace->type = ACCESS_ALLOWED_ACE_TYPE;
+	ace->flags = 0;
+	ace->size = const_cpu_to_le16(0x18);
+	ace->mask = SYNCHRONIZE | READ_CONTROL | FILE_READ_ATTRIBUTES |
+			FILE_TRAVERSE | FILE_READ_EA | FILE_LIST_DIRECTORY;
+	ace->sid.revision = SID_REVISION;
+	ace->sid.sub_authority_count = 0x02;
+	/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
+	ace->sid.identifier_authority.value[0] = 0;
+	ace->sid.identifier_authority.value[1] = 0;
+	ace->sid.identifier_authority.value[2] = 0;
+	ace->sid.identifier_authority.value[3] = 0;
+	ace->sid.identifier_authority.value[4] = 0;
+	ace->sid.identifier_authority.value[5] = 5;
+	sub_authorities = ace->sid.sub_authority;
+	*sub_authorities++ =
+			const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
+	*sub_authorities = const_cpu_to_le32(DOMAIN_ALIAS_RID_USERS);
+
+	//ace8
+	ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size));
+	ace->type = ACCESS_ALLOWED_ACE_TYPE;
+	ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE |
+			INHERIT_ONLY_ACE;
+	ace->size = const_cpu_to_le16(0x18);
+	ace->mask = GENERIC_READ | GENERIC_EXECUTE;
+	ace->sid.revision = SID_REVISION;
+	ace->sid.sub_authority_count = 0x02;
+	/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
+	ace->sid.identifier_authority.value[0] = 0;
+	ace->sid.identifier_authority.value[1] = 0;
+	ace->sid.identifier_authority.value[2] = 0;
+	ace->sid.identifier_authority.value[3] = 0;
+	ace->sid.identifier_authority.value[4] = 0;
+	ace->sid.identifier_authority.value[5] = 5;
+	sub_authorities = ace->sid.sub_authority;
+	*sub_authorities++ =
+			const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
+	*sub_authorities = const_cpu_to_le32(DOMAIN_ALIAS_RID_USERS);
+
+	//owner sid
+	sid = (SID*)((char*)sd + le32_to_cpu(sd->owner));
+	sid->revision = 0x01;
+	sid->sub_authority_count = 0x01;
+	/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
+	sid->identifier_authority.value[0] = 0;
+	sid->identifier_authority.value[1] = 0;
+	sid->identifier_authority.value[2] = 0;
+	sid->identifier_authority.value[3] = 0;
+	sid->identifier_authority.value[4] = 0;
+	sid->identifier_authority.value[5] = 5;
+	sid->sub_authority[0] = const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID);
+
+	//group sid
+	sid = (SID*)((char*)sd + le32_to_cpu(sd->group));
+	sid->revision = 0x01;
+	sid->sub_authority_count = 0x01;
+	/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
+	sid->identifier_authority.value[0] = 0;
+	sid->identifier_authority.value[1] = 0;
+	sid->identifier_authority.value[2] = 0;
+	sid->identifier_authority.value[3] = 0;
+	sid->identifier_authority.value[4] = 0;
+	sid->identifier_authority.value[5] = 5;
+	sid->sub_authority[0] = const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID);
+}
+
+/**
+ * init_secure_sds -
+ *
+ * NTFS 3.1 - System files security decriptors
+ * ===========================================
+ * Create the security descriptor entries in $SDS data stream like they
+ * are in a partition, newly formatted with windows 2003
+ */
+void init_secure_sds(char *sd_val)
+{
+	SECURITY_DESCRIPTOR_HEADER *sds;
+	SECURITY_DESCRIPTOR_RELATIVE *sd;
+	ACL *acl;
+	ACCESS_ALLOWED_ACE *ace;
+	SID *sid;
+
+/*
+ * security descriptor #1
+ */
+	//header
+	sds = (SECURITY_DESCRIPTOR_HEADER*)((char*)sd_val);
+	sds->hash = const_cpu_to_le32(0xF80312F0);
+	sds->security_id = const_cpu_to_le32(0x0100);
+	sds->offset = const_cpu_to_le64(0x00);
+	sds->length = const_cpu_to_le32(0x7C);
+	//security descriptor relative
+	sd = (SECURITY_DESCRIPTOR_RELATIVE*)((char*)sds +
+			sizeof(SECURITY_DESCRIPTOR_HEADER));
+	sd->revision = 0x01;
+	sd->alignment = 0x00;
+	sd->control = SE_SELF_RELATIVE | SE_DACL_PRESENT;
+	sd->owner = const_cpu_to_le32(0x48);
+	sd->group = const_cpu_to_le32(0x58);
+	sd->sacl = const_cpu_to_le32(0x00);
+	sd->dacl = const_cpu_to_le32(0x14);
+
+	//acl
+	acl = (ACL*)((char*)sd + sizeof(SECURITY_DESCRIPTOR_RELATIVE));
+	acl->revision = 0x02;
+	acl->alignment1 = 0x00;
+	acl->size = const_cpu_to_le16(0x34);
+	acl->ace_count = const_cpu_to_le16(0x02);
+	acl->alignment2 = 0x00;
+
+	//ace1
+	ace = (ACCESS_ALLOWED_ACE*)((char*)acl + sizeof(ACL));
+	ace->type = 0x00;
+	ace->flags = 0x00;
+	ace->size = const_cpu_to_le16(0x14);
+	ace->mask = const_cpu_to_le32(0x120089);
+	ace->sid.revision = 0x01;
+	ace->sid.sub_authority_count = 0x01;
+	/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
+	ace->sid.identifier_authority.value[0] = 0;
+	ace->sid.identifier_authority.value[1] = 0;
+	ace->sid.identifier_authority.value[2] = 0;
+	ace->sid.identifier_authority.value[3] = 0;
+	ace->sid.identifier_authority.value[4] = 0;
+	ace->sid.identifier_authority.value[5] = 5;
+	ace->sid.sub_authority[0] =
+			const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID);
+	//ace2
+	ace = (ACCESS_ALLOWED_ACE*)((char*)ace + le16_to_cpu(ace->size));
+	ace->type = 0x00;
+	ace->flags = 0x00;
+	ace->size = const_cpu_to_le16(0x18);
+	ace->mask = const_cpu_to_le32(0x120089);
+	ace->sid.revision = 0x01;
+	ace->sid.sub_authority_count = 0x02;
+	/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
+	ace->sid.identifier_authority.value[0] = 0;
+	ace->sid.identifier_authority.value[1] = 0;
+	ace->sid.identifier_authority.value[2] = 0;
+	ace->sid.identifier_authority.value[3] = 0;
+	ace->sid.identifier_authority.value[4] = 0;
+	ace->sid.identifier_authority.value[5] = 5;
+	ace->sid.sub_authority[0] =
+		const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
+	ace->sid.sub_authority[1] =
+		const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
+
+	//owner sid
+	sid = (SID*)((char*)sd + le32_to_cpu(sd->owner));
+	sid->revision = 0x01;
+	sid->sub_authority_count = 0x02;
+	/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
+	sid->identifier_authority.value[0] = 0;
+	sid->identifier_authority.value[1] = 0;
+	sid->identifier_authority.value[2] = 0;
+	sid->identifier_authority.value[3] = 0;
+	sid->identifier_authority.value[4] = 0;
+	sid->identifier_authority.value[5] = 5;
+	sid->sub_authority[0] =
+		const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
+	sid->sub_authority[1] =
+		const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
+	//group sid
+	sid = (SID*)((char*)sd + le32_to_cpu(sd->group));
+	sid->revision = 0x01;
+	sid->sub_authority_count = 0x02;
+	/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
+	sid->identifier_authority.value[0] = 0;
+	sid->identifier_authority.value[1] = 0;
+	sid->identifier_authority.value[2] = 0;
+	sid->identifier_authority.value[3] = 0;
+	sid->identifier_authority.value[4] = 0;
+	sid->identifier_authority.value[5] = 5;
+	sid->sub_authority[0] =
+		const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
+	sid->sub_authority[1] =
+		const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
+/*
+ * security descriptor #2
+ */
+	//header
+	sds = (SECURITY_DESCRIPTOR_HEADER*)((char*)sd_val + 0x80);
+	sds->hash = const_cpu_to_le32(0xB32451);
+	sds->security_id = const_cpu_to_le32(0x0101);
+	sds->offset = const_cpu_to_le64(0x80);
+	sds->length = const_cpu_to_le32(0x7C);
+
+	//security descriptor relative
+	sd = (SECURITY_DESCRIPTOR_RELATIVE*)((char*)sds +
+		 sizeof(SECURITY_DESCRIPTOR_HEADER));
+	sd->revision = 0x01;
+	sd->alignment = 0x00;
+	sd->control = SE_SELF_RELATIVE | SE_DACL_PRESENT;
+	sd->owner = const_cpu_to_le32(0x48);
+	sd->group = const_cpu_to_le32(0x58);
+	sd->sacl = const_cpu_to_le32(0x00);
+	sd->dacl = const_cpu_to_le32(0x14);
+
+	//acl
+	acl = (ACL*)((char*)sd + sizeof(SECURITY_DESCRIPTOR_RELATIVE));
+	acl->revision = 0x02;
+	acl->alignment1 = 0x00;
+	acl->size = const_cpu_to_le16(0x34);
+	acl->ace_count = const_cpu_to_le16(0x02);
+	acl->alignment2 = 0x00;
+
+	//ace1
+	ace = (ACCESS_ALLOWED_ACE*)((char*)acl + sizeof(ACL));
+	ace->type = 0x00;
+	ace->flags = 0x00;
+	ace->size = const_cpu_to_le16(0x14);
+	ace->mask = const_cpu_to_le32(0x12019F);
+	ace->sid.revision = 0x01;
+	ace->sid.sub_authority_count = 0x01;
+	/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
+	ace->sid.identifier_authority.value[0] = 0;
+	ace->sid.identifier_authority.value[1] = 0;
+	ace->sid.identifier_authority.value[2] = 0;
+	ace->sid.identifier_authority.value[3] = 0;
+	ace->sid.identifier_authority.value[4] = 0;
+	ace->sid.identifier_authority.value[5] = 5;
+	ace->sid.sub_authority[0] =
+		const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID);
+	//ace2
+	ace = (ACCESS_ALLOWED_ACE*)((char*)ace + le16_to_cpu(ace->size));
+	ace->type = 0x00;
+	ace->flags = 0x00;
+	ace->size = const_cpu_to_le16(0x18);
+	ace->mask = const_cpu_to_le32(0x12019F);
+	ace->sid.revision = 0x01;
+	ace->sid.sub_authority_count = 0x02;
+	/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
+	ace->sid.identifier_authority.value[0] = 0;
+	ace->sid.identifier_authority.value[1] = 0;
+	ace->sid.identifier_authority.value[2] = 0;
+	ace->sid.identifier_authority.value[3] = 0;
+	ace->sid.identifier_authority.value[4] = 0;
+	ace->sid.identifier_authority.value[5] = 5;
+	ace->sid.sub_authority[0] =
+		const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
+	ace->sid.sub_authority[1] =
+		const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
+
+	//owner sid
+	sid = (SID*)((char*)sd + le32_to_cpu(sd->owner));
+	sid->revision = 0x01;
+	sid->sub_authority_count = 0x02;
+	/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
+	sid->identifier_authority.value[0] = 0;
+	sid->identifier_authority.value[1] = 0;
+	sid->identifier_authority.value[2] = 0;
+	sid->identifier_authority.value[3] = 0;
+	sid->identifier_authority.value[4] = 0;
+	sid->identifier_authority.value[5] = 5;
+	sid->sub_authority[0] =
+		const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
+	sid->sub_authority[1] =
+		const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
+
+	//group sid
+	sid = (SID*)((char*)sd + le32_to_cpu(sd->group));
+	sid->revision = 0x01;
+	sid->sub_authority_count = 0x02;
+	/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
+	sid->identifier_authority.value[0] = 0;
+	sid->identifier_authority.value[1] = 0;
+	sid->identifier_authority.value[2] = 0;
+	sid->identifier_authority.value[3] = 0;
+	sid->identifier_authority.value[4] = 0;
+	sid->identifier_authority.value[5] = 5;
+	sid->sub_authority[0] =
+		const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
+	sid->sub_authority[1] =
+		const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
+
+	return;
+}
diff --git a/ntfsprogs/sd.h b/ntfsprogs/sd.h
new file mode 100755
index 0000000000000000000000000000000000000000..7ad3e6a79c5317de6626be144851135f48ffd16f
--- /dev/null
+++ b/ntfsprogs/sd.h
@@ -0,0 +1,11 @@
+#ifndef _NTFS_SD_H_
+#define _NTFS_SD_H_
+
+#include "types.h"
+
+void init_system_file_sd(int sys_file_no, u8 **sd_val, int *sd_val_len);
+void init_root_sd(u8 **sd_val, int *sd_val_len);
+void init_secure_sds(char *sd_val);
+
+#endif /* _NTFS_SD_H_ */
+
diff --git a/ntfsprogs/utils.c b/ntfsprogs/utils.c
new file mode 100755
index 0000000000000000000000000000000000000000..7ac31163dc4cea9565459fb41e1e76b43b533d52
--- /dev/null
+++ b/ntfsprogs/utils.c
@@ -0,0 +1,1204 @@
+/**
+ * utils.c - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2002-2005 Richard Russon
+ * Copyright (c) 2003-2006 Anton Altaparmakov
+ * Copyright (c) 2003 Lode Leroy
+ * Copyright (c) 2005-2007 Yura Pakhuchiy
+ * Copyright (c) 2014      Jean-Pierre Andre
+ *
+ * A set of shared functions for ntfs utilities
+ *
+ * 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 Linux-NTFS
+ * 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_STDARG_H
+#include <stdarg.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+#ifdef HAVE_LIBINTL_H
+#include <libintl.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+
+#include "utils.h"
+#include "types.h"
+#include "volume.h"
+#include "debug.h"
+#include "dir.h"
+/* #include "version.h" */
+#include "logging.h"
+#include "misc.h"
+
+const char *ntfs_bugs = "Developers' email address: "NTFS_DEV_LIST"\n";
+const char *ntfs_gpl = "This program is free software, released under the GNU "
+	"General Public License\nand you are welcome to redistribute it under "
+	"certain conditions.  It comes with\nABSOLUTELY NO WARRANTY; for "
+	"details read the GNU General Public License to be\nfound in the file "
+	"\"COPYING\" distributed with this program, or online at:\n"
+	"http://www.gnu.org/copyleft/gpl.html\n";
+
+static const char *invalid_ntfs_msg =
+"The device '%s' doesn't have a valid NTFS.\n"
+"Maybe you selected the wrong device? Or the whole disk instead of a\n"
+"partition (e.g. /dev/hda, not /dev/hda1)? Or the other way around?\n";
+
+static const char *corrupt_volume_msg =
+"NTFS is inconsistent. Run chkdsk /f on Windows then reboot it TWICE!\n"
+"The usage of the /f parameter is very IMPORTANT! No modification was\n"
+"made to NTFS by this software.\n";
+
+static const char *hibernated_volume_msg =
+"The NTFS partition is hibernated. Please resume Windows and turned it \n"
+"off properly, so mounting could be done safely.\n";
+
+static const char *unclean_journal_msg =
+"Access is denied because the NTFS journal file is unclean. Choices are:\n"
+" A) Shutdown Windows properly.\n"
+" B) Click the 'Safely Remove Hardware' icon in the Windows taskbar\n"
+"    notification area before disconnecting the device.\n"
+" C) Use 'Eject' from Windows Explorer to safely remove the device.\n"
+" D) If you ran chkdsk previously then boot Windows again which will\n"
+"    automatically initialize the journal.\n"
+" E) Submit 'force' option (WARNING: This solution it not recommended).\n"
+" F) ntfsmount: Mount the volume read-only by using the 'ro' mount option.\n";
+
+static const char *opened_volume_msg =
+"Access is denied because the NTFS volume is already exclusively opened.\n"
+"The volume may be already mounted, or another software may use it which\n"
+"could be identified for example by the help of the 'fuser' command.\n";
+
+static const char *dirty_volume_msg =
+"Volume is scheduled for check.\n"
+"Please boot into Windows TWICE, or use the 'force' option.\n"
+"NOTE: If you had not scheduled check and last time accessed this volume\n"
+"using ntfsmount and shutdown system properly, then init scripts in your\n"
+"distribution are broken. Please report to your distribution developers\n"
+"(NOT to us!) that init scripts kill ntfsmount or mount.ntfs-fuse during\n"
+"shutdown instead of proper umount.\n";
+
+static const char *fakeraid_msg =
+"You seem to have a SoftRAID/FakeRAID hardware and must use an activated,\n"
+"different device under /dev/mapper, (e.g. /dev/mapper/nvidia_eahaabcc1)\n"
+"to mount NTFS. Please see the 'dmraid' documentation for help.\n";
+
+/**
+ * utils_set_locale
+ */
+int utils_set_locale(void)
+{
+	const char *locale;
+
+	locale = setlocale(LC_ALL, "");
+	if (!locale) {
+		locale = setlocale(LC_ALL, NULL);
+		ntfs_log_error("Failed to set locale, using default '%s'.\n",
+				locale);
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+/**
+ * linux-ntfs's ntfs_mbstoucs has different semantics, so we emulate it with
+ * ntfs-3g's.
+ */
+int ntfs_mbstoucs_libntfscompat(const char *ins,
+		ntfschar **outs, int outs_len)
+{
+	if(!outs) {
+		errno = EINVAL;
+		return -1;
+	}
+	else if(*outs != NULL) {
+		/* Note: libntfs's mbstoucs implementation allows the caller to
+		 * specify a preallocated buffer while libntfs-3g's always
+		 * allocates the output buffer.
+		 */
+		ntfschar *tmpstr = NULL;
+		int tmpstr_len;
+
+		tmpstr_len = ntfs_mbstoucs(ins, &tmpstr);
+		if(tmpstr_len >= 0) {
+			if((tmpstr_len + 1) > outs_len) {
+				/* Doing a realloc instead of reusing tmpstr
+				 * because it emulates libntfs's mbstoucs more
+				 * closely. */
+				ntfschar *re_outs = realloc(*outs,
+					sizeof(ntfschar)*(tmpstr_len + 1));
+				if(!re_outs)
+					tmpstr_len = -1;
+				else
+					*outs = re_outs;
+			}
+
+			if(tmpstr_len >= 0) {
+				/* The extra character is the \0 terminator. */
+				memcpy(*outs, tmpstr,
+					sizeof(ntfschar)*(tmpstr_len + 1));
+			}
+
+			free(tmpstr);
+		}
+
+		return tmpstr_len;
+	}
+	else
+		return ntfs_mbstoucs(ins, outs);
+}
+
+/**
+ * utils_valid_device - Perform some safety checks on the device, before start
+ * @name:   Full pathname of the device/file to work with
+ * @force:  Continue regardless of problems
+ *
+ * Check that the name refers to a device and that is isn't already mounted.
+ * These checks can be overridden by using the force option.
+ *
+ * Return:  1  Success, we can continue
+ *	    0  Error, we cannot use this device
+ */
+int utils_valid_device(const char *name, int force)
+{
+	unsigned long mnt_flags = 0;
+	struct stat st;
+
+#if defined(HAVE_WINDOWS_H) | defined(__CYGWIN32__) 
+	/* FIXME: This doesn't work for Cygwin, so just return success. */
+	return 1;
+#endif
+	if (!name) {
+		errno = EINVAL;
+		return 0;
+	}
+
+	if (stat(name, &st) == -1) {
+		if (errno == ENOENT)
+			ntfs_log_error("The device %s doesn't exist\n", name);
+		else
+			ntfs_log_perror("Error getting information about %s",
+					name);
+		return 0;
+	}
+
+	/* Make sure the file system is not mounted. */
+	if (ntfs_check_if_mounted(name, &mnt_flags)) {
+		ntfs_log_perror("Failed to determine whether %s is mounted",
+				name);
+		if (!force) {
+			ntfs_log_error("Use the force option to ignore this "
+					"error.\n");
+			return 0;
+		}
+		ntfs_log_warning("Forced to continue.\n");
+	} else if (mnt_flags & NTFS_MF_MOUNTED) {
+		if (!force) {
+			ntfs_log_error("%s", opened_volume_msg);
+			ntfs_log_error("You can use force option to avoid this "
+					"check, but this is not recommended\n"
+					"and may lead to data corruption.\n");
+			return 0;
+		}
+		ntfs_log_warning("Forced to continue.\n");
+	}
+
+	return 1;
+}
+
+/**
+ * utils_mount_volume - Mount an NTFS volume
+ */
+ntfs_volume * utils_mount_volume(const char *device, unsigned long flags)
+{
+	ntfs_volume *vol;
+
+	if (!device) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	/* Porting notes:
+	 *
+	 * libntfs-3g does not have the 'force' flag in ntfs_mount_flags.
+	 * The 'force' flag in libntfs bypasses two safety checks when mounting
+	 * read/write:
+	 *   1. Do not mount when the VOLUME_IS_DIRTY flag in
+	 *      VOLUME_INFORMATION is set.
+	 *   2. Do not mount when the logfile is unclean.
+	 *
+	 * libntfs-3g only has safety check number 2. The dirty flag is simply
+	 * ignored because we are confident that we can handle a dirty volume.
+	 * So we treat NTFS_MNT_RECOVER like NTFS_MNT_FORCE, knowing that the
+	 * first check is always bypassed.
+	 */
+
+	if (!utils_valid_device(device, flags & NTFS_MNT_RECOVER))
+		return NULL;
+
+	vol = ntfs_mount(device, flags);
+	if (!vol) {
+		ntfs_log_perror("Failed to mount '%s'", device);
+		if (errno == EINVAL)
+			ntfs_log_error(invalid_ntfs_msg, device);
+		else if (errno == EIO)
+			ntfs_log_error("%s", corrupt_volume_msg);
+		else if (errno == EPERM)
+			ntfs_log_error("%s", hibernated_volume_msg);
+		else if (errno == EOPNOTSUPP)
+			ntfs_log_error("%s", unclean_journal_msg);
+		else if (errno == EBUSY)
+			ntfs_log_error("%s", opened_volume_msg);
+		else if (errno == ENXIO)
+			ntfs_log_error("%s", fakeraid_msg);
+		return NULL;
+	}
+
+	/* Porting notes:
+	 * libntfs-3g does not record whether the volume log file was dirty
+	 * before mount, so we can only warn if the VOLUME_IS_DIRTY flag is set
+	 * in VOLUME_INFORMATION. */
+	if (vol->flags & VOLUME_IS_DIRTY) {
+		if (!(flags & NTFS_MNT_RECOVER)) {
+			ntfs_log_error("%s", dirty_volume_msg);
+			ntfs_umount(vol, FALSE);
+			return NULL;
+		}
+		ntfs_log_error("WARNING: Dirty volume mount was forced by the "
+				"'force' mount option.\n");
+	}
+	return vol;
+}
+
+/**
+ * utils_parse_size - Convert a string representing a size
+ * @value:  String to be parsed
+ * @size:   Parsed size
+ * @scale:  Whether or not to allow a suffix to scale the value
+ *
+ * Read a string and convert it to a number.  Strings may be suffixed to scale
+ * them.  Any number without a suffix is assumed to be in bytes.
+ *
+ * Suffix  Description  Multiple
+ *  [tT]    Terabytes     10^12
+ *  [gG]    Gigabytes     10^9
+ *  [mM]    Megabytes     10^6
+ *  [kK]    Kilobytes     10^3
+ *
+ * Notes:
+ *     Only the first character of the suffix is read.
+ *     The multipliers are decimal thousands, not binary: 1000, not 1024.
+ *     If parse_size fails, @size will not be changed
+ *
+ * Return:  1  Success
+ *	    0  Error, the string was malformed
+ */
+int utils_parse_size(const char *value, s64 *size, BOOL scale)
+{
+	long long result;
+	char *suffix = NULL;
+
+	if (!value || !size) {
+		errno = EINVAL;
+		return 0;
+	}
+
+	ntfs_log_debug("Parsing size '%s'.\n", value);
+
+	result = strtoll(value, &suffix, 0);
+	if (result < 0 || errno == ERANGE) {
+		ntfs_log_error("Invalid size '%s'.\n", value);
+		return 0;
+	}
+
+	if (!suffix) {
+		ntfs_log_error("Internal error, strtoll didn't return a suffix.\n");
+		return 0;
+	}
+
+	if (scale) {
+		switch (suffix[0]) {
+			case 't': case 'T': result *= 1000;
+			case 'g': case 'G': result *= 1000;
+			case 'm': case 'M': result *= 1000;
+			case 'k': case 'K': result *= 1000;
+			case '-': case 0:
+				break;
+			default:
+				ntfs_log_error("Invalid size suffix '%s'.  Use T, G, M, or K.\n", suffix);
+				return 0;
+		}
+	} else {
+		if ((suffix[0] != '-') && (suffix[0] != 0)) {
+			ntfs_log_error("Invalid number '%.*s'.\n", (int)(suffix - value + 1), value);
+			return 0;
+		}
+	}
+
+	ntfs_log_debug("Parsed size = %lld.\n", result);
+	*size = result;
+	return 1;
+}
+
+/**
+ * utils_parse_range - Convert a string representing a range of numbers
+ * @string:  The string to be parsed
+ * @start:   The beginning of the range will be stored here
+ * @finish:  The end of the range will be stored here
+ *
+ * Read a string of the form n-m.  If the lower end is missing, zero will be
+ * substituted.  If the upper end is missing LONG_MAX will be used.  If the
+ * string cannot be parsed correctly, @start and @finish will not be changed.
+ *
+ * Return:  1  Success, a valid string was found
+ *	    0  Error, the string was not a valid range
+ */
+int utils_parse_range(const char *string, s64 *start, s64 *finish, BOOL scale)
+{
+	s64 a, b;
+	char *middle;
+
+	if (!string || !start || !finish) {
+		errno = EINVAL;
+		return 0;
+	}
+
+	middle = strchr(string, '-');
+	if (string == middle) {
+		ntfs_log_debug("Range has no beginning, defaulting to 0.\n");
+		a = 0;
+	} else {
+		if (!utils_parse_size(string, &a, scale))
+			return 0;
+	}
+
+	if (middle) {
+		if (middle[1] == 0) {
+			b = LONG_MAX;		// XXX ULLONG_MAX
+			ntfs_log_debug("Range has no end, defaulting to %lld.\n", b);
+		} else {
+			if (!utils_parse_size(middle+1, &b, scale))
+				return 0;
+		}
+	} else {
+		b = a;
+	}
+
+	ntfs_log_debug("Range '%s' = %lld - %lld\n", string, a, b);
+
+	*start  = a;
+	*finish = b;
+	return 1;
+}
+
+/**
+ * find_attribute - Find an attribute of the given type
+ * @type:  An attribute type, e.g. AT_FILE_NAME
+ * @ctx:   A search context, created using ntfs_get_attr_search_ctx
+ *
+ * Using the search context to keep track, find the first/next occurrence of a
+ * given attribute type.
+ *
+ * N.B.  This will return a pointer into @mft.  As long as the search context
+ *       has been created without an inode, it won't overflow the buffer.
+ *
+ * Return:  Pointer  Success, an attribute was found
+ *	    NULL     Error, no matching attributes were found
+ */
+ATTR_RECORD * find_attribute(const ATTR_TYPES type, ntfs_attr_search_ctx *ctx)
+{
+	if (!ctx) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	if (ntfs_attr_lookup(type, NULL, 0, 0, 0, NULL, 0, ctx) != 0) {
+		ntfs_log_debug("find_attribute didn't find an attribute of type: 0x%02x.\n", type);
+		return NULL;	/* None / no more of that type */
+	}
+
+	ntfs_log_debug("find_attribute found an attribute of type: 0x%02x.\n", type);
+	return ctx->attr;
+}
+
+/**
+ * find_first_attribute - Find the first attribute of a given type
+ * @type:  An attribute type, e.g. AT_FILE_NAME
+ * @mft:   A buffer containing a raw MFT record
+ *
+ * Search through a raw MFT record for an attribute of a given type.
+ * The return value is a pointer into the MFT record that was supplied.
+ *
+ * N.B.  This will return a pointer into @mft.  The pointer won't stray outside
+ *       the buffer, since we created the search context without an inode.
+ *
+ * Return:  Pointer  Success, an attribute was found
+ *	    NULL     Error, no matching attributes were found
+ */
+ATTR_RECORD * find_first_attribute(const ATTR_TYPES type, MFT_RECORD *mft)
+{
+	ntfs_attr_search_ctx *ctx;
+	ATTR_RECORD *rec;
+
+	if (!mft) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	ctx = ntfs_attr_get_search_ctx(NULL, mft);
+	if (!ctx) {
+		ntfs_log_error("Couldn't create a search context.\n");
+		return NULL;
+	}
+
+	rec = find_attribute(type, ctx);
+	ntfs_attr_put_search_ctx(ctx);
+	if (rec)
+		ntfs_log_debug("find_first_attribute: found attr of type 0x%02x.\n", type);
+	else
+		ntfs_log_debug("find_first_attribute: didn't find attr of type 0x%02x.\n", type);
+	return rec;
+}
+
+/**
+ * utils_inode_get_name
+ *
+ * using inode
+ * get filename
+ * add name to list
+ * get parent
+ * if parent is 5 (/) stop
+ * get inode of parent
+ */
+#define max_path 20
+int utils_inode_get_name(ntfs_inode *inode, char *buffer, int bufsize)
+{
+	// XXX option: names = posix/win32 or dos
+	// flags: path, filename, or both
+
+
+	ntfs_volume *vol;
+	ntfs_attr_search_ctx *ctx;
+	ATTR_RECORD *rec;
+	FILE_NAME_ATTR *attr;
+	int name_space;
+	MFT_REF parent = FILE_root;
+	char *names[max_path + 1];// XXX ntfs_malloc? and make max bigger?
+	int i, len, offset = 0;
+
+	if (!inode || !buffer) {
+		errno = EINVAL;
+		return 0;
+	}
+
+	vol = inode->vol;
+
+	//ntfs_log_debug("sizeof(char*) = %d, sizeof(names) = %d\n", sizeof(char*), sizeof(names));
+	memset(names, 0, sizeof(names));
+
+	for (i = 0; i < max_path; i++) {
+
+		ctx = ntfs_attr_get_search_ctx(inode, NULL);
+		if (!ctx) {
+			ntfs_log_error("Couldn't create a search context.\n");
+			return 0;
+		}
+
+		//ntfs_log_debug("i = %d, inode = %p (%lld)\n", i, inode, inode->mft_no);
+
+		name_space = 4;
+		while ((rec = find_attribute(AT_FILE_NAME, ctx))) {
+			/* We know this will always be resident. */
+			attr = (FILE_NAME_ATTR *) ((char *) rec + le16_to_cpu(rec->value_offset));
+
+			if (attr->file_name_type > name_space) { //XXX find the ...
+				continue;
+			}
+
+			name_space = attr->file_name_type;
+			parent     = le64_to_cpu(attr->parent_directory);
+
+			if (names[i]) {
+				free(names[i]);
+				names[i] = NULL;
+			}
+
+			if (ntfs_ucstombs(attr->file_name, attr->file_name_length,
+			    &names[i], 0) < 0) {
+				char *temp;
+				ntfs_log_error("Couldn't translate filename to current locale.\n");
+				temp = ntfs_malloc(30);
+				if (!temp)
+					return 0;
+				snprintf(temp, 30, "<MFT%llu>", (unsigned
+						long long)inode->mft_no);
+				names[i] = temp;
+			}
+
+			//ntfs_log_debug("names[%d] %s\n", i, names[i]);
+			//ntfs_log_debug("parent = %lld\n", MREF(parent));
+		}
+
+		ntfs_attr_put_search_ctx(ctx);
+
+		if (i > 0)			/* Don't close the original inode */
+			ntfs_inode_close(inode);
+
+		if (MREF(parent) == FILE_root) {	/* The root directory, stop. */
+			//ntfs_log_debug("inode 5\n");
+			break;
+		}
+
+		inode = ntfs_inode_open(vol, parent);
+		if (!inode) {
+			ntfs_log_error("Couldn't open inode %llu.\n",
+					(unsigned long long)MREF(parent));
+			break;
+		}
+	}
+
+	if (i >= max_path) {
+		/* If we get into an infinite loop, we'll end up here. */
+		ntfs_log_error("The directory structure is too deep (over %d) nested directories.\n", max_path);
+		return 0;
+	}
+
+	/* Assemble the names in the correct order. */
+	for (i = max_path; i >= 0; i--) {
+		if (!names[i])
+			continue;
+
+		len = snprintf(buffer + offset, bufsize - offset, "%c%s", PATH_SEP, names[i]);
+		if (len >= (bufsize - offset)) {
+			ntfs_log_error("Pathname was truncated.\n");
+			break;
+		}
+
+		offset += len;
+	}
+
+	/* Free all the allocated memory */
+	for (i = 0; i < max_path; i++)
+		free(names[i]);
+
+	ntfs_log_debug("Pathname: %s\n", buffer);
+
+	return 1;
+}
+#undef max_path
+
+/**
+ * utils_attr_get_name
+ */
+int utils_attr_get_name(ntfs_volume *vol, ATTR_RECORD *attr, char *buffer, int bufsize)
+{
+	int len, namelen;
+	char *name;
+	ATTR_DEF *attrdef;
+
+	// flags: attr, name, or both
+	if (!attr || !buffer) {
+		errno = EINVAL;
+		return 0;
+	}
+
+	attrdef = ntfs_attr_find_in_attrdef(vol, attr->type);
+	if (attrdef) {
+		name    = NULL;
+		namelen = ntfs_ucsnlen(attrdef->name, sizeof(attrdef->name));
+		if (ntfs_ucstombs(attrdef->name, namelen, &name, 0) < 0) {
+			ntfs_log_error("Couldn't translate attribute type to "
+					"current locale.\n");
+			// <UNKNOWN>?
+			return 0;
+		}
+		len = snprintf(buffer, bufsize, "%s", name);
+	} else {
+		ntfs_log_error("Unknown attribute type 0x%02x\n", attr->type);
+		len = snprintf(buffer, bufsize, "<UNKNOWN>");
+	}
+
+	if (len >= bufsize) {
+		ntfs_log_error("Attribute type was truncated.\n");
+		return 0;
+	}
+
+	if (!attr->name_length) {
+		return 0;
+	}
+
+	buffer  += len;
+	bufsize -= len;
+
+	name    = NULL;
+	namelen = attr->name_length;
+	if (ntfs_ucstombs((ntfschar *)((char *)attr
+					+ le16_to_cpu(attr->name_offset)),
+				namelen, &name, 0) < 0) {
+		ntfs_log_error("Couldn't translate attribute name to current "
+				"locale.\n");
+		// <UNKNOWN>?
+		len = snprintf(buffer, bufsize, "<UNKNOWN>");
+		return 0;
+	}
+
+	len = snprintf(buffer, bufsize, "(%s)", name);
+	free(name);
+
+	if (len >= bufsize) {
+		ntfs_log_error("Attribute name was truncated.\n");
+		return 0;
+	}
+
+	return 0;
+}
+
+/**
+ * utils_cluster_in_use - Determine if a cluster is in use
+ * @vol:  An ntfs volume obtained from ntfs_mount
+ * @lcn:  The Logical Cluster Number to test
+ *
+ * The metadata file $Bitmap has one binary bit representing each cluster on
+ * disk.  The bit will be set for each cluster that is in use.  The function
+ * reads the relevant part of $Bitmap into a buffer and tests the bit.
+ *
+ * This function has a static buffer in which it caches a section of $Bitmap.
+ * If the lcn, being tested, lies outside the range, the buffer will be
+ * refreshed. @bmplcn stores offset to the first bit (in bits) stored in the
+ * buffer.
+ *
+ * NOTE: Be very carefull with shifts by 3 everywhere in this function.
+ *
+ * Return:  1  Cluster is in use
+ *	    0  Cluster is free space
+ *	   -1  Error occurred
+ */
+int utils_cluster_in_use(ntfs_volume *vol, long long lcn)
+{
+	static unsigned char buffer[512];
+	static long long bmplcn = -(sizeof(buffer) << 3);
+	int byte, bit;
+	ntfs_attr *attr;
+
+	if (!vol) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	/* Does lcn lie in the section of $Bitmap we already have cached? */
+	if ((lcn < bmplcn)
+	    || (lcn >= (long long)(bmplcn + (sizeof(buffer) << 3)))) {
+		ntfs_log_debug("Bit lies outside cache.\n");
+		attr = ntfs_attr_open(vol->lcnbmp_ni, AT_DATA, AT_UNNAMED, 0);
+		if (!attr) {
+			ntfs_log_perror("Couldn't open $Bitmap");
+			return -1;
+		}
+
+		/* Mark the buffer as in use, in case the read is shorter. */
+		memset(buffer, 0xFF, sizeof(buffer));
+		bmplcn = lcn & (~((sizeof(buffer) << 3) - 1));
+
+		if (ntfs_attr_pread(attr, (bmplcn >> 3), sizeof(buffer),
+					buffer) < 0) {
+			ntfs_log_perror("Couldn't read $Bitmap");
+			ntfs_attr_close(attr);
+			return -1;
+		}
+
+		ntfs_log_debug("Reloaded bitmap buffer.\n");
+		ntfs_attr_close(attr);
+	}
+
+	bit  = 1 << (lcn & 7);
+	byte = (lcn >> 3) & (sizeof(buffer) - 1);
+	ntfs_log_debug("cluster = %lld, bmplcn = %lld, byte = %d, bit = %d, "
+			"in use %d\n", lcn, bmplcn, byte, bit, buffer[byte] &
+			bit);
+
+	return (buffer[byte] & bit);
+}
+
+/**
+ * utils_mftrec_in_use - Determine if a MFT Record is in use
+ * @vol:   An ntfs volume obtained from ntfs_mount
+ * @mref:  MFT Reference (inode number)
+ *
+ * The metadata file $BITMAP has one binary bit representing each record in the
+ * MFT.  The bit will be set for each record that is in use.  The function
+ * reads the relevant part of $BITMAP into a buffer and tests the bit.
+ *
+ * This function has a static buffer in which it caches a section of $BITMAP.
+ * If the mref, being tested, lies outside the range, the buffer will be
+ * refreshed.
+ *
+ * Return:  1  MFT Record is in use
+ *	    0  MFT Record is unused
+ *	   -1  Error occurred
+ */
+int utils_mftrec_in_use(ntfs_volume *vol, MFT_REF mref)
+{
+	static u8 buffer[512];
+	static s64 bmpmref = -(sizeof(buffer) << 3) - 1; /* Which bit of $BITMAP is in the buffer */
+	int byte, bit;
+
+	ntfs_log_trace("Entering.\n");
+
+	if (!vol) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	/* Does mref lie in the section of $Bitmap we already have cached? */
+	if (((s64)MREF(mref) < bmpmref)
+	    || ((s64)MREF(mref) >= (s64)(bmpmref + (sizeof(buffer) << 3)))) {
+		ntfs_log_debug("Bit lies outside cache.\n");
+
+		/* Mark the buffer as not in use, in case the read is shorter. */
+		memset(buffer, 0, sizeof(buffer));
+		bmpmref = mref & (~((sizeof(buffer) << 3) - 1));
+
+		if (ntfs_attr_pread(vol->mftbmp_na, (bmpmref>>3), sizeof(buffer), buffer) < 0) {
+			ntfs_log_perror("Couldn't read $MFT/$BITMAP");
+			return -1;
+		}
+
+		ntfs_log_debug("Reloaded bitmap buffer.\n");
+	}
+
+	bit  = 1 << (mref & 7);
+	byte = (mref >> 3) & (sizeof(buffer) - 1);
+	ntfs_log_debug("cluster = %lld, bmpmref = %lld, byte = %d, bit = %d, in use %d\n", mref, bmpmref, byte, bit, buffer[byte] & bit);
+
+	return (buffer[byte] & bit);
+}
+
+/**
+ * __metadata
+ */
+static int __metadata(ntfs_volume *vol, u64 num)
+{
+	if (num <= FILE_UpCase)
+		return 1;
+	if (!vol)
+		return -1;
+	if ((vol->major_ver == 3) && (num == FILE_Extend))
+		return 1;
+
+	return 0;
+}
+
+/**
+ * utils_is_metadata - Determine if an inode represents a metadata file
+ * @inode:  An ntfs inode to be tested
+ *
+ * A handful of files in the volume contain filesystem data - metadata.
+ * They can be identified by their inode number (offset in MFT/$DATA) or by
+ * their parent.
+ *
+ * Return:  1  inode is a metadata file
+ *	    0  inode is not a metadata file
+ *	   -1  Error occurred
+ */
+int utils_is_metadata(ntfs_inode *inode)
+{
+	ntfs_volume *vol;
+	ATTR_RECORD *rec;
+	FILE_NAME_ATTR *attr;
+	MFT_RECORD *file;
+	u64 num;
+
+	if (!inode) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	vol = inode->vol;
+	if (!vol)
+		return -1;
+
+	num = inode->mft_no;
+	if (__metadata(vol, num) == 1)
+		return 1;
+
+	file = inode->mrec;
+	if (file && (file->base_mft_record != 0)) {
+		num = MREF_LE(file->base_mft_record);
+		if (__metadata(vol, num) == 1)
+			return 1;
+	}
+
+	rec = find_first_attribute(AT_FILE_NAME, inode->mrec);
+	if (!rec)
+		return -1;
+
+	/* We know this will always be resident. */
+	attr = (FILE_NAME_ATTR *)((char *)rec + le16_to_cpu(rec->value_offset));
+
+	num = MREF_LE(attr->parent_directory);
+	if ((num != FILE_root) && (__metadata(vol, num) == 1))
+		return 1;
+
+	return 0;
+}
+
+/**
+ * utils_dump_mem - Display a block of memory in hex and ascii
+ * @buf:     Buffer to be displayed
+ * @start:   Offset into @buf to start from
+ * @length:  Number of bytes to display
+ * @flags:   Options to change the style of the output
+ *
+ * Display a block of memory in a tradition hex-dump manner.
+ * Optionally the ascii part can be turned off.
+ *
+ * The flags, described fully in utils.h, default to 0 (DM_DEFAULTS).
+ * Examples are: DM_INDENT (indent the output by one tab); DM_RED (colour the
+ * output); DM_NO_ASCII (only print the hex values).
+ */
+void utils_dump_mem(void *buf, int start, int length, int flags)
+{
+	int off, i, s, e, col;
+	u8 *mem = buf;
+
+	s =  start                & ~15;	// round down
+	e = (start + length + 15) & ~15;	// round up
+
+	for (off = s; off < e; off += 16) {
+		col = 30;
+		if (flags & DM_RED)
+			col += 1;
+		if (flags & DM_GREEN)
+			col += 2;
+		if (flags & DM_BLUE)
+			col += 4;
+		if (flags & DM_INDENT)
+			ntfs_log_debug("\t");
+		if (flags & DM_BOLD)
+			ntfs_log_debug("\e[01m");
+		if (flags & (DM_RED | DM_BLUE | DM_GREEN | DM_BOLD))
+			ntfs_log_debug("\e[%dm", col);
+		if (off == s)
+			ntfs_log_debug("%6.6x ", start);
+		else
+			ntfs_log_debug("%6.6x ", off);
+
+		for (i = 0; i < 16; i++) {
+			if ((i == 8) && (!(flags & DM_NO_DIVIDER)))
+				ntfs_log_debug(" -");
+			if (((off+i) >= start) && ((off+i) < (start+length)))
+				ntfs_log_debug(" %02X", mem[off+i]);
+			else
+				ntfs_log_debug("   ");
+		}
+		if (!(flags & DM_NO_ASCII)) {
+			ntfs_log_debug("  ");
+			for (i = 0; i < 16; i++) {
+				if (((off+i) < start) || ((off+i) >= (start+length)))
+					ntfs_log_debug(" ");
+				else if (isprint(mem[off + i]))
+					ntfs_log_debug("%c", mem[off + i]);
+				else
+					ntfs_log_debug(".");
+			}
+		}
+		if (flags & (DM_RED | DM_BLUE | DM_GREEN | DM_BOLD))
+			ntfs_log_debug("\e[0m");
+		ntfs_log_debug("\n");
+	}
+}
+
+
+/**
+ * mft_get_search_ctx
+ */
+struct mft_search_ctx * mft_get_search_ctx(ntfs_volume *vol)
+{
+	struct mft_search_ctx *ctx;
+
+	if (!vol) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	ctx = (struct mft_search_ctx*)calloc(1, sizeof *ctx);
+
+	ctx->mft_num = -1;
+	ctx->vol = vol;
+
+	return ctx;
+}
+
+/**
+ * mft_put_search_ctx
+ */
+void mft_put_search_ctx(struct mft_search_ctx *ctx)
+{
+	if (!ctx)
+		return;
+	if (ctx->inode)
+		ntfs_inode_close(ctx->inode);
+	free(ctx);
+}
+
+/**
+ * mft_next_record
+ */
+int mft_next_record(struct mft_search_ctx *ctx)
+{
+	s64 nr_mft_records;
+	ATTR_RECORD *attr10 = NULL;
+	ATTR_RECORD *attr20 = NULL;
+	ATTR_RECORD *attr80 = NULL;
+	ntfs_attr_search_ctx *attr_ctx;
+
+	if (!ctx) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (ctx->inode) {
+		ntfs_inode_close(ctx->inode);
+		ctx->inode = NULL;
+	}
+
+	nr_mft_records = ctx->vol->mft_na->initialized_size >>
+			ctx->vol->mft_record_size_bits;
+
+	for (ctx->mft_num++; (s64)ctx->mft_num < nr_mft_records; ctx->mft_num++) {
+		int in_use;
+
+		ctx->flags_match = 0;
+		in_use = utils_mftrec_in_use(ctx->vol, (MFT_REF) ctx->mft_num);
+		if (in_use == -1) {
+			ntfs_log_error("Error reading inode %llu.  Aborting.\n",
+					(unsigned long long)ctx->mft_num);
+			return -1;
+		}
+
+		if (in_use) {
+			ctx->flags_match |= FEMR_IN_USE;
+
+			ctx->inode = ntfs_inode_open(ctx->vol, (MFT_REF) ctx->mft_num);
+			if (ctx->inode == NULL) {
+				MFT_RECORD *mrec;
+				int r;
+				MFT_REF base_inode;
+
+				mrec = (MFT_RECORD*)NULL;
+				r = ntfs_file_record_read(ctx->vol,
+					(MFT_REF) ctx->mft_num, &mrec, NULL);
+				if (r || !mrec || !mrec->base_mft_record)
+					ntfs_log_error(
+						"Error reading inode %lld.\n",
+						(long long)ctx->mft_num);
+				else {
+					base_inode = le64_to_cpu(
+						mrec->base_mft_record);
+					ntfs_log_error("Inode %lld is an "
+						"extent of inode %lld.\n",
+						(long long)ctx->mft_num,
+						(long long)MREF(base_inode));
+				}
+				free (mrec);
+				continue;
+			}
+
+			attr10 = find_first_attribute(AT_STANDARD_INFORMATION, ctx->inode->mrec);
+			attr20 = find_first_attribute(AT_ATTRIBUTE_LIST,       ctx->inode->mrec);
+			attr80 = find_first_attribute(AT_DATA, ctx->inode->mrec);
+
+			if (attr10)
+				ctx->flags_match |= FEMR_BASE_RECORD;
+			else
+				ctx->flags_match |= FEMR_NOT_BASE_RECORD;
+
+			if (attr20)
+				ctx->flags_match |= FEMR_BASE_RECORD;
+
+			if (attr80)
+				ctx->flags_match |= FEMR_FILE;
+
+			if (ctx->flags_search & FEMR_DIR) {
+				attr_ctx = ntfs_attr_get_search_ctx(ctx->inode, NULL);
+				if (attr_ctx) {
+					if (ntfs_attr_lookup(AT_INDEX_ROOT, NTFS_INDEX_I30, 4, 0, 0, NULL, 0, attr_ctx) == 0)
+						ctx->flags_match |= FEMR_DIR;
+
+					ntfs_attr_put_search_ctx(attr_ctx);
+				} else {
+					ntfs_log_error("Couldn't create a search context.\n");
+					return -1;
+				}
+			}
+
+			switch (utils_is_metadata(ctx->inode)) {
+				case 1: ctx->flags_match |= FEMR_METADATA;     break;
+				case 0: ctx->flags_match |= FEMR_NOT_METADATA; break;
+				default:
+					ctx->flags_match |= FEMR_NOT_METADATA; break;
+					//ntfs_log_error("Error reading inode %lld.\n", ctx->mft_num);
+					//return -1;
+			}
+
+		} else {		// !in_use
+			ntfs_attr *mft;
+
+			ctx->flags_match |= FEMR_NOT_IN_USE;
+
+			ctx->inode = (ntfs_inode*)calloc(1, sizeof(*ctx->inode));
+			if (!ctx->inode) {
+				ntfs_log_error("Out of memory.  Aborting.\n");
+				return -1;
+			}
+
+			ctx->inode->mft_no = ctx->mft_num;
+			ctx->inode->vol    = ctx->vol;
+			ctx->inode->mrec   = ntfs_malloc(ctx->vol->mft_record_size);
+			if (!ctx->inode->mrec) {
+				free(ctx->inode); // == ntfs_inode_close
+				return -1;
+			}
+
+			mft = ntfs_attr_open(ctx->vol->mft_ni, AT_DATA,
+					AT_UNNAMED, 0);
+			if (!mft) {
+				ntfs_log_perror("Couldn't open $MFT/$DATA");
+				// free / close
+				return -1;
+			}
+
+			if (ntfs_attr_pread(mft, ctx->vol->mft_record_size * ctx->mft_num, ctx->vol->mft_record_size, ctx->inode->mrec) < ctx->vol->mft_record_size) {
+				ntfs_log_perror("Couldn't read MFT Record %llu",
+					(unsigned long long) ctx->mft_num);
+				// free / close
+				ntfs_attr_close(mft);
+				return -1;
+			}
+
+			ntfs_attr_close(mft);
+		}
+
+		if (ctx->flags_match & ctx->flags_search) {
+			break;
+		}
+
+		if (ntfs_inode_close(ctx->inode)) {
+			ntfs_log_error("Error closing inode %llu.\n",
+					(unsigned long long)ctx->mft_num);
+			return -errno;
+		}
+
+		ctx->inode = NULL;
+	}
+
+	return (ctx->inode == NULL);
+}
+
+#ifdef HAVE_WINDOWS_H
+
+/*
+ *		Translate formats for older Windows
+ *
+ *	Up to Windows XP, msvcrt.dll does not support long long format
+ *	specifications (%lld, %llx, etc). We have to translate them
+ *	to %I64.
+ */
+
+char *ntfs_utils_reformat(char *out, int sz, const char *fmt)
+{
+	const char *f;
+	char *p;
+	int i;
+	enum { F_INIT, F_PERCENT, F_FIRST } state;
+
+	i = 0;
+	f = fmt;
+	p = out;
+	state = F_INIT;
+	while (*f && ((i + 3) < sz)) {
+		switch (state) {
+		case F_INIT :
+			if (*f == '%')
+				state = F_PERCENT;
+			*p++ = *f++;
+			i++;
+			break;
+		case F_PERCENT :
+			if (*f == 'l') {
+				state = F_FIRST;
+				f++;
+			} else {
+				if (((*f < '0') || (*f > '9'))
+				    && (*f != '*') && (*f != '-'))
+					state = F_INIT;
+				*p++ = *f++;
+				i++;
+			}
+			break;
+		case F_FIRST :
+			if (*f == 'l') {
+				*p++ = 'I';
+				*p++ = '6';
+				*p++ = '4';
+				f++;
+				i += 3;
+			} else {
+				*p++ = 'l';
+				*p++ = *f++;
+				i += 2;
+			}
+			state = F_INIT;
+			break;
+		}
+	}
+	*p++ = 0;
+	return (out);
+}
+
+#endif
diff --git a/ntfsprogs/utils.h b/ntfsprogs/utils.h
new file mode 100755
index 0000000000000000000000000000000000000000..8b6bfae5e8ba4a486e6004f67a8fc00797f435df
--- /dev/null
+++ b/ntfsprogs/utils.h
@@ -0,0 +1,137 @@
+/*
+ * utils.h - Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2002-2005 Richard Russon
+ * Copyright (c) 2004 Anton Altaparmakov
+ *
+ * A set of shared functions for ntfs utilities
+ *
+ * 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 Linux-NTFS
+ * 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_UTILS_H_
+#define _NTFS_UTILS_H_
+
+#include "config.h"
+
+#include "types.h"
+#include "layout.h"
+#include "volume.h"
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+
+extern const char *ntfs_bugs;
+extern const char *ntfs_gpl;
+
+int utils_set_locale(void);
+int utils_parse_size(const char *value, s64 *size, BOOL scale);
+int utils_parse_range(const char *string, s64 *start, s64 *finish, BOOL scale);
+int utils_inode_get_name(ntfs_inode *inode, char *buffer, int bufsize);
+int utils_attr_get_name(ntfs_volume *vol, ATTR_RECORD *attr, char *buffer, int bufsize);
+int utils_cluster_in_use(ntfs_volume *vol, long long lcn);
+int utils_mftrec_in_use(ntfs_volume *vol, MFT_REF mref);
+int utils_is_metadata(ntfs_inode *inode);
+void utils_dump_mem(void *buf, int start, int length, int flags);
+
+ATTR_RECORD * find_attribute(const ATTR_TYPES type, ntfs_attr_search_ctx *ctx);
+ATTR_RECORD * find_first_attribute(const ATTR_TYPES type, MFT_RECORD *mft);
+
+int utils_valid_device(const char *name, int force);
+ntfs_volume * utils_mount_volume(const char *device, unsigned long flags);
+
+/**
+ * defines...
+ * if *not in use* then the other flags are ignored?
+ */
+#define FEMR_IN_USE		(1 << 0)
+#define FEMR_NOT_IN_USE		(1 << 1)
+#define FEMR_FILE		(1 << 2)		// $DATA
+#define FEMR_DIR		(1 << 3)		// $INDEX_ROOT, "$I30"
+#define FEMR_METADATA		(1 << 4)
+#define FEMR_NOT_METADATA	(1 << 5)
+#define FEMR_BASE_RECORD	(1 << 6)
+#define FEMR_NOT_BASE_RECORD	(1 << 7)
+#define FEMR_ALL_RECORDS	0xFF
+
+/**
+ * struct mft_search_ctx
+ */
+struct mft_search_ctx {
+	int flags_search;
+	int flags_match;
+	ntfs_inode *inode;
+	ntfs_volume *vol;
+	u64 mft_num;
+};
+
+struct mft_search_ctx * mft_get_search_ctx(ntfs_volume *vol);
+void mft_put_search_ctx(struct mft_search_ctx *ctx);
+int mft_next_record(struct mft_search_ctx *ctx);
+
+// Flags for dump mem
+#define DM_DEFAULTS	0
+#define DM_NO_ASCII	(1 << 0)
+#define DM_NO_DIVIDER	(1 << 1)
+#define DM_INDENT	(1 << 2)
+#define DM_RED		(1 << 3)
+#define DM_GREEN	(1 << 4)
+#define DM_BLUE		(1 << 5)
+#define DM_BOLD		(1 << 6)
+
+/* MAX_PATH definition was missing in ntfs-3g's headers. */
+#ifndef MAX_PATH
+#define MAX_PATH 1024
+#endif
+
+#ifdef HAVE_WINDOWS_H
+/*
+ *	Macroes to hide the needs to translate formats on older Windows
+ */
+#define MAX_FMT 1536
+char *ntfs_utils_reformat(char *out, int sz, const char *fmt);
+#define ntfs_log_redirect(fn,fi,li,le,d,fmt, args...) \
+		do { char buf[MAX_FMT]; ntfs_log_redirect(fn,fi,li,le,d, \
+		ntfs_utils_reformat(buf,MAX_FMT,fmt), args); } while (0)
+#define printf(fmt, args...) \
+		do { char buf[MAX_FMT]; \
+		printf(ntfs_utils_reformat(buf,MAX_FMT,fmt), args); } while (0)
+#define fprintf(str, fmt, args...) \
+		do { char buf[MAX_FMT]; \
+		fprintf(str, ntfs_utils_reformat(buf,MAX_FMT,fmt), args); } while (0)
+#define vfprintf(file, fmt, args) \
+		do { char buf[MAX_FMT]; vfprintf(file, \
+		ntfs_utils_reformat(buf,MAX_FMT,fmt), args); } while (0)
+#endif
+
+/**
+ * linux-ntfs's ntfs_mbstoucs has different semantics, so we emulate it with
+ * ntfs-3g's.
+ */
+int ntfs_mbstoucs_libntfscompat(const char *ins,
+		ntfschar **outs, int outs_len);
+
+/* This simple utility function was missing from libntfs-3g. */
+static __inline__ ntfschar *ntfs_attr_get_name(ATTR_RECORD *attr)
+{
+	return (ntfschar*)((u8*)attr + le16_to_cpu(attr->name_offset));
+}
+
+#endif /* _NTFS_UTILS_H_ */
diff --git a/src/Android.mk b/src/Android.mk
new file mode 100755
index 0000000000000000000000000000000000000000..cddce78b3cd7365798610d9df22c1bc7fa9950d9
--- /dev/null
+++ b/src/Android.mk
@@ -0,0 +1,76 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+	ntfs-3g_common.c \
+	ntfs-3g.c
+ 
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH)/.. \
+	$(LOCAL_PATH)/../src \
+	$(LOCAL_PATH)/../include/fuse-lite \
+	$(LOCAL_PATH)/../include/ntfs-3g
+ 
+LOCAL_CFLAGS := -O2 -g -W -Wall \
+	-D_LARGEFILE_SOURCE \
+	-D_FILE_OFFSET_BITS=64 \
+	-DHAVE_CONFIG_H
+ 
+LOCAL_MODULE := ntfs-3g
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := libc libutils libntfs-3g
+LOCAL_STATIC_LIBRARIES := libfuse-lite 
+ 
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+	ntfs-3g_common.c \
+	lowntfs-3g.c
+ 
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH)/.. \
+	$(LOCAL_PATH)/../src \
+	$(LOCAL_PATH)/../include/fuse-lite \
+	$(LOCAL_PATH)/../include/ntfs-3g
+ 
+LOCAL_CFLAGS := -O2 -g -W -Wall \
+	-D_LARGEFILE_SOURCE \
+	-D_FILE_OFFSET_BITS=64 \
+	-DHAVE_CONFIG_H
+ 
+LOCAL_MODULE := lowntfs-3g
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := libc libutils libntfs-3g
+LOCAL_STATIC_LIBRARIES := libfuse-lite 
+ 
+#include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+	usermap.c
+ 
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH)/.. \
+	$(LOCAL_PATH)/../src \
+	$(LOCAL_PATH)/../include/fuse-lite \
+	$(LOCAL_PATH)/../include/ntfs-3g
+ 
+LOCAL_CFLAGS := -O2 -g -W -Wall \
+	-D_LARGEFILE_SOURCE \
+	-D_FILE_OFFSET_BITS=64 \
+	-DHAVE_CONFIG_H
+ 
+LOCAL_MODULE := usermap
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := libc libutils libntfs-3g
+LOCAL_STATIC_LIBRARIES := libfuse-lite 
+ 
+#include $(BUILD_EXECUTABLE)
+
+
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100755
index 0000000000000000000000000000000000000000..89ac5ce09f8b36f59b7d7869d056d473ecbab777
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,86 @@
+
+EXTRA_DIST = secaudit.h ntfs-3g_common.h
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+if FUSE_INTERNAL
+FUSE_CFLAGS = -I$(top_srcdir)/include/fuse-lite
+FUSE_LIBS   = $(top_builddir)/libfuse-lite/libfuse-lite.la
+else
+FUSE_CFLAGS = $(FUSE_MODULE_CFLAGS)
+FUSE_LIBS   = $(FUSE_MODULE_LIBS)
+endif
+
+if ENABLE_NTFS_3G
+
+bin_PROGRAMS	 = ntfs-3g.probe \
+		ntfs-3g.usermap \
+		ntfs-3g.secaudit
+rootbin_PROGRAMS = ntfs-3g lowntfs-3g
+rootsbin_DATA 	 = #Create directory
+man_MANS	 = ntfs-3g.8 ntfs-3g.probe.8 \
+		ntfs-3g.usermap.8 \
+		ntfs-3g.secaudit.8
+
+ntfs_3g_LDADD    = $(FUSE_LIBS) $(top_builddir)/libntfs-3g/libntfs-3g.la
+if REALLYSTATIC
+ntfs_3g_LDFLAGS  = $(AM_LDFLAGS) -all-static
+endif
+ntfs_3g_CFLAGS   =			\
+	$(AM_CFLAGS) 			\
+	-DFUSE_USE_VERSION=26 		\
+	$(FUSE_CFLAGS) 			\
+	-I$(top_srcdir)/include/ntfs-3g
+ntfs_3g_SOURCES  = ntfs-3g.c ntfs-3g_common.c
+
+lowntfs_3g_LDADD    = $(FUSE_LIBS) $(top_builddir)/libntfs-3g/libntfs-3g.la
+if REALLYSTATIC
+lowntfs_3g_LDFLAGS  = $(AM_LDFLAGS) -all-static
+endif
+lowntfs_3g_CFLAGS   =			\
+	$(AM_CFLAGS) 			\
+	-DFUSE_USE_VERSION=26 		\
+	$(FUSE_CFLAGS) 			\
+	-I$(top_srcdir)/include/ntfs-3g
+lowntfs_3g_SOURCES  = lowntfs-3g.c ntfs-3g_common.c
+
+ntfs_3g_probe_LDADD 	= $(top_builddir)/libntfs-3g/libntfs-3g.la
+ntfs_3g_usermap_LDADD 	= $(top_builddir)/libntfs-3g/libntfs-3g.la
+ntfs_3g_secaudit_LDADD 	= $(top_builddir)/libntfs-3g/libntfs-3g.la
+if REALLYSTATIC
+ntfs_3g_probe_LDFLAGS	= $(AM_LDFLAGS) -all-static
+ntfs_3g_usermap_LDFLAGS	= $(AM_LDFLAGS) -all-static
+ntfs_3g_secaudit_LDFLAGS	= $(AM_LDFLAGS) -all-static
+endif
+ntfs_3g_probe_CFLAGS  	= $(AM_CFLAGS) -I$(top_srcdir)/include/ntfs-3g
+ntfs_3g_usermap_CFLAGS  	= $(AM_CFLAGS) -I$(top_srcdir)/include/ntfs-3g
+ntfs_3g_secaudit_CFLAGS  	= $(AM_CFLAGS) -I$(top_srcdir)/include/ntfs-3g
+ntfs_3g_probe_SOURCES 	= ntfs-3g.probe.c
+ntfs_3g_usermap_SOURCES 	= usermap.c
+ntfs_3g_secaudit_SOURCES 	= secaudit.c
+
+drivers : $(FUSE_LIBS) ntfs-3g lowntfs-3g
+
+if RUN_LDCONFIG
+install-exec-hook:
+	$(LDCONFIG)
+endif
+
+if ENABLE_MOUNT_HELPER
+install-exec-local:	install-rootbinPROGRAMS
+	$(MKDIR_P) "$(DESTDIR)/sbin"
+	$(LN_S) -f "$(rootbindir)/ntfs-3g" "$(DESTDIR)/sbin/mount.ntfs-3g"
+	$(LN_S) -f "$(rootbindir)/lowntfs-3g" "$(DESTDIR)/sbin/mount.lowntfs-3g"
+endif
+
+install-data-local:	install-man8
+	$(LN_S) -f ntfs-3g.8 "$(DESTDIR)$(man8dir)/mount.ntfs-3g.8"
+	$(LN_S) -f ntfs-3g.8 "$(DESTDIR)$(man8dir)/mount.lowntfs-3g.8"
+
+uninstall-local:
+	$(RM) -f "$(DESTDIR)$(man8dir)/mount.ntfs-3g.8"
+if ENABLE_MOUNT_HELPER
+	$(RM) -f "$(DESTDIR)/sbin/mount.ntfs-3g" "$(DESTDIR)/sbin/mount.lowntfs-3g"
+endif
+
+endif # ENABLE_NTFS_3G
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100755
index 0000000000000000000000000000000000000000..ce94059e54966a4a470cf4cbd4603332bbdde560
--- /dev/null
+++ b/src/Makefile.in
@@ -0,0 +1,1057 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@ENABLE_NTFS_3G_TRUE@bin_PROGRAMS = ntfs-3g.probe$(EXEEXT) \
+@ENABLE_NTFS_3G_TRUE@	ntfs-3g.usermap$(EXEEXT) \
+@ENABLE_NTFS_3G_TRUE@	ntfs-3g.secaudit$(EXEEXT)
+@ENABLE_NTFS_3G_TRUE@rootbin_PROGRAMS = ntfs-3g$(EXEEXT) \
+@ENABLE_NTFS_3G_TRUE@	lowntfs-3g$(EXEEXT)
+subdir = src
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+	$(srcdir)/ntfs-3g.8.in $(srcdir)/ntfs-3g.probe.8.in \
+	$(srcdir)/ntfs-3g.usermap.8.in $(srcdir)/ntfs-3g.secaudit.8.in \
+	$(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = ntfs-3g.8 ntfs-3g.probe.8 ntfs-3g.usermap.8 \
+	ntfs-3g.secaudit.8
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(rootbindir)" \
+	"$(DESTDIR)$(man8dir)" "$(DESTDIR)$(rootsbindir)"
+PROGRAMS = $(bin_PROGRAMS) $(rootbin_PROGRAMS)
+am__lowntfs_3g_SOURCES_DIST = lowntfs-3g.c ntfs-3g_common.c
+@ENABLE_NTFS_3G_TRUE@am_lowntfs_3g_OBJECTS =  \
+@ENABLE_NTFS_3G_TRUE@	lowntfs_3g-lowntfs-3g.$(OBJEXT) \
+@ENABLE_NTFS_3G_TRUE@	lowntfs_3g-ntfs-3g_common.$(OBJEXT)
+lowntfs_3g_OBJECTS = $(am_lowntfs_3g_OBJECTS)
+am__DEPENDENCIES_1 =
+@FUSE_INTERNAL_FALSE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
+@FUSE_INTERNAL_TRUE@am__DEPENDENCIES_2 = $(top_builddir)/libfuse-lite/libfuse-lite.la
+@ENABLE_NTFS_3G_TRUE@lowntfs_3g_DEPENDENCIES = $(am__DEPENDENCIES_2) \
+@ENABLE_NTFS_3G_TRUE@	$(top_builddir)/libntfs-3g/libntfs-3g.la
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
+lowntfs_3g_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(lowntfs_3g_CFLAGS) \
+	$(CFLAGS) $(lowntfs_3g_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfs_3g_SOURCES_DIST = ntfs-3g.c ntfs-3g_common.c
+@ENABLE_NTFS_3G_TRUE@am_ntfs_3g_OBJECTS = ntfs_3g-ntfs-3g.$(OBJEXT) \
+@ENABLE_NTFS_3G_TRUE@	ntfs_3g-ntfs-3g_common.$(OBJEXT)
+ntfs_3g_OBJECTS = $(am_ntfs_3g_OBJECTS)
+@ENABLE_NTFS_3G_TRUE@ntfs_3g_DEPENDENCIES = $(am__DEPENDENCIES_2) \
+@ENABLE_NTFS_3G_TRUE@	$(top_builddir)/libntfs-3g/libntfs-3g.la
+ntfs_3g_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ntfs_3g_CFLAGS) \
+	$(CFLAGS) $(ntfs_3g_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfs_3g_probe_SOURCES_DIST = ntfs-3g.probe.c
+@ENABLE_NTFS_3G_TRUE@am_ntfs_3g_probe_OBJECTS =  \
+@ENABLE_NTFS_3G_TRUE@	ntfs_3g_probe-ntfs-3g.probe.$(OBJEXT)
+ntfs_3g_probe_OBJECTS = $(am_ntfs_3g_probe_OBJECTS)
+@ENABLE_NTFS_3G_TRUE@ntfs_3g_probe_DEPENDENCIES =  \
+@ENABLE_NTFS_3G_TRUE@	$(top_builddir)/libntfs-3g/libntfs-3g.la
+ntfs_3g_probe_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ntfs_3g_probe_CFLAGS) \
+	$(CFLAGS) $(ntfs_3g_probe_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfs_3g_secaudit_SOURCES_DIST = secaudit.c
+@ENABLE_NTFS_3G_TRUE@am_ntfs_3g_secaudit_OBJECTS =  \
+@ENABLE_NTFS_3G_TRUE@	ntfs_3g_secaudit-secaudit.$(OBJEXT)
+ntfs_3g_secaudit_OBJECTS = $(am_ntfs_3g_secaudit_OBJECTS)
+@ENABLE_NTFS_3G_TRUE@ntfs_3g_secaudit_DEPENDENCIES =  \
+@ENABLE_NTFS_3G_TRUE@	$(top_builddir)/libntfs-3g/libntfs-3g.la
+ntfs_3g_secaudit_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(ntfs_3g_secaudit_CFLAGS) $(CFLAGS) \
+	$(ntfs_3g_secaudit_LDFLAGS) $(LDFLAGS) -o $@
+am__ntfs_3g_usermap_SOURCES_DIST = usermap.c
+@ENABLE_NTFS_3G_TRUE@am_ntfs_3g_usermap_OBJECTS =  \
+@ENABLE_NTFS_3G_TRUE@	ntfs_3g_usermap-usermap.$(OBJEXT)
+ntfs_3g_usermap_OBJECTS = $(am_ntfs_3g_usermap_OBJECTS)
+@ENABLE_NTFS_3G_TRUE@ntfs_3g_usermap_DEPENDENCIES =  \
+@ENABLE_NTFS_3G_TRUE@	$(top_builddir)/libntfs-3g/libntfs-3g.la
+ntfs_3g_usermap_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(ntfs_3g_usermap_CFLAGS) $(CFLAGS) $(ntfs_3g_usermap_LDFLAGS) \
+	$(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
+SOURCES = $(lowntfs_3g_SOURCES) $(ntfs_3g_SOURCES) \
+	$(ntfs_3g_probe_SOURCES) $(ntfs_3g_secaudit_SOURCES) \
+	$(ntfs_3g_usermap_SOURCES)
+DIST_SOURCES = $(am__lowntfs_3g_SOURCES_DIST) \
+	$(am__ntfs_3g_SOURCES_DIST) $(am__ntfs_3g_probe_SOURCES_DIST) \
+	$(am__ntfs_3g_secaudit_SOURCES_DIST) \
+	$(am__ntfs_3g_usermap_SOURCES_DIST)
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+man8dir = $(mandir)/man8
+NROFF = nroff
+MANS = $(man_MANS)
+DATA = $(rootsbin_DATA)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FUSE_MODULE_CFLAGS = @FUSE_MODULE_CFLAGS@
+FUSE_MODULE_LIBS = @FUSE_MODULE_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDCONFIG = @LDCONFIG@
+LDFLAGS = @LDFLAGS@
+LIBFUSE_LITE_CFLAGS = @LIBFUSE_LITE_CFLAGS@
+LIBFUSE_LITE_LIBS = @LIBFUSE_LITE_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBNTFS_3G_VERSION = @LIBNTFS_3G_VERSION@
+LIBNTFS_CPPFLAGS = @LIBNTFS_CPPFLAGS@
+LIBNTFS_LIBS = @LIBNTFS_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MKNTFS_CPPFLAGS = @MKNTFS_CPPFLAGS@
+MKNTFS_LIBS = @MKNTFS_LIBS@
+MV = @MV@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NTFSPROGS_STATIC_LIBS = @NTFSPROGS_STATIC_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+OUTPUT_FORMAT = @OUTPUT_FORMAT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+RM = @RM@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+all_includes = @all_includes@
+all_libraries = @all_libraries@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+ntfs3gincludedir = @ntfs3gincludedir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgconfigdir = @pkgconfigdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+rootbindir = @rootbindir@
+rootlibdir = @rootlibdir@
+rootsbindir = @rootsbindir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = secaudit.h ntfs-3g_common.h
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+@FUSE_INTERNAL_FALSE@FUSE_CFLAGS = $(FUSE_MODULE_CFLAGS)
+@FUSE_INTERNAL_TRUE@FUSE_CFLAGS = -I$(top_srcdir)/include/fuse-lite
+@FUSE_INTERNAL_FALSE@FUSE_LIBS = $(FUSE_MODULE_LIBS)
+@FUSE_INTERNAL_TRUE@FUSE_LIBS = $(top_builddir)/libfuse-lite/libfuse-lite.la
+@ENABLE_NTFS_3G_TRUE@rootsbin_DATA = #Create directory
+@ENABLE_NTFS_3G_TRUE@man_MANS = ntfs-3g.8 ntfs-3g.probe.8 \
+@ENABLE_NTFS_3G_TRUE@		ntfs-3g.usermap.8 \
+@ENABLE_NTFS_3G_TRUE@		ntfs-3g.secaudit.8
+
+@ENABLE_NTFS_3G_TRUE@ntfs_3g_LDADD = $(FUSE_LIBS) $(top_builddir)/libntfs-3g/libntfs-3g.la
+@ENABLE_NTFS_3G_TRUE@@REALLYSTATIC_TRUE@ntfs_3g_LDFLAGS = $(AM_LDFLAGS) -all-static
+@ENABLE_NTFS_3G_TRUE@ntfs_3g_CFLAGS = \
+@ENABLE_NTFS_3G_TRUE@	$(AM_CFLAGS) 			\
+@ENABLE_NTFS_3G_TRUE@	-DFUSE_USE_VERSION=26 		\
+@ENABLE_NTFS_3G_TRUE@	$(FUSE_CFLAGS) 			\
+@ENABLE_NTFS_3G_TRUE@	-I$(top_srcdir)/include/ntfs-3g
+
+@ENABLE_NTFS_3G_TRUE@ntfs_3g_SOURCES = ntfs-3g.c ntfs-3g_common.c
+@ENABLE_NTFS_3G_TRUE@lowntfs_3g_LDADD = $(FUSE_LIBS) $(top_builddir)/libntfs-3g/libntfs-3g.la
+@ENABLE_NTFS_3G_TRUE@@REALLYSTATIC_TRUE@lowntfs_3g_LDFLAGS = $(AM_LDFLAGS) -all-static
+@ENABLE_NTFS_3G_TRUE@lowntfs_3g_CFLAGS = \
+@ENABLE_NTFS_3G_TRUE@	$(AM_CFLAGS) 			\
+@ENABLE_NTFS_3G_TRUE@	-DFUSE_USE_VERSION=26 		\
+@ENABLE_NTFS_3G_TRUE@	$(FUSE_CFLAGS) 			\
+@ENABLE_NTFS_3G_TRUE@	-I$(top_srcdir)/include/ntfs-3g
+
+@ENABLE_NTFS_3G_TRUE@lowntfs_3g_SOURCES = lowntfs-3g.c ntfs-3g_common.c
+@ENABLE_NTFS_3G_TRUE@ntfs_3g_probe_LDADD = $(top_builddir)/libntfs-3g/libntfs-3g.la
+@ENABLE_NTFS_3G_TRUE@ntfs_3g_usermap_LDADD = $(top_builddir)/libntfs-3g/libntfs-3g.la
+@ENABLE_NTFS_3G_TRUE@ntfs_3g_secaudit_LDADD = $(top_builddir)/libntfs-3g/libntfs-3g.la
+@ENABLE_NTFS_3G_TRUE@@REALLYSTATIC_TRUE@ntfs_3g_probe_LDFLAGS = $(AM_LDFLAGS) -all-static
+@ENABLE_NTFS_3G_TRUE@@REALLYSTATIC_TRUE@ntfs_3g_usermap_LDFLAGS = $(AM_LDFLAGS) -all-static
+@ENABLE_NTFS_3G_TRUE@@REALLYSTATIC_TRUE@ntfs_3g_secaudit_LDFLAGS = $(AM_LDFLAGS) -all-static
+@ENABLE_NTFS_3G_TRUE@ntfs_3g_probe_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/include/ntfs-3g
+@ENABLE_NTFS_3G_TRUE@ntfs_3g_usermap_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/include/ntfs-3g
+@ENABLE_NTFS_3G_TRUE@ntfs_3g_secaudit_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/include/ntfs-3g
+@ENABLE_NTFS_3G_TRUE@ntfs_3g_probe_SOURCES = ntfs-3g.probe.c
+@ENABLE_NTFS_3G_TRUE@ntfs_3g_usermap_SOURCES = usermap.c
+@ENABLE_NTFS_3G_TRUE@ntfs_3g_secaudit_SOURCES = secaudit.c
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+ntfs-3g.8: $(top_builddir)/config.status $(srcdir)/ntfs-3g.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfs-3g.probe.8: $(top_builddir)/config.status $(srcdir)/ntfs-3g.probe.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfs-3g.usermap.8: $(top_builddir)/config.status $(srcdir)/ntfs-3g.usermap.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ntfs-3g.secaudit.8: $(top_builddir)/config.status $(srcdir)/ntfs-3g.secaudit.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+	fi; \
+	for p in $$list; do echo "$$p $$p"; done | \
+	sed 's/$(EXEEXT)$$//' | \
+	while read p p1; do if test -f $$p \
+	 || test -f $$p1 \
+	  ; then echo "$$p"; echo "$$p"; else :; fi; \
+	done | \
+	sed -e 'p;s,.*/,,;n;h' \
+	    -e 's|.*|.|' \
+	    -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+	sed 'N;N;N;s,\n, ,g' | \
+	$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+	  { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+	    if ($$2 == $$4) files[d] = files[d] " " $$1; \
+	    else { print "f", $$3 "/" $$4, $$1; } } \
+	  END { for (d in files) print "f", d, files[d] }' | \
+	while read type dir files; do \
+	    if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+	    test -z "$$files" || { \
+	    echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+	    $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+	    } \
+	; done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+	files=`for p in $$list; do echo "$$p"; done | \
+	  sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+	      -e 's/$$/$(EXEEXT)/' \
+	`; \
+	test -n "$$list" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+	@list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
+	echo " rm -f" $$list; \
+	rm -f $$list || exit $$?; \
+	test -n "$(EXEEXT)" || exit 0; \
+	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+	echo " rm -f" $$list; \
+	rm -f $$list
+install-rootbinPROGRAMS: $(rootbin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	@list='$(rootbin_PROGRAMS)'; test -n "$(rootbindir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(rootbindir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(rootbindir)" || exit 1; \
+	fi; \
+	for p in $$list; do echo "$$p $$p"; done | \
+	sed 's/$(EXEEXT)$$//' | \
+	while read p p1; do if test -f $$p \
+	 || test -f $$p1 \
+	  ; then echo "$$p"; echo "$$p"; else :; fi; \
+	done | \
+	sed -e 'p;s,.*/,,;n;h' \
+	    -e 's|.*|.|' \
+	    -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+	sed 'N;N;N;s,\n, ,g' | \
+	$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+	  { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+	    if ($$2 == $$4) files[d] = files[d] " " $$1; \
+	    else { print "f", $$3 "/" $$4, $$1; } } \
+	  END { for (d in files) print "f", d, files[d] }' | \
+	while read type dir files; do \
+	    if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+	    test -z "$$files" || { \
+	    echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(rootbindir)$$dir'"; \
+	    $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(rootbindir)$$dir" || exit $$?; \
+	    } \
+	; done
+
+uninstall-rootbinPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(rootbin_PROGRAMS)'; test -n "$(rootbindir)" || list=; \
+	files=`for p in $$list; do echo "$$p"; done | \
+	  sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+	      -e 's/$$/$(EXEEXT)/' \
+	`; \
+	test -n "$$list" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(rootbindir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(rootbindir)" && rm -f $$files
+
+clean-rootbinPROGRAMS:
+	@list='$(rootbin_PROGRAMS)'; test -n "$$list" || exit 0; \
+	echo " rm -f" $$list; \
+	rm -f $$list || exit $$?; \
+	test -n "$(EXEEXT)" || exit 0; \
+	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+	echo " rm -f" $$list; \
+	rm -f $$list
+
+lowntfs-3g$(EXEEXT): $(lowntfs_3g_OBJECTS) $(lowntfs_3g_DEPENDENCIES) $(EXTRA_lowntfs_3g_DEPENDENCIES) 
+	@rm -f lowntfs-3g$(EXEEXT)
+	$(AM_V_CCLD)$(lowntfs_3g_LINK) $(lowntfs_3g_OBJECTS) $(lowntfs_3g_LDADD) $(LIBS)
+
+ntfs-3g$(EXEEXT): $(ntfs_3g_OBJECTS) $(ntfs_3g_DEPENDENCIES) $(EXTRA_ntfs_3g_DEPENDENCIES) 
+	@rm -f ntfs-3g$(EXEEXT)
+	$(AM_V_CCLD)$(ntfs_3g_LINK) $(ntfs_3g_OBJECTS) $(ntfs_3g_LDADD) $(LIBS)
+
+ntfs-3g.probe$(EXEEXT): $(ntfs_3g_probe_OBJECTS) $(ntfs_3g_probe_DEPENDENCIES) $(EXTRA_ntfs_3g_probe_DEPENDENCIES) 
+	@rm -f ntfs-3g.probe$(EXEEXT)
+	$(AM_V_CCLD)$(ntfs_3g_probe_LINK) $(ntfs_3g_probe_OBJECTS) $(ntfs_3g_probe_LDADD) $(LIBS)
+
+ntfs-3g.secaudit$(EXEEXT): $(ntfs_3g_secaudit_OBJECTS) $(ntfs_3g_secaudit_DEPENDENCIES) $(EXTRA_ntfs_3g_secaudit_DEPENDENCIES) 
+	@rm -f ntfs-3g.secaudit$(EXEEXT)
+	$(AM_V_CCLD)$(ntfs_3g_secaudit_LINK) $(ntfs_3g_secaudit_OBJECTS) $(ntfs_3g_secaudit_LDADD) $(LIBS)
+
+ntfs-3g.usermap$(EXEEXT): $(ntfs_3g_usermap_OBJECTS) $(ntfs_3g_usermap_DEPENDENCIES) $(EXTRA_ntfs_3g_usermap_DEPENDENCIES) 
+	@rm -f ntfs-3g.usermap$(EXEEXT)
+	$(AM_V_CCLD)$(ntfs_3g_usermap_LINK) $(ntfs_3g_usermap_OBJECTS) $(ntfs_3g_usermap_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lowntfs_3g-lowntfs-3g.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lowntfs_3g-ntfs-3g_common.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfs_3g-ntfs-3g.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfs_3g-ntfs-3g_common.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfs_3g_probe-ntfs-3g.probe.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfs_3g_secaudit-secaudit.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfs_3g_usermap-usermap.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+lowntfs_3g-lowntfs-3g.o: lowntfs-3g.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lowntfs_3g_CFLAGS) $(CFLAGS) -MT lowntfs_3g-lowntfs-3g.o -MD -MP -MF $(DEPDIR)/lowntfs_3g-lowntfs-3g.Tpo -c -o lowntfs_3g-lowntfs-3g.o `test -f 'lowntfs-3g.c' || echo '$(srcdir)/'`lowntfs-3g.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lowntfs_3g-lowntfs-3g.Tpo $(DEPDIR)/lowntfs_3g-lowntfs-3g.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lowntfs-3g.c' object='lowntfs_3g-lowntfs-3g.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lowntfs_3g_CFLAGS) $(CFLAGS) -c -o lowntfs_3g-lowntfs-3g.o `test -f 'lowntfs-3g.c' || echo '$(srcdir)/'`lowntfs-3g.c
+
+lowntfs_3g-lowntfs-3g.obj: lowntfs-3g.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lowntfs_3g_CFLAGS) $(CFLAGS) -MT lowntfs_3g-lowntfs-3g.obj -MD -MP -MF $(DEPDIR)/lowntfs_3g-lowntfs-3g.Tpo -c -o lowntfs_3g-lowntfs-3g.obj `if test -f 'lowntfs-3g.c'; then $(CYGPATH_W) 'lowntfs-3g.c'; else $(CYGPATH_W) '$(srcdir)/lowntfs-3g.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lowntfs_3g-lowntfs-3g.Tpo $(DEPDIR)/lowntfs_3g-lowntfs-3g.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='lowntfs-3g.c' object='lowntfs_3g-lowntfs-3g.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lowntfs_3g_CFLAGS) $(CFLAGS) -c -o lowntfs_3g-lowntfs-3g.obj `if test -f 'lowntfs-3g.c'; then $(CYGPATH_W) 'lowntfs-3g.c'; else $(CYGPATH_W) '$(srcdir)/lowntfs-3g.c'; fi`
+
+lowntfs_3g-ntfs-3g_common.o: ntfs-3g_common.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lowntfs_3g_CFLAGS) $(CFLAGS) -MT lowntfs_3g-ntfs-3g_common.o -MD -MP -MF $(DEPDIR)/lowntfs_3g-ntfs-3g_common.Tpo -c -o lowntfs_3g-ntfs-3g_common.o `test -f 'ntfs-3g_common.c' || echo '$(srcdir)/'`ntfs-3g_common.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lowntfs_3g-ntfs-3g_common.Tpo $(DEPDIR)/lowntfs_3g-ntfs-3g_common.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ntfs-3g_common.c' object='lowntfs_3g-ntfs-3g_common.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lowntfs_3g_CFLAGS) $(CFLAGS) -c -o lowntfs_3g-ntfs-3g_common.o `test -f 'ntfs-3g_common.c' || echo '$(srcdir)/'`ntfs-3g_common.c
+
+lowntfs_3g-ntfs-3g_common.obj: ntfs-3g_common.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lowntfs_3g_CFLAGS) $(CFLAGS) -MT lowntfs_3g-ntfs-3g_common.obj -MD -MP -MF $(DEPDIR)/lowntfs_3g-ntfs-3g_common.Tpo -c -o lowntfs_3g-ntfs-3g_common.obj `if test -f 'ntfs-3g_common.c'; then $(CYGPATH_W) 'ntfs-3g_common.c'; else $(CYGPATH_W) '$(srcdir)/ntfs-3g_common.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lowntfs_3g-ntfs-3g_common.Tpo $(DEPDIR)/lowntfs_3g-ntfs-3g_common.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ntfs-3g_common.c' object='lowntfs_3g-ntfs-3g_common.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lowntfs_3g_CFLAGS) $(CFLAGS) -c -o lowntfs_3g-ntfs-3g_common.obj `if test -f 'ntfs-3g_common.c'; then $(CYGPATH_W) 'ntfs-3g_common.c'; else $(CYGPATH_W) '$(srcdir)/ntfs-3g_common.c'; fi`
+
+ntfs_3g-ntfs-3g.o: ntfs-3g.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_CFLAGS) $(CFLAGS) -MT ntfs_3g-ntfs-3g.o -MD -MP -MF $(DEPDIR)/ntfs_3g-ntfs-3g.Tpo -c -o ntfs_3g-ntfs-3g.o `test -f 'ntfs-3g.c' || echo '$(srcdir)/'`ntfs-3g.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/ntfs_3g-ntfs-3g.Tpo $(DEPDIR)/ntfs_3g-ntfs-3g.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ntfs-3g.c' object='ntfs_3g-ntfs-3g.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_CFLAGS) $(CFLAGS) -c -o ntfs_3g-ntfs-3g.o `test -f 'ntfs-3g.c' || echo '$(srcdir)/'`ntfs-3g.c
+
+ntfs_3g-ntfs-3g.obj: ntfs-3g.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_CFLAGS) $(CFLAGS) -MT ntfs_3g-ntfs-3g.obj -MD -MP -MF $(DEPDIR)/ntfs_3g-ntfs-3g.Tpo -c -o ntfs_3g-ntfs-3g.obj `if test -f 'ntfs-3g.c'; then $(CYGPATH_W) 'ntfs-3g.c'; else $(CYGPATH_W) '$(srcdir)/ntfs-3g.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/ntfs_3g-ntfs-3g.Tpo $(DEPDIR)/ntfs_3g-ntfs-3g.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ntfs-3g.c' object='ntfs_3g-ntfs-3g.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_CFLAGS) $(CFLAGS) -c -o ntfs_3g-ntfs-3g.obj `if test -f 'ntfs-3g.c'; then $(CYGPATH_W) 'ntfs-3g.c'; else $(CYGPATH_W) '$(srcdir)/ntfs-3g.c'; fi`
+
+ntfs_3g-ntfs-3g_common.o: ntfs-3g_common.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_CFLAGS) $(CFLAGS) -MT ntfs_3g-ntfs-3g_common.o -MD -MP -MF $(DEPDIR)/ntfs_3g-ntfs-3g_common.Tpo -c -o ntfs_3g-ntfs-3g_common.o `test -f 'ntfs-3g_common.c' || echo '$(srcdir)/'`ntfs-3g_common.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/ntfs_3g-ntfs-3g_common.Tpo $(DEPDIR)/ntfs_3g-ntfs-3g_common.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ntfs-3g_common.c' object='ntfs_3g-ntfs-3g_common.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_CFLAGS) $(CFLAGS) -c -o ntfs_3g-ntfs-3g_common.o `test -f 'ntfs-3g_common.c' || echo '$(srcdir)/'`ntfs-3g_common.c
+
+ntfs_3g-ntfs-3g_common.obj: ntfs-3g_common.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_CFLAGS) $(CFLAGS) -MT ntfs_3g-ntfs-3g_common.obj -MD -MP -MF $(DEPDIR)/ntfs_3g-ntfs-3g_common.Tpo -c -o ntfs_3g-ntfs-3g_common.obj `if test -f 'ntfs-3g_common.c'; then $(CYGPATH_W) 'ntfs-3g_common.c'; else $(CYGPATH_W) '$(srcdir)/ntfs-3g_common.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/ntfs_3g-ntfs-3g_common.Tpo $(DEPDIR)/ntfs_3g-ntfs-3g_common.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ntfs-3g_common.c' object='ntfs_3g-ntfs-3g_common.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_CFLAGS) $(CFLAGS) -c -o ntfs_3g-ntfs-3g_common.obj `if test -f 'ntfs-3g_common.c'; then $(CYGPATH_W) 'ntfs-3g_common.c'; else $(CYGPATH_W) '$(srcdir)/ntfs-3g_common.c'; fi`
+
+ntfs_3g_probe-ntfs-3g.probe.o: ntfs-3g.probe.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_probe_CFLAGS) $(CFLAGS) -MT ntfs_3g_probe-ntfs-3g.probe.o -MD -MP -MF $(DEPDIR)/ntfs_3g_probe-ntfs-3g.probe.Tpo -c -o ntfs_3g_probe-ntfs-3g.probe.o `test -f 'ntfs-3g.probe.c' || echo '$(srcdir)/'`ntfs-3g.probe.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/ntfs_3g_probe-ntfs-3g.probe.Tpo $(DEPDIR)/ntfs_3g_probe-ntfs-3g.probe.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ntfs-3g.probe.c' object='ntfs_3g_probe-ntfs-3g.probe.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_probe_CFLAGS) $(CFLAGS) -c -o ntfs_3g_probe-ntfs-3g.probe.o `test -f 'ntfs-3g.probe.c' || echo '$(srcdir)/'`ntfs-3g.probe.c
+
+ntfs_3g_probe-ntfs-3g.probe.obj: ntfs-3g.probe.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_probe_CFLAGS) $(CFLAGS) -MT ntfs_3g_probe-ntfs-3g.probe.obj -MD -MP -MF $(DEPDIR)/ntfs_3g_probe-ntfs-3g.probe.Tpo -c -o ntfs_3g_probe-ntfs-3g.probe.obj `if test -f 'ntfs-3g.probe.c'; then $(CYGPATH_W) 'ntfs-3g.probe.c'; else $(CYGPATH_W) '$(srcdir)/ntfs-3g.probe.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/ntfs_3g_probe-ntfs-3g.probe.Tpo $(DEPDIR)/ntfs_3g_probe-ntfs-3g.probe.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ntfs-3g.probe.c' object='ntfs_3g_probe-ntfs-3g.probe.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_probe_CFLAGS) $(CFLAGS) -c -o ntfs_3g_probe-ntfs-3g.probe.obj `if test -f 'ntfs-3g.probe.c'; then $(CYGPATH_W) 'ntfs-3g.probe.c'; else $(CYGPATH_W) '$(srcdir)/ntfs-3g.probe.c'; fi`
+
+ntfs_3g_secaudit-secaudit.o: secaudit.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_secaudit_CFLAGS) $(CFLAGS) -MT ntfs_3g_secaudit-secaudit.o -MD -MP -MF $(DEPDIR)/ntfs_3g_secaudit-secaudit.Tpo -c -o ntfs_3g_secaudit-secaudit.o `test -f 'secaudit.c' || echo '$(srcdir)/'`secaudit.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/ntfs_3g_secaudit-secaudit.Tpo $(DEPDIR)/ntfs_3g_secaudit-secaudit.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='secaudit.c' object='ntfs_3g_secaudit-secaudit.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_secaudit_CFLAGS) $(CFLAGS) -c -o ntfs_3g_secaudit-secaudit.o `test -f 'secaudit.c' || echo '$(srcdir)/'`secaudit.c
+
+ntfs_3g_secaudit-secaudit.obj: secaudit.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_secaudit_CFLAGS) $(CFLAGS) -MT ntfs_3g_secaudit-secaudit.obj -MD -MP -MF $(DEPDIR)/ntfs_3g_secaudit-secaudit.Tpo -c -o ntfs_3g_secaudit-secaudit.obj `if test -f 'secaudit.c'; then $(CYGPATH_W) 'secaudit.c'; else $(CYGPATH_W) '$(srcdir)/secaudit.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/ntfs_3g_secaudit-secaudit.Tpo $(DEPDIR)/ntfs_3g_secaudit-secaudit.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='secaudit.c' object='ntfs_3g_secaudit-secaudit.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_secaudit_CFLAGS) $(CFLAGS) -c -o ntfs_3g_secaudit-secaudit.obj `if test -f 'secaudit.c'; then $(CYGPATH_W) 'secaudit.c'; else $(CYGPATH_W) '$(srcdir)/secaudit.c'; fi`
+
+ntfs_3g_usermap-usermap.o: usermap.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_usermap_CFLAGS) $(CFLAGS) -MT ntfs_3g_usermap-usermap.o -MD -MP -MF $(DEPDIR)/ntfs_3g_usermap-usermap.Tpo -c -o ntfs_3g_usermap-usermap.o `test -f 'usermap.c' || echo '$(srcdir)/'`usermap.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/ntfs_3g_usermap-usermap.Tpo $(DEPDIR)/ntfs_3g_usermap-usermap.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='usermap.c' object='ntfs_3g_usermap-usermap.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_usermap_CFLAGS) $(CFLAGS) -c -o ntfs_3g_usermap-usermap.o `test -f 'usermap.c' || echo '$(srcdir)/'`usermap.c
+
+ntfs_3g_usermap-usermap.obj: usermap.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_usermap_CFLAGS) $(CFLAGS) -MT ntfs_3g_usermap-usermap.obj -MD -MP -MF $(DEPDIR)/ntfs_3g_usermap-usermap.Tpo -c -o ntfs_3g_usermap-usermap.obj `if test -f 'usermap.c'; then $(CYGPATH_W) 'usermap.c'; else $(CYGPATH_W) '$(srcdir)/usermap.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/ntfs_3g_usermap-usermap.Tpo $(DEPDIR)/ntfs_3g_usermap-usermap.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='usermap.c' object='ntfs_3g_usermap-usermap.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_usermap_CFLAGS) $(CFLAGS) -c -o ntfs_3g_usermap-usermap.obj `if test -f 'usermap.c'; then $(CYGPATH_W) 'usermap.c'; else $(CYGPATH_W) '$(srcdir)/usermap.c'; fi`
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+install-man8: $(man_MANS)
+	@$(NORMAL_INSTALL)
+	@list1=''; \
+	list2='$(man_MANS)'; \
+	test -n "$(man8dir)" \
+	  && test -n "`echo $$list1$$list2`" \
+	  || exit 0; \
+	echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
+	$(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \
+	{ for i in $$list1; do echo "$$i"; done;  \
+	if test -n "$$list2"; then \
+	  for i in $$list2; do echo "$$i"; done \
+	    | sed -n '/\.8[a-z]*$$/p'; \
+	fi; \
+	} | while read p; do \
+	  if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; echo "$$p"; \
+	done | \
+	sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+	sed 'N;N;s,\n, ,g' | { \
+	list=; while read file base inst; do \
+	  if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+	    echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
+	    $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \
+	  fi; \
+	done; \
+	for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+	while read files; do \
+	  test -z "$$files" || { \
+	    echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \
+	    $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
+	done; }
+
+uninstall-man8:
+	@$(NORMAL_UNINSTALL)
+	@list=''; test -n "$(man8dir)" || exit 0; \
+	files=`{ for i in $$list; do echo "$$i"; done; \
+	l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+	  sed -n '/\.8[a-z]*$$/p'; \
+	} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+	dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
+install-rootsbinDATA: $(rootsbin_DATA)
+	@$(NORMAL_INSTALL)
+	@list='$(rootsbin_DATA)'; test -n "$(rootsbindir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(rootsbindir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(rootsbindir)" || exit 1; \
+	fi; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(rootsbindir)'"; \
+	  $(INSTALL_DATA) $$files "$(DESTDIR)$(rootsbindir)" || exit $$?; \
+	done
+
+uninstall-rootsbinDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(rootsbin_DATA)'; test -n "$(rootsbindir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	dir='$(DESTDIR)$(rootsbindir)'; $(am__uninstall_files_from_dir)
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) $(MANS) $(DATA)
+installdirs:
+	for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(rootbindir)" "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(rootsbindir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+@ENABLE_MOUNT_HELPER_FALSE@install-exec-local:
+@ENABLE_NTFS_3G_FALSE@install-exec-local:
+@ENABLE_NTFS_3G_FALSE@install-data-local:
+@ENABLE_NTFS_3G_FALSE@uninstall-local:
+@ENABLE_NTFS_3G_FALSE@install-exec-hook:
+@RUN_LDCONFIG_FALSE@install-exec-hook:
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool \
+	clean-rootbinPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-data-local install-man \
+	install-rootbinPROGRAMS install-rootsbinDATA
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS install-exec-local
+	@$(NORMAL_INSTALL)
+	$(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man: install-man8
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-local uninstall-man \
+	uninstall-rootbinPROGRAMS uninstall-rootsbinDATA
+
+uninstall-man: uninstall-man8
+
+.MAKE: install-am install-exec-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
+	clean-binPROGRAMS clean-generic clean-libtool \
+	clean-rootbinPROGRAMS cscopelist-am ctags ctags-am distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-binPROGRAMS install-data \
+	install-data-am install-data-local install-dvi install-dvi-am \
+	install-exec install-exec-am install-exec-hook \
+	install-exec-local install-html install-html-am install-info \
+	install-info-am install-man install-man8 install-pdf \
+	install-pdf-am install-ps install-ps-am \
+	install-rootbinPROGRAMS install-rootsbinDATA install-strip \
+	installcheck installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	tags tags-am uninstall uninstall-am uninstall-binPROGRAMS \
+	uninstall-local uninstall-man uninstall-man8 \
+	uninstall-rootbinPROGRAMS uninstall-rootsbinDATA
+
+
+@ENABLE_NTFS_3G_TRUE@drivers : $(FUSE_LIBS) ntfs-3g lowntfs-3g
+
+@ENABLE_NTFS_3G_TRUE@@RUN_LDCONFIG_TRUE@install-exec-hook:
+@ENABLE_NTFS_3G_TRUE@@RUN_LDCONFIG_TRUE@	$(LDCONFIG)
+
+@ENABLE_MOUNT_HELPER_TRUE@@ENABLE_NTFS_3G_TRUE@install-exec-local:	install-rootbinPROGRAMS
+@ENABLE_MOUNT_HELPER_TRUE@@ENABLE_NTFS_3G_TRUE@	$(MKDIR_P) "$(DESTDIR)/sbin"
+@ENABLE_MOUNT_HELPER_TRUE@@ENABLE_NTFS_3G_TRUE@	$(LN_S) -f "$(rootbindir)/ntfs-3g" "$(DESTDIR)/sbin/mount.ntfs-3g"
+@ENABLE_MOUNT_HELPER_TRUE@@ENABLE_NTFS_3G_TRUE@	$(LN_S) -f "$(rootbindir)/lowntfs-3g" "$(DESTDIR)/sbin/mount.lowntfs-3g"
+
+@ENABLE_NTFS_3G_TRUE@install-data-local:	install-man8
+@ENABLE_NTFS_3G_TRUE@	$(LN_S) -f ntfs-3g.8 "$(DESTDIR)$(man8dir)/mount.ntfs-3g.8"
+@ENABLE_NTFS_3G_TRUE@	$(LN_S) -f ntfs-3g.8 "$(DESTDIR)$(man8dir)/mount.lowntfs-3g.8"
+
+@ENABLE_NTFS_3G_TRUE@uninstall-local:
+@ENABLE_NTFS_3G_TRUE@	$(RM) -f "$(DESTDIR)$(man8dir)/mount.ntfs-3g.8"
+@ENABLE_MOUNT_HELPER_TRUE@@ENABLE_NTFS_3G_TRUE@	$(RM) -f "$(DESTDIR)/sbin/mount.ntfs-3g" "$(DESTDIR)/sbin/mount.lowntfs-3g"
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/lowntfs-3g.c b/src/lowntfs-3g.c
new file mode 100755
index 0000000000000000000000000000000000000000..3ff8b9de4cd20b4fbc05a3792b8e660bda261416
--- /dev/null
+++ b/src/lowntfs-3g.c
@@ -0,0 +1,4191 @@
+/**
+ * ntfs-3g - Third Generation NTFS Driver
+ *
+ * Copyright (c) 2005-2007 Yura Pakhuchiy
+ * Copyright (c) 2005 Yuval Fledel
+ * Copyright (c) 2006-2009 Szabolcs Szakacsits
+ * Copyright (c) 2007-2015 Jean-Pierre Andre
+ * Copyright (c) 2009 Erik Larsson
+ *
+ * This file is originated from the Linux-NTFS project.
+ *
+ * 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
+ */
+
+#include "config.h"
+
+#include <fuse.h>
+#include <fuse_lowlevel.h>
+
+#if !defined(FUSE_VERSION) || (FUSE_VERSION < 26)
+#error "***********************************************************"
+#error "*                                                         *"
+#error "*     Compilation requires at least FUSE version 2.6.0!   *"
+#error "*                                                         *"
+#error "***********************************************************"
+#endif
+
+#ifdef HAVE_STDIO_H
+#include <stdio.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_LOCALE_H
+#include <locale.h>
+#endif
+#include <signal.h>
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#include <syslog.h>
+#include <sys/wait.h>
+
+#ifdef HAVE_SETXATTR
+#include <sys/xattr.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_MKDEV_H
+#include <sys/mkdev.h>
+#endif
+
+#if defined(__APPLE__) || defined(__DARWIN__)
+#include <sys/dirent.h>
+#elif defined(__sun) && defined (__SVR4)
+#include <sys/param.h>
+#endif /* defined(__APPLE__) || defined(__DARWIN__), ... */
+
+#ifdef HAVE_LINUX_FS_H
+#include <linux/fs.h>
+#endif
+
+#include "compat.h"
+#include "bitmap.h"
+#include "attrib.h"
+#include "inode.h"
+#include "volume.h"
+#include "dir.h"
+#include "unistr.h"
+#include "layout.h"
+#include "index.h"
+#include "ntfstime.h"
+#include "security.h"
+#include "reparse.h"
+#include "object_id.h"
+#include "efs.h"
+#include "logging.h"
+#include "xattrs.h"
+#include "misc.h"
+#include "ioctl.h"
+
+#include "ntfs-3g_common.h"
+
+/*
+ *	The following permission checking modes are governed by
+ *	the LPERMSCONFIG value in param.h
+ */
+
+/*	ACLS may be checked by kernel (requires a fuse patch) or here */
+#define KERNELACLS ((LPERMSCONFIG > 6) & (LPERMSCONFIG < 10))
+/*	basic permissions may be checked by kernel or here */
+#define KERNELPERMS (((LPERMSCONFIG - 1) % 6) < 3)
+/*	may want to use fuse/kernel cacheing */
+#define CACHEING (!(LPERMSCONFIG % 3))
+
+#if KERNELACLS & !KERNELPERMS
+#error "Incompatible options KERNELACLS and KERNELPERMS"
+#endif
+
+#if CACHEING & (KERNELACLS | !KERNELPERMS)
+#warning "Fuse cacheing is only usable with basic permissions checked by kernel"
+#endif
+
+#if !CACHEING
+#define ATTR_TIMEOUT 0.0
+#define ENTRY_TIMEOUT 0.0
+#else
+	/*
+	 * FUSE cacheing is only usable with basic permissions
+	 * checked by the kernel with external fuse >= 2.8
+	 */
+#define ATTR_TIMEOUT (ctx->vol->secure_flags & (1 << SECURITY_DEFAULT) ? 1.0 : 0.0)
+#define ENTRY_TIMEOUT (ctx->vol->secure_flags & (1 << SECURITY_DEFAULT) ? 1.0 : 0.0)
+#endif
+#define GHOSTLTH 40 /* max length of a ghost file name - see ghostformat */
+
+		/* sometimes the kernel cannot check access */
+#define ntfs_real_allowed_access(scx, ni, type) ntfs_allowed_access(scx, ni, type)
+#if POSIXACLS & KERNELPERMS & !KERNELACLS
+		/* short-circuit if PERMS checked by kernel and ACLs by fs */
+#define ntfs_allowed_access(scx, ni, type) \
+	((scx)->vol->secure_flags & (1 << SECURITY_DEFAULT) \
+	    ? 1 : ntfs_allowed_access(scx, ni, type))
+#endif
+
+#define set_archive(ni) (ni)->flags |= FILE_ATTR_ARCHIVE
+#define INODE(ino) ((ino) == 1 ? (MFT_REF)FILE_root : (MFT_REF)(ino))
+
+typedef enum {
+	FSTYPE_NONE,
+	FSTYPE_UNKNOWN,
+	FSTYPE_FUSE,
+	FSTYPE_FUSEBLK
+} fuse_fstype;
+
+typedef struct fill_item {
+	struct fill_item *next;
+	size_t bufsize;
+	size_t off;
+	char buf[0];
+} ntfs_fuse_fill_item_t;
+
+typedef struct fill_context {
+	struct fill_item *first;
+	struct fill_item *last;
+	fuse_req_t req;
+	fuse_ino_t ino;
+	BOOL filled;
+} ntfs_fuse_fill_context_t;
+
+struct open_file {
+	struct open_file *next;
+	struct open_file *previous;
+	long long ghost;
+	fuse_ino_t ino;
+	fuse_ino_t parent;
+	int state;
+} ;
+
+enum {
+	CLOSE_GHOST = 1,
+	CLOSE_COMPRESSED = 2,
+	CLOSE_ENCRYPTED = 4,
+	CLOSE_DMTIME = 8
+};
+
+enum RM_TYPES {
+	RM_LINK,
+	RM_DIR,
+	RM_ANY,
+} ;
+
+static struct ntfs_options opts;
+
+const char *EXEC_NAME = "lowntfs-3g";
+
+static ntfs_fuse_context_t *ctx;
+static u32 ntfs_sequence;
+static const char ghostformat[] = ".ghost-ntfs-3g-%020llu";
+
+static const char *usage_msg = 
+"\n"
+"%s %s %s %d - Third Generation NTFS Driver\n"
+"\t\tConfiguration type %d, "
+#ifdef HAVE_SETXATTR
+"XATTRS are on, "
+#else
+"XATTRS are off, "
+#endif
+#if POSIXACLS
+"POSIX ACLS are on\n"
+#else
+"POSIX ACLS are off\n"
+#endif
+"\n"
+"Copyright (C) 2005-2007 Yura Pakhuchiy\n"
+"Copyright (C) 2006-2009 Szabolcs Szakacsits\n"
+"Copyright (C) 2007-2015 Jean-Pierre Andre\n"
+"Copyright (C) 2009 Erik Larsson\n"
+"\n"
+"Usage:    %s [-o option[,...]] <device|image_file> <mount_point>\n"
+"\n"
+"Options:  ro (read-only mount), windows_names, uid=, gid=,\n" 
+"          umask=, fmask=, dmask=, streams_interface=.\n"
+"          Please see the details in the manual (type: man ntfs-3g).\n"
+"\n"
+"Example: ntfs-3g /dev/sda1 /mnt/windows\n"
+"\n"
+"%s";
+
+static const char ntfs_bad_reparse[] = "unsupported reparse point";
+
+#ifdef FUSE_INTERNAL
+int drop_privs(void);
+int restore_privs(void);
+#else
+/*
+ * setuid and setgid root ntfs-3g denies to start with external FUSE, 
+ * therefore the below functions are no-op in such case.
+ */
+static int drop_privs(void)    { return 0; }
+#if defined(linux) || defined(__uClinux__)
+static int restore_privs(void) { return 0; }
+#endif
+
+static const char *setuid_msg =
+"Mount is denied because setuid and setgid root ntfs-3g is insecure with the\n"
+"external FUSE library. Either remove the setuid/setgid bit from the binary\n"
+"or rebuild NTFS-3G with integrated FUSE support and make it setuid root.\n"
+"Please see more information at\n"
+"http://tuxera.com/community/ntfs-3g-faq/#unprivileged\n";
+
+static const char *unpriv_fuseblk_msg =
+"Unprivileged user can not mount NTFS block devices using the external FUSE\n"
+"library. Either mount the volume as root, or rebuild NTFS-3G with integrated\n"
+"FUSE support and make it setuid root. Please see more information at\n"
+"http://tuxera.com/community/ntfs-3g-faq/#unprivileged\n";
+#endif	
+
+
+static void ntfs_fuse_update_times(ntfs_inode *ni, ntfs_time_update_flags mask)
+{
+	if (ctx->atime == ATIME_DISABLED)
+		mask &= ~NTFS_UPDATE_ATIME;
+	else if (ctx->atime == ATIME_RELATIVE && mask == NTFS_UPDATE_ATIME &&
+			(le64_to_cpu(ni->last_access_time)
+				>= le64_to_cpu(ni->last_data_change_time)) &&
+			(le64_to_cpu(ni->last_access_time)
+				>= le64_to_cpu(ni->last_mft_change_time)))
+		return;
+	ntfs_inode_update_times(ni, mask);
+}
+
+static s64 ntfs_get_nr_free_mft_records(ntfs_volume *vol)
+{
+	ntfs_attr *na = vol->mftbmp_na;
+	s64 nr_free = ntfs_attr_get_free_bits(na);
+
+	if (nr_free >= 0)
+		nr_free += (na->allocated_size - na->data_size) << 3;
+	return nr_free;
+}
+
+/*
+ *	Fill a security context as needed by security functions
+ *	returns TRUE if there is a user mapping,
+ *		FALSE if there is none
+ *			This is not an error and the context is filled anyway,
+ *			it is used for implicit Windows-like inheritance
+ */
+
+static BOOL ntfs_fuse_fill_security_context(fuse_req_t req,
+			struct SECURITY_CONTEXT *scx)
+{
+	const struct fuse_ctx *fusecontext;
+
+	scx->vol = ctx->vol;
+	scx->mapping[MAPUSERS] = ctx->security.mapping[MAPUSERS];
+	scx->mapping[MAPGROUPS] = ctx->security.mapping[MAPGROUPS];
+	scx->pseccache = &ctx->seccache;
+	if (req) {
+		fusecontext = fuse_req_ctx(req);
+		scx->uid = fusecontext->uid;
+		scx->gid = fusecontext->gid;
+		scx->tid = fusecontext->pid;
+#ifdef FUSE_CAP_DONT_MASK
+			/* the umask can be processed by the file system */
+		scx->umask = fusecontext->umask;
+#else
+			/* the umask if forced by fuse on creation */
+		scx->umask = 0;
+#endif
+
+	} else {
+		scx->uid = 0;
+		scx->gid = 0;
+		scx->tid = 0;
+		scx->umask = 0;
+	}
+	return (ctx->security.mapping[MAPUSERS] != (struct MAPPING*)NULL);
+}
+
+static u64 ntfs_fuse_inode_lookup(fuse_ino_t parent, const char *name)
+{
+	u64 ino = (u64)-1;
+	u64 inum;
+	ntfs_inode *dir_ni;
+
+	/* Open target directory. */
+	dir_ni = ntfs_inode_open(ctx->vol, INODE(parent));
+	if (dir_ni) {
+		/* Lookup file */
+		inum = ntfs_inode_lookup_by_mbsname(dir_ni, name);
+			/* never return inodes 0 and 1 */
+		if (MREF(inum) <= 1) {
+			inum = (u64)-1;
+			errno = ENOENT;
+		}
+		if (ntfs_inode_close(dir_ni)
+		    || (inum == (u64)-1))
+			ino = (u64)-1;
+		else
+			ino = MREF(inum);
+	}
+	return (ino);
+}
+
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+
+/*
+ *		Check access to parent directory
+ *
+ *	file inode is only opened when not fed in and S_ISVTX is requested,
+ *	when already open and S_ISVTX, it *HAS TO* be fed in.
+ *
+ *	returns 1 if allowed,
+ *		0 if not allowed or some error occurred (errno tells why)
+ */
+
+static int ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx,
+			ntfs_inode *dir_ni, fuse_ino_t ino,
+			ntfs_inode *ni, mode_t accesstype)
+{
+	int allowed;
+	ntfs_inode *ni2;
+	struct stat stbuf;
+
+	allowed = ntfs_allowed_access(scx, dir_ni, accesstype);
+		/*
+		 * for an not-owned sticky directory, have to
+		 * check whether file itself is owned
+		 */
+	if ((accesstype == (S_IWRITE + S_IEXEC + S_ISVTX))
+	   && (allowed == 2)) {
+		if (ni)
+			ni2 = ni;
+		else
+			ni2 = ntfs_inode_open(ctx->vol, INODE(ino));
+		allowed = 0;
+		if (ni2) {
+			allowed = (ntfs_get_owner_mode(scx,ni2,&stbuf) >= 0)
+				&& (stbuf.st_uid == scx->uid);
+			if (!ni)
+				ntfs_inode_close(ni2);
+		}
+	}
+	return (allowed);
+}
+
+#endif /* !KERNELPERMS | (POSIXACLS & !KERNELACLS) */
+
+/**
+ * ntfs_fuse_statfs - return information about mounted NTFS volume
+ * @path:	ignored (but fuse requires it)
+ * @sfs:	statfs structure in which to return the information
+ *
+ * Return information about the mounted NTFS volume @sb in the statfs structure
+ * pointed to by @sfs (this is initialized with zeros before ntfs_statfs is
+ * called). We interpret the values to be correct of the moment in time at
+ * which we are called. Most values are variable otherwise and this isn't just
+ * the free values but the totals as well. For example we can increase the
+ * total number of file nodes if we run out and we can keep doing this until
+ * there is no more space on the volume left at all.
+ *
+ * This code based on ntfs_statfs from ntfs kernel driver.
+ *
+ * Returns 0 on success or -errno on error.
+ */
+
+static void ntfs_fuse_statfs(fuse_req_t req,
+			fuse_ino_t ino __attribute__((unused)))
+{
+	struct statvfs sfs;
+	s64 size;
+	int delta_bits;
+	ntfs_volume *vol;
+
+	vol = ctx->vol;
+	if (vol) {
+	/* 
+	 * File system block size. Used to calculate used/free space by df.
+	 * Incorrectly documented as "optimal transfer block size". 
+	 */
+		sfs.f_bsize = vol->cluster_size;
+
+	/* Fundamental file system block size, used as the unit. */
+		sfs.f_frsize = vol->cluster_size;
+
+	/*
+	 * Total number of blocks on file system in units of f_frsize.
+	 * Since inodes are also stored in blocks ($MFT is a file) hence
+	 * this is the number of clusters on the volume.
+	 */
+		sfs.f_blocks = vol->nr_clusters;
+
+	/* Free blocks available for all and for non-privileged processes. */
+		size = vol->free_clusters;
+		if (size < 0)
+			size = 0;
+		sfs.f_bavail = sfs.f_bfree = size;
+
+	/* Free inodes on the free space */
+		delta_bits = vol->cluster_size_bits - vol->mft_record_size_bits;
+		if (delta_bits >= 0)
+			size <<= delta_bits;
+		else
+			size >>= -delta_bits;
+
+	/* Number of inodes at this point in time. */
+		sfs.f_files = (vol->mftbmp_na->allocated_size << 3) + size;
+
+	/* Free inodes available for all and for non-privileged processes. */
+		size += vol->free_mft_records;
+		if (size < 0)
+			size = 0;
+		sfs.f_ffree = sfs.f_favail = size;
+
+	/* Maximum length of filenames. */
+		sfs.f_namemax = NTFS_MAX_NAME_LEN;
+		fuse_reply_statfs(req, &sfs);
+	} else
+		fuse_reply_err(req, ENODEV);
+
+}
+
+static void set_fuse_error(int *err)
+{
+	if (!*err)
+		*err = -errno;
+}
+
+#if 0 && (defined(__APPLE__) || defined(__DARWIN__)) /* Unfinished. */
+static int ntfs_macfuse_getxtimes(const char *org_path,
+		struct timespec *bkuptime, struct timespec *crtime)
+{
+	int res = 0;
+	ntfs_inode *ni;
+	char *path = NULL;
+	ntfschar *stream_name;
+	int stream_name_len;
+
+	stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);
+	if (stream_name_len < 0)
+		return stream_name_len;
+	memset(bkuptime, 0, sizeof(struct timespec));
+	memset(crtime, 0, sizeof(struct timespec));
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni) {
+		res = -errno;
+		goto exit;
+	}
+        
+	/* We have no backup timestamp in NTFS. */
+	crtime->tv_sec = ni->creation_time;
+exit:
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	free(path);
+	if (stream_name_len)
+		free(stream_name);
+	return res;
+}
+
+int ntfs_macfuse_setcrtime(const char *path, const struct timespec *tv)
+{
+	ntfs_inode *ni;
+	int res = 0;
+
+	if (ntfs_fuse_is_named_data_stream(path))
+		return -EINVAL; /* n/a for named data streams. */
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni)
+		return -errno;
+        
+	if (tv) {
+		ni->creation_time = tv->tv_sec;
+		ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);
+	}
+
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	return res;
+}
+
+int ntfs_macfuse_setbkuptime(const char *path, const struct timespec *tv)
+{
+	ntfs_inode *ni;
+	int res = 0;
+        
+	if (ntfs_fuse_is_named_data_stream(path))
+		return -EINVAL; /* n/a for named data streams. */
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni)
+		return -errno;
+        
+	/* 
+	 * Only pretending to set backup time successfully to please the APIs of
+	 * Mac OS X. In reality, NTFS has no backup time.
+	 */
+        
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	return res;
+}
+
+int ntfs_macfuse_setchgtime(const char *path, const struct timespec *tv)
+{
+	ntfs_inode *ni;
+	int res = 0;
+
+	if (ntfs_fuse_is_named_data_stream(path))
+		return -EINVAL; /* n/a for named data streams. */
+	ni = ntfs_pathname_to_inode(ctx-&gt;vol, NULL, path);
+	if (!ni)
+		return -errno;
+
+	if (tv) {
+		ni-&gt;last_mft_change_time = tv-&gt;tv_sec;
+		ntfs_fuse_update_times(ni, 0);
+	}
+
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&amp;res);
+	return res;
+}
+#endif /* defined(__APPLE__) || defined(__DARWIN__) */
+
+static void ntfs_init(void *userdata __attribute__((unused)),
+			struct fuse_conn_info *conn)
+{
+#if defined(__APPLE__) || defined(__DARWIN__)
+	FUSE_ENABLE_XTIMES(conn);
+#endif
+#ifdef FUSE_CAP_DONT_MASK
+		/* request umask not to be enforced by fuse */
+	conn->want |= FUSE_CAP_DONT_MASK;
+#endif /* defined FUSE_CAP_DONT_MASK */
+#ifdef FUSE_CAP_BIG_WRITES
+	if (ctx->big_writes
+	    && ((ctx->vol->nr_clusters << ctx->vol->cluster_size_bits)
+			>= SAFE_CAPACITY_FOR_BIG_WRITES))
+		conn->want |= FUSE_CAP_BIG_WRITES;
+#endif
+#ifdef FUSE_CAP_IOCTL_DIR
+	conn->want |= FUSE_CAP_IOCTL_DIR;
+#endif /* defined(FUSE_CAP_IOCTL_DIR) */
+}
+
+static int ntfs_fuse_getstat(struct SECURITY_CONTEXT *scx,
+				ntfs_inode *ni, struct stat *stbuf)
+{
+	int res = 0;
+	ntfs_attr *na;
+	BOOL withusermapping;
+
+	memset(stbuf, 0, sizeof(struct stat));
+	withusermapping = (scx->mapping[MAPUSERS] != (struct MAPPING*)NULL);
+	if ((ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
+	    || (ni->flags & FILE_ATTR_REPARSE_POINT)) {
+		if (ni->flags & FILE_ATTR_REPARSE_POINT) {
+			char *target;
+			int attr_size;
+
+			errno = 0;
+			target = ntfs_make_symlink(ni, ctx->abs_mnt_point,
+					&attr_size);
+				/*
+				 * If the reparse point is not a valid
+				 * directory junction, and there is no error
+				 * we still display as a symlink
+				 */
+			if (target || (errno == EOPNOTSUPP)) {
+					/* returning attribute size */
+				if (target)
+					stbuf->st_size = attr_size;
+				else
+					stbuf->st_size = 
+						sizeof(ntfs_bad_reparse);
+				stbuf->st_blocks =
+					(ni->allocated_size + 511) >> 9;
+				stbuf->st_nlink =
+					le16_to_cpu(ni->mrec->link_count);
+				stbuf->st_mode = S_IFLNK;
+				free(target);
+			} else {
+				res = -errno;
+				goto exit;
+			}
+		} else {
+			/* Directory. */
+			stbuf->st_mode = S_IFDIR | (0777 & ~ctx->dmask);
+			/* get index size, if not known */
+			if (!test_nino_flag(ni, KnownSize)) {
+				na = ntfs_attr_open(ni, AT_INDEX_ALLOCATION,
+						NTFS_INDEX_I30, 4);
+				if (na) {
+					ni->data_size = na->data_size;
+					ni->allocated_size = na->allocated_size;
+					set_nino_flag(ni, KnownSize);
+					ntfs_attr_close(na);
+				}
+			}
+			stbuf->st_size = ni->data_size;
+			stbuf->st_blocks = ni->allocated_size >> 9;
+			stbuf->st_nlink = 1;	/* Make find(1) work */
+		}
+	} else {
+		/* Regular or Interix (INTX) file. */
+		stbuf->st_mode = S_IFREG;
+		stbuf->st_size = ni->data_size;
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+		/*
+		 * return data size rounded to next 512 byte boundary for
+		 * encrypted files to include padding required for decryption
+		 * also include 2 bytes for padding info
+		*/
+		if (ctx->efs_raw
+		    && (ni->flags & FILE_ATTR_ENCRYPTED)
+		    && ni->data_size)
+			stbuf->st_size = ((ni->data_size + 511) & ~511) + 2;
+#endif /* HAVE_SETXATTR */
+		/* 
+		 * Temporary fix to make ActiveSync work via Samba 3.0.
+		 * See more on the ntfs-3g-devel list.
+		 */
+		stbuf->st_blocks = (ni->allocated_size + 511) >> 9;
+		stbuf->st_nlink = le16_to_cpu(ni->mrec->link_count);
+		if (ni->flags & FILE_ATTR_SYSTEM) {
+			na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
+			if (!na) {
+				stbuf->st_ino = ni->mft_no;
+				goto nodata;
+			}
+			/* Check whether it's Interix FIFO or socket. */
+			if (!(ni->flags & FILE_ATTR_HIDDEN)) {
+				/* FIFO. */
+				if (na->data_size == 0)
+					stbuf->st_mode = S_IFIFO;
+				/* Socket link. */
+				if (na->data_size == 1)
+					stbuf->st_mode = S_IFSOCK;
+			}
+			/*
+			 * Check whether it's Interix symbolic link, block or
+			 * character device.
+			 */
+			if ((u64)na->data_size <= sizeof(INTX_FILE_TYPES)
+					+ sizeof(ntfschar) * PATH_MAX
+				&& (u64)na->data_size >
+					sizeof(INTX_FILE_TYPES)) {
+				INTX_FILE *intx_file;
+
+				intx_file =
+					(INTX_FILE*)ntfs_malloc(na->data_size);
+				if (!intx_file) {
+					res = -errno;
+					ntfs_attr_close(na);
+					goto exit;
+				}
+				if (ntfs_attr_pread(na, 0, na->data_size,
+						intx_file) != na->data_size) {
+					res = -errno;
+					free(intx_file);
+					ntfs_attr_close(na);
+					goto exit;
+				}
+				if (intx_file->magic == INTX_BLOCK_DEVICE &&
+						na->data_size == (s64)offsetof(
+						INTX_FILE, device_end)) {
+					stbuf->st_mode = S_IFBLK;
+					stbuf->st_rdev = makedev(le64_to_cpu(
+							intx_file->major),
+							le64_to_cpu(
+							intx_file->minor));
+				}
+				if (intx_file->magic == INTX_CHARACTER_DEVICE &&
+						na->data_size == (s64)offsetof(
+						INTX_FILE, device_end)) {
+					stbuf->st_mode = S_IFCHR;
+					stbuf->st_rdev = makedev(le64_to_cpu(
+							intx_file->major),
+							le64_to_cpu(
+							intx_file->minor));
+				}
+				if (intx_file->magic == INTX_SYMBOLIC_LINK)
+					stbuf->st_mode = S_IFLNK;
+				free(intx_file);
+			}
+			ntfs_attr_close(na);
+		}
+		stbuf->st_mode |= (0777 & ~ctx->fmask);
+	}
+	if (withusermapping) {
+		if (ntfs_get_owner_mode(scx,ni,stbuf) < 0)
+			set_fuse_error(&res);
+	} else {
+		stbuf->st_uid = ctx->uid;
+		stbuf->st_gid = ctx->gid;
+	}
+	if (S_ISLNK(stbuf->st_mode))
+		stbuf->st_mode |= 0777;
+nodata :
+	stbuf->st_ino = ni->mft_no;
+#ifdef HAVE_STRUCT_STAT_ST_ATIMESPEC
+	stbuf->st_atimespec = ntfs2timespec(ni->last_access_time);
+	stbuf->st_ctimespec = ntfs2timespec(ni->last_mft_change_time);
+	stbuf->st_mtimespec = ntfs2timespec(ni->last_data_change_time);
+#elif defined(HAVE_STRUCT_STAT_ST_ATIM)
+	stbuf->st_atim = ntfs2timespec(ni->last_access_time);
+	stbuf->st_ctim = ntfs2timespec(ni->last_mft_change_time);
+	stbuf->st_mtim = ntfs2timespec(ni->last_data_change_time);
+#elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC)
+	{
+	struct timespec ts;
+
+	ts = ntfs2timespec(ni->last_access_time);
+	stbuf->st_atime = ts.tv_sec;
+	stbuf->st_atimensec = ts.tv_nsec;
+	ts = ntfs2timespec(ni->last_mft_change_time);
+	stbuf->st_ctime = ts.tv_sec;
+	stbuf->st_ctimensec = ts.tv_nsec;
+	ts = ntfs2timespec(ni->last_data_change_time);
+	stbuf->st_mtime = ts.tv_sec;
+	stbuf->st_mtimensec = ts.tv_nsec;
+	}
+#else
+#warning "No known way to set nanoseconds in struct stat !"
+	{
+	struct timespec ts;
+
+	ts = ntfs2timespec(ni->last_access_time);
+	stbuf->st_atime = ts.tv_sec;
+	ts = ntfs2timespec(ni->last_mft_change_time);
+	stbuf->st_ctime = ts.tv_sec;
+	ts = ntfs2timespec(ni->last_data_change_time);
+	stbuf->st_mtime = ts.tv_sec;
+	}
+#endif
+exit:
+	return (res);
+}
+
+static void ntfs_fuse_getattr(fuse_req_t req, fuse_ino_t ino,
+			struct fuse_file_info *fi __attribute__((unused)))
+{
+	int res;
+	ntfs_inode *ni;
+	struct stat stbuf;
+	struct SECURITY_CONTEXT security;
+
+	ni = ntfs_inode_open(ctx->vol, INODE(ino));
+	if (!ni)
+		res = -errno;
+	else {
+		ntfs_fuse_fill_security_context(req, &security);
+		res = ntfs_fuse_getstat(&security, ni, &stbuf);
+		if (ntfs_inode_close(ni))
+			set_fuse_error(&res);
+	}
+	if (!res)
+		fuse_reply_attr(req, &stbuf, ATTR_TIMEOUT);
+	else
+		fuse_reply_err(req, -res);
+}
+
+static __inline__ BOOL ntfs_fuse_fillstat(struct SECURITY_CONTEXT *scx,
+			struct fuse_entry_param *pentry, u64 iref)
+{
+	ntfs_inode *ni;
+	BOOL ok = FALSE;
+
+	pentry->ino = MREF(iref);
+	ni = ntfs_inode_open(ctx->vol, pentry->ino);
+	if (ni) {
+		if (!ntfs_fuse_getstat(scx, ni, &pentry->attr)) {
+			pentry->generation = 1;
+			pentry->attr_timeout = ATTR_TIMEOUT;
+			pentry->entry_timeout = ENTRY_TIMEOUT;
+			ok = TRUE;
+		}
+		if (ntfs_inode_close(ni))
+		       ok = FALSE;
+	}
+	return (ok);
+}
+
+
+static void ntfs_fuse_lookup(fuse_req_t req, fuse_ino_t parent,
+			const char *name)
+{
+	struct SECURITY_CONTEXT security;
+	struct fuse_entry_param entry;
+	ntfs_inode *dir_ni;
+	u64 iref;
+	BOOL ok = FALSE;
+
+	if (strlen(name) < 256) {
+		dir_ni = ntfs_inode_open(ctx->vol, INODE(parent));
+		if (dir_ni) {
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+			/*
+			 * make sure the parent directory is searchable
+			 */
+			if (ntfs_fuse_fill_security_context(req, &security)
+			    && !ntfs_allowed_access(&security,dir_ni,S_IEXEC)) {
+				ntfs_inode_close(dir_ni);
+				errno = EACCES;
+			} else {
+#else
+				ntfs_fuse_fill_security_context(req, &security);
+#endif
+				iref = ntfs_inode_lookup_by_mbsname(dir_ni,
+								name);
+					/* never return inodes 0 and 1 */
+				if (MREF(iref) <= 1) {
+					iref = (u64)-1;
+					errno = ENOENT;
+				}
+				ok = !ntfs_inode_close(dir_ni)
+					&& (iref != (u64)-1)
+					&& ntfs_fuse_fillstat(
+						&security,&entry,iref);
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+			}
+#endif
+		}
+	} else
+		errno = ENAMETOOLONG;
+	if (!ok)
+		fuse_reply_err(req, errno);
+	else
+		fuse_reply_entry(req, &entry);
+}
+
+static void ntfs_fuse_readlink(fuse_req_t req, fuse_ino_t ino)
+{
+	ntfs_inode *ni = NULL;
+	ntfs_attr *na = NULL;
+	INTX_FILE *intx_file = NULL;
+	char *buf = (char*)NULL;
+	int res = 0;
+
+	/* Get inode. */
+	ni = ntfs_inode_open(ctx->vol, INODE(ino));
+	if (!ni) {
+		res = -errno;
+		goto exit;
+	}
+		/*
+		 * Reparse point : analyze as a junction point
+		 */
+	if (ni->flags & FILE_ATTR_REPARSE_POINT) {
+		int attr_size;
+
+		errno = 0;
+		res = 0;
+		buf = ntfs_make_symlink(ni, ctx->abs_mnt_point, &attr_size);
+		if (!buf) {
+			if (errno == EOPNOTSUPP)
+				buf = strdup(ntfs_bad_reparse);
+			if (!buf)
+				res = -errno;
+		}
+		goto exit;
+	}
+	/* Sanity checks. */
+	if (!(ni->flags & FILE_ATTR_SYSTEM)) {
+		res = -EINVAL;
+		goto exit;
+	}
+	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
+	if (!na) {
+		res = -errno;
+		goto exit;
+	}
+	if ((size_t)na->data_size <= sizeof(INTX_FILE_TYPES)) {
+		res = -EINVAL;
+		goto exit;
+	}
+	if ((size_t)na->data_size > sizeof(INTX_FILE_TYPES) +
+			sizeof(ntfschar) * PATH_MAX) {
+		res = -ENAMETOOLONG;
+		goto exit;
+	}
+	/* Receive file content. */
+	intx_file = (INTX_FILE*)ntfs_malloc(na->data_size);
+	if (!intx_file) {
+		res = -errno;
+		goto exit;
+	}
+	if (ntfs_attr_pread(na, 0, na->data_size, intx_file) != na->data_size) {
+		res = -errno;
+		goto exit;
+	}
+	/* Sanity check. */
+	if (intx_file->magic != INTX_SYMBOLIC_LINK) {
+		res = -EINVAL;
+		goto exit;
+	}
+	/* Convert link from unicode to local encoding. */
+	if (ntfs_ucstombs(intx_file->target, (na->data_size -
+			offsetof(INTX_FILE, target)) / sizeof(ntfschar),
+			&buf, 0) < 0) {
+		res = -errno;
+		goto exit;
+	}
+exit:
+	if (intx_file)
+		free(intx_file);
+	if (na)
+		ntfs_attr_close(na);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+
+	if (res < 0)
+		fuse_reply_err(req, -res);
+	else
+		fuse_reply_readlink(req, buf);
+	if (buf != ntfs_bad_reparse)
+		free(buf);
+}
+
+static int ntfs_fuse_filler(ntfs_fuse_fill_context_t *fill_ctx,
+		const ntfschar *name, const int name_len, const int name_type,
+		const s64 pos __attribute__((unused)), const MFT_REF mref,
+		const unsigned dt_type __attribute__((unused)))
+{
+	char *filename = NULL;
+	int ret = 0;
+	int filenamelen = -1;
+	size_t sz;
+	ntfs_fuse_fill_item_t *current;
+	ntfs_fuse_fill_item_t *newone;
+
+	if (name_type == FILE_NAME_DOS)
+		return 0;
+        
+	if ((filenamelen = ntfs_ucstombs(name, name_len, &filename, 0)) < 0) {
+		ntfs_log_perror("Filename decoding failed (inode %llu)",
+				(unsigned long long)MREF(mref));
+		return -1;
+	}
+		/* never return inodes 0 and 1 */
+	if (MREF(mref) > 1) {
+		struct stat st = { .st_ino = MREF(mref) };
+		 
+		switch (dt_type) {
+		case NTFS_DT_DIR :
+			st.st_mode = S_IFDIR | (0777 & ~ctx->dmask); 
+			break;
+		case NTFS_DT_LNK :
+			st.st_mode = S_IFLNK | 0777;
+			break;
+		case NTFS_DT_FIFO :
+			st.st_mode = S_IFIFO;
+			break;
+		case NTFS_DT_SOCK :
+			st.st_mode = S_IFSOCK;
+			break;
+		case NTFS_DT_BLK :
+			st.st_mode = S_IFBLK;
+			break;
+		case NTFS_DT_CHR :
+			st.st_mode = S_IFCHR;
+			break;
+		default : /* unexpected types shown as plain files */
+		case NTFS_DT_REG :
+			st.st_mode = S_IFREG | (0777 & ~ctx->fmask);
+			break;
+		}
+	        
+#if defined(__APPLE__) || defined(__DARWIN__)
+		/* 
+		 * Returning file names larger than MAXNAMLEN (255) bytes
+		 * causes Darwin/Mac OS X to bug out and skip the entry. 
+		 */
+		if (filenamelen > MAXNAMLEN) {
+			ntfs_log_debug("Truncating %d byte filename to "
+				       "%d bytes.\n", filenamelen, MAXNAMLEN);
+			ntfs_log_debug("  before: '%s'\n", filename);
+			memset(filename + MAXNAMLEN, 0, filenamelen - MAXNAMLEN);
+			ntfs_log_debug("   after: '%s'\n", filename);
+		}
+#elif defined(__sun) && defined (__SVR4)
+		/*
+		 * Returning file names larger than MAXNAMELEN (256) bytes
+		 * causes Solaris/Illumos to return an I/O error from the system
+		 * call.
+		 * However we also need space for a terminating NULL, or user
+		 * space tools will bug out since they expect a NULL terminator.
+		 * Effectively the maximum length of a file name is MAXNAMELEN -
+		 * 1 (255).
+		 */
+		if (filenamelen > (MAXNAMELEN - 1)) {
+			ntfs_log_debug("Truncating %d byte filename to %d "
+				"bytes.\n", filenamelen, MAXNAMELEN - 1);
+			ntfs_log_debug("  before: '%s'\n", filename);
+			memset(&filename[MAXNAMELEN - 1], 0,
+				filenamelen - (MAXNAMELEN - 1));
+			ntfs_log_debug("   after: '%s'\n", filename);
+		}
+#endif /* defined(__APPLE__) || defined(__DARWIN__), ... */
+	
+		current = fill_ctx->last;
+		sz = fuse_add_direntry(fill_ctx->req,
+				&current->buf[current->off],
+				current->bufsize - current->off,
+				filename, &st, current->off);
+		if (!sz || ((current->off + sz) > current->bufsize)) {
+			newone = (ntfs_fuse_fill_item_t*)ntfs_malloc
+				(sizeof(ntfs_fuse_fill_item_t)
+				     + current->bufsize);
+			if (newone) {
+				newone->off = 0;
+				newone->bufsize = current->bufsize;
+				newone->next = (ntfs_fuse_fill_item_t*)NULL;
+				current->next = newone;
+				fill_ctx->last = newone;
+				current = newone;
+				sz = fuse_add_direntry(fill_ctx->req,
+					current->buf,
+					current->bufsize - current->off,
+					filename, &st, current->off);
+				if (!sz) {
+					errno = EIO;
+					ntfs_log_error("Could not add a"
+						" directory entry (inode %lld)\n",
+						(unsigned long long)MREF(mref));
+				}
+			} else {
+				sz = 0;
+				errno = ENOMEM;
+			}
+		}
+		if (sz) {
+			current->off += sz;
+		} else {
+			ret = -1;
+		}
+	}
+        
+	free(filename);
+	return ret;
+}
+
+static void ntfs_fuse_opendir(fuse_req_t req, fuse_ino_t ino,
+			 struct fuse_file_info *fi)
+{
+	int res = 0;
+	ntfs_inode *ni;
+	int accesstype;
+	ntfs_fuse_fill_context_t *fill;
+	struct SECURITY_CONTEXT security;
+
+	ni = ntfs_inode_open(ctx->vol, INODE(ino));
+	if (ni) {
+		if (ntfs_fuse_fill_security_context(req, &security)) {
+			if (fi->flags & O_WRONLY)
+				accesstype = S_IWRITE;
+			else
+				if (fi->flags & O_RDWR)
+					accesstype = S_IWRITE | S_IREAD;
+				else
+					accesstype = S_IREAD;
+			if (!ntfs_allowed_access(&security,ni,accesstype))
+				res = -EACCES;
+		}
+		if (ntfs_inode_close(ni))
+			set_fuse_error(&res);
+		if (!res) {
+			fill = (ntfs_fuse_fill_context_t*)
+				ntfs_malloc(sizeof(ntfs_fuse_fill_context_t));
+			if (!fill)
+				res = -errno;
+			else {
+				fill->first = fill->last
+					= (ntfs_fuse_fill_item_t*)NULL;
+				fill->filled = FALSE;
+				fill->ino = ino;
+			}
+			fi->fh = (long)fill;
+		}
+	} else
+		res = -errno;
+	if (!res)
+		fuse_reply_open(req, fi);
+	else
+		fuse_reply_err(req, -res);
+}
+
+
+static void ntfs_fuse_releasedir(fuse_req_t req,
+			fuse_ino_t ino __attribute__((unused)),
+			struct fuse_file_info *fi)
+{
+	ntfs_fuse_fill_context_t *fill;
+	ntfs_fuse_fill_item_t *current;
+
+	fill = (ntfs_fuse_fill_context_t*)(long)fi->fh;
+	if (fill && (fill->ino == ino)) {
+			/* make sure to clear results */
+		current = fill->first;
+		while (current) {
+			current = current->next;
+			free(fill->first);
+			fill->first = current;
+		}
+		fill->ino = 0;
+		free(fill);
+	}
+	fuse_reply_err(req, 0);
+}
+
+static void ntfs_fuse_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
+			off_t off __attribute__((unused)),
+			struct fuse_file_info *fi __attribute__((unused)))
+{
+	ntfs_fuse_fill_item_t *first;
+	ntfs_fuse_fill_item_t *current;
+	ntfs_fuse_fill_context_t *fill;
+	ntfs_inode *ni;
+	s64 pos = 0;
+	int err = 0;
+
+	fill = (ntfs_fuse_fill_context_t*)(long)fi->fh;
+	if (fill && (fill->ino == ino)) {
+		if (!fill->filled) {
+				/* initial call : build the full list */
+			first = (ntfs_fuse_fill_item_t*)ntfs_malloc
+				(sizeof(ntfs_fuse_fill_item_t) + size);
+			if (first) {
+				first->bufsize = size;
+				first->off = 0;
+				first->next = (ntfs_fuse_fill_item_t*)NULL;
+				fill->req = req;
+				fill->first = first;
+				fill->last = first;
+				ni = ntfs_inode_open(ctx->vol,INODE(ino));
+				if (!ni)
+					err = -errno;
+				else {
+					if (ntfs_readdir(ni, &pos, fill,
+						(ntfs_filldir_t)
+							ntfs_fuse_filler))
+						err = -errno;
+					fill->filled = TRUE;
+					ntfs_fuse_update_times(ni,
+						NTFS_UPDATE_ATIME);
+					if (ntfs_inode_close(ni))
+						set_fuse_error(&err);
+				}
+				if (!err)
+					fuse_reply_buf(req, first->buf,
+							first->off);
+				/* reply sent, now must exit with no error */
+				fill->first = first->next;
+				free(first);
+			} else
+				err = -errno;
+		} else {
+			/* subsequent call : return next non-empty buffer */
+			current = fill->first;
+			while (current && !current->off) {
+				current = current->next;
+				free(fill->first);
+				fill->first = current;
+			}
+			if (current) {
+				fuse_reply_buf(req, current->buf, current->off);
+				fill->first = current->next;
+				free(current);
+			} else {
+				fuse_reply_buf(req, (char*)NULL, 0);
+				/* reply sent, now must exit with no error */
+			}
+		}
+	} else {
+		errno = EIO;
+		err = -errno;
+		ntfs_log_error("Uninitialized fuse_readdir()\n");
+	}
+	if (err)
+		fuse_reply_err(req, -err);
+}
+
+static void ntfs_fuse_open(fuse_req_t req, fuse_ino_t ino,
+		      struct fuse_file_info *fi)
+{
+	ntfs_inode *ni;
+	ntfs_attr *na;
+	struct open_file *of;
+	int state = 0;
+	char *path = NULL;
+	int res = 0;
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	int accesstype;
+	struct SECURITY_CONTEXT security;
+#endif
+
+	ni = ntfs_inode_open(ctx->vol, INODE(ino));
+	if (ni) {
+		na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
+		if (na) {
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+			if (ntfs_fuse_fill_security_context(req, &security)) {
+				if (fi->flags & O_WRONLY)
+					accesstype = S_IWRITE;
+				else
+					if (fi->flags & O_RDWR)
+						accesstype = S_IWRITE | S_IREAD;
+					else
+						accesstype = S_IREAD;
+			     /* check whether requested access is allowed */
+				if (!ntfs_allowed_access(&security,
+						ni,accesstype))
+					res = -EACCES;
+			}
+#endif
+			if ((res >= 0)
+			    && (fi->flags & (O_WRONLY | O_RDWR))) {
+			/* mark a future need to compress the last chunk */
+				if (na->data_flags & ATTR_COMPRESSION_MASK)
+					state |= CLOSE_COMPRESSED;
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+			/* mark a future need to fixup encrypted inode */
+				if (ctx->efs_raw
+				    && !(na->data_flags & ATTR_IS_ENCRYPTED)
+				    && (ni->flags & FILE_ATTR_ENCRYPTED))
+					state |= CLOSE_ENCRYPTED;
+#endif /* HAVE_SETXATTR */
+			/* mark a future need to update the mtime */
+				if (ctx->dmtime)
+					state |= CLOSE_DMTIME;
+			/* deny opening metadata files for writing */
+				if (ino < FILE_first_user)
+					res = -EPERM;
+			}
+			ntfs_attr_close(na);
+		} else
+			res = -errno;
+		if (ntfs_inode_close(ni))
+			set_fuse_error(&res);
+	} else
+		res = -errno;
+	free(path);
+	if (res >= 0) {
+		of = (struct open_file*)malloc(sizeof(struct open_file));
+		if (of) {
+			of->parent = 0;
+			of->ino = ino;
+			of->state = state;
+			of->next = ctx->open_files;
+			of->previous = (struct open_file*)NULL;
+			if (ctx->open_files)
+				ctx->open_files->previous = of;
+			ctx->open_files = of;
+			fi->fh = (long)of;
+		}
+	}
+	if (res)
+		fuse_reply_err(req, -res);
+	else
+		fuse_reply_open(req, fi);
+}
+
+static void ntfs_fuse_read(fuse_req_t req, fuse_ino_t ino, size_t size,
+			off_t offset,
+			struct fuse_file_info *fi __attribute__((unused)))
+{
+	ntfs_inode *ni = NULL;
+	ntfs_attr *na = NULL;
+	int res;
+	char *buf = (char*)NULL;
+	s64 total = 0;
+	s64 max_read;
+
+	if (!size) {
+		res = 0;
+		goto exit;
+	}
+	buf = (char*)ntfs_malloc(size);
+	if (!buf) {
+		res = -errno;
+		goto exit;
+	}
+
+	ni = ntfs_inode_open(ctx->vol, INODE(ino));
+	if (!ni) {
+		res = -errno;
+		goto exit;
+	}
+	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
+	if (!na) {
+		res = -errno;
+		goto exit;
+	}
+	max_read = na->data_size;
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+	/* limit reads at next 512 byte boundary for encrypted attributes */
+	if (ctx->efs_raw
+	    && max_read
+	    && (na->data_flags & ATTR_IS_ENCRYPTED)
+	    && NAttrNonResident(na)) {
+		max_read = ((na->data_size+511) & ~511) + 2;
+	}
+#endif /* HAVE_SETXATTR */
+	if (offset + (off_t)size > max_read) {
+		if (max_read < offset)
+			goto ok;
+		size = max_read - offset;
+	}
+	while (size > 0) {
+		s64 ret = ntfs_attr_pread(na, offset, size, buf + total);
+		if (ret != (s64)size)
+			ntfs_log_perror("ntfs_attr_pread error reading inode %lld at "
+				"offset %lld: %lld <> %lld", (long long)ni->mft_no,
+				(long long)offset, (long long)size, (long long)ret);
+		if (ret <= 0 || ret > (s64)size) {
+			res = (ret < 0) ? -errno : -EIO;
+			goto exit;
+		}
+		size -= ret;
+		offset += ret;
+		total += ret;
+	}
+ok:
+	ntfs_fuse_update_times(na->ni, NTFS_UPDATE_ATIME);
+	res = total;
+exit:
+	if (na)
+		ntfs_attr_close(na);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	if (res < 0)
+		fuse_reply_err(req, -res);
+	else
+		fuse_reply_buf(req, buf, res);
+	free(buf);
+}
+
+static void ntfs_fuse_write(fuse_req_t req, fuse_ino_t ino, const char *buf, 
+			size_t size, off_t offset,
+			struct fuse_file_info *fi __attribute__((unused)))
+{
+	ntfs_inode *ni = NULL;
+	ntfs_attr *na = NULL;
+	int res, total = 0;
+
+	ni = ntfs_inode_open(ctx->vol, INODE(ino));
+	if (!ni) {
+		res = -errno;
+		goto exit;
+	}
+	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
+	if (!na) {
+		res = -errno;
+		goto exit;
+	}
+	while (size) {
+		s64 ret = ntfs_attr_pwrite(na, offset, size, buf + total);
+		if (ret <= 0) {
+			res = -errno;
+			goto exit;
+		}
+		size   -= ret;
+		offset += ret;
+		total  += ret;
+	}
+	res = total;
+	if ((res > 0)
+	    && (!ctx->dmtime
+		|| (le64_to_cpu(ntfs_current_time())
+		     - le64_to_cpu(ni->last_data_change_time)) > ctx->dmtime))
+		ntfs_fuse_update_times(na->ni, NTFS_UPDATE_MCTIME);
+exit:
+	if (na)
+		ntfs_attr_close(na);
+	if (total)
+		set_archive(ni);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	if (res < 0)
+		fuse_reply_err(req, -res);
+	else
+		fuse_reply_write(req, res);
+}
+
+static int ntfs_fuse_chmod(struct SECURITY_CONTEXT *scx, fuse_ino_t ino,
+		mode_t mode, struct stat *stbuf)
+{
+	int res = 0;
+	ntfs_inode *ni;
+
+	  /* Unsupported if inherit or no user mapping has been defined */
+	if ((!scx->mapping[MAPUSERS] || ctx->inherit)
+	    && !ctx->silent) {
+		res = -EOPNOTSUPP;
+	} else {
+		ni = ntfs_inode_open(ctx->vol, INODE(ino));
+		if (!ni)
+			res = -errno;
+		else {
+			/* ignore if Windows inheritance is forced */
+			if (scx->mapping[MAPUSERS] && !ctx->inherit) {
+				if (ntfs_set_mode(scx, ni, mode))
+					res = -errno;
+				else {
+					ntfs_fuse_update_times(ni,
+							NTFS_UPDATE_CTIME);
+					/*
+					 * Must return updated times, and
+					 * inode has been updated, so hope
+					 * we get no further errors
+					 */
+					res = ntfs_fuse_getstat(scx, ni, stbuf);
+				}
+				NInoSetDirty(ni);
+			} else
+				res = ntfs_fuse_getstat(scx, ni, stbuf);
+			if (ntfs_inode_close(ni))
+				set_fuse_error(&res);
+		}
+	}
+	return res;
+}
+
+static int ntfs_fuse_chown(struct SECURITY_CONTEXT *scx, fuse_ino_t ino,
+			uid_t uid, gid_t gid, struct stat *stbuf)
+{
+	ntfs_inode *ni;
+	int res;
+
+	  /* Unsupported if inherit or no user mapping has been defined */
+	if ((!scx->mapping[MAPUSERS] || ctx->inherit)
+			&& !ctx->silent
+			&& ((uid != ctx->uid) || (gid != ctx->gid)))
+		res = -EOPNOTSUPP;
+	else {
+		res = 0;
+		ni = ntfs_inode_open(ctx->vol, INODE(ino));
+		if (!ni)
+			res = -errno;
+		else {
+			/* ignore if Windows inheritance is forced */
+			if (scx->mapping[MAPUSERS]
+			  && !ctx->inherit
+			  && (((int)uid != -1) || ((int)gid != -1))) {
+				if (ntfs_set_owner(scx, ni, uid, gid))
+					res = -errno;
+				else {
+					ntfs_fuse_update_times(ni,
+							NTFS_UPDATE_CTIME);
+				/*
+				 * Must return updated times, and
+				 * inode has been updated, so hope
+				 * we get no further errors
+				 */
+					res = ntfs_fuse_getstat(scx, ni, stbuf);
+				}
+			} else
+				res = ntfs_fuse_getstat(scx, ni, stbuf);
+			if (ntfs_inode_close(ni))
+				set_fuse_error(&res);
+		}
+	}
+	return (res);
+}
+
+static int ntfs_fuse_chownmod(struct SECURITY_CONTEXT *scx, fuse_ino_t ino,
+			uid_t uid, gid_t gid, mode_t mode, struct stat *stbuf)
+{
+	ntfs_inode *ni;
+	int res;
+
+	  /* Unsupported if inherit or no user mapping has been defined */
+	if ((!scx->mapping[MAPUSERS] || ctx->inherit)
+			&& !ctx->silent
+			&& ((uid != ctx->uid) || (gid != ctx->gid)))
+		res = -EOPNOTSUPP;
+	else {
+		res = 0;
+		ni = ntfs_inode_open(ctx->vol, INODE(ino));
+		if (!ni)
+			res = -errno;
+		else {
+			/* ignore if Windows inheritance is forced */
+			if (scx->mapping[MAPUSERS] && !ctx->inherit) {
+				if (ntfs_set_ownmod(scx, ni, uid, gid, mode))
+					res = -errno;
+				else {
+					ntfs_fuse_update_times(ni,
+							NTFS_UPDATE_CTIME);
+					/*
+					 * Must return updated times, and
+					 * inode has been updated, so hope
+					 * we get no further errors
+					 */
+					res = ntfs_fuse_getstat(scx, ni, stbuf);
+				}
+			} else
+				res = ntfs_fuse_getstat(scx, ni, stbuf);
+			if (ntfs_inode_close(ni))
+				set_fuse_error(&res);
+		}
+	}
+	return (res);
+}
+
+static int ntfs_fuse_trunc(struct SECURITY_CONTEXT *scx, fuse_ino_t ino, 
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+		off_t size, BOOL chkwrite, struct stat *stbuf)
+#else
+		off_t size, BOOL chkwrite __attribute__((unused)),
+		struct stat *stbuf)
+#endif
+{
+	ntfs_inode *ni = NULL;
+	ntfs_attr *na = NULL;
+	int res;
+	s64 oldsize;
+
+	ni = ntfs_inode_open(ctx->vol, INODE(ino));
+	if (!ni)
+		goto exit;
+
+	/* deny truncating metadata files */
+	if (ino < FILE_first_user) {
+		errno = EPERM;
+		goto exit;
+	}
+	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
+	if (!na)
+		goto exit;
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	/*
+	 * deny truncation if cannot write to file
+	 * (already checked for ftruncate())
+	 */
+	if (scx->mapping[MAPUSERS]
+	    && chkwrite
+	    && !ntfs_allowed_access(scx, ni, S_IWRITE)) {
+		errno = EACCES;
+		goto exit;
+	}
+#endif
+		/*
+		 * for compressed files, upsizing is done by inserting a final
+		 * zero, which is optimized as creating a hole when possible. 
+		 */
+	oldsize = na->data_size;
+	if ((na->data_flags & ATTR_COMPRESSION_MASK)
+	    && (size > na->initialized_size)) {
+		char zero = 0;
+		if (ntfs_attr_pwrite(na, size - 1, 1, &zero) <= 0)
+			goto exit;
+	} else
+		if (ntfs_attr_truncate(na, size))
+			goto exit;
+	if (oldsize != size)
+		set_archive(ni);
+        
+	ntfs_fuse_update_times(na->ni, NTFS_UPDATE_MCTIME);
+	res = ntfs_fuse_getstat(scx, ni, stbuf);
+	errno = (res ? -res : 0);
+exit:
+	res = -errno;
+	ntfs_attr_close(na);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	return res;
+}
+
+#if defined(HAVE_UTIMENSAT) & defined(FUSE_SET_ATTR_ATIME_NOW)
+
+static int ntfs_fuse_utimens(struct SECURITY_CONTEXT *scx, fuse_ino_t ino,
+		struct stat *stin, struct stat *stbuf, int to_set)
+{
+	ntfs_inode *ni;
+	int res = 0;
+
+	ni = ntfs_inode_open(ctx->vol, INODE(ino));
+	if (!ni)
+		return -errno;
+
+			/* no check or update if both UTIME_OMIT */
+	if (to_set & (FUSE_SET_ATTR_ATIME + FUSE_SET_ATTR_MTIME)) {
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+		if (ntfs_allowed_as_owner(scx, ni)
+		    || ((to_set & FUSE_SET_ATTR_ATIME_NOW)
+			&& (to_set & FUSE_SET_ATTR_MTIME_NOW)
+			&& ntfs_allowed_access(scx, ni, S_IWRITE))) {
+#endif
+			ntfs_time_update_flags mask = NTFS_UPDATE_CTIME;
+
+			if (to_set & FUSE_SET_ATTR_ATIME_NOW)
+				mask |= NTFS_UPDATE_ATIME;
+			else
+				if (to_set & FUSE_SET_ATTR_ATIME)
+					ni->last_access_time
+						= timespec2ntfs(stin->st_atim);
+			if (to_set & FUSE_SET_ATTR_MTIME_NOW)
+				mask |= NTFS_UPDATE_MTIME;
+			else
+				if (to_set & FUSE_SET_ATTR_MTIME)
+					ni->last_data_change_time 
+						= timespec2ntfs(stin->st_mtim);
+			ntfs_inode_update_times(ni, mask);
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+		} else
+			res = -errno;
+#endif
+	}
+	if (!res)
+		res = ntfs_fuse_getstat(scx, ni, stbuf);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	return res;
+}
+
+#else /* defined(HAVE_UTIMENSAT) & defined(FUSE_SET_ATTR_ATIME_NOW) */
+
+static int ntfs_fuse_utime(struct SECURITY_CONTEXT *scx, fuse_ino_t ino,
+		struct stat *stin, struct stat *stbuf)
+{
+	ntfs_inode *ni;
+	int res = 0;
+	struct timespec actime;
+	struct timespec modtime;
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	BOOL ownerok;
+	BOOL writeok;
+#endif
+
+	ni = ntfs_inode_open(ctx->vol, INODE(ino));
+	if (!ni)
+		return -errno;
+        
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	ownerok = ntfs_allowed_as_owner(scx, ni);
+	if (stin) {
+		/*
+		 * fuse never calls with a NULL buf and we do not
+		 * know whether the specific condition can be applied
+		 * So we have to accept updating by a non-owner having
+		 * write access.
+		 */
+		writeok = !ownerok
+			&& (stin->st_atime == stin->st_mtime)
+			&& ntfs_allowed_access(scx, ni, S_IWRITE);
+			/* Must be owner */
+		if (!ownerok && !writeok)
+			res = (stin->st_atime == stin->st_mtime
+					? -EACCES : -EPERM);
+		else {
+			actime.tv_sec = stin->st_atime;
+			actime.tv_nsec = 0;
+			modtime.tv_sec = stin->st_mtime;
+			modtime.tv_nsec = 0;
+			ni->last_access_time = timespec2ntfs(actime);
+			ni->last_data_change_time = timespec2ntfs(modtime);
+			ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);
+		}
+	} else {
+			/* Must be owner or have write access */
+		writeok = !ownerok
+			&& ntfs_allowed_access(scx, ni, S_IWRITE);
+		if (!ownerok && !writeok)
+			res = -EACCES;
+		else
+			ntfs_inode_update_times(ni, NTFS_UPDATE_AMCTIME);
+	}
+#else
+	if (stin) {
+		actime.tv_sec = stin->st_atime;
+		actime.tv_nsec = 0;
+		modtime.tv_sec = stin->st_mtime;
+		modtime.tv_nsec = 0;
+		ni->last_access_time = timespec2ntfs(actime);
+		ni->last_data_change_time = timespec2ntfs(modtime);
+		ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);
+	} else
+		ntfs_inode_update_times(ni, NTFS_UPDATE_AMCTIME);
+#endif
+
+	res = ntfs_fuse_getstat(scx, ni, stbuf);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	return res;
+}
+
+#endif /* defined(HAVE_UTIMENSAT) & defined(FUSE_SET_ATTR_ATIME_NOW) */
+
+static void ntfs_fuse_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
+			 int to_set, struct fuse_file_info *fi __attribute__((unused)))
+{
+	struct stat stbuf;
+	ntfs_inode *ni;
+	int res;
+	struct SECURITY_CONTEXT security;
+
+	res = 0;
+	ntfs_fuse_fill_security_context(req, &security);
+						/* no flags */
+	if (!(to_set
+		    & (FUSE_SET_ATTR_MODE
+			| FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID
+			| FUSE_SET_ATTR_SIZE
+			| FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))) {
+		ni = ntfs_inode_open(ctx->vol, INODE(ino));
+		if (!ni)
+			res = -errno;
+		else {
+			res = ntfs_fuse_getstat(&security, ni, &stbuf);
+			if (ntfs_inode_close(ni))
+				set_fuse_error(&res);
+		}
+	}
+						/* some set of uid/gid/mode */
+	if (to_set
+		    & (FUSE_SET_ATTR_MODE
+			| FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID)) {
+		switch (to_set
+			    & (FUSE_SET_ATTR_MODE
+				| FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID)) {
+		case FUSE_SET_ATTR_MODE :
+			res = ntfs_fuse_chmod(&security, ino,
+						attr->st_mode & 07777, &stbuf);
+			break;
+		case FUSE_SET_ATTR_UID :
+			res = ntfs_fuse_chown(&security, ino, attr->st_uid,
+						(gid_t)-1, &stbuf);
+			break;
+		case FUSE_SET_ATTR_GID :
+			res = ntfs_fuse_chown(&security, ino, (uid_t)-1,
+						attr->st_gid, &stbuf);
+			break;
+		case FUSE_SET_ATTR_UID + FUSE_SET_ATTR_GID :
+			res = ntfs_fuse_chown(&security, ino, attr->st_uid,
+						attr->st_gid, &stbuf);
+			break;
+		case FUSE_SET_ATTR_UID + FUSE_SET_ATTR_MODE:
+			res = ntfs_fuse_chownmod(&security, ino, attr->st_uid,
+						(gid_t)-1,attr->st_mode,
+						&stbuf);
+			break;
+		case FUSE_SET_ATTR_GID + FUSE_SET_ATTR_MODE:
+			res = ntfs_fuse_chownmod(&security, ino, (uid_t)-1,
+						attr->st_gid,attr->st_mode,
+						&stbuf);
+			break;
+		case FUSE_SET_ATTR_UID + FUSE_SET_ATTR_GID + FUSE_SET_ATTR_MODE:
+			res = ntfs_fuse_chownmod(&security, ino, attr->st_uid,
+					attr->st_gid,attr->st_mode, &stbuf);
+			break;
+		default :
+			break;
+		}
+	}
+						/* size */
+	if (!res && (to_set & FUSE_SET_ATTR_SIZE)) {
+		res = ntfs_fuse_trunc(&security, ino, attr->st_size,
+					!fi, &stbuf);
+	}
+						/* some set of atime/mtime */
+	if (!res && (to_set & (FUSE_SET_ATTR_ATIME + FUSE_SET_ATTR_MTIME))) {
+#if defined(HAVE_UTIMENSAT) & defined(FUSE_SET_ATTR_ATIME_NOW)
+		res = ntfs_fuse_utimens(&security, ino, attr, &stbuf, to_set);
+#else /* defined(HAVE_UTIMENSAT) & defined(FUSE_SET_ATTR_ATIME_NOW) */
+		res = ntfs_fuse_utime(&security, ino, attr, &stbuf);
+#endif /* defined(HAVE_UTIMENSAT) & defined(FUSE_SET_ATTR_ATIME_NOW) */
+	}
+	if (res)
+		fuse_reply_err(req, -res);
+	else
+		fuse_reply_attr(req, &stbuf, ATTR_TIMEOUT);
+}
+
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+
+static void ntfs_fuse_access(fuse_req_t req, fuse_ino_t ino, int mask)
+{
+	int res = 0;
+	int mode;
+	ntfs_inode *ni;
+	struct SECURITY_CONTEXT security;
+
+	  /* JPA return unsupported if no user mapping has been defined */
+	if (!ntfs_fuse_fill_security_context(req, &security)) {
+		if (ctx->silent)
+			res = 0;
+		else
+			res = -EOPNOTSUPP;
+	} else {
+		ni = ntfs_inode_open(ctx->vol, INODE(ino));
+		if (!ni) {
+			res = -errno;
+		} else {
+			mode = 0;
+			if (mask & (X_OK | W_OK | R_OK)) {
+				if (mask & X_OK) mode += S_IEXEC;
+				if (mask & W_OK) mode += S_IWRITE;
+				if (mask & R_OK) mode += S_IREAD;
+				if (!ntfs_allowed_access(&security,
+						ni, mode))
+					res = -errno;
+			}
+			if (ntfs_inode_close(ni))
+				set_fuse_error(&res);
+		}
+	}
+	if (res < 0)
+		fuse_reply_err(req, -res);
+	else
+		fuse_reply_err(req, 0);
+}
+
+#endif /* !KERNELPERMS | (POSIXACLS & !KERNELACLS) */
+
+static int ntfs_fuse_create(fuse_req_t req, fuse_ino_t parent, const char *name,
+		mode_t typemode, dev_t dev,
+		struct fuse_entry_param *e,
+		const char *target, struct fuse_file_info *fi)
+{
+	ntfschar *uname = NULL, *utarget = NULL;
+	ntfs_inode *dir_ni = NULL, *ni;
+	struct open_file *of;
+	int state = 0;
+	le32 securid;
+	gid_t gid;
+	mode_t dsetgid;
+	mode_t type = typemode & ~07777;
+	mode_t perm;
+	struct SECURITY_CONTEXT security;
+	int res = 0, uname_len, utarget_len;
+
+	/* Generate unicode filename. */
+	uname_len = ntfs_mbstoucs(name, &uname);
+	if ((uname_len < 0)
+	    || (ctx->windows_names
+		&& ntfs_forbidden_names(ctx->vol,uname,uname_len))) {
+		res = -errno;
+		goto exit;
+	}
+	/* Open parent directory. */
+	dir_ni = ntfs_inode_open(ctx->vol, INODE(parent));
+	if (!dir_ni) {
+		res = -errno;
+		goto exit;
+	}
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+		/* make sure parent directory is writeable and executable */
+	if (!ntfs_fuse_fill_security_context(req, &security)
+	       || ntfs_allowed_create(&security,
+				dir_ni, &gid, &dsetgid)) {
+#else
+		ntfs_fuse_fill_security_context(req, &security);
+		ntfs_allowed_create(&security, dir_ni, &gid, &dsetgid);
+#endif
+		if (S_ISDIR(type))
+			perm = (typemode & ~ctx->dmask & 0777)
+				| (dsetgid & S_ISGID);
+		else
+			perm = typemode & ~ctx->fmask & 0777;
+			/*
+			 * Try to get a security id available for
+			 * file creation (from inheritance or argument).
+			 * This is not possible for NTFS 1.x, and we will
+			 * have to build a security attribute later.
+			 */
+		if (!ctx->security.mapping[MAPUSERS])
+			securid = const_cpu_to_le32(0);
+		else
+			if (ctx->inherit)
+				securid = ntfs_inherited_id(&security,
+					dir_ni, S_ISDIR(type));
+			else
+#if POSIXACLS
+				securid = ntfs_alloc_securid(&security,
+					security.uid, gid,
+					dir_ni, perm, S_ISDIR(type));
+#else
+				securid = ntfs_alloc_securid(&security,
+					security.uid, gid,
+					perm & ~security.umask, S_ISDIR(type));
+#endif
+		/* Create object specified in @type. */
+		switch (type) {
+			case S_IFCHR:
+			case S_IFBLK:
+				ni = ntfs_create_device(dir_ni, securid,
+						uname, uname_len, type, dev);
+				break;
+			case S_IFLNK:
+				utarget_len = ntfs_mbstoucs(target, &utarget);
+				if (utarget_len < 0) {
+					res = -errno;
+					goto exit;
+				}
+				ni = ntfs_create_symlink(dir_ni, securid,
+						uname, uname_len,
+						utarget, utarget_len);
+				break;
+			default:
+				ni = ntfs_create(dir_ni, securid, uname,
+						uname_len, type);
+				break;
+		}
+		if (ni) {
+				/*
+				 * set the security attribute if a security id
+				 * could not be allocated (eg NTFS 1.x)
+				 */
+			if (ctx->security.mapping[MAPUSERS]) {
+#if POSIXACLS
+				if (!securid
+				   && ntfs_set_inherited_posix(&security, ni,
+					security.uid, gid,
+					dir_ni, perm) < 0)
+					set_fuse_error(&res);
+#else
+				if (!securid
+				   && ntfs_set_owner_mode(&security, ni,
+					security.uid, gid, 
+					perm & ~security.umask) < 0)
+					set_fuse_error(&res);
+#endif
+			}
+			set_archive(ni);
+			/* mark a need to compress the end of file */
+			if (fi && (ni->flags & FILE_ATTR_COMPRESSED)) {
+				state |= CLOSE_COMPRESSED;
+			}
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+			/* mark a future need to fixup encrypted inode */
+			if (fi
+			    && ctx->efs_raw
+			    && (ni->flags & FILE_ATTR_ENCRYPTED))
+				state |= CLOSE_ENCRYPTED;
+#endif /* HAVE_SETXATTR */
+			if (fi && ctx->dmtime)
+				state |= CLOSE_DMTIME;
+			ntfs_inode_update_mbsname(dir_ni, name, ni->mft_no);
+			NInoSetDirty(ni);
+			e->ino = ni->mft_no;
+			e->generation = 1;
+			e->attr_timeout = ATTR_TIMEOUT;
+			e->entry_timeout = ENTRY_TIMEOUT;
+			res = ntfs_fuse_getstat(&security, ni, &e->attr);
+			/*
+			 * closing ni requires access to dir_ni to
+			 * synchronize the index, avoid double opening.
+			 */
+			if (ntfs_inode_close_in_dir(ni, dir_ni))
+				set_fuse_error(&res);
+			ntfs_fuse_update_times(dir_ni, NTFS_UPDATE_MCTIME);
+		} else
+			res = -errno;
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	} else
+		res = -errno;
+#endif
+
+exit:
+	free(uname);
+	if (ntfs_inode_close(dir_ni))
+		set_fuse_error(&res);
+	if (utarget)
+		free(utarget);
+	if ((res >= 0) && fi) {
+		of = (struct open_file*)malloc(sizeof(struct open_file));
+		if (of) {
+			of->parent = 0;
+			of->ino = e->ino;
+			of->state = state;
+			of->next = ctx->open_files;
+			of->previous = (struct open_file*)NULL;
+			if (ctx->open_files)
+				ctx->open_files->previous = of;
+			ctx->open_files = of;
+			fi->fh = (long)of;
+		}
+	}
+	return res;
+}
+
+static void ntfs_fuse_create_file(fuse_req_t req, fuse_ino_t parent,
+			const char *name, mode_t mode,
+			struct fuse_file_info *fi)
+{
+	int res;
+	struct fuse_entry_param entry;
+
+	res = ntfs_fuse_create(req, parent, name, mode & (S_IFMT | 07777),
+				0, &entry, NULL, fi);
+	if (res < 0)
+		fuse_reply_err(req, -res);
+	else
+		fuse_reply_create(req, &entry, fi);
+}
+
+static void ntfs_fuse_mknod(fuse_req_t req, fuse_ino_t parent, const char *name,
+		       mode_t mode, dev_t rdev)
+{
+	int res;
+	struct fuse_entry_param e;
+
+	res = ntfs_fuse_create(req, parent, name, mode & (S_IFMT | 07777),
+				rdev, &e,NULL,(struct fuse_file_info*)NULL);
+	if (res < 0)
+		fuse_reply_err(req, -res);
+	else
+		fuse_reply_entry(req, &e);
+}
+
+static void ntfs_fuse_symlink(fuse_req_t req, const char *target,
+			fuse_ino_t parent, const char *name)
+{
+	int res;
+	struct fuse_entry_param entry;
+
+	res = ntfs_fuse_create(req, parent, name, S_IFLNK, 0,
+			&entry, target, (struct fuse_file_info*)NULL);
+	if (res < 0)
+		fuse_reply_err(req, -res);
+	else
+		fuse_reply_entry(req, &entry);
+}
+
+
+static int ntfs_fuse_newlink(fuse_req_t req __attribute__((unused)),
+			fuse_ino_t ino, fuse_ino_t newparent,
+			const char *newname, struct fuse_entry_param *e)
+{
+	ntfschar *uname = NULL;
+	ntfs_inode *dir_ni = NULL, *ni;
+	int res = 0, uname_len;
+	struct SECURITY_CONTEXT security;
+
+	/* Open file for which create hard link. */
+	ni = ntfs_inode_open(ctx->vol, INODE(ino));
+	if (!ni) {
+		res = -errno;
+		goto exit;
+	}
+        
+	/* Do not accept linking to a directory (except for renaming) */
+	if (e && (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
+		errno = EPERM;
+		res = -errno;
+		goto exit;
+	}
+	/* Generate unicode filename. */
+	uname_len = ntfs_mbstoucs(newname, &uname);
+	if ((uname_len < 0)
+            || (ctx->windows_names
+                && ntfs_forbidden_names(ctx->vol,uname,uname_len))) {
+		res = -errno;
+		goto exit;
+	}
+	/* Open parent directory. */
+	dir_ni = ntfs_inode_open(ctx->vol, INODE(newparent));
+	if (!dir_ni) {
+		res = -errno;
+		goto exit;
+	}
+
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+		/* make sure the target parent directory is writeable */
+	if (ntfs_fuse_fill_security_context(req, &security)
+	    && !ntfs_allowed_access(&security,dir_ni,S_IWRITE + S_IEXEC))
+		res = -EACCES;
+	else
+#else
+	ntfs_fuse_fill_security_context(req, &security);
+#endif
+	{
+		if (ntfs_link(ni, dir_ni, uname, uname_len)) {
+			res = -errno;
+			goto exit;
+		}
+		ntfs_inode_update_mbsname(dir_ni, newname, ni->mft_no);
+		if (e) {
+			e->ino = ni->mft_no;
+			e->generation = 1;
+			e->attr_timeout = ATTR_TIMEOUT;
+			e->entry_timeout = ENTRY_TIMEOUT;
+			res = ntfs_fuse_getstat(&security, ni, &e->attr);
+		}
+		set_archive(ni);
+		ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);
+		ntfs_fuse_update_times(dir_ni, NTFS_UPDATE_MCTIME);
+	}
+exit:
+	/* 
+	 * Must close dir_ni first otherwise ntfs_inode_sync_file_name(ni)
+	 * may fail because ni may not be in parent's index on the disk yet.
+	 */
+	if (ntfs_inode_close(dir_ni))
+		set_fuse_error(&res);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	free(uname);
+	return (res);
+}
+
+static void ntfs_fuse_link(fuse_req_t req, fuse_ino_t ino,
+			fuse_ino_t newparent, const char *newname)
+{
+	struct fuse_entry_param entry;
+	int res;
+
+	res = ntfs_fuse_newlink(req, ino, newparent, newname, &entry);
+	if (res)
+		fuse_reply_err(req, -res);
+	else
+		fuse_reply_entry(req, &entry);
+}
+
+static int ntfs_fuse_rm(fuse_req_t req, fuse_ino_t parent, const char *name,
+			enum RM_TYPES rm_type __attribute__((unused)))
+{
+	ntfschar *uname = NULL;
+	ntfschar *ugname;
+	ntfs_inode *dir_ni = NULL, *ni = NULL;
+	int res = 0, uname_len;
+	int ugname_len;
+	u64 iref;
+	fuse_ino_t ino;
+	struct open_file *of;
+	char ghostname[GHOSTLTH];
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	struct SECURITY_CONTEXT security;
+#endif
+
+	/* Open parent directory. */
+	dir_ni = ntfs_inode_open(ctx->vol, INODE(parent));
+	if (!dir_ni) {
+		res = -errno;
+		goto exit;
+	}
+	/* Generate unicode filename. */
+	uname_len = ntfs_mbstoucs(name, &uname);
+	if (uname_len < 0) {
+		res = -errno;
+		goto exit;
+	}
+	/* Open object for delete. */
+	iref = ntfs_inode_lookup_by_mbsname(dir_ni, name);
+	if (iref == (u64)-1) {
+		res = -errno;
+		goto exit;
+	}
+	ino = (fuse_ino_t)MREF(iref);
+	/* deny unlinking metadata files */
+	if (ino < FILE_first_user) {
+		res = -EPERM;
+		goto exit;
+	}
+
+	ni = ntfs_inode_open(ctx->vol, ino);
+	if (!ni) {
+		res = -errno;
+		goto exit;
+	}
+        
+#if defined(__sun) && defined (__SVR4)
+	/* on Solaris : deny unlinking directories */
+	if (rm_type
+	    == (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY ? RM_LINK : RM_DIR)) {
+		errno = EPERM;
+		res = -errno;
+		goto exit;
+	}
+#endif /* defined(__sun) && defined (__SVR4) */
+
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	/* JPA deny unlinking if directory is not writable and executable */
+	if (ntfs_fuse_fill_security_context(req, &security)
+	    && !ntfs_allowed_dir_access(&security, dir_ni, ino, ni,
+				   S_IEXEC + S_IWRITE + S_ISVTX)) {
+		errno = EACCES;
+		res = -errno;
+		goto exit;
+	}
+#endif
+		/*
+		 * We keep one open_file record per opening, to avoid
+		 * having to check the list of open files when opening
+		 * and closing (which are more frequent than unlinking).
+		 * As a consequence, we may have to create several
+		 * ghosts names for the same file.
+		 * The file may have been opened with a different name
+		 * in a different parent directory. The ghost is
+		 * nevertheless created in the parent directory of the
+		 * name being unlinked, and permissions to do so are the
+		 * same as required for unlinking.
+		 */
+	for (of=ctx->open_files; of; of = of->next) {
+		if ((of->ino == ino) && !(of->state & CLOSE_GHOST)) {
+			/* file was open, create a ghost in unlink parent */
+			ntfs_inode *gni;
+			u64 gref;
+
+			/* ni has to be closed for linking ghost */
+			if (ni) {
+				if (ntfs_inode_close(ni)) {
+					res = -errno;
+					goto exit;
+				}
+				ni = (ntfs_inode*)NULL;
+			}
+			of->state |= CLOSE_GHOST;
+			of->parent = parent;
+			of->ghost = ++ctx->latest_ghost;
+			sprintf(ghostname,ghostformat,of->ghost);
+				/* Generate unicode filename. */
+			ugname = (ntfschar*)NULL;
+			ugname_len = ntfs_mbstoucs(ghostname, &ugname);
+			if (ugname_len < 0) {
+				res = -errno;
+				goto exit;
+			}
+			/* sweep existing ghost if any, ignoring errors */
+			gref = ntfs_inode_lookup_by_mbsname(dir_ni, ghostname);
+			if (gref != (u64)-1) {
+				gni = ntfs_inode_open(ctx->vol, MREF(gref));
+				ntfs_delete(ctx->vol, (char*)NULL, gni, dir_ni,
+					 ugname, ugname_len);
+				/* ntfs_delete() always closes gni and dir_ni */
+				dir_ni = (ntfs_inode*)NULL;
+			} else {
+				if (ntfs_inode_close(dir_ni)) {
+					res = -errno;
+					goto out;
+				}
+				dir_ni = (ntfs_inode*)NULL;
+			}
+			free(ugname);
+			res = ntfs_fuse_newlink(req, of->ino, parent, ghostname,
+					(struct fuse_entry_param*)NULL);
+			if (res)
+				goto out;
+				/* now reopen then parent directory */
+			dir_ni = ntfs_inode_open(ctx->vol, INODE(parent));
+			if (!dir_ni) {
+				res = -errno;
+				goto exit;
+			}
+		}
+	}
+	if (!ni) {
+		ni = ntfs_inode_open(ctx->vol, ino);
+		if (!ni) {
+			res = -errno;
+			goto exit;
+		}
+	}
+	if (ntfs_delete(ctx->vol, (char*)NULL, ni, dir_ni,
+				 uname, uname_len))
+		res = -errno;
+		/* ntfs_delete() always closes ni and dir_ni */
+	ni = dir_ni = NULL;
+exit:
+	if (ntfs_inode_close(ni) && !res)
+		res = -errno;
+	if (ntfs_inode_close(dir_ni) && !res)
+		res = -errno;
+out :
+	free(uname);
+	return res;
+}
+
+static void ntfs_fuse_unlink(fuse_req_t req, fuse_ino_t parent,
+				const char *name)
+{
+	int res;
+
+	res = ntfs_fuse_rm(req, parent, name, RM_LINK);
+	if (res)
+		fuse_reply_err(req, -res);
+	else
+		fuse_reply_err(req, 0);
+}
+
+static int ntfs_fuse_safe_rename(fuse_req_t req, fuse_ino_t ino,
+			fuse_ino_t parent, const char *name, fuse_ino_t xino,
+			fuse_ino_t newparent, const char *newname,
+			const char *tmp)
+{
+	int ret;
+
+	ntfs_log_trace("Entering\n");
+        
+	ret = ntfs_fuse_newlink(req, xino, newparent, tmp,
+				(struct fuse_entry_param*)NULL);
+	if (ret)
+		return ret;
+        
+	ret = ntfs_fuse_rm(req, newparent, newname, RM_ANY);
+	if (!ret) {
+	        
+		ret = ntfs_fuse_newlink(req, ino, newparent, newname,
+					(struct fuse_entry_param*)NULL);
+		if (ret)
+			goto restore;
+	        
+		ret = ntfs_fuse_rm(req, parent, name, RM_ANY);
+		if (ret) {
+			if (ntfs_fuse_rm(req, newparent, newname, RM_ANY))
+				goto err;
+			goto restore;
+		}
+	}
+        
+	goto cleanup;
+restore:
+	if (ntfs_fuse_newlink(req, xino, newparent, newname,
+				(struct fuse_entry_param*)NULL)) {
+err:
+		ntfs_log_perror("Rename failed. Existing file '%s' was renamed "
+				"to '%s'", newname, tmp);
+	} else {
+cleanup:
+		/*
+		 * Condition for this unlink has already been checked in
+		 * "ntfs_fuse_rename_existing_dest()", so it should never
+		 * fail (unless concurrent access to directories when fuse
+		 * is multithreaded)
+		 */
+		if (ntfs_fuse_rm(req, newparent, tmp, RM_ANY) < 0)
+			ntfs_log_perror("Rename failed. Existing file '%s' still present "
+				"as '%s'", newname, tmp);
+	}
+	return	ret;
+}
+
+static int ntfs_fuse_rename_existing_dest(fuse_req_t req, fuse_ino_t ino,
+			fuse_ino_t parent, const char *name,
+			fuse_ino_t xino, fuse_ino_t newparent,
+			const char *newname)
+{
+	int ret, len;
+	char *tmp;
+	const char *ext = ".ntfs-3g-";
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	ntfs_inode *newdir_ni;
+	struct SECURITY_CONTEXT security;
+#endif
+
+	ntfs_log_trace("Entering\n");
+        
+	len = strlen(newname) + strlen(ext) + 10 + 1; /* wc(str(2^32)) + \0 */
+	tmp = (char*)ntfs_malloc(len);
+	if (!tmp)
+		return -errno;
+        
+	ret = snprintf(tmp, len, "%s%s%010d", newname, ext, ++ntfs_sequence);
+	if (ret != len - 1) {
+		ntfs_log_error("snprintf failed: %d != %d\n", ret, len - 1);
+		ret = -EOVERFLOW;
+	} else {
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+			/*
+			 * Make sure existing dest can be removed.
+			 * This is only needed if parent directory is
+			 * sticky, because in this situation condition
+			 * for unlinking is different from condition for
+			 * linking
+			 */
+		newdir_ni = ntfs_inode_open(ctx->vol, INODE(newparent));
+		if (newdir_ni) {
+			if (!ntfs_fuse_fill_security_context(req,&security)
+			    || ntfs_allowed_dir_access(&security, newdir_ni,
+					xino, (ntfs_inode*)NULL,
+					S_IEXEC + S_IWRITE + S_ISVTX)) {
+				if (ntfs_inode_close(newdir_ni))
+					ret = -errno;
+				else
+					ret = ntfs_fuse_safe_rename(req, ino,
+							parent, name, xino,
+							newparent, newname,
+							tmp);
+			} else {
+				ntfs_inode_close(newdir_ni);
+				ret = -EACCES;
+			}
+		} else
+			ret = -errno;
+#else
+		ret = ntfs_fuse_safe_rename(req, ino, parent, name,
+					xino, newparent, newname, tmp);
+#endif
+	}
+	free(tmp);
+	return	ret;
+}
+
+static void ntfs_fuse_rename(fuse_req_t req, fuse_ino_t parent,
+			const char *name, fuse_ino_t newparent,
+			const char *newname)
+{
+	int ret;
+	fuse_ino_t ino;
+	fuse_ino_t xino;
+	ntfs_inode *ni;
+        
+	ntfs_log_debug("rename: old: '%s'  new: '%s'\n", name, newname);
+        
+	/*
+	 *  FIXME: Rename should be atomic.
+	 */
+        
+	ino = ntfs_fuse_inode_lookup(parent, name);
+	if (ino == (fuse_ino_t)-1) {
+		ret = -errno;
+		goto out;
+	}
+	/* Check whether target is present */
+	xino = ntfs_fuse_inode_lookup(newparent, newname);
+	if (xino != (fuse_ino_t)-1) {
+			/*
+			 * Target exists : no need to check whether it
+			 * designates the same inode, this has already
+			 * been checked (by fuse ?)
+			 */
+		ni = ntfs_inode_open(ctx->vol, INODE(xino));
+		if (!ni)
+			ret = -errno;
+		else {
+			ret = ntfs_check_empty_dir(ni);
+			if (ret < 0) {
+				ret = -errno;
+				ntfs_inode_close(ni);
+				goto out;
+			}
+	        
+			if (ntfs_inode_close(ni)) {
+				set_fuse_error(&ret);
+				goto out;
+			}
+			ret = ntfs_fuse_rename_existing_dest(req, ino, parent,
+						name, xino, newparent, newname);
+		}
+	} else {
+			/* target does not exist */
+		ret = ntfs_fuse_newlink(req, ino, newparent, newname,
+					(struct fuse_entry_param*)NULL);
+		if (ret)
+			goto out;
+        
+		ret = ntfs_fuse_rm(req, parent, name, RM_ANY);
+		if (ret)
+			ntfs_fuse_rm(req, newparent, newname, RM_ANY);
+	}
+out:
+	if (ret)
+		fuse_reply_err(req, -ret);
+	else
+		fuse_reply_err(req, 0);
+}
+
+static void ntfs_fuse_release(fuse_req_t req, fuse_ino_t ino,
+			 struct fuse_file_info *fi)
+{
+	ntfs_inode *ni = NULL;
+	ntfs_attr *na = NULL;
+	struct open_file *of;
+	char ghostname[GHOSTLTH];
+	int res;
+
+	of = (struct open_file*)(long)fi->fh;
+	/* Only for marked descriptors there is something to do */
+	if (!of
+	    || !(of->state & (CLOSE_COMPRESSED
+				| CLOSE_ENCRYPTED | CLOSE_DMTIME))) {
+		res = 0;
+		goto out;
+	}
+	ni = ntfs_inode_open(ctx->vol, INODE(ino));
+	if (!ni) {
+		res = -errno;
+		goto exit;
+	}
+	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
+	if (!na) {
+		res = -errno;
+		goto exit;
+	}
+	res = 0;
+	if (of->state & CLOSE_DMTIME)
+		ntfs_inode_update_times(ni,NTFS_UPDATE_MCTIME);
+	if (of->state & CLOSE_COMPRESSED)
+		res = ntfs_attr_pclose(na);
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+	if (of->state & CLOSE_ENCRYPTED)
+		res = ntfs_efs_fixup_attribute(NULL, na);
+#endif /* HAVE_SETXATTR */
+exit:
+	if (na)
+		ntfs_attr_close(na);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+out:    
+		/* remove the associate ghost file (even if release failed) */
+	if (of) {
+		if (of->state & CLOSE_GHOST) {
+			sprintf(ghostname,ghostformat,of->ghost);
+			ntfs_fuse_rm(req, of->parent, ghostname, RM_ANY);
+		}
+			/* remove from open files list */
+		if (of->next)
+			of->next->previous = of->previous;
+		if (of->previous)
+			of->previous->next = of->next;
+		else
+			ctx->open_files = of->next;
+		free(of);
+	}
+	if (res)
+		fuse_reply_err(req, -res);
+	else
+		fuse_reply_err(req, 0);
+}
+
+static void ntfs_fuse_mkdir(fuse_req_t req, fuse_ino_t parent,
+		       const char *name, mode_t mode)
+{
+	int res;
+	struct fuse_entry_param entry;
+
+	res = ntfs_fuse_create(req, parent, name, S_IFDIR | (mode & 07777),
+			0, &entry, (char*)NULL, (struct fuse_file_info*)NULL);
+	if (res < 0)
+		fuse_reply_err(req, -res);
+	else
+		fuse_reply_entry(req, &entry);
+}
+
+static void ntfs_fuse_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name)
+{
+	int res;
+
+	res = ntfs_fuse_rm(req, parent, name, RM_DIR);
+	if (res)
+		fuse_reply_err(req, -res);
+	else
+		fuse_reply_err(req, 0);
+}
+
+static void ntfs_fuse_fsync(fuse_req_t req,
+			fuse_ino_t ino __attribute__((unused)),
+			int type __attribute__((unused)),
+			struct fuse_file_info *fi __attribute__((unused)))
+{
+		/* sync the full device */
+	if (ntfs_device_sync(ctx->vol->dev))
+		fuse_reply_err(req, errno);
+	else
+		fuse_reply_err(req, 0);
+}
+
+#if defined(FUSE_INTERNAL) || (FUSE_VERSION >= 28)
+static void ntfs_fuse_ioctl(fuse_req_t req __attribute__((unused)),
+			fuse_ino_t ino __attribute__((unused)),
+			int cmd, void *arg,
+			struct fuse_file_info *fi __attribute__((unused)),
+			unsigned flags, const void *data,
+			size_t in_bufsz, size_t out_bufsz)
+{
+	ntfs_inode *ni;
+	char *buf = (char*)NULL;
+	int bufsz;
+	int ret = 0;
+
+	if (flags & FUSE_IOCTL_COMPAT) {
+		ret = -ENOSYS;
+	} else {
+		ni = ntfs_inode_open(ctx->vol, INODE(ino));
+		if (!ni) {
+			ret = -errno;
+			goto fail;
+		}
+		bufsz = (in_bufsz > out_bufsz ? in_bufsz : out_bufsz);
+		if (bufsz) {
+			buf = ntfs_malloc(bufsz);
+			if (!buf) {
+				ret = ENOMEM;
+				goto fail;
+			}
+			memcpy(buf, data, in_bufsz);
+		}
+		ret = ntfs_ioctl(ni, cmd, arg, flags, buf);
+		if (ntfs_inode_close (ni))
+			set_fuse_error(&ret);
+	}
+	if (ret)
+fail :
+		fuse_reply_err(req, -ret);
+	else
+		fuse_reply_ioctl(req, 0, buf, out_bufsz);
+	if (buf)
+		free(buf);
+}
+#endif /* defined(FUSE_INTERNAL) || (FUSE_VERSION >= 28) */
+
+static void ntfs_fuse_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize,
+		      uint64_t vidx)
+{
+	ntfs_inode *ni;
+	ntfs_attr *na;
+	LCN lcn;
+	uint64_t lidx = 0;
+	int ret = 0; 
+	int cl_per_bl = ctx->vol->cluster_size / blocksize;
+
+	if (blocksize > ctx->vol->cluster_size) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	ni = ntfs_inode_open(ctx->vol, INODE(ino));
+	if (!ni) {
+		ret = -errno;
+		goto done;
+	}
+
+	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
+	if (!na) {
+		ret = -errno;
+		goto close_inode;
+	}
+        
+	if ((na->data_flags & (ATTR_COMPRESSION_MASK | ATTR_IS_ENCRYPTED))
+			 || !NAttrNonResident(na)) {
+		ret = -EINVAL;
+		goto close_attr;
+	}
+        
+	if (ntfs_attr_map_whole_runlist(na)) {
+		ret = -errno;
+		goto close_attr;
+	}
+        
+	lcn = ntfs_rl_vcn_to_lcn(na->rl, vidx / cl_per_bl);
+	lidx = (lcn > 0) ? lcn * cl_per_bl + vidx % cl_per_bl : 0;
+        
+close_attr:
+	ntfs_attr_close(na);
+close_inode:
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&ret);
+done :
+	if (ret < 0)
+		fuse_reply_err(req, -ret);
+	else
+		fuse_reply_bmap(req, lidx);
+}
+
+#ifdef HAVE_SETXATTR
+
+/*
+ *		  Name space identifications and prefixes
+ */
+
+enum {
+	XATTRNS_NONE,
+	XATTRNS_USER,
+	XATTRNS_SYSTEM,
+	XATTRNS_SECURITY,
+	XATTRNS_TRUSTED,
+	XATTRNS_OPEN
+} ;
+
+/*
+ *		Check whether access to internal data as an extended
+ *	attribute in system name space is allowed
+ *
+ *	Returns pointer to inode if allowed,
+ *		NULL and errno set if not allowed
+ */
+
+static ntfs_inode *ntfs_check_access_xattr(fuse_req_t req,
+			struct SECURITY_CONTEXT *security,
+			fuse_ino_t ino, int attr, BOOL setting)
+{
+	ntfs_inode *dir_ni;
+	ntfs_inode *ni;
+	BOOL foracl;
+	BOOL bad;
+	mode_t acctype;
+
+	ni = (ntfs_inode*)NULL;
+	foracl = (attr == XATTR_POSIX_ACC)
+		 || (attr == XATTR_POSIX_DEF);
+	/*
+	 * When accessing Posix ACL, return unsupported if ACL
+	 * were disabled or no user mapping has been defined,
+	 * or trying to change a Windows-inherited ACL.
+	 * However no error will be returned to getfacl
+	 */
+	if (((!ntfs_fuse_fill_security_context(req, security)
+		|| (ctx->secure_flags
+		    & ((1 << SECURITY_DEFAULT) | (1 << SECURITY_RAW))))
+		|| !(ctx->secure_flags & (1 << SECURITY_ACL))
+		|| (setting && ctx->inherit))
+	    && foracl) {
+		if (ctx->silent)
+			errno = 0;
+		else
+			errno = EOPNOTSUPP;
+	} else {
+			/*
+			 * parent directory must be executable, and
+			 * for setting a DOS name it must be writeable
+			 */
+		if (setting && (attr == XATTR_NTFS_DOS_NAME))
+			acctype = S_IEXEC | S_IWRITE;
+		else
+			acctype = S_IEXEC;
+		ni = ntfs_inode_open(ctx->vol, INODE(ino));
+			/* basic access was checked previously in a lookup */
+		if (ni && (acctype != S_IEXEC)) {
+			bad = FALSE;
+				/* do not reopen root */
+			if (ni->mft_no == FILE_root) {
+				/* forbid getting/setting names on root */
+				if ((attr == XATTR_NTFS_DOS_NAME)
+				    || !ntfs_real_allowed_access(security,
+						ni, acctype))
+					bad = TRUE;
+			} else {
+				dir_ni = ntfs_dir_parent_inode(ni);
+				if (dir_ni) {
+					if (!ntfs_real_allowed_access(security,
+							dir_ni, acctype))
+						bad = TRUE;
+					if (ntfs_inode_close(dir_ni))
+						bad = TRUE;
+				} else
+					bad = TRUE;
+			}
+			if (bad) {
+				ntfs_inode_close(ni);
+				ni = (ntfs_inode*)NULL;
+			}
+		}
+	}
+	return (ni);
+}
+
+/*
+ *		Determine the name space of an extended attribute
+ */
+
+static int xattr_namespace(const char *name)
+{
+	int namespace;
+
+	if (ctx->streams == NF_STREAMS_INTERFACE_XATTR) {
+		namespace = XATTRNS_NONE;
+		if (!strncmp(name, nf_ns_user_prefix, 
+			nf_ns_user_prefix_len)
+		    && (strlen(name) != (size_t)nf_ns_user_prefix_len))
+			namespace = XATTRNS_USER;
+		else if (!strncmp(name, nf_ns_system_prefix, 
+			nf_ns_system_prefix_len)
+		    && (strlen(name) != (size_t)nf_ns_system_prefix_len))
+			namespace = XATTRNS_SYSTEM;
+		else if (!strncmp(name, nf_ns_security_prefix, 
+			nf_ns_security_prefix_len)
+		    && (strlen(name) != (size_t)nf_ns_security_prefix_len))
+			namespace = XATTRNS_SECURITY;
+		else if (!strncmp(name, nf_ns_trusted_prefix, 
+			nf_ns_trusted_prefix_len)
+		    && (strlen(name) != (size_t)nf_ns_trusted_prefix_len))
+			namespace = XATTRNS_TRUSTED;
+	} else
+		namespace = XATTRNS_OPEN;
+	return (namespace);
+}
+
+/*
+ *		Fix the prefix of an extended attribute
+ */
+
+static int fix_xattr_prefix(const char *name, int namespace, ntfschar **lename)
+{
+	int len;
+	char *prefixed;
+
+	*lename = (ntfschar*)NULL;
+	switch (namespace) {
+	case XATTRNS_USER :
+		/*
+		 * user name space : remove user prefix
+		 */
+		len = ntfs_mbstoucs(name + nf_ns_user_prefix_len, lename);
+		break;
+	case XATTRNS_SYSTEM :
+	case XATTRNS_SECURITY :
+	case XATTRNS_TRUSTED :
+		/*
+		 * security, trusted and unmapped system name spaces :
+		 * insert ntfs-3g prefix
+		 */
+		prefixed = (char*)ntfs_malloc(strlen(xattr_ntfs_3g)
+			 + strlen(name) + 1);
+		if (prefixed) {
+			strcpy(prefixed,xattr_ntfs_3g);
+			strcat(prefixed,name);
+			len = ntfs_mbstoucs(prefixed, lename);
+			free(prefixed);
+		} else
+			len = -1;
+		break;
+	case XATTRNS_OPEN :
+		/*
+		 * in open name space mode : do no fix prefix
+		 */
+		len = ntfs_mbstoucs(name, lename);
+		break;
+	default :
+		len = -1;
+	}
+	return (len);
+}
+
+static void ntfs_fuse_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
+{
+	ntfs_attr_search_ctx *actx = NULL;
+	ntfs_inode *ni;
+	char *list = (char*)NULL;
+	int ret = 0;
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	struct SECURITY_CONTEXT security;
+#endif
+
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	ntfs_fuse_fill_security_context(req, &security);
+#endif
+	ni = ntfs_inode_open(ctx->vol, INODE(ino));
+	if (!ni) {
+		ret = -errno;
+		goto out;
+	}
+		/* Return with no result for symlinks, fifo, etc. */
+	if (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT))
+		goto exit;
+		/* otherwise file must be readable */
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	if (!ntfs_allowed_access(&security,ni,S_IREAD)) {
+		ret = -EACCES;
+		goto exit;
+	}
+#endif
+	actx = ntfs_attr_get_search_ctx(ni, NULL);
+	if (!actx) {
+		ret = -errno;
+		goto exit;
+	}
+	if (size) {
+		list = (char*)malloc(size);
+		if (!list) {
+			ret = -errno;
+			goto exit;
+		}
+	}
+
+	if ((ctx->streams == NF_STREAMS_INTERFACE_XATTR)
+	    || (ctx->streams == NF_STREAMS_INTERFACE_OPENXATTR)) {
+		ret = ntfs_fuse_listxattr_common(ni, actx, list, size,
+				ctx->streams == NF_STREAMS_INTERFACE_XATTR);
+		if (ret < 0)
+			goto exit;
+	}
+	if (errno != ENOENT)
+		ret = -errno;
+exit:
+	if (actx)
+		ntfs_attr_put_search_ctx(actx);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&ret);
+out :
+	if (ret < 0)
+		fuse_reply_err(req, -ret);
+	else
+		if (size)
+			fuse_reply_buf(req, list, ret);
+		else
+			fuse_reply_xattr(req, ret);
+	free(list);
+}
+
+static void ntfs_fuse_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
+			  size_t size)
+{
+	ntfs_inode *ni;
+	ntfs_inode *dir_ni;
+	ntfs_attr *na = NULL;
+	char *value = (char*)NULL;
+	ntfschar *lename = (ntfschar*)NULL;
+	int lename_len;
+	int res;
+	s64 rsize;
+	enum SYSTEMXATTRS attr;
+	int namespace;
+	struct SECURITY_CONTEXT security;
+
+	attr = ntfs_xattr_system_type(name,ctx->vol);
+	if (attr != XATTR_UNMAPPED) {
+		/*
+		 * hijack internal data and ACL retrieval, whatever
+		 * mode was selected for xattr (from the user's
+		 * point of view, ACLs are not xattr)
+		 */
+		if (size)
+			value = (char*)ntfs_malloc(size);
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+		if (!size || value) {
+			ni = ntfs_check_access_xattr(req, &security, ino,
+					attr, FALSE);
+			if (ni) {
+				if (ntfs_allowed_access(&security,ni,S_IREAD)) {
+					if (attr == XATTR_NTFS_DOS_NAME)
+						dir_ni = ntfs_dir_parent_inode(ni);
+					else
+						dir_ni = (ntfs_inode*)NULL;
+					res = ntfs_xattr_system_getxattr(&security,
+						attr, ni, dir_ni, value, size);
+					if (dir_ni && ntfs_inode_close(dir_ni))
+						set_fuse_error(&res);
+				} else
+					res = -errno;
+				if (ntfs_inode_close(ni))
+					set_fuse_error(&res);
+			} else
+				res = -errno;
+#else
+			/*
+			 * Standard access control has been done by fuse/kernel
+			 */
+		if (!size || value) {
+			ni = ntfs_inode_open(ctx->vol, INODE(ino));
+			if (ni) {
+					/* user mapping not mandatory */
+				ntfs_fuse_fill_security_context(req, &security);
+				if (attr == XATTR_NTFS_DOS_NAME)
+					dir_ni = ntfs_dir_parent_inode(ni);
+				else
+					dir_ni = (ntfs_inode*)NULL;
+				res = ntfs_xattr_system_getxattr(&security,
+					attr, ni, dir_ni, value, size);
+				if (dir_ni && ntfs_inode_close(dir_ni))
+					set_fuse_error(&res);
+				if (ntfs_inode_close(ni))
+					set_fuse_error(&res);
+			} else
+				res = -errno;
+#endif
+		} else
+			res = -errno;
+		if (res < 0)
+			fuse_reply_err(req, -res);
+		else
+			if (size)
+				fuse_reply_buf(req, value, res);
+			else
+				fuse_reply_xattr(req, res);
+		free(value);
+		return;
+	}
+	if (ctx->streams == NF_STREAMS_INTERFACE_NONE) {
+		res = -EOPNOTSUPP;
+		goto out;
+	}
+	namespace = xattr_namespace(name);
+	if (namespace == XATTRNS_NONE) {
+		res = -EOPNOTSUPP;
+		goto out;
+	}
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	ntfs_fuse_fill_security_context(req,&security);
+		/* trusted only readable by root */
+	if ((namespace == XATTRNS_TRUSTED)
+	    && security.uid) {
+		res = -ENODATA;
+		goto out;
+	}
+#endif
+	ni = ntfs_inode_open(ctx->vol, INODE(ino));
+	if (!ni) {
+		res = -errno;
+		goto out;
+	}
+		/* Return with no result for symlinks, fifo, etc. */
+	if (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT)) {
+		res = -ENODATA;
+		goto exit;
+	}
+		/* otherwise file must be readable */
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	if (!ntfs_allowed_access(&security, ni, S_IREAD)) {
+		res = -errno;
+		goto exit;
+	}
+#endif
+	lename_len = fix_xattr_prefix(name, namespace, &lename);
+	if (lename_len == -1) {
+		res = -errno;
+		goto exit;
+	}
+	na = ntfs_attr_open(ni, AT_DATA, lename, lename_len);
+	if (!na) {
+		res = -ENODATA;
+		goto exit;
+	}
+	rsize = na->data_size;
+	if (ctx->efs_raw
+	    && rsize
+	    && (na->data_flags & ATTR_IS_ENCRYPTED)
+	    && NAttrNonResident(na))
+		rsize = ((na->data_size + 511) & ~511) + 2;
+	if (size) {
+		if (size >= (size_t)rsize) {
+			value = (char*)ntfs_malloc(rsize);
+			if (value)
+				res = ntfs_attr_pread(na, 0, rsize, value);
+			if (!value || (res != rsize))
+				res = -errno;
+		} else
+			res = -ERANGE;
+	} else
+		res = rsize;
+exit:
+	if (na)
+		ntfs_attr_close(na);
+	free(lename);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+
+out :
+	if (res < 0)
+		fuse_reply_err(req, -res);
+	else
+		if (size)
+			fuse_reply_buf(req, value, res);
+		else
+			fuse_reply_xattr(req, res);
+	free(value);
+}
+
+static void ntfs_fuse_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
+			  const char *value, size_t size, int flags)
+{
+	ntfs_inode *ni;
+	ntfs_inode *dir_ni;
+	ntfs_attr *na = NULL;
+	ntfschar *lename = NULL;
+	int res, lename_len;
+	size_t total;
+	s64 part;
+	enum SYSTEMXATTRS attr;
+	int namespace;
+	struct SECURITY_CONTEXT security;
+
+	attr = ntfs_xattr_system_type(name,ctx->vol);
+	if (attr != XATTR_UNMAPPED) {
+		/*
+		 * hijack internal data and ACL setting, whatever
+		 * mode was selected for xattr (from the user's
+		 * point of view, ACLs are not xattr)
+		 * Note : ctime updated on successful settings
+		 */
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+		ni = ntfs_check_access_xattr(req,&security,ino,attr,TRUE);
+		if (ni) {
+			if (ntfs_allowed_as_owner(&security, ni)) {
+				if (attr == XATTR_NTFS_DOS_NAME)
+					dir_ni = ntfs_dir_parent_inode(ni);
+				else
+					dir_ni = (ntfs_inode*)NULL;
+				res = ntfs_xattr_system_setxattr(&security,
+					attr, ni, dir_ni, value, size, flags);
+				/* never have to close dir_ni */
+				if (res)
+					res = -errno;
+			} else
+				res = -errno;
+			if (attr != XATTR_NTFS_DOS_NAME) {
+				if (!res)
+					ntfs_fuse_update_times(ni,
+							NTFS_UPDATE_CTIME);
+				if (ntfs_inode_close(ni))
+					set_fuse_error(&res);
+			}
+		} else
+			res = -errno;
+#else
+		/* creation of a new name is not controlled by fuse */
+		if (attr == XATTR_NTFS_DOS_NAME)
+			ni = ntfs_check_access_xattr(req, &security,
+					ino, attr, TRUE);
+		else
+			ni = ntfs_inode_open(ctx->vol, INODE(ino));
+		if (ni) {
+				/*
+				 * user mapping is not mandatory
+				 * if defined, only owner is allowed
+				 */
+			if (!ntfs_fuse_fill_security_context(req, &security)
+			   || ntfs_allowed_as_owner(&security, ni)) {
+				if (attr == XATTR_NTFS_DOS_NAME)
+					dir_ni = ntfs_dir_parent_inode(ni);
+				else
+					dir_ni = (ntfs_inode*)NULL;
+				res = ntfs_xattr_system_setxattr(&security,
+					attr, ni, dir_ni, value, size, flags);
+				/* never have to close dir_ni */
+				if (res)
+					res = -errno;
+			} else
+				res = -errno;
+			if (attr != XATTR_NTFS_DOS_NAME) {
+				if (!res)
+					ntfs_fuse_update_times(ni,
+							NTFS_UPDATE_CTIME);
+				if (ntfs_inode_close(ni))
+					set_fuse_error(&res);
+			}
+		} else
+			res = -errno;
+#endif
+#if CACHEING && !defined(FUSE_INTERNAL)
+		/*
+		 * Most of system xattr settings cause changes to some
+		 * file attribute (st_mode, st_nlink, st_mtime, etc.),
+		 * so we must invalidate cached data when cacheing is
+		 * in use (not possible with internal fuse or external
+		 * fuse before 2.8)
+		 */
+		if ((res >= 0)
+		    && fuse_lowlevel_notify_inval_inode(ctx->fc, ino, -1, 0))
+			res = -errno;
+#endif
+		if (res < 0)
+			fuse_reply_err(req, -res);
+		else
+			fuse_reply_err(req, 0);
+		return;
+	}
+	if ((ctx->streams != NF_STREAMS_INTERFACE_XATTR)
+	    && (ctx->streams != NF_STREAMS_INTERFACE_OPENXATTR)) {
+		res = -EOPNOTSUPP;
+		goto out;
+		}
+	namespace = xattr_namespace(name);
+	if (namespace == XATTRNS_NONE) {
+		res = -EOPNOTSUPP;
+		goto out;
+	}
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	ntfs_fuse_fill_security_context(req,&security);
+		/* security and trusted only settable by root */
+	if (((namespace == XATTRNS_SECURITY)
+	   || (namespace == XATTRNS_TRUSTED))
+		&& security.uid) {
+			res = -EPERM;
+			goto out;
+		}
+#endif
+	ni = ntfs_inode_open(ctx->vol, INODE(ino));
+	if (!ni) {
+		res = -errno;
+		goto out;
+	}
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	switch (namespace) {
+	case XATTRNS_SECURITY :
+	case XATTRNS_TRUSTED :
+		if (security.uid) {
+			res = -EPERM;
+			goto exit;
+		}
+		break;
+	case XATTRNS_SYSTEM :
+		if (!ntfs_allowed_as_owner(&security, ni)) {
+			res = -EACCES;
+			goto exit;
+		}
+		break;
+	default :
+		/* User xattr not allowed for symlinks, fifo, etc. */
+		if (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT)) {
+			res = -EPERM;
+			goto exit;
+		}
+		if (!ntfs_allowed_access(&security,ni,S_IWRITE)) {
+			res = -EACCES;
+			goto exit;
+		}
+		break;
+	}
+#else
+		/* User xattr not allowed for symlinks, fifo, etc. */
+	if ((namespace == XATTRNS_USER)
+	    && (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT))) {
+		res = -EPERM;
+		goto exit;
+	}
+#endif
+	lename_len = fix_xattr_prefix(name, namespace, &lename);
+	if ((lename_len == -1)
+	    || (ctx->windows_names
+		&& ntfs_forbidden_chars(lename,lename_len))) {
+		res = -errno;
+		goto exit;
+	}
+	na = ntfs_attr_open(ni, AT_DATA, lename, lename_len);
+	if (na && flags == XATTR_CREATE) {
+		res = -EEXIST;
+		goto exit;
+	}
+	if (!na) {
+		if (flags == XATTR_REPLACE) {
+			res = -ENODATA;
+			goto exit;
+		}
+		if (ntfs_attr_add(ni, AT_DATA, lename, lename_len, NULL, 0)) {
+			res = -errno;
+			goto exit;
+		}
+		if (!(ni->flags & FILE_ATTR_ARCHIVE)) {
+			set_archive(ni);
+			NInoFileNameSetDirty(ni);
+		}
+		na = ntfs_attr_open(ni, AT_DATA, lename, lename_len);
+		if (!na) {
+			res = -errno;
+			goto exit;
+		}
+	} else {
+			/* currently compressed streams can only be wiped out */
+		if (ntfs_attr_truncate(na, (s64)0 /* size */)) {
+			res = -errno;
+			goto exit;
+		}
+	}
+	total = 0;
+	res = 0;
+	if (size) {
+		do {
+			part = ntfs_attr_pwrite(na, total, size - total,
+					 &value[total]);
+			if (part > 0)
+				total += part;
+		} while ((part > 0) && (total < size));
+	}
+	if ((total != size) || ntfs_attr_pclose(na))
+		res = -errno;
+	else {
+		if (ctx->efs_raw 
+		   && (ni->flags & FILE_ATTR_ENCRYPTED)) {
+			if (ntfs_efs_fixup_attribute(NULL,na))
+				res = -errno;
+		}
+	}
+	if (!res) {
+		ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);
+		if (!(ni->flags & FILE_ATTR_ARCHIVE)) {
+			set_archive(ni);
+			NInoFileNameSetDirty(ni);
+		}
+	}
+exit:
+	if (na)
+		ntfs_attr_close(na);
+	free(lename);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+out :
+	if (res < 0)
+		fuse_reply_err(req, -res);
+	else
+		fuse_reply_err(req, 0);
+}
+
+static void ntfs_fuse_removexattr(fuse_req_t req, fuse_ino_t ino, const char *name)
+{
+	ntfs_inode *ni;
+	ntfs_inode *dir_ni;
+	ntfschar *lename = NULL;
+	int res = 0, lename_len;
+	enum SYSTEMXATTRS attr;
+	int namespace;
+	struct SECURITY_CONTEXT security;
+
+	attr = ntfs_xattr_system_type(name,ctx->vol);
+	if (attr != XATTR_UNMAPPED) {
+		switch (attr) {
+			/*
+			 * Removal of NTFS ACL, ATTRIB, EFSINFO or TIMES
+			 * is never allowed
+			 */
+		case XATTR_NTFS_ACL :
+		case XATTR_NTFS_ATTRIB :
+		case XATTR_NTFS_ATTRIB_BE :
+		case XATTR_NTFS_EFSINFO :
+		case XATTR_NTFS_TIMES :
+		case XATTR_NTFS_TIMES_BE :
+		case XATTR_NTFS_CRTIME :
+		case XATTR_NTFS_CRTIME_BE :
+			res = -EPERM;
+			break;
+		default :
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+			ni = ntfs_check_access_xattr(req, &security, ino,
+					attr,TRUE);
+			if (ni) {
+				if (ntfs_allowed_as_owner(&security, ni)) {
+					if (attr == XATTR_NTFS_DOS_NAME)
+						dir_ni = ntfs_dir_parent_inode(ni);
+					else
+						dir_ni = (ntfs_inode*)NULL;
+					res = ntfs_xattr_system_removexattr(&security,
+							attr, ni, dir_ni);
+					if (res)
+						res = -errno;
+					/* never have to close dir_ni */
+				} else
+					res = -errno;
+				if (attr != XATTR_NTFS_DOS_NAME) {
+					if (!res)
+						ntfs_fuse_update_times(ni,
+							NTFS_UPDATE_CTIME);
+					if (ntfs_inode_close(ni))
+						set_fuse_error(&res);
+				}
+			} else
+				res = -errno;
+#else
+			/* creation of a new name is not controlled by fuse */
+			if (attr == XATTR_NTFS_DOS_NAME)
+				ni = ntfs_check_access_xattr(req, &security,
+						ino, attr, TRUE);
+			else
+				ni = ntfs_inode_open(ctx->vol, INODE(ino));
+			if (ni) {
+				/*
+				 * user mapping is not mandatory
+				 * if defined, only owner is allowed
+				 */
+				if (!ntfs_fuse_fill_security_context(req, &security)
+				   || ntfs_allowed_as_owner(&security, ni)) {
+					if (attr == XATTR_NTFS_DOS_NAME)
+						dir_ni = ntfs_dir_parent_inode(ni);
+					else
+						dir_ni = (ntfs_inode*)NULL;
+					res = ntfs_xattr_system_removexattr(&security,
+						attr, ni, dir_ni);
+					/* never have to close dir_ni */
+					if (res)
+						res = -errno;
+				} else
+					res = -errno;
+				if (attr != XATTR_NTFS_DOS_NAME) {
+					if (!res)
+						ntfs_fuse_update_times(ni,
+							NTFS_UPDATE_CTIME);
+					if (ntfs_inode_close(ni))
+						set_fuse_error(&res);
+				}
+			} else
+				res = -errno;
+#endif
+#if CACHEING && !defined(FUSE_INTERNAL)
+		/*
+		 * Some allowed system xattr removals cause changes to
+		 * some file attribute (st_mode, st_nlink, etc.),
+		 * so we must invalidate cached data when cacheing is
+		 * in use (not possible with internal fuse or external
+		 * fuse before 2.8)
+		 */
+			if ((res >= 0)
+			    && fuse_lowlevel_notify_inval_inode(ctx->fc,
+						ino, -1, 0))
+				res = -errno;
+#endif
+			break;
+		}
+		if (res < 0)
+			fuse_reply_err(req, -res);
+		else
+			fuse_reply_err(req, 0);
+		return;
+	}
+	if ((ctx->streams != NF_STREAMS_INTERFACE_XATTR)
+	    && (ctx->streams != NF_STREAMS_INTERFACE_OPENXATTR)) {
+		res = -EOPNOTSUPP;
+		goto out;
+	}
+	namespace = xattr_namespace(name);
+	if (namespace == XATTRNS_NONE) {
+		res = -EOPNOTSUPP;
+		goto out;
+	}
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	ntfs_fuse_fill_security_context(req,&security);
+		/* security and trusted only settable by root */
+	if (((namespace == XATTRNS_SECURITY)
+	   || (namespace == XATTRNS_TRUSTED))
+		&& security.uid) {
+			res = -EACCES;
+			goto out;
+		}
+#endif
+	ni = ntfs_inode_open(ctx->vol, INODE(ino));
+	if (!ni) {
+		res = -errno;
+		goto out;
+	}
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	switch (namespace) {
+	case XATTRNS_SECURITY :
+	case XATTRNS_TRUSTED :
+		if (security.uid) {
+			res = -EPERM;
+			goto exit;
+		}
+		break;
+	case XATTRNS_SYSTEM :
+		if (!ntfs_allowed_as_owner(&security, ni)) {
+			res = -EACCES;
+			goto exit;
+		}
+		break;
+	default :
+		/* User xattr not allowed for symlinks, fifo, etc. */
+		if (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT)) {
+			res = -EPERM;
+			goto exit;
+		}
+		if (!ntfs_allowed_access(&security,ni,S_IWRITE)) {
+			res = -EACCES;
+			goto exit;
+		}
+		break;
+	}
+#else
+		/* User xattr not allowed for symlinks, fifo, etc. */
+	if ((namespace == XATTRNS_USER)
+	    && (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT))) {
+		res = -EPERM;
+		goto exit;
+	}
+#endif
+	lename_len = fix_xattr_prefix(name, namespace, &lename);
+	if (lename_len == -1) {
+		res = -errno;
+		goto exit;
+	}
+	if (ntfs_attr_remove(ni, AT_DATA, lename, lename_len)) {
+		if (errno == ENOENT)
+			errno = ENODATA;
+		res = -errno;
+	}
+	if (!res) {
+		ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);
+		if (!(ni->flags & FILE_ATTR_ARCHIVE)) {
+			set_archive(ni);
+			NInoFileNameSetDirty(ni);
+		}
+	}
+exit:
+	free(lename);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+out :
+	if (res < 0)
+		fuse_reply_err(req, -res);
+	else
+		fuse_reply_err(req, 0);
+	return;
+
+}
+
+#else
+#if POSIXACLS
+#error "Option inconsistency : POSIXACLS requires SETXATTR"
+#endif
+#endif /* HAVE_SETXATTR */
+
+static void ntfs_close(void)
+{
+	struct SECURITY_CONTEXT security;
+
+	if (!ctx)
+		return;
+        
+	if (!ctx->vol)
+		return;
+        
+	if (ctx->mounted) {
+		ntfs_log_info("Unmounting %s (%s)\n", opts.device, 
+			      ctx->vol->vol_name);
+		if (ntfs_fuse_fill_security_context((fuse_req_t)NULL, &security)) {
+			if (ctx->seccache && ctx->seccache->head.p_reads) {
+				ntfs_log_info("Permissions cache : %lu writes, "
+				"%lu reads, %lu.%1lu%% hits\n",
+			      ctx->seccache->head.p_writes,
+			      ctx->seccache->head.p_reads,
+			      100 * ctx->seccache->head.p_hits
+				 / ctx->seccache->head.p_reads,
+			      1000 * ctx->seccache->head.p_hits
+				 / ctx->seccache->head.p_reads % 10);
+			}
+		}
+		ntfs_close_secure(&security);
+	}
+        
+	if (ntfs_umount(ctx->vol, FALSE))
+		ntfs_log_perror("Failed to close volume %s", opts.device);
+        
+	ctx->vol = NULL;
+}
+
+static void ntfs_fuse_destroy2(void *notused __attribute__((unused)))
+{
+	ntfs_close();
+}
+
+static struct fuse_lowlevel_ops ntfs_3g_ops = {
+	.lookup 	= ntfs_fuse_lookup,
+	.getattr	= ntfs_fuse_getattr,
+	.readlink	= ntfs_fuse_readlink,
+	.opendir	= ntfs_fuse_opendir,
+	.readdir	= ntfs_fuse_readdir,
+	.releasedir	= ntfs_fuse_releasedir,
+	.open		= ntfs_fuse_open,
+	.release	= ntfs_fuse_release,
+	.read		= ntfs_fuse_read,
+	.write		= ntfs_fuse_write,
+	.setattr	= ntfs_fuse_setattr,
+	.statfs 	= ntfs_fuse_statfs,
+	.create 	= ntfs_fuse_create_file,
+	.mknod		= ntfs_fuse_mknod,
+	.symlink	= ntfs_fuse_symlink,
+	.link		= ntfs_fuse_link,
+	.unlink 	= ntfs_fuse_unlink,
+	.rename 	= ntfs_fuse_rename,
+	.mkdir		= ntfs_fuse_mkdir,
+	.rmdir		= ntfs_fuse_rmdir,
+	.fsync		= ntfs_fuse_fsync,
+	.fsyncdir	= ntfs_fuse_fsync,
+	.bmap		= ntfs_fuse_bmap,
+	.destroy	= ntfs_fuse_destroy2,
+#if defined(FUSE_INTERNAL) || (FUSE_VERSION >= 28)
+	.ioctl		= ntfs_fuse_ioctl,
+#endif /* defined(FUSE_INTERNAL) || (FUSE_VERSION >= 28) */
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	.access 	= ntfs_fuse_access,
+#endif
+#ifdef HAVE_SETXATTR
+	.getxattr	= ntfs_fuse_getxattr,
+	.setxattr	= ntfs_fuse_setxattr,
+	.removexattr	= ntfs_fuse_removexattr,
+	.listxattr	= ntfs_fuse_listxattr,
+#endif /* HAVE_SETXATTR */
+#if 0 && (defined(__APPLE__) || defined(__DARWIN__)) /* Unfinished. */
+	/* MacFUSE extensions. */
+	.getxtimes	= ntfs_macfuse_getxtimes,
+	.setcrtime	= ntfs_macfuse_setcrtime,
+	.setbkuptime	= ntfs_macfuse_setbkuptime,
+	.setchgtime	= ntfs_macfuse_setchgtime,
+#endif /* defined(__APPLE__) || defined(__DARWIN__) */
+	.init		= ntfs_init
+};
+
+static int ntfs_fuse_init(void)
+{
+	ctx = (ntfs_fuse_context_t*)ntfs_calloc(sizeof(ntfs_fuse_context_t));
+	if (!ctx)
+		return -1;
+        
+	*ctx = (ntfs_fuse_context_t) {
+		.uid	 = getuid(),
+		.gid	 = getgid(),
+#if defined(linux)		        
+		.streams = NF_STREAMS_INTERFACE_XATTR,
+#else		        
+		.streams = NF_STREAMS_INTERFACE_NONE,
+#endif		        
+		.atime	 = ATIME_RELATIVE,
+		.silent  = TRUE,
+		.recover = TRUE
+	};
+	return 0;
+}
+
+static int ntfs_open(const char *device)
+{
+	unsigned long flags = 0;
+	ntfs_volume *vol;
+        
+	if (!ctx->blkdev)
+		flags |= NTFS_MNT_EXCLUSIVE;
+	if (ctx->ro)
+		flags |= NTFS_MNT_RDONLY;
+	if (ctx->recover)
+		flags |= NTFS_MNT_RECOVER;
+	if (ctx->hiberfile)
+		flags |= NTFS_MNT_IGNORE_HIBERFILE;
+
+	ctx->vol = vol = ntfs_mount(device, flags);
+	if (!vol) {
+		ntfs_log_perror("Failed to mount '%s'", device);
+		goto err_out;
+	}
+	if (ctx->sync && ctx->vol->dev)
+		NDevSetSync(ctx->vol->dev);
+	if (ctx->compression)
+		NVolSetCompression(ctx->vol);
+	else
+		NVolClearCompression(ctx->vol);
+#ifdef HAVE_SETXATTR
+			/* archivers must see hidden files */
+	if (ctx->efs_raw)
+		ctx->hide_hid_files = FALSE;
+#endif
+	if (ntfs_set_shown_files(ctx->vol, ctx->show_sys_files,
+				!ctx->hide_hid_files, ctx->hide_dot_files))
+		goto err_out;
+
+	if (ctx->ignore_case && ntfs_set_ignore_case(vol))
+		goto err_out;
+        
+	vol->free_clusters = ntfs_attr_get_free_bits(vol->lcnbmp_na);
+	if (vol->free_clusters < 0) {
+		ntfs_log_perror("Failed to read NTFS $Bitmap");
+		goto err_out;
+	}
+
+	vol->free_mft_records = ntfs_get_nr_free_mft_records(vol);
+	if (vol->free_mft_records < 0) {
+		ntfs_log_perror("Failed to calculate free MFT records");
+		goto err_out;
+	}
+
+	if (ctx->hiberfile && ntfs_volume_check_hiberfile(vol, 0)) {
+		if (errno != EPERM)
+			goto err_out;
+		if (ntfs_fuse_rm((fuse_req_t)NULL,FILE_root,"hiberfil.sys",
+					RM_LINK))
+			goto err_out;
+	}
+        
+	errno = 0;
+err_out:
+	return ntfs_volume_error(errno);
+        
+}
+
+static void usage(void)
+{
+	ntfs_log_info(usage_msg, EXEC_NAME, VERSION, FUSE_TYPE, fuse_version(),
+			5 + POSIXACLS*6 - KERNELPERMS*3 + CACHEING,
+			EXEC_NAME, ntfs_home);
+}
+
+#if defined(linux) || defined(__uClinux__)
+
+static const char *dev_fuse_msg =
+"HINT: You should be root, or make ntfs-3g setuid root, or load the FUSE\n"
+"      kernel module as root ('modprobe fuse' or 'insmod <path_to>/fuse.ko'"
+"      or insmod <path_to>/fuse.o'). Make also sure that the fuse device"
+"      exists. It's usually either /dev/fuse or /dev/misc/fuse.";
+
+static const char *fuse26_kmod_msg =
+"WARNING: Deficient Linux kernel detected. Some driver features are\n"
+"         not available (swap file on NTFS, boot from NTFS by LILO), and\n"
+"         unmount is not safe unless it's made sure the ntfs-3g process\n"
+"         naturally terminates after calling 'umount'. If you wish this\n"
+"         message to disappear then you should upgrade to at least kernel\n"
+"         version 2.6.20, or request help from your distribution to fix\n"
+"         the kernel problem. The below web page has more information:\n"
+"         http://tuxera.com/community/ntfs-3g-faq/#fuse26\n"
+"\n";
+
+static void mknod_dev_fuse(const char *dev)
+{
+	struct stat st;
+        
+	if (stat(dev, &st) && (errno == ENOENT)) {
+		mode_t mask = umask(0); 
+		if (mknod(dev, S_IFCHR | 0666, makedev(10, 229))) {
+			ntfs_log_perror("Failed to create '%s'", dev);
+			if (errno == EPERM)
+				ntfs_log_error("%s", dev_fuse_msg);
+		}
+		umask(mask);
+	}
+}
+
+static void create_dev_fuse(void)
+{
+	mknod_dev_fuse("/dev/fuse");
+
+#ifdef __UCLIBC__
+	{
+		struct stat st;
+		/* The fuse device is under /dev/misc using devfs. */
+		if (stat("/dev/misc", &st) && (errno == ENOENT)) {
+			mode_t mask = umask(0); 
+			mkdir("/dev/misc", 0775);
+			umask(mask);
+		}
+		mknod_dev_fuse("/dev/misc/fuse");
+	}
+#endif
+}
+
+static fuse_fstype get_fuse_fstype(void)
+{
+	char buf[256];
+	fuse_fstype fstype = FSTYPE_NONE;
+        
+	FILE *f = fopen("/proc/filesystems", "r");
+	if (!f) {
+		ntfs_log_perror("Failed to open /proc/filesystems");
+		return FSTYPE_UNKNOWN;
+	}
+        
+	while (fgets(buf, sizeof(buf), f)) {
+		if (strstr(buf, "fuseblk\n")) {
+			fstype = FSTYPE_FUSEBLK;
+			break;
+		}
+		if (strstr(buf, "fuse\n"))
+			fstype = FSTYPE_FUSE;
+	}
+        
+	fclose(f);
+	return fstype;
+}
+
+static fuse_fstype load_fuse_module(void)
+{
+	int i;
+	struct stat st;
+	pid_t pid;
+	const char *cmd = "/sbin/modprobe";
+	struct timespec req = { 0, 100000000 };   /* 100 msec */
+	fuse_fstype fstype;
+        
+	if (!stat(cmd, &st) && !geteuid()) {
+		pid = fork();
+		if (!pid) {
+			execl(cmd, cmd, "fuse", NULL);
+			_exit(1);
+		} else if (pid != -1)
+			waitpid(pid, NULL, 0);
+	}
+        
+	for (i = 0; i < 10; i++) {
+		/* 
+		 * We sleep first because despite the detection of the loaded
+		 * FUSE kernel module, fuse_mount() can still fail if it's not 
+		 * fully functional/initialized. Note, of course this is still
+		 * unreliable but usually helps.
+		 */  
+		nanosleep(&req, NULL);
+		fstype = get_fuse_fstype();
+		if (fstype != FSTYPE_NONE)
+			break;
+	}
+	return fstype;
+}
+
+#endif
+
+static struct fuse_chan *try_fuse_mount(char *parsed_options)
+{
+	struct fuse_chan *fc = NULL;
+	struct fuse_args margs = FUSE_ARGS_INIT(0, NULL);
+        
+	/* The fuse_mount() options get modified, so we always rebuild it */
+	if ((fuse_opt_add_arg(&margs, EXEC_NAME) == -1 ||
+	     fuse_opt_add_arg(&margs, "-o") == -1 ||
+	     fuse_opt_add_arg(&margs, parsed_options) == -1)) {
+		ntfs_log_error("Failed to set FUSE options.\n");
+		goto free_args;
+	}
+        
+	fc = fuse_mount(opts.mnt_point, &margs);
+free_args:
+	fuse_opt_free_args(&margs);
+	return fc;
+	        
+}
+	        
+static int set_fuseblk_options(char **parsed_options)
+{
+	char options[64];
+	long pagesize; 
+	u32 blksize = ctx->vol->cluster_size;
+        
+	pagesize = sysconf(_SC_PAGESIZE);
+	if (pagesize < 1)
+		pagesize = 4096;
+        
+	if (blksize > (u32)pagesize)
+		blksize = pagesize;
+        
+	snprintf(options, sizeof(options), ",blkdev,blksize=%u", blksize);
+	if (ntfs_strappend(parsed_options, options))
+		return -1;
+	return 0;
+}
+
+static struct fuse_session *mount_fuse(char *parsed_options)
+{
+	struct fuse_session *se = NULL;
+	struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
+        
+	ctx->fc = try_fuse_mount(parsed_options);
+	if (!ctx->fc)
+		return NULL;
+        
+	if (fuse_opt_add_arg(&args, "") == -1)
+		goto err;
+	if (ctx->debug)
+		if (fuse_opt_add_arg(&args, "-odebug") == -1)
+			goto err;
+        
+	se = fuse_lowlevel_new(&args , &ntfs_3g_ops, sizeof(ntfs_3g_ops), NULL);
+	if (!se)
+		goto err;
+        
+        
+	if (fuse_set_signal_handlers(se))
+		goto err_destroy;
+	fuse_session_add_chan(se, ctx->fc);
+out:
+	fuse_opt_free_args(&args);
+	return se;
+err_destroy:
+	fuse_session_destroy(se);
+	se = NULL;
+err:    
+	fuse_unmount(opts.mnt_point, ctx->fc);
+	goto out;
+}
+
+static void setup_logging(char *parsed_options)
+{
+	if (!ctx->no_detach) {
+		if (daemon(0, ctx->debug))
+			ntfs_log_error("Failed to daemonize.\n");
+		else if (!ctx->debug) {
+#ifndef DEBUG
+			ntfs_log_set_handler(ntfs_log_handler_syslog);
+			/* Override default libntfs identify. */
+			openlog(EXEC_NAME, LOG_PID, LOG_DAEMON);
+#endif
+		}
+	}
+
+	ctx->seccache = (struct PERMISSIONS_CACHE*)NULL;
+
+	ntfs_log_info("Version %s %s %d\n", VERSION, FUSE_TYPE, fuse_version());
+	if (strcmp(opts.arg_device,opts.device))
+		ntfs_log_info("Requested device %s canonicalized as %s\n",
+				opts.arg_device,opts.device);
+	ntfs_log_info("Mounted %s (%s, label \"%s\", NTFS %d.%d)\n",
+			opts.device, (ctx->ro) ? "Read-Only" : "Read-Write",
+			ctx->vol->vol_name, ctx->vol->major_ver,
+			ctx->vol->minor_ver);
+	ntfs_log_info("Cmdline options: %s\n", opts.options ? opts.options : "");
+	ntfs_log_info("Mount options: %s\n", parsed_options);
+}
+
+int main(int argc, char *argv[])
+{
+	char *parsed_options = NULL;
+	struct fuse_session *se;
+#if !(defined(__sun) && defined (__SVR4))
+	fuse_fstype fstype = FSTYPE_UNKNOWN;
+#endif
+	const char *permissions_mode = (const char*)NULL;
+	const char *failed_secure = (const char*)NULL;
+#if defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS)
+	struct XATTRMAPPING *xattr_mapping = (struct XATTRMAPPING*)NULL;
+#endif /* defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS) */
+	struct stat sbuf;
+	unsigned long existing_mount;
+	int err, fd;
+
+	/*
+	 * 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);
+
+#ifndef FUSE_INTERNAL
+	if ((getuid() != geteuid()) || (getgid() != getegid())) {
+		fprintf(stderr, "%s", setuid_msg);
+		return NTFS_VOLUME_INSECURE;
+	}
+#endif
+	if (drop_privs())
+		return NTFS_VOLUME_NO_PRIVILEGE;
+        
+	ntfs_set_locale();
+	ntfs_log_set_handler(ntfs_log_handler_stderr);
+
+	if (ntfs_parse_options(&opts, usage, argc, argv)) {
+		usage();
+		return NTFS_VOLUME_SYNTAX_ERROR;
+	}
+
+	if (ntfs_fuse_init()) {
+		err = NTFS_VOLUME_OUT_OF_MEMORY;
+		goto err2;
+	}
+        
+	parsed_options = parse_mount_options(ctx, &opts, TRUE);
+	if (!parsed_options) {
+		err = NTFS_VOLUME_SYNTAX_ERROR;
+		goto err_out;
+	}
+	if (!ntfs_check_if_mounted(opts.device,&existing_mount)
+	    && (existing_mount & NTFS_MF_MOUNTED)
+		/* accept multiple read-only mounts */
+	    && (!(existing_mount & NTFS_MF_READONLY) || !ctx->ro)) {
+		err = NTFS_VOLUME_LOCKED;
+		goto err_out;
+	}
+
+			/* need absolute mount point for junctions */
+	if (opts.mnt_point[0] == '/')
+		ctx->abs_mnt_point = strdup(opts.mnt_point);
+	else {
+		ctx->abs_mnt_point = (char*)ntfs_malloc(PATH_MAX);
+		if (ctx->abs_mnt_point) {
+			if (getcwd(ctx->abs_mnt_point,
+				     PATH_MAX - strlen(opts.mnt_point) - 1)) {
+				strcat(ctx->abs_mnt_point, "/");
+				strcat(ctx->abs_mnt_point, opts.mnt_point);
+#if defined(__sun) && defined (__SVR4)
+			/* Solaris also wants the absolute mount point */
+				opts.mnt_point = ctx->abs_mnt_point;
+#endif /* defined(__sun) && defined (__SVR4) */
+			}
+		}
+	}
+	if (!ctx->abs_mnt_point) {
+		err = NTFS_VOLUME_OUT_OF_MEMORY;
+		goto err_out;
+	}
+
+	ctx->security.uid = 0;
+	ctx->security.gid = 0;
+	if ((opts.mnt_point[0] == '/')
+	   && !stat(opts.mnt_point,&sbuf)) {
+		/* collect owner of mount point, useful for default mapping */
+		ctx->security.uid = sbuf.st_uid;
+		ctx->security.gid = sbuf.st_gid;
+	}
+
+#if defined(linux) || defined(__uClinux__)
+	fstype = get_fuse_fstype();
+
+	err = NTFS_VOLUME_NO_PRIVILEGE;
+	if (restore_privs())
+		goto err_out;
+
+	if (fstype == FSTYPE_NONE || fstype == FSTYPE_UNKNOWN)
+		fstype = load_fuse_module();
+	create_dev_fuse();
+
+	if (drop_privs())
+		goto err_out;
+#endif  
+	if (stat(opts.device, &sbuf)) {
+		ntfs_log_perror("Failed to access '%s'", opts.device);
+		err = NTFS_VOLUME_NO_PRIVILEGE;
+		goto err_out;
+	}
+
+#if !(defined(__sun) && defined (__SVR4))
+	/* Always use fuseblk for block devices unless it's surely missing. */
+	if (S_ISBLK(sbuf.st_mode) && (fstype != FSTYPE_FUSE))
+		ctx->blkdev = TRUE;
+#endif
+
+#ifndef FUSE_INTERNAL
+	if (getuid() && ctx->blkdev) {
+		ntfs_log_error("%s", unpriv_fuseblk_msg);
+		err = NTFS_VOLUME_NO_PRIVILEGE;
+		goto err2;
+	}
+#endif
+	err = ntfs_open(opts.device);
+	if (err)
+		goto err_out;
+        
+	/* Force read-only mount if the device was found read-only */
+	if (!ctx->ro && NVolReadOnly(ctx->vol)) {
+		ctx->ro = TRUE;
+		if (ntfs_strinsert(&parsed_options, ",ro")) 
+                	goto err_out;
+	}
+	/* We must do this after ntfs_open() to be able to set the blksize */
+	if (ctx->blkdev && set_fuseblk_options(&parsed_options))
+		goto err_out;
+
+	ctx->security.vol = ctx->vol;
+	ctx->vol->secure_flags = ctx->secure_flags;
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+	ctx->vol->efs_raw = ctx->efs_raw;
+#endif /* HAVE_SETXATTR */
+		/* JPA open $Secure, (whatever NTFS version !) */
+		/* to initialize security data */
+	if (ntfs_open_secure(ctx->vol) && (ctx->vol->major_ver >= 3))
+		failed_secure = "Could not open file $Secure";
+	if (!ntfs_build_mapping(&ctx->security,ctx->usermap_path,
+		(ctx->vol->secure_flags
+			& ((1 << SECURITY_DEFAULT) | (1 << SECURITY_ACL)))
+		&& !ctx->inherit
+		&& !(ctx->vol->secure_flags & (1 << SECURITY_WANTED)))) {
+#if POSIXACLS
+		/* use basic permissions if requested */
+		if (ctx->vol->secure_flags & (1 << SECURITY_DEFAULT))
+			permissions_mode = "User mapping built, Posix ACLs not used";
+		else {
+			permissions_mode = "User mapping built, Posix ACLs in use";
+#if KERNELACLS
+			if (ntfs_strinsert(&parsed_options,
+					",default_permissions,acl")) {
+				err = NTFS_VOLUME_SYNTAX_ERROR;
+				goto err_out;
+			}
+#endif /* KERNELACLS */
+		}
+#else /* POSIXACLS */
+		if (!(ctx->vol->secure_flags
+			& ((1 << SECURITY_DEFAULT) | (1 << SECURITY_ACL)))) {
+			/*
+			 * No explicit option but user mapping found
+			 * force default security
+			 */
+#if KERNELPERMS
+			ctx->vol->secure_flags |= (1 << SECURITY_DEFAULT);
+			if (ntfs_strinsert(&parsed_options, ",default_permissions")) {
+				err = NTFS_VOLUME_SYNTAX_ERROR;
+				goto err_out;
+			}
+#endif /* KERNELPERMS */
+		}
+		permissions_mode = "User mapping built";
+#endif /* POSIXACLS */
+		ctx->dmask = ctx->fmask = 0;
+	} else {
+		ctx->security.uid = ctx->uid;
+		ctx->security.gid = ctx->gid;
+		/* same ownership/permissions for all files */
+		ctx->security.mapping[MAPUSERS] = (struct MAPPING*)NULL;
+		ctx->security.mapping[MAPGROUPS] = (struct MAPPING*)NULL;
+		if ((ctx->vol->secure_flags & (1 << SECURITY_WANTED))
+		   && !(ctx->vol->secure_flags & (1 << SECURITY_DEFAULT))) {
+			ctx->vol->secure_flags |= (1 << SECURITY_DEFAULT);
+			if (ntfs_strinsert(&parsed_options, ",default_permissions")) {
+				err = NTFS_VOLUME_SYNTAX_ERROR;
+				goto err_out;
+			}
+		}
+		if (ctx->vol->secure_flags & (1 << SECURITY_DEFAULT)) {
+			ctx->vol->secure_flags |= (1 << SECURITY_RAW);
+			permissions_mode = "Global ownership and permissions enforced";
+		} else {
+			ctx->vol->secure_flags &= ~(1 << SECURITY_RAW);
+			permissions_mode = "Ownership and permissions disabled";
+		}
+	}
+	if (ctx->usermap_path)
+		free (ctx->usermap_path);
+
+#if defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS)
+	xattr_mapping = ntfs_xattr_build_mapping(ctx->vol,
+				ctx->xattrmap_path);
+	ctx->vol->xattr_mapping = xattr_mapping;
+	/*
+	 * Errors are logged, do not refuse mounting, it would be
+	 * too difficult to fix the unmountable mapping file.
+	 */
+	if (ctx->xattrmap_path)
+		free(ctx->xattrmap_path);
+#endif /* defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS) */
+
+	se = mount_fuse(parsed_options);
+	if (!se) {
+		err = NTFS_VOLUME_FUSE_ERROR;
+		goto err_out;
+	}
+        
+	ctx->mounted = TRUE;
+
+#if defined(linux) || defined(__uClinux__)
+	if (S_ISBLK(sbuf.st_mode) && (fstype == FSTYPE_FUSE))
+		ntfs_log_info("%s", fuse26_kmod_msg);
+#endif  
+	setup_logging(parsed_options);
+	if (failed_secure)
+		ntfs_log_info("%s\n",failed_secure);
+	if (permissions_mode)
+		ntfs_log_info("%s, configuration type %d\n",permissions_mode,
+			5 + POSIXACLS*6 - KERNELPERMS*3 + CACHEING);
+        
+	fuse_session_loop(se);
+	fuse_remove_signal_handlers(se);
+        
+	err = 0;
+
+	fuse_unmount(opts.mnt_point, ctx->fc);
+	fuse_session_destroy(se);
+err_out:
+	ntfs_mount_error(opts.device, opts.mnt_point, err);
+	if (ctx->abs_mnt_point)
+		free(ctx->abs_mnt_point);
+#if defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS)
+	ntfs_xattr_free_mapping(xattr_mapping);
+#endif /* defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS) */
+err2:
+	ntfs_close();
+	free(ctx);
+	free(parsed_options);
+	free(opts.options);
+	free(opts.device);
+	return err;
+}
+
diff --git a/src/ntfs-3g.8 b/src/ntfs-3g.8
new file mode 100755
index 0000000000000000000000000000000000000000..65b98be0f4870e5441d01fa010909129cdeb479d
--- /dev/null
+++ b/src/ntfs-3g.8
@@ -0,0 +1,465 @@
+.\" Copyright (c) 2005-2006 Yura Pakhuchiy.
+.\" Copyright (c) 2005 Richard Russon.
+.\" Copyright (c) 2006-2009 Szabolcs Szakacsits.
+.\" Copyright (c) 2009-2014 Jean-Pierre Andre
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFS-3G 8 "Mar 2014" "ntfs-3g 2015.3.14"
+.SH NAME
+ntfs-3g \- Third Generation Read/Write NTFS Driver
+.SH SYNOPSIS
+.B ntfs-3g
+\fB[-o \fIoption\fP\fB[,...]]\fR
+.I volume mount_point
+.br
+.B mount \-t ntfs-3g
+\fB[-o \fIoption\fP\fB[,...]]\fR
+.I volume mount_point
+.br
+.B lowntfs-3g
+\fB[-o \fIoption\fP\fB[,...]]\fR
+.I volume mount_point
+.br
+.B mount \-t lowntfs-3g
+\fB[-o \fIoption\fP\fB[,...]]\fR
+.I volume mount_point
+.SH DESCRIPTION
+\fBntfs-3g\fR is an NTFS driver, which can create, remove, rename, move
+files, directories, hard links, and streams; it can read and write files,
+including streams, sparse files and transparently compressed files; it can
+handle special files like symbolic links, devices, and FIFOs; moreover it
+provides standard management of file ownership and permissions, including
+POSIX ACLs.
+.PP
+It comes in two variants \fBntfs-3g\fR and \fBlowntfs-3g\fR with
+a few differences mentioned below in relevant options descriptions.
+.PP
+The \fIvolume\fR to be mounted can be either a block device or 
+an image file.
+.SS Windows hibernation and fast restarting
+On computers which can be dual-booted into Windows or Linux, Windows has
+to be fully shut down before booting into Linux, otherwise the NTFS file
+systems on internal disks may be left in an inconsistent state and changes
+made by Linux may be ignored by Windows.
+.P
+So, Windows may not be left in hibernation when starting Linux, in order
+to avoid inconsistencies. Moreover, the fast restart feature available on
+recent Windows systems has to be disabled. This can be achieved by issuing
+as an Administrator the Windows command which disables both
+hibernation and fast restarting :
+.RS
+.sp
+powercfg /h off
+.sp
+.RE
+.SS Access Handling and Security
+By default, files and directories are owned by the effective 
+user and group of the mounting process, and everybody has
+full read, write, execution and directory browsing permissions.
+You can also assign permissions to a single user by using the
+.B uid
+and/or the
+.B gid 
+options together with the 
+.B umask,
+or
+.B fmask
+and
+.B dmask
+options.
+.PP
+Doing so, Windows users have full access to the files created by 
+.B ntfs-3g.
+.PP
+But, by setting the \fBpermissions\fR option, you can benefit from the full
+ownership and permissions features as defined by POSIX. Moreover, by defining
+a Windows-to-Linux user mapping, the ownerships and permissions are even
+applied to Windows users and conversely.
+.PP
+If 
+.B ntfs-3g 
+is set setuid-root then non-root users will 
+be also able to mount volumes.
+.SS Windows Filename Compatibility
+NTFS supports several filename namespaces: DOS, Win32 and POSIX. While the
+\fBntfs-3g\fR driver handles all of them, it always creates new files in the 
+POSIX namespace for maximum portability and interoperability reasons. 
+This means that filenames are case sensitive and all characters are
+allowed except '/' and '\\0'. This is perfectly legal on Windows, though
+some application may get confused. The option \fBwindows_names\fP may be
+used to apply Windows restrictions to new file names.
+.SS Alternate Data Streams (ADS)
+NTFS stores all data in streams. Every file has exactly one unnamed
+data stream and can have many named data streams.  The size of a file is the
+size of its unnamed data stream.  By default, \fBntfs-3g\fR will only read
+the unnamed data stream.
+.PP
+By using the options "streams_interface=windows", with the ntfs-3g driver
+(not possible with lowntfs-3g), you will be able to read any named data
+streams, simply by specifying the stream's name after a colon.
+For example:
+.RS
+.sp
+cat some.mp3:artist
+.sp
+.RE
+Named data streams act like normal files, so you can read from them, write to
+them and even delete them (using rm).  You can list all the named data streams
+a file has by getting the "ntfs.streams.list" extended attribute.
+.SH OPTIONS
+Below is a summary of the options that \fBntfs-3g\fR accepts.
+.TP
+\fBuid=\fP\fIvalue\fP and \fBgid=\fP\fIvalue\fP
+Set the owner and the group of files and directories. The values are numerical.
+The defaults are the uid and gid of the current process.
+.TP
+.BI umask= value
+Set the  bitmask of the file and directory permissions that are not
+present. The value is given in octal. The default value is 0 which
+means full access to everybody.
+.TP
+.BI fmask= value
+Set the  bitmask of the file permissions that are not present. 
+The value is given in octal. The default value is 0 which
+means full access to everybody.
+.TP
+.BI dmask= value
+Set the  bitmask of the directory permissions that are not
+present. The value is given in octal. The default value is 0 which
+means full access to everybody.
+.TP
+.BI usermapping= file-name
+Use file \fIfile-name\fP as the user mapping file instead of the default
+\fB.NTFS-3G/UserMapping\fP. If \fIfile-name\fP defines a full path, the
+file must be located on a partition previously mounted. If it defines a
+relative path, it is interpreted relative to the root of NTFS partition
+being mounted.
+.P
+.RS
+When a user mapping file is defined, the options \fBuid=\fP, \fBgid=\fP,
+\fBumask=\fP, \fBfmask=\fP, \fBdmask=\fP and \fBsilent\fP are ignored.
+.RE
+.TP
+.B permissions
+Set standard permissions on created files and use standard access control.
+This option is set by default when a user mapping file is present.
+.TP
+.B acl
+Enable setting Posix ACLs on created files and use them for access control.
+This option is only available on specific builds. It is set by default
+when a user mapping file is present and the
+.B permissions
+mount option is not set.
+.TP
+.B inherit
+When creating a new file, set its initial protections
+according to inheritance rules defined in parent directory. These rules
+deviate from Posix specifications, but yield a better Windows
+compatibility. The \fBpermissions\fR option or a valid user mapping file
+is required for this option to be effective.
+.TP
+.B ro
+Mount filesystem read\-only. Useful if Windows is hibernated or the
+NTFS journal file is unclean.
+.TP
+.BI locale= value
+This option can be useful when wanting a language specific locale environment.
+It is however discouraged as it leads to files with untranslatable chars
+to not be visible.
+.TP
+.B force
+This option is obsolete. It has been superseded by the \fBrecover\fR and
+\fBnorecover\fR options.
+.TP
+.B recover
+Recover and try to mount a partition which was not unmounted properly by
+Windows. The Windows logfile is cleared, which may cause inconsistencies.
+Currently this is the default option.
+.TP
+.B norecover
+Do not try to mount a partition which was not unmounted properly by Windows.
+.TP
+.B ignore_case \fP(only with lowntfs-3g)
+Ignore character case when accessing a file (\fBFOO\fR, \fBFoo\fR, \fBfoo\fR,
+etc. designate the same file). All files are displayed with lower case in
+directory listings.
+.TP
+.B remove_hiberfile
+Unlike in case of read-only mount, the read-write mount is denied if 
+the NTFS volume is hibernated. One needs either to resume Windows and
+shutdown it properly, or use this option which will remove the Windows
+hibernation file. Please note, this means that the saved Windows 
+session will be completely lost. Use this option under your own 
+responsibility.
+.TP
+.B atime, noatime, relatime
+The 
+.B atime 
+option updates inode access time for each access.
+
+The 
+.B noatime 
+option disables inode access time updates which can speed up
+file operations and prevent sleeping (notebook) disks spinning 
+up too often thus saving energy and disk lifetime.
+
+The
+.B relatime 
+option is very similar to 
+.B noatime. 
+It updates inode access times relative to modify or change time. 
+The access time is only updated if the previous access time was earlier 
+than the current modify or change time. Unlike
+.B noatime
+this option doesn't break applications that need to know 
+if a file has been read since the last time it was modified.
+This is the default behaviour.
+.TP
+.B delay_mtime[= value]
+Only update the file modification time and the file change time of a file
+when it is closed or when the indicated delay since the previous update has
+elapsed. The argument is a number of seconds, with a default value of 60.
+This is mainly useful for big files which are kept open for a long
+time and written to without changing their size, such as databases or file
+system images mounted as loop.
+.TP
+.B show_sys_files
+Show the metafiles in directory listings. Otherwise the default behaviour is
+to hide the metafiles, which are special files used to store the NTFS
+structure. Please note that even when this option is specified, "$MFT" may
+not be visible due to a glibc bug. Furthermore, irrespectively of
+show_sys_files, all files are accessible by name, for example you can always
+do
+"ls \-l '$UpCase'".
+.TP
+.B hide_hid_files
+Hide the hidden files and directories in directory listings, the hidden files
+and directories being the ones whose NTFS attribute have the hidden flag set.
+The hidden files will not be selected when using wildcards in commands,
+but all files and directories remain accessible by full name, for example you
+can always display the Windows trash bin directory by :
+"ls \-ld '$RECYCLE.BIN'".
+.TP
+.B hide_dot_files
+Set the hidden flag in the NTFS attribute for created files and directories
+whose first character of the name is a dot. Such files and directories
+normally do not appear in directory listings, and when the flag is set
+they do not appear in Windows directory displays either.
+When a file is renamed or linked with a new name, the hidden flag is
+adjusted to the latest name.
+.TP
+.B windows_names
+This option prevents files, directories and extended attributes to be
+created with a name not allowed by windows, because
+.RS
+.RS
+.sp
+- it contains some not allowed character,
+.br
+- or the last character is a space or a dot,
+.br
+- or the name is reserved.
+.sp
+.RE
+The forbidden characters are the nine characters " * / : < > ? \\ | and
+those whose code is less than 0x20, and
+the reserved names are CON, PRN, AUX, NUL, COM1..COM9, LPT1..LPT9,
+with no suffix or followed by a dot.
+.sp
+Existing such files can still be read (and renamed).
+.RE
+.TP
+.B allow_other
+This option overrides the security measure restricting file access
+to the user mounting the filesystem. This option is only
+allowed to root, but this restriction can be overridden by
+the 'user_allow_other' option in the /etc/fuse.conf file.
+.TP
+.BI max_read= value
+With this option the maximum size of read operations can be set.
+The default is infinite.  Note that the size of read requests is
+limited anyway to 32 pages (which is 128kbyte on i386).
+.TP
+.B silent
+Do nothing, without returning any error, on chmod and chown operations
+and on permission checking errors,
+when the \fBpermissions\fR option is not set and no user mapping file
+is defined. This option is on by default, and when set off (through option
+\fBno_def_opts\fR) ownership and permissions parameters have to be set.
+.TP
+.B no_def_opts
+By default ntfs-3g acts as if "silent" (ignore permission errors when
+permissions are not enabled),
+"allow_other" (allow any user to access files) and "nonempty"
+(allow mounting on non-empty directories) were set, and "no_def_opts"
+cancels these default options.
+.TP
+.BI streams_interface= value
+This option controls how the user can access Alternate Data Streams (ADS) or
+in other words, named data streams. It can be set to, one of \fBnone\fR,
+\fBwindows\fR or \fBxattr\fR. If the option is set to \fBnone\fR, the user
+will have no access to the named data streams. If it is set to \fBwindows\fR
+(not possible with lowntfs-3g), then the user can access them just like in
+Windows (eg. cat file:stream). If it's set to \fBxattr\fR, then the named
+data streams are mapped to xattrs and user can manipulate them using
+\fB{get,set}fattr\fR utilities. The default is \fBxattr\fR.
+.TP
+.B user_xattr
+Same as \fBstreams_interface=\fP\fIxattr\fP.
+.TP
+.B efs_raw
+This option should only be used in backup or restore situation.
+It changes the apparent size of files and the behavior of read and
+write operation so that encrypted files can be saved and restored
+without being decrypted. The \fBuser.ntfs.efsinfo\fP extended attribute
+has also to be saved and restored for the file to be decrypted.
+.TP
+.B compression
+This option enables creating new transparently compressed files in
+directories marked for compression. A directory is marked for compression by
+setting the bit 11 (value 0x00000800) in its Windows attribute. In such a
+directory, new files are created compressed and new subdirectories are
+themselves marked for compression. The option and the flag have no effect
+on existing files. Currently this is the default option.
+.TP
+.B nocompression
+This option disables creating new transparently compressed files in directories
+marked for compression. Existing compressed files can still be read and
+updated.
+.TP
+.B big_writes
+This option prevents fuse from splitting write buffers into 4K chunks,
+enabling big write buffers to be transferred from the application in a
+single step (up to some system limit, generally 128K bytes).
+.TP
+.B debug
+Makes ntfs-3g to print a lot of debug output from libntfs-3g and FUSE.
+.TP
+.B no_detach
+Makes ntfs-3g to not detach from terminal and print some debug output.
+.SH USER MAPPING
+NTFS uses specific ids to record the ownership of files instead of
+the \fBuid\fP and \fBgid\fP used by Linux. As a consequence a mapping
+between the ids has to be defined for ownerships to be recorded into
+NTFS and recognized.
+.P
+By default, this mapping is fetched from the file \fB.NTFS-3G/UserMapping\fP
+located in the NTFS partition. The option \fBusermapping=\fP may be used
+to define another location. When the option permissions is set and
+no mapping file is found, a default mapping is used.
+.P
+Each line in the user mapping file defines a mapping. It is organized
+in three fields separated by colons. The first field identifies a \fBuid\fP,
+the second field identifies a \fBgid\fP and the third one identifies the
+corresponding NTFS id, known as a \fBSID\fP. The \fBuid\fP and the \fBgid\fP
+are optional and defining both of them for the same \fBSID\fP is not
+recommended.
+.P
+If no interoperation with Windows is needed, you can use the option
+\fBpermissions\fP to define a standard mapping. Alternately, you may define
+your own mapping by setting a single default mapping with no uid and gid. In
+both cases, files created on Linux will appear to Windows as owned by a
+foreign user, and files created on Windows will appear to Linux as owned by
+root. Just copy the example below and replace the 9 and 10-digit numbers by
+any number not greater than 4294967295. The resulting behavior is the same as
+the one with the option permission set with no ownership option and no user
+mapping file available.
+.RS
+.sp
+.B ::S-1-5-21-3141592653-589793238-462643383-10000
+.sp
+.RE
+If a strong interoperation with Windows is needed, the mapping has to be
+defined for each user and group known in both system, and the \fBSID\fPs used
+by Windows has to be collected. This will lead to a user mapping file like :
+.RS
+.sp
+.B john::S-1-5-21-3141592653-589793238-462643383-1008
+.B mary::S-1-5-21-3141592653-589793238-462643383-1009
+.B :smith:S-1-5-21-3141592653-589793238-462643383-513
+.B ::S-1-5-21-3141592653-589793238-462643383-10000
+.sp
+.RE
+.P
+The utility \fBntfs-3g.usermap\fP may be used to create such a user
+mapping file.
+.SH EXAMPLES
+Mount /dev/sda1 to /mnt/windows:
+.RS
+.sp
+.B ntfs-3g /dev/sda1 /mnt/windows
+.RE
+or
+.RS
+.B mount -t ntfs-3g /dev/sda1 /mnt/windows
+.sp
+.RE
+Mount the ntfs data partition /dev/sda3 to /mnt/data with standard Linux
+permissions applied :
+.RS
+.sp
+.B ntfs-3g -o permissions /dev/sda3 /mnt/data
+.RE
+or
+.RS
+.B mount -t ntfs-3g -o permissions /dev/sda3 /mnt/data
+.sp
+.RE
+Read\-only mount /dev/sda5 to /home/user/mnt and make user with uid 1000 
+to be the owner of all files:
+.RS
+.sp
+.B ntfs-3g /dev/sda5 /home/user/mnt \-o ro,uid=1000
+.sp
+.RE
+/etc/fstab entry for the above (the sixth and last field has to be zero to
+avoid a file system check at boot time) :
+.RS
+.sp
+.B /dev/sda5 /home/user/mnt ntfs\-3g ro,uid=1000 0 0
+.sp
+.RE
+Unmount /mnt/windows:
+.RS
+.sp
+.B umount /mnt/windows
+.sp
+.RE
+.SH EXIT CODES
+To facilitate the use of the
+.B ntfs-3g
+driver in scripts, an exit code is returned to give an indication of the 
+mountability status of a volume. Value 0 means success, and all other
+ones mean an error. The unique error codes are documented in the
+.BR ntfs-3g.probe (8)
+manual page.
+.SH KNOWN ISSUES
+Please see 
+.RS
+.sp
+http://www.tuxera.com/support/
+.sp
+.RE
+for common questions and known issues.
+If you would find a new one in the latest release of
+the software then please send an email describing it
+in detail. You can contact the 
+development team on the ntfs\-3g\-devel@lists.sf.net
+address.
+.SH AUTHORS
+.B ntfs-3g 
+was based on and a major improvement to ntfsmount and libntfs which were
+written by Yura Pakhuchiy and the Linux-NTFS team. The improvements were 
+made, the ntfs-3g project was initiated and currently led by long time 
+Linux-NTFS team developer Szabolcs Szakacsits (szaka@tuxera.com).
+.SH THANKS
+Several people made heroic efforts, often over five or more
+years which resulted the ntfs-3g driver. Most importantly they are 
+Anton Altaparmakov, Jean-Pierre André, Richard Russon, Szabolcs Szakacsits,
+Yura Pakhuchiy, Yuval Fledel, and the author of the groundbreaking FUSE
+filesystem development framework, Miklos Szeredi.
+.SH SEE ALSO
+.BR ntfs-3g.probe (8),
+.BR ntfsprogs (8),
+.BR attr (5),
+.BR getfattr (1)
diff --git a/src/ntfs-3g.8.in b/src/ntfs-3g.8.in
new file mode 100755
index 0000000000000000000000000000000000000000..57fffc962c9571e89da17b295a1bae738c0833bb
--- /dev/null
+++ b/src/ntfs-3g.8.in
@@ -0,0 +1,465 @@
+.\" Copyright (c) 2005-2006 Yura Pakhuchiy.
+.\" Copyright (c) 2005 Richard Russon.
+.\" Copyright (c) 2006-2009 Szabolcs Szakacsits.
+.\" Copyright (c) 2009-2014 Jean-Pierre Andre
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFS-3G 8 "Mar 2014" "ntfs-3g @VERSION@"
+.SH NAME
+ntfs-3g \- Third Generation Read/Write NTFS Driver
+.SH SYNOPSIS
+.B ntfs-3g
+\fB[-o \fIoption\fP\fB[,...]]\fR
+.I volume mount_point
+.br
+.B mount \-t ntfs-3g
+\fB[-o \fIoption\fP\fB[,...]]\fR
+.I volume mount_point
+.br
+.B lowntfs-3g
+\fB[-o \fIoption\fP\fB[,...]]\fR
+.I volume mount_point
+.br
+.B mount \-t lowntfs-3g
+\fB[-o \fIoption\fP\fB[,...]]\fR
+.I volume mount_point
+.SH DESCRIPTION
+\fBntfs-3g\fR is an NTFS driver, which can create, remove, rename, move
+files, directories, hard links, and streams; it can read and write files,
+including streams, sparse files and transparently compressed files; it can
+handle special files like symbolic links, devices, and FIFOs; moreover it
+provides standard management of file ownership and permissions, including
+POSIX ACLs.
+.PP
+It comes in two variants \fBntfs-3g\fR and \fBlowntfs-3g\fR with
+a few differences mentioned below in relevant options descriptions.
+.PP
+The \fIvolume\fR to be mounted can be either a block device or 
+an image file.
+.SS Windows hibernation and fast restarting
+On computers which can be dual-booted into Windows or Linux, Windows has
+to be fully shut down before booting into Linux, otherwise the NTFS file
+systems on internal disks may be left in an inconsistent state and changes
+made by Linux may be ignored by Windows.
+.P
+So, Windows may not be left in hibernation when starting Linux, in order
+to avoid inconsistencies. Moreover, the fast restart feature available on
+recent Windows systems has to be disabled. This can be achieved by issuing
+as an Administrator the Windows command which disables both
+hibernation and fast restarting :
+.RS
+.sp
+powercfg /h off
+.sp
+.RE
+.SS Access Handling and Security
+By default, files and directories are owned by the effective 
+user and group of the mounting process, and everybody has
+full read, write, execution and directory browsing permissions.
+You can also assign permissions to a single user by using the
+.B uid
+and/or the
+.B gid 
+options together with the 
+.B umask,
+or
+.B fmask
+and
+.B dmask
+options.
+.PP
+Doing so, Windows users have full access to the files created by 
+.B ntfs-3g.
+.PP
+But, by setting the \fBpermissions\fR option, you can benefit from the full
+ownership and permissions features as defined by POSIX. Moreover, by defining
+a Windows-to-Linux user mapping, the ownerships and permissions are even
+applied to Windows users and conversely.
+.PP
+If 
+.B ntfs-3g 
+is set setuid-root then non-root users will 
+be also able to mount volumes.
+.SS Windows Filename Compatibility
+NTFS supports several filename namespaces: DOS, Win32 and POSIX. While the
+\fBntfs-3g\fR driver handles all of them, it always creates new files in the 
+POSIX namespace for maximum portability and interoperability reasons. 
+This means that filenames are case sensitive and all characters are
+allowed except '/' and '\\0'. This is perfectly legal on Windows, though
+some application may get confused. The option \fBwindows_names\fP may be
+used to apply Windows restrictions to new file names.
+.SS Alternate Data Streams (ADS)
+NTFS stores all data in streams. Every file has exactly one unnamed
+data stream and can have many named data streams.  The size of a file is the
+size of its unnamed data stream.  By default, \fBntfs-3g\fR will only read
+the unnamed data stream.
+.PP
+By using the options "streams_interface=windows", with the ntfs-3g driver
+(not possible with lowntfs-3g), you will be able to read any named data
+streams, simply by specifying the stream's name after a colon.
+For example:
+.RS
+.sp
+cat some.mp3:artist
+.sp
+.RE
+Named data streams act like normal files, so you can read from them, write to
+them and even delete them (using rm).  You can list all the named data streams
+a file has by getting the "ntfs.streams.list" extended attribute.
+.SH OPTIONS
+Below is a summary of the options that \fBntfs-3g\fR accepts.
+.TP
+\fBuid=\fP\fIvalue\fP and \fBgid=\fP\fIvalue\fP
+Set the owner and the group of files and directories. The values are numerical.
+The defaults are the uid and gid of the current process.
+.TP
+.BI umask= value
+Set the  bitmask of the file and directory permissions that are not
+present. The value is given in octal. The default value is 0 which
+means full access to everybody.
+.TP
+.BI fmask= value
+Set the  bitmask of the file permissions that are not present. 
+The value is given in octal. The default value is 0 which
+means full access to everybody.
+.TP
+.BI dmask= value
+Set the  bitmask of the directory permissions that are not
+present. The value is given in octal. The default value is 0 which
+means full access to everybody.
+.TP
+.BI usermapping= file-name
+Use file \fIfile-name\fP as the user mapping file instead of the default
+\fB.NTFS-3G/UserMapping\fP. If \fIfile-name\fP defines a full path, the
+file must be located on a partition previously mounted. If it defines a
+relative path, it is interpreted relative to the root of NTFS partition
+being mounted.
+.P
+.RS
+When a user mapping file is defined, the options \fBuid=\fP, \fBgid=\fP,
+\fBumask=\fP, \fBfmask=\fP, \fBdmask=\fP and \fBsilent\fP are ignored.
+.RE
+.TP
+.B permissions
+Set standard permissions on created files and use standard access control.
+This option is set by default when a user mapping file is present.
+.TP
+.B acl
+Enable setting Posix ACLs on created files and use them for access control.
+This option is only available on specific builds. It is set by default
+when a user mapping file is present and the
+.B permissions
+mount option is not set.
+.TP
+.B inherit
+When creating a new file, set its initial protections
+according to inheritance rules defined in parent directory. These rules
+deviate from Posix specifications, but yield a better Windows
+compatibility. The \fBpermissions\fR option or a valid user mapping file
+is required for this option to be effective.
+.TP
+.B ro
+Mount filesystem read\-only. Useful if Windows is hibernated or the
+NTFS journal file is unclean.
+.TP
+.BI locale= value
+This option can be useful when wanting a language specific locale environment.
+It is however discouraged as it leads to files with untranslatable chars
+to not be visible.
+.TP
+.B force
+This option is obsolete. It has been superseded by the \fBrecover\fR and
+\fBnorecover\fR options.
+.TP
+.B recover
+Recover and try to mount a partition which was not unmounted properly by
+Windows. The Windows logfile is cleared, which may cause inconsistencies.
+Currently this is the default option.
+.TP
+.B norecover
+Do not try to mount a partition which was not unmounted properly by Windows.
+.TP
+.B ignore_case \fP(only with lowntfs-3g)
+Ignore character case when accessing a file (\fBFOO\fR, \fBFoo\fR, \fBfoo\fR,
+etc. designate the same file). All files are displayed with lower case in
+directory listings.
+.TP
+.B remove_hiberfile
+Unlike in case of read-only mount, the read-write mount is denied if 
+the NTFS volume is hibernated. One needs either to resume Windows and
+shutdown it properly, or use this option which will remove the Windows
+hibernation file. Please note, this means that the saved Windows 
+session will be completely lost. Use this option under your own 
+responsibility.
+.TP
+.B atime, noatime, relatime
+The 
+.B atime 
+option updates inode access time for each access.
+
+The 
+.B noatime 
+option disables inode access time updates which can speed up
+file operations and prevent sleeping (notebook) disks spinning 
+up too often thus saving energy and disk lifetime.
+
+The
+.B relatime 
+option is very similar to 
+.B noatime. 
+It updates inode access times relative to modify or change time. 
+The access time is only updated if the previous access time was earlier 
+than the current modify or change time. Unlike
+.B noatime
+this option doesn't break applications that need to know 
+if a file has been read since the last time it was modified.
+This is the default behaviour.
+.TP
+.B delay_mtime[= value]
+Only update the file modification time and the file change time of a file
+when it is closed or when the indicated delay since the previous update has
+elapsed. The argument is a number of seconds, with a default value of 60.
+This is mainly useful for big files which are kept open for a long
+time and written to without changing their size, such as databases or file
+system images mounted as loop.
+.TP
+.B show_sys_files
+Show the metafiles in directory listings. Otherwise the default behaviour is
+to hide the metafiles, which are special files used to store the NTFS
+structure. Please note that even when this option is specified, "$MFT" may
+not be visible due to a glibc bug. Furthermore, irrespectively of
+show_sys_files, all files are accessible by name, for example you can always
+do
+"ls \-l '$UpCase'".
+.TP
+.B hide_hid_files
+Hide the hidden files and directories in directory listings, the hidden files
+and directories being the ones whose NTFS attribute have the hidden flag set.
+The hidden files will not be selected when using wildcards in commands,
+but all files and directories remain accessible by full name, for example you
+can always display the Windows trash bin directory by :
+"ls \-ld '$RECYCLE.BIN'".
+.TP
+.B hide_dot_files
+Set the hidden flag in the NTFS attribute for created files and directories
+whose first character of the name is a dot. Such files and directories
+normally do not appear in directory listings, and when the flag is set
+they do not appear in Windows directory displays either.
+When a file is renamed or linked with a new name, the hidden flag is
+adjusted to the latest name.
+.TP
+.B windows_names
+This option prevents files, directories and extended attributes to be
+created with a name not allowed by windows, because
+.RS
+.RS
+.sp
+- it contains some not allowed character,
+.br
+- or the last character is a space or a dot,
+.br
+- or the name is reserved.
+.sp
+.RE
+The forbidden characters are the nine characters " * / : < > ? \\ | and
+those whose code is less than 0x20, and
+the reserved names are CON, PRN, AUX, NUL, COM1..COM9, LPT1..LPT9,
+with no suffix or followed by a dot.
+.sp
+Existing such files can still be read (and renamed).
+.RE
+.TP
+.B allow_other
+This option overrides the security measure restricting file access
+to the user mounting the filesystem. This option is only
+allowed to root, but this restriction can be overridden by
+the 'user_allow_other' option in the /etc/fuse.conf file.
+.TP
+.BI max_read= value
+With this option the maximum size of read operations can be set.
+The default is infinite.  Note that the size of read requests is
+limited anyway to 32 pages (which is 128kbyte on i386).
+.TP
+.B silent
+Do nothing, without returning any error, on chmod and chown operations
+and on permission checking errors,
+when the \fBpermissions\fR option is not set and no user mapping file
+is defined. This option is on by default, and when set off (through option
+\fBno_def_opts\fR) ownership and permissions parameters have to be set.
+.TP
+.B no_def_opts
+By default ntfs-3g acts as if "silent" (ignore permission errors when
+permissions are not enabled),
+"allow_other" (allow any user to access files) and "nonempty"
+(allow mounting on non-empty directories) were set, and "no_def_opts"
+cancels these default options.
+.TP
+.BI streams_interface= value
+This option controls how the user can access Alternate Data Streams (ADS) or
+in other words, named data streams. It can be set to, one of \fBnone\fR,
+\fBwindows\fR or \fBxattr\fR. If the option is set to \fBnone\fR, the user
+will have no access to the named data streams. If it is set to \fBwindows\fR
+(not possible with lowntfs-3g), then the user can access them just like in
+Windows (eg. cat file:stream). If it's set to \fBxattr\fR, then the named
+data streams are mapped to xattrs and user can manipulate them using
+\fB{get,set}fattr\fR utilities. The default is \fBxattr\fR.
+.TP
+.B user_xattr
+Same as \fBstreams_interface=\fP\fIxattr\fP.
+.TP
+.B efs_raw
+This option should only be used in backup or restore situation.
+It changes the apparent size of files and the behavior of read and
+write operation so that encrypted files can be saved and restored
+without being decrypted. The \fBuser.ntfs.efsinfo\fP extended attribute
+has also to be saved and restored for the file to be decrypted.
+.TP
+.B compression
+This option enables creating new transparently compressed files in
+directories marked for compression. A directory is marked for compression by
+setting the bit 11 (value 0x00000800) in its Windows attribute. In such a
+directory, new files are created compressed and new subdirectories are
+themselves marked for compression. The option and the flag have no effect
+on existing files. Currently this is the default option.
+.TP
+.B nocompression
+This option disables creating new transparently compressed files in directories
+marked for compression. Existing compressed files can still be read and
+updated.
+.TP
+.B big_writes
+This option prevents fuse from splitting write buffers into 4K chunks,
+enabling big write buffers to be transferred from the application in a
+single step (up to some system limit, generally 128K bytes).
+.TP
+.B debug
+Makes ntfs-3g to print a lot of debug output from libntfs-3g and FUSE.
+.TP
+.B no_detach
+Makes ntfs-3g to not detach from terminal and print some debug output.
+.SH USER MAPPING
+NTFS uses specific ids to record the ownership of files instead of
+the \fBuid\fP and \fBgid\fP used by Linux. As a consequence a mapping
+between the ids has to be defined for ownerships to be recorded into
+NTFS and recognized.
+.P
+By default, this mapping is fetched from the file \fB.NTFS-3G/UserMapping\fP
+located in the NTFS partition. The option \fBusermapping=\fP may be used
+to define another location. When the option permissions is set and
+no mapping file is found, a default mapping is used.
+.P
+Each line in the user mapping file defines a mapping. It is organized
+in three fields separated by colons. The first field identifies a \fBuid\fP,
+the second field identifies a \fBgid\fP and the third one identifies the
+corresponding NTFS id, known as a \fBSID\fP. The \fBuid\fP and the \fBgid\fP
+are optional and defining both of them for the same \fBSID\fP is not
+recommended.
+.P
+If no interoperation with Windows is needed, you can use the option
+\fBpermissions\fP to define a standard mapping. Alternately, you may define
+your own mapping by setting a single default mapping with no uid and gid. In
+both cases, files created on Linux will appear to Windows as owned by a
+foreign user, and files created on Windows will appear to Linux as owned by
+root. Just copy the example below and replace the 9 and 10-digit numbers by
+any number not greater than 4294967295. The resulting behavior is the same as
+the one with the option permission set with no ownership option and no user
+mapping file available.
+.RS
+.sp
+.B ::S-1-5-21-3141592653-589793238-462643383-10000
+.sp
+.RE
+If a strong interoperation with Windows is needed, the mapping has to be
+defined for each user and group known in both system, and the \fBSID\fPs used
+by Windows has to be collected. This will lead to a user mapping file like :
+.RS
+.sp
+.B john::S-1-5-21-3141592653-589793238-462643383-1008
+.B mary::S-1-5-21-3141592653-589793238-462643383-1009
+.B :smith:S-1-5-21-3141592653-589793238-462643383-513
+.B ::S-1-5-21-3141592653-589793238-462643383-10000
+.sp
+.RE
+.P
+The utility \fBntfs-3g.usermap\fP may be used to create such a user
+mapping file.
+.SH EXAMPLES
+Mount /dev/sda1 to /mnt/windows:
+.RS
+.sp
+.B ntfs-3g /dev/sda1 /mnt/windows
+.RE
+or
+.RS
+.B mount -t ntfs-3g /dev/sda1 /mnt/windows
+.sp
+.RE
+Mount the ntfs data partition /dev/sda3 to /mnt/data with standard Linux
+permissions applied :
+.RS
+.sp
+.B ntfs-3g -o permissions /dev/sda3 /mnt/data
+.RE
+or
+.RS
+.B mount -t ntfs-3g -o permissions /dev/sda3 /mnt/data
+.sp
+.RE
+Read\-only mount /dev/sda5 to /home/user/mnt and make user with uid 1000 
+to be the owner of all files:
+.RS
+.sp
+.B ntfs-3g /dev/sda5 /home/user/mnt \-o ro,uid=1000
+.sp
+.RE
+/etc/fstab entry for the above (the sixth and last field has to be zero to
+avoid a file system check at boot time) :
+.RS
+.sp
+.B /dev/sda5 /home/user/mnt ntfs\-3g ro,uid=1000 0 0
+.sp
+.RE
+Unmount /mnt/windows:
+.RS
+.sp
+.B umount /mnt/windows
+.sp
+.RE
+.SH EXIT CODES
+To facilitate the use of the
+.B ntfs-3g
+driver in scripts, an exit code is returned to give an indication of the 
+mountability status of a volume. Value 0 means success, and all other
+ones mean an error. The unique error codes are documented in the
+.BR ntfs-3g.probe (8)
+manual page.
+.SH KNOWN ISSUES
+Please see 
+.RS
+.sp
+http://www.tuxera.com/support/
+.sp
+.RE
+for common questions and known issues.
+If you would find a new one in the latest release of
+the software then please send an email describing it
+in detail. You can contact the 
+development team on the ntfs\-3g\-devel@lists.sf.net
+address.
+.SH AUTHORS
+.B ntfs-3g 
+was based on and a major improvement to ntfsmount and libntfs which were
+written by Yura Pakhuchiy and the Linux-NTFS team. The improvements were 
+made, the ntfs-3g project was initiated and currently led by long time 
+Linux-NTFS team developer Szabolcs Szakacsits (szaka@tuxera.com).
+.SH THANKS
+Several people made heroic efforts, often over five or more
+years which resulted the ntfs-3g driver. Most importantly they are 
+Anton Altaparmakov, Jean-Pierre André, Richard Russon, Szabolcs Szakacsits,
+Yura Pakhuchiy, Yuval Fledel, and the author of the groundbreaking FUSE
+filesystem development framework, Miklos Szeredi.
+.SH SEE ALSO
+.BR ntfs-3g.probe (8),
+.BR ntfsprogs (8),
+.BR attr (5),
+.BR getfattr (1)
diff --git a/src/ntfs-3g.c b/src/ntfs-3g.c
new file mode 100755
index 0000000000000000000000000000000000000000..de0f920eeee023294d50f07edd3d75fb9f17ae3a
--- /dev/null
+++ b/src/ntfs-3g.c
@@ -0,0 +1,4013 @@
+/**
+ * ntfs-3g - Third Generation NTFS Driver
+ *
+ * Copyright (c) 2005-2007 Yura Pakhuchiy
+ * Copyright (c) 2005 Yuval Fledel
+ * Copyright (c) 2006-2009 Szabolcs Szakacsits
+ * Copyright (c) 2007-2015 Jean-Pierre Andre
+ * Copyright (c) 2009 Erik Larsson
+ *
+ * This file is originated from the Linux-NTFS project.
+ *
+ * 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
+ */
+
+#include "config.h"
+
+#include <fuse.h>
+
+#if !defined(FUSE_VERSION) || (FUSE_VERSION < 26)
+#error "***********************************************************"
+#error "*                                                         *"
+#error "*     Compilation requires at least FUSE version 2.6.0!   *"
+#error "*                                                         *"
+#error "***********************************************************"
+#endif
+
+#ifdef HAVE_STDIO_H
+#include <stdio.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_LOCALE_H
+#include <locale.h>
+#endif
+#include <signal.h>
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#include <syslog.h>
+#include <sys/wait.h>
+
+#ifdef HAVE_SETXATTR
+#include <sys/xattr.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_MKDEV_H
+#include <sys/mkdev.h>
+#endif
+
+#if defined(__APPLE__) || defined(__DARWIN__)
+#include <sys/dirent.h>
+#elif defined(__sun) && defined (__SVR4)
+#include <sys/param.h>
+#endif /* defined(__APPLE__) || defined(__DARWIN__), ... */
+
+#include "compat.h"
+#include "attrib.h"
+#include "inode.h"
+#include "volume.h"
+#include "dir.h"
+#include "unistr.h"
+#include "layout.h"
+#include "index.h"
+#include "ntfstime.h"
+#include "security.h"
+#include "reparse.h"
+#include "object_id.h"
+#include "efs.h"
+#include "logging.h"
+#include "xattrs.h"
+#include "misc.h"
+#include "ioctl.h"
+
+#include "ntfs-3g_common.h"
+
+/*
+ *	The following permission checking modes are governed by
+ *	the HPERMSCONFIG value in param.h
+ */
+
+/*	ACLS may be checked by kernel (requires a fuse patch) or here */
+#define KERNELACLS ((HPERMSCONFIG > 6) & (HPERMSCONFIG < 10))
+/*	basic permissions may be checked by kernel or here */
+#define KERNELPERMS (((HPERMSCONFIG - 1) % 6) < 3)
+/*	may want to use fuse/kernel cacheing */
+#define CACHEING (!(HPERMSCONFIG % 3))
+
+#if KERNELACLS & !KERNELPERMS
+#error Incompatible options KERNELACLS and KERNELPERMS
+#endif
+
+		/* sometimes the kernel cannot check access */
+#define ntfs_real_allowed_access(scx, ni, type) ntfs_allowed_access(scx, ni, type)
+#if POSIXACLS & KERNELPERMS & !KERNELACLS
+		/* short-circuit if PERMS checked by kernel and ACLs by fs */
+#define ntfs_allowed_access(scx, ni, type) \
+	((scx)->vol->secure_flags & (1 << SECURITY_DEFAULT) \
+	    ? 1 : ntfs_allowed_access(scx, ni, type))
+#endif
+
+#define set_archive(ni) (ni)->flags |= FILE_ATTR_ARCHIVE
+
+typedef enum {
+	FSTYPE_NONE,
+	FSTYPE_UNKNOWN,
+	FSTYPE_FUSE,
+	FSTYPE_FUSEBLK
+} fuse_fstype;
+
+typedef struct {
+	fuse_fill_dir_t filler;
+	void *buf;
+} ntfs_fuse_fill_context_t;
+
+enum {
+	CLOSE_COMPRESSED = 1,
+	CLOSE_ENCRYPTED = 2,
+	CLOSE_DMTIME = 4
+};
+
+static struct ntfs_options opts;
+
+const char *EXEC_NAME = "ntfs-3g";
+
+static ntfs_fuse_context_t *ctx;
+static u32 ntfs_sequence;
+
+static const char *usage_msg = 
+"\n"
+"%s %s %s %d - Third Generation NTFS Driver\n"
+"\t\tConfiguration type %d, "
+#ifdef HAVE_SETXATTR
+"XATTRS are on, "
+#else
+"XATTRS are off, "
+#endif
+#if POSIXACLS
+"POSIX ACLS are on\n"
+#else
+"POSIX ACLS are off\n"
+#endif
+"\n"
+"Copyright (C) 2005-2007 Yura Pakhuchiy\n"
+"Copyright (C) 2006-2009 Szabolcs Szakacsits\n"
+"Copyright (C) 2007-2015 Jean-Pierre Andre\n"
+"Copyright (C) 2009 Erik Larsson\n"
+"\n"
+"Usage:    %s [-o option[,...]] <device|image_file> <mount_point>\n"
+"\n"
+"Options:  ro (read-only mount), windows_names, uid=, gid=,\n" 
+"          umask=, fmask=, dmask=, streams_interface=.\n"
+"          Please see the details in the manual (type: man ntfs-3g).\n"
+"\n"
+"Example: ntfs-3g /dev/sda1 /mnt/windows\n"
+"\n"
+"%s";
+
+static const char ntfs_bad_reparse[] = "unsupported reparse point";
+
+#ifdef FUSE_INTERNAL
+int drop_privs(void);
+int restore_privs(void);
+#else
+/*
+ * setuid and setgid root ntfs-3g denies to start with external FUSE, 
+ * therefore the below functions are no-op in such case.
+ */
+static int drop_privs(void)    { return 0; }
+#if defined(linux) || defined(__uClinux__)
+static int restore_privs(void) { return 0; }
+#endif
+
+static const char *setuid_msg =
+"Mount is denied because setuid and setgid root ntfs-3g is insecure with the\n"
+"external FUSE library. Either remove the setuid/setgid bit from the binary\n"
+"or rebuild NTFS-3G with integrated FUSE support and make it setuid root.\n"
+"Please see more information at\n"
+"http://tuxera.com/community/ntfs-3g-faq/#unprivileged\n";
+
+static const char *unpriv_fuseblk_msg =
+"Unprivileged user can not mount NTFS block devices using the external FUSE\n"
+"library. Either mount the volume as root, or rebuild NTFS-3G with integrated\n"
+"FUSE support and make it setuid root. Please see more information at\n"
+"http://tuxera.com/community/ntfs-3g-faq/#unprivileged\n";
+#endif	
+
+
+/**
+ * ntfs_fuse_is_named_data_stream - check path to be to named data stream
+ * @path:	path to check
+ *
+ * Returns 1 if path is to named data stream or 0 otherwise.
+ */
+static int ntfs_fuse_is_named_data_stream(const char *path)
+{
+	if (strchr(path, ':') && ctx->streams == NF_STREAMS_INTERFACE_WINDOWS)
+		return 1;
+	return 0;
+}
+
+static void ntfs_fuse_update_times(ntfs_inode *ni, ntfs_time_update_flags mask)
+{
+	if (ctx->atime == ATIME_DISABLED)
+		mask &= ~NTFS_UPDATE_ATIME;
+	else if (ctx->atime == ATIME_RELATIVE && mask == NTFS_UPDATE_ATIME &&
+			(le64_to_cpu(ni->last_access_time)
+				>= le64_to_cpu(ni->last_data_change_time)) &&
+			(le64_to_cpu(ni->last_access_time)
+				>= le64_to_cpu(ni->last_mft_change_time)))
+		return;
+	ntfs_inode_update_times(ni, mask);
+}
+
+static s64 ntfs_get_nr_free_mft_records(ntfs_volume *vol)
+{
+	ntfs_attr *na = vol->mftbmp_na;
+	s64 nr_free = ntfs_attr_get_free_bits(na);
+
+	if (nr_free >= 0)
+		nr_free += (na->allocated_size - na->data_size) << 3;
+	return nr_free;
+}
+
+/*
+ *      Fill a security context as needed by security functions
+ *      returns TRUE if there is a user mapping,
+ *              FALSE if there is none
+ *			This is not an error and the context is filled anyway,
+ *			it is used for implicit Windows-like inheritance
+ */
+
+static BOOL ntfs_fuse_fill_security_context(struct SECURITY_CONTEXT *scx)
+{
+	struct fuse_context *fusecontext;
+
+	scx->vol = ctx->vol;
+	scx->mapping[MAPUSERS] = ctx->security.mapping[MAPUSERS];
+	scx->mapping[MAPGROUPS] = ctx->security.mapping[MAPGROUPS];
+	scx->pseccache = &ctx->seccache;
+	fusecontext = fuse_get_context();
+	scx->uid = fusecontext->uid;
+	scx->gid = fusecontext->gid;
+	scx->tid = fusecontext->pid;
+#ifdef FUSE_CAP_DONT_MASK
+		/* the umask can be processed by the file system */
+	scx->umask = fusecontext->umask;
+#else
+		/* the umask if forced by fuse on creation */
+	scx->umask = 0;
+#endif
+
+	return (ctx->security.mapping[MAPUSERS] != (struct MAPPING*)NULL);
+}
+
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+
+/*
+ *		Check access to parent directory
+ *
+ *	directory and file inodes are only opened when not fed in,
+ *	they *HAVE TO* be fed in when already open, however
+ *	file inode is only useful when S_ISVTX is requested
+ *
+ *	returns 1 if allowed,
+ *		0 if not allowed or some error occurred (errno tells why)
+ */
+
+static int ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx,
+			const char *path, ntfs_inode *dir_ni,
+			ntfs_inode *ni, mode_t accesstype)
+{
+	int allowed;
+	ntfs_inode *ni2;
+	ntfs_inode *dir_ni2;
+	char *dirpath;
+	char *name;
+	struct stat stbuf;
+
+#if POSIXACLS & KERNELPERMS & !KERNELACLS
+		/* short-circuit if PERMS checked by kernel and ACLs by fs */
+	if (scx->vol->secure_flags & (1 << SECURITY_DEFAULT))
+		allowed = 1;
+	else
+#endif
+		if (dir_ni)
+			allowed = ntfs_real_allowed_access(scx, dir_ni,
+					accesstype);
+		else {
+			allowed = 0;
+			dirpath = strdup(path);
+			if (dirpath) {
+		/* the root of file system is seen as a parent of itself */
+		/* is that correct ? */
+				name = strrchr(dirpath, '/');
+				*name = 0;
+				dir_ni2 = ntfs_pathname_to_inode(scx->vol,
+						NULL, dirpath);
+				if (dir_ni2) {
+					allowed = ntfs_real_allowed_access(scx,
+						 dir_ni2, accesstype);
+					if (ntfs_inode_close(dir_ni2))
+						allowed = 0;
+				}
+				free(dirpath);
+			}
+		}
+			/*
+			 * for a not-owned sticky directory, have to
+			 * check whether file itself is owned
+			 */
+		if ((accesstype == (S_IWRITE + S_IEXEC + S_ISVTX))
+		   && (allowed == 2)) {
+			if (ni)
+				ni2 = ni;
+			else
+				ni2 = ntfs_pathname_to_inode(scx->vol, NULL,
+					path);
+			allowed = 0;
+			if (ni2) {
+				allowed = (ntfs_get_owner_mode(scx,ni2,&stbuf)
+						>= 0)
+					&& (stbuf.st_uid == scx->uid);
+				if (!ni)
+					ntfs_inode_close(ni2);
+			}
+		}
+	return (allowed);
+}
+
+#endif
+
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+
+/*
+ *		Check access to parent directory
+ *
+ *	for non-standard cases where access control cannot be checked by kernel
+ *
+ *	no known situations where S_ISVTX is requested
+ *
+ *	returns 1 if allowed,
+ *		0 if not allowed or some error occurred (errno tells why)
+ */
+
+static int ntfs_allowed_real_dir_access(struct SECURITY_CONTEXT *scx,
+			const char *path, ntfs_inode *dir_ni,
+			mode_t accesstype)
+{
+	int allowed;
+	ntfs_inode *dir_ni2;
+	char *dirpath;
+	char *name;
+
+	if (dir_ni)
+		allowed = ntfs_real_allowed_access(scx, dir_ni, accesstype);
+	else {
+		allowed = 0;
+		dirpath = strdup(path);
+		if (dirpath) {
+		/* the root of file system is seen as a parent of itself */
+		/* is that correct ? */
+			name = strrchr(dirpath, '/');
+			*name = 0;
+			dir_ni2 = ntfs_pathname_to_inode(scx->vol, NULL,
+					dirpath);
+			if (dir_ni2) {
+				allowed = ntfs_real_allowed_access(scx,
+					dir_ni2, accesstype);
+				if (ntfs_inode_close(dir_ni2))
+					allowed = 0;
+			}
+			free(dirpath);
+		}
+	}
+	return (allowed);
+}
+
+static ntfs_inode *get_parent_dir(const char *path)
+{
+	ntfs_inode *dir_ni;
+	char *dirpath;
+	char *p;
+
+	dirpath = strdup(path);
+	dir_ni = (ntfs_inode*)NULL;
+	if (dirpath) {
+		p = strrchr(dirpath,'/');
+		if (p) {  /* always present, be safe */
+			*p = 0;
+			dir_ni = ntfs_pathname_to_inode(ctx->vol,
+						NULL, dirpath);
+		}			
+		free(dirpath);
+	} else
+		errno = ENOMEM;
+	return (dir_ni);
+}
+
+
+#endif /* HAVE_SETXATTR */
+
+/**
+ * ntfs_fuse_statfs - return information about mounted NTFS volume
+ * @path:	ignored (but fuse requires it)
+ * @sfs:	statfs structure in which to return the information
+ *
+ * Return information about the mounted NTFS volume @sb in the statfs structure
+ * pointed to by @sfs (this is initialized with zeros before ntfs_statfs is
+ * called). We interpret the values to be correct of the moment in time at
+ * which we are called. Most values are variable otherwise and this isn't just
+ * the free values but the totals as well. For example we can increase the
+ * total number of file nodes if we run out and we can keep doing this until
+ * there is no more space on the volume left at all.
+ *
+ * This code based on ntfs_statfs from ntfs kernel driver.
+ *
+ * Returns 0 on success or -errno on error.
+ */
+static int ntfs_fuse_statfs(const char *path __attribute__((unused)),
+			    struct statvfs *sfs)
+{
+	s64 size;
+	int delta_bits;
+	ntfs_volume *vol;
+
+	vol = ctx->vol;
+	if (!vol)
+		return -ENODEV;
+	
+	/* 
+	 * File system block size. Used to calculate used/free space by df.
+	 * Incorrectly documented as "optimal transfer block size". 
+	 */
+	sfs->f_bsize = vol->cluster_size;
+	
+	/* Fundamental file system block size, used as the unit. */
+	sfs->f_frsize = vol->cluster_size;
+	
+	/*
+	 * Total number of blocks on file system in units of f_frsize.
+	 * Since inodes are also stored in blocks ($MFT is a file) hence
+	 * this is the number of clusters on the volume.
+	 */
+	sfs->f_blocks = vol->nr_clusters;
+	
+	/* Free blocks available for all and for non-privileged processes. */
+	size = vol->free_clusters;
+	if (size < 0)
+		size = 0;
+	sfs->f_bavail = sfs->f_bfree = size;
+	
+	/* Free inodes on the free space */
+	delta_bits = vol->cluster_size_bits - vol->mft_record_size_bits;
+	if (delta_bits >= 0)
+		size <<= delta_bits;
+	else
+		size >>= -delta_bits;
+	
+	/* Number of inodes at this point in time. */
+	sfs->f_files = (vol->mftbmp_na->allocated_size << 3) + size;
+	
+	/* Free inodes available for all and for non-privileged processes. */
+	size += vol->free_mft_records;
+	if (size < 0)
+		size = 0;
+	sfs->f_ffree = sfs->f_favail = size;
+	
+	/* Maximum length of filenames. */
+	sfs->f_namemax = NTFS_MAX_NAME_LEN;
+	return 0;
+}
+
+/**
+ * ntfs_fuse_parse_path - split path to path and stream name.
+ * @org_path:		path to split
+ * @path:		pointer to buffer in which parsed path saved
+ * @stream_name:	pointer to buffer where stream name in unicode saved
+ *
+ * This function allocates buffers for @*path and @*stream, user must free them
+ * after use.
+ *
+ * Return values:
+ *	<0	Error occurred, return -errno;
+ *	 0	No stream name, @*stream is not allocated and set to AT_UNNAMED.
+ *	>0	Stream name length in unicode characters.
+ */
+static int ntfs_fuse_parse_path(const char *org_path, char **path,
+		ntfschar **stream_name)
+{
+	char *stream_name_mbs;
+	int res;
+
+	stream_name_mbs = strdup(org_path);
+	if (!stream_name_mbs)
+		return -errno;
+	if (ctx->streams == NF_STREAMS_INTERFACE_WINDOWS) {
+		*path = strsep(&stream_name_mbs, ":");
+		if (stream_name_mbs) {
+			*stream_name = NULL;
+			res = ntfs_mbstoucs(stream_name_mbs, stream_name);
+			if (res < 0) {
+				free(*path);
+				*path = NULL;
+				return -errno;
+			}
+			return res;
+		}
+	} else
+		*path = stream_name_mbs;
+	*stream_name = AT_UNNAMED;
+	return 0;
+}
+
+static void set_fuse_error(int *err)
+{
+	if (!*err)
+		*err = -errno;
+}
+
+#if defined(__APPLE__) || defined(__DARWIN__)
+static int ntfs_macfuse_getxtimes(const char *org_path,
+		struct timespec *bkuptime, struct timespec *crtime)
+{
+	int res = 0;
+	ntfs_inode *ni;
+	char *path = NULL;
+	ntfschar *stream_name;
+	int stream_name_len;
+
+	stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);
+	if (stream_name_len < 0)
+		return stream_name_len;
+	memset(bkuptime, 0, sizeof(struct timespec));
+	memset(crtime, 0, sizeof(struct timespec));
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni) {
+		res = -errno;
+		goto exit;
+	}
+	
+	/* We have no backup timestamp in NTFS. */
+	crtime->tv_sec = ni->creation_time;
+exit:
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	free(path);
+	if (stream_name_len)
+		free(stream_name);
+	return res;
+}
+
+int ntfs_macfuse_setcrtime(const char *path, const struct timespec *tv)
+{
+	ntfs_inode *ni;
+	int res = 0;
+
+	if (ntfs_fuse_is_named_data_stream(path))
+		return -EINVAL; /* n/a for named data streams. */
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni)
+		return -errno;
+	
+	if (tv) {
+		ni->creation_time = tv->tv_sec;
+		ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);
+	}
+
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	return res;
+}
+
+int ntfs_macfuse_setbkuptime(const char *path, const struct timespec *tv)
+{
+	ntfs_inode *ni;
+	int res = 0;
+	
+	if (ntfs_fuse_is_named_data_stream(path))
+		return -EINVAL; /* n/a for named data streams. */
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni)
+		return -errno;
+	
+	/* 
+	 * Only pretending to set backup time successfully to please the APIs of
+	 * Mac OS X. In reality, NTFS has no backup time.
+	 */
+	
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	return res;
+}
+
+int ntfs_macfuse_setchgtime(const char *path, const struct timespec *tv)
+{
+	ntfs_inode *ni;
+	int res = 0;
+
+	if (ntfs_fuse_is_named_data_stream(path))
+		return -EINVAL; /* n/a for named data streams. */
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni)
+		return -errno;
+
+	if (tv) {
+		ni->last_mft_change_time = tv->tv_sec;
+		ntfs_fuse_update_times(ni, 0);
+	}
+
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	return res;
+}
+#endif /* defined(__APPLE__) || defined(__DARWIN__) */
+
+static void *ntfs_init(struct fuse_conn_info *conn)
+{
+#if defined(__APPLE__) || defined(__DARWIN__)
+	FUSE_ENABLE_XTIMES(conn);
+#endif
+#ifdef FUSE_CAP_DONT_MASK
+		/* request umask not to be enforced by fuse */
+	conn->want |= FUSE_CAP_DONT_MASK;
+#endif /* defined FUSE_CAP_DONT_MASK */
+#ifdef FUSE_CAP_BIG_WRITES
+	if (ctx->big_writes
+	    && ((ctx->vol->nr_clusters << ctx->vol->cluster_size_bits)
+			>= SAFE_CAPACITY_FOR_BIG_WRITES))
+		conn->want |= FUSE_CAP_BIG_WRITES;
+#endif
+#ifdef FUSE_CAP_IOCTL_DIR
+	conn->want |= FUSE_CAP_IOCTL_DIR;
+#endif /* defined(FUSE_CAP_IOCTL_DIR) */
+	return NULL;
+}
+
+static int ntfs_fuse_getattr(const char *org_path, struct stat *stbuf)
+{
+	int res = 0;
+	ntfs_inode *ni;
+	ntfs_attr *na;
+	char *path = NULL;
+	ntfschar *stream_name;
+	int stream_name_len;
+	BOOL withusermapping;
+	struct SECURITY_CONTEXT security;
+
+	stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);
+	if (stream_name_len < 0)
+		return stream_name_len;
+	memset(stbuf, 0, sizeof(struct stat));
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni) {
+		res = -errno;
+		goto exit;
+	}
+	withusermapping = ntfs_fuse_fill_security_context(&security);
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+		/*
+		 * make sure the parent directory is searchable
+		 */
+	if (withusermapping
+	    && !ntfs_allowed_dir_access(&security,path,
+			(!strcmp(org_path,"/") ? ni : (ntfs_inode*)NULL),
+			ni, S_IEXEC)) {
+               	res = -EACCES;
+               	goto exit;
+	}
+#endif
+	if (((ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
+		|| (ni->flags & FILE_ATTR_REPARSE_POINT))
+	    && !stream_name_len) {
+		if (ni->flags & FILE_ATTR_REPARSE_POINT) {
+			char *target;
+			int attr_size;
+
+			errno = 0;
+			target = ntfs_make_symlink(ni, ctx->abs_mnt_point, &attr_size);
+				/*
+				 * If the reparse point is not a valid
+				 * directory junction, and there is no error
+				 * we still display as a symlink
+				 */
+			if (target || (errno == EOPNOTSUPP)) {
+					/* returning attribute size */
+				if (target)
+					stbuf->st_size = attr_size;
+				else
+					stbuf->st_size = sizeof(ntfs_bad_reparse);
+				stbuf->st_blocks = (ni->allocated_size + 511) >> 9;
+				stbuf->st_nlink = le16_to_cpu(ni->mrec->link_count);
+				stbuf->st_mode = S_IFLNK;
+				free(target);
+			} else {
+				res = -errno;
+				goto exit;
+			}
+		} else {
+			/* Directory. */
+			stbuf->st_mode = S_IFDIR | (0777 & ~ctx->dmask);
+			/* get index size, if not known */
+			if (!test_nino_flag(ni, KnownSize)) {
+				na = ntfs_attr_open(ni, AT_INDEX_ALLOCATION, NTFS_INDEX_I30, 4);
+				if (na) {
+					ni->data_size = na->data_size;
+					ni->allocated_size = na->allocated_size;
+					set_nino_flag(ni, KnownSize);
+					ntfs_attr_close(na);
+				}
+			}
+			stbuf->st_size = ni->data_size;
+			stbuf->st_blocks = ni->allocated_size >> 9;
+			stbuf->st_nlink = 1;	/* Make find(1) work */
+		}
+	} else {
+		/* Regular or Interix (INTX) file. */
+		stbuf->st_mode = S_IFREG;
+		stbuf->st_size = ni->data_size;
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+		/*
+		 * return data size rounded to next 512 byte boundary for
+		 * encrypted files to include padding required for decryption
+		 * also include 2 bytes for padding info
+		*/
+		if (ctx->efs_raw
+		    && (ni->flags & FILE_ATTR_ENCRYPTED)
+		    && ni->data_size)
+			stbuf->st_size = ((ni->data_size + 511) & ~511) + 2;
+#endif /* HAVE_SETXATTR */
+		/* 
+		 * Temporary fix to make ActiveSync work via Samba 3.0.
+		 * See more on the ntfs-3g-devel list.
+		 */
+		stbuf->st_blocks = (ni->allocated_size + 511) >> 9;
+		stbuf->st_nlink = le16_to_cpu(ni->mrec->link_count);
+		if (ni->flags & FILE_ATTR_SYSTEM || stream_name_len) {
+			na = ntfs_attr_open(ni, AT_DATA, stream_name,
+					stream_name_len);
+			if (!na) {
+				if (stream_name_len) {
+					res = -ENOENT;
+					goto exit;
+				} else
+					goto nodata;
+			}
+			if (stream_name_len) {
+				stbuf->st_size = na->data_size;
+				stbuf->st_blocks = na->allocated_size >> 9;
+			}
+			/* Check whether it's Interix FIFO or socket. */
+			if (!(ni->flags & FILE_ATTR_HIDDEN) &&
+					!stream_name_len) {
+				/* FIFO. */
+				if (na->data_size == 0)
+					stbuf->st_mode = S_IFIFO;
+				/* Socket link. */
+				if (na->data_size == 1)
+					stbuf->st_mode = S_IFSOCK;
+			}
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+			/* encrypted named stream */
+			/* round size up to next 512 byte boundary */
+			if (ctx->efs_raw && stream_name_len && 
+			    (na->data_flags & ATTR_IS_ENCRYPTED) &&
+			    NAttrNonResident(na)) 
+				stbuf->st_size = ((na->data_size+511) & ~511)+2;
+#endif /* HAVE_SETXATTR */
+			/*
+			 * Check whether it's Interix symbolic link, block or
+			 * character device.
+			 */
+			if ((u64)na->data_size <= sizeof(INTX_FILE_TYPES)
+					+ sizeof(ntfschar) * PATH_MAX
+				&& (u64)na->data_size >
+					sizeof(INTX_FILE_TYPES)
+				&& !stream_name_len) {
+				
+				INTX_FILE *intx_file;
+
+				intx_file = ntfs_malloc(na->data_size);
+				if (!intx_file) {
+					res = -errno;
+					ntfs_attr_close(na);
+					goto exit;
+				}
+				if (ntfs_attr_pread(na, 0, na->data_size,
+						intx_file) != na->data_size) {
+					res = -errno;
+					free(intx_file);
+					ntfs_attr_close(na);
+					goto exit;
+				}
+				if (intx_file->magic == INTX_BLOCK_DEVICE &&
+						na->data_size == offsetof(
+						INTX_FILE, device_end)) {
+					stbuf->st_mode = S_IFBLK;
+					stbuf->st_rdev = makedev(le64_to_cpu(
+							intx_file->major),
+							le64_to_cpu(
+							intx_file->minor));
+				}
+				if (intx_file->magic == INTX_CHARACTER_DEVICE &&
+						na->data_size == offsetof(
+						INTX_FILE, device_end)) {
+					stbuf->st_mode = S_IFCHR;
+					stbuf->st_rdev = makedev(le64_to_cpu(
+							intx_file->major),
+							le64_to_cpu(
+							intx_file->minor));
+				}
+				if (intx_file->magic == INTX_SYMBOLIC_LINK)
+					stbuf->st_mode = S_IFLNK;
+				free(intx_file);
+			}
+			ntfs_attr_close(na);
+		}
+		stbuf->st_mode |= (0777 & ~ctx->fmask);
+	}
+	if (withusermapping) {
+		if (ntfs_get_owner_mode(&security,ni,stbuf) < 0)
+			set_fuse_error(&res);
+	} else {
+		stbuf->st_uid = ctx->uid;
+       		stbuf->st_gid = ctx->gid;
+	}
+	if (S_ISLNK(stbuf->st_mode))
+		stbuf->st_mode |= 0777;
+nodata :
+	stbuf->st_ino = ni->mft_no;
+#ifdef HAVE_STRUCT_STAT_ST_ATIMESPEC
+	stbuf->st_atimespec = ntfs2timespec(ni->last_access_time);
+	stbuf->st_ctimespec = ntfs2timespec(ni->last_mft_change_time);
+	stbuf->st_mtimespec = ntfs2timespec(ni->last_data_change_time);
+#elif defined(HAVE_STRUCT_STAT_ST_ATIM)
+ 	stbuf->st_atim = ntfs2timespec(ni->last_access_time);
+ 	stbuf->st_ctim = ntfs2timespec(ni->last_mft_change_time);
+ 	stbuf->st_mtim = ntfs2timespec(ni->last_data_change_time);
+#elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC)
+	{
+	struct timespec ts;
+
+	ts = ntfs2timespec(ni->last_access_time);
+	stbuf->st_atime = ts.tv_sec;
+	stbuf->st_atimensec = ts.tv_nsec;
+	ts = ntfs2timespec(ni->last_mft_change_time);
+	stbuf->st_ctime = ts.tv_sec;
+	stbuf->st_ctimensec = ts.tv_nsec;
+	ts = ntfs2timespec(ni->last_data_change_time);
+	stbuf->st_mtime = ts.tv_sec;
+	stbuf->st_mtimensec = ts.tv_nsec;
+	}
+#else
+#warning "No known way to set nanoseconds in struct stat !"
+	{
+	struct timespec ts;
+
+	ts = ntfs2timespec(ni->last_access_time);
+	stbuf->st_atime = ts.tv_sec;
+	ts = ntfs2timespec(ni->last_mft_change_time);
+	stbuf->st_ctime = ts.tv_sec;
+	ts = ntfs2timespec(ni->last_data_change_time);
+	stbuf->st_mtime = ts.tv_sec;
+	}
+#endif
+exit:
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	free(path);
+	if (stream_name_len)
+		free(stream_name);
+	return res;
+}
+
+static int ntfs_fuse_readlink(const char *org_path, char *buf, size_t buf_size)
+{
+	char *path = NULL;
+	ntfschar *stream_name;
+	ntfs_inode *ni = NULL;
+	ntfs_attr *na = NULL;
+	INTX_FILE *intx_file = NULL;
+	int stream_name_len, res = 0;
+
+	/* Get inode. */
+	stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);
+	if (stream_name_len < 0)
+		return stream_name_len;
+	if (stream_name_len > 0) {
+		res = -EINVAL;
+		goto exit;
+	}
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni) {
+		res = -errno;
+		goto exit;
+	}
+		/*
+		 * Reparse point : analyze as a junction point
+		 */
+	if (ni->flags & FILE_ATTR_REPARSE_POINT) {
+		char *target;
+		int attr_size;
+
+		errno = 0;
+		res = 0;
+		target = ntfs_make_symlink(ni, ctx->abs_mnt_point, &attr_size);
+		if (target) {
+			strncpy(buf,target,buf_size);
+			free(target);
+		} else
+			if (errno == EOPNOTSUPP)
+				strcpy(buf,ntfs_bad_reparse);
+			else
+				res = -errno;
+		goto exit;
+	}
+	/* Sanity checks. */
+	if (!(ni->flags & FILE_ATTR_SYSTEM)) {
+		res = -EINVAL;
+		goto exit;
+	}
+	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
+	if (!na) {
+		res = -errno;
+		goto exit;
+	}
+	if ((size_t)na->data_size <= sizeof(INTX_FILE_TYPES)) {
+		res = -EINVAL;
+		goto exit;
+	}
+	if ((size_t)na->data_size > sizeof(INTX_FILE_TYPES) +
+			sizeof(ntfschar) * PATH_MAX) {
+		res = -ENAMETOOLONG;
+		goto exit;
+	}
+	/* Receive file content. */
+	intx_file = ntfs_malloc(na->data_size);
+	if (!intx_file) {
+		res = -errno;
+		goto exit;
+	}
+	if (ntfs_attr_pread(na, 0, na->data_size, intx_file) != na->data_size) {
+		res = -errno;
+		goto exit;
+	}
+	/* Sanity check. */
+	if (intx_file->magic != INTX_SYMBOLIC_LINK) {
+		res = -EINVAL;
+		goto exit;
+	}
+	/* Convert link from unicode to local encoding. */
+	if (ntfs_ucstombs(intx_file->target, (na->data_size -
+			offsetof(INTX_FILE, target)) / sizeof(ntfschar),
+			&buf, buf_size) < 0) {
+		res = -errno;
+		goto exit;
+	}
+exit:
+	if (intx_file)
+		free(intx_file);
+	if (na)
+		ntfs_attr_close(na);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	free(path);
+	if (stream_name_len)
+		free(stream_name);
+	return res;
+}
+
+static int ntfs_fuse_filler(ntfs_fuse_fill_context_t *fill_ctx,
+		const ntfschar *name, const int name_len, const int name_type,
+		const s64 pos __attribute__((unused)), const MFT_REF mref,
+		const unsigned dt_type __attribute__((unused)))
+{
+	char *filename = NULL;
+	int ret = 0;
+	int filenamelen = -1;
+
+	if (name_type == FILE_NAME_DOS)
+		return 0;
+	
+	if ((filenamelen = ntfs_ucstombs(name, name_len, &filename, 0)) < 0) {
+		ntfs_log_perror("Filename decoding failed (inode %llu)",
+				(unsigned long long)MREF(mref));
+		return -1;
+	}
+	
+	if (ntfs_fuse_is_named_data_stream(filename)) {
+		ntfs_log_error("Unable to access '%s' (inode %llu) with "
+				"current named streams access interface.\n",
+				filename, (unsigned long long)MREF(mref));
+		free(filename);
+		return 0;
+	} else {
+		struct stat st = { .st_ino = MREF(mref) };
+		 
+		switch (dt_type) {
+		case NTFS_DT_DIR :
+			st.st_mode = S_IFDIR | (0777 & ~ctx->dmask); 
+			break;
+		case NTFS_DT_LNK :
+			st.st_mode = S_IFLNK | 0777;
+			break;
+		case NTFS_DT_FIFO :
+			st.st_mode = S_IFIFO;
+			break;
+		case NTFS_DT_SOCK :
+			st.st_mode = S_IFSOCK;
+			break;
+		case NTFS_DT_BLK :
+			st.st_mode = S_IFBLK;
+			break;
+		case NTFS_DT_CHR :
+			st.st_mode = S_IFCHR;
+			break;
+		default : /* unexpected types shown as plain files */
+		case NTFS_DT_REG :
+			st.st_mode = S_IFREG | (0777 & ~ctx->fmask);
+			break;
+		}
+		
+#if defined(__APPLE__) || defined(__DARWIN__)
+		/* 
+		 * Returning file names larger than MAXNAMLEN (255) bytes
+		 * causes Darwin/Mac OS X to bug out and skip the entry. 
+		 */
+		if (filenamelen > MAXNAMLEN) {
+			ntfs_log_debug("Truncating %d byte filename to "
+				       "%d bytes.\n", filenamelen, MAXNAMLEN);
+			ntfs_log_debug("  before: '%s'\n", filename);
+			memset(filename + MAXNAMLEN, 0, filenamelen - MAXNAMLEN);
+			ntfs_log_debug("   after: '%s'\n", filename);
+		}
+#elif defined(__sun) && defined (__SVR4)
+		/*
+		 * Returning file names larger than MAXNAMELEN (256) bytes
+		 * causes Solaris/Illumos to return an I/O error from the system
+		 * call.
+		 * However we also need space for a terminating NULL, or user
+		 * space tools will bug out since they expect a NULL terminator.
+		 * Effectively the maximum length of a file name is MAXNAMELEN -
+		 * 1 (255).
+		 */
+		if (filenamelen > (MAXNAMELEN - 1)) {
+			ntfs_log_debug("Truncating %d byte filename to %d "
+				"bytes.\n", filenamelen, MAXNAMELEN - 1);
+			ntfs_log_debug("  before: '%s'\n", filename);
+			memset(&filename[MAXNAMELEN - 1], 0,
+				filenamelen - (MAXNAMELEN - 1));
+			ntfs_log_debug("   after: '%s'\n", filename);
+		}
+#endif /* defined(__APPLE__) || defined(__DARWIN__), ... */
+	
+		ret = fill_ctx->filler(fill_ctx->buf, filename, &st, 0);
+	}
+	
+	free(filename);
+	return ret;
+}
+
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+
+static int ntfs_fuse_opendir(const char *path,
+		struct fuse_file_info *fi)
+{
+	int res = 0;
+	ntfs_inode *ni;
+	int accesstype;
+	struct SECURITY_CONTEXT security;
+
+	if (ntfs_fuse_is_named_data_stream(path))
+		return -EINVAL; /* n/a for named data streams. */
+
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (ni) {
+		if (ntfs_fuse_fill_security_context(&security)) {
+			if (fi->flags & O_WRONLY)
+				accesstype = S_IWRITE;
+			else
+				if (fi->flags & O_RDWR)
+					accesstype = S_IWRITE | S_IREAD;
+				else
+					accesstype = S_IREAD;
+				/*
+				 * directory must be searchable
+				 * and requested access be allowed
+				 */
+			if (!strcmp(path,"/")
+				? !ntfs_allowed_dir_access(&security,
+					path, ni, ni, accesstype | S_IEXEC)
+				: !ntfs_allowed_dir_access(&security, path,
+						(ntfs_inode*)NULL, ni, S_IEXEC)
+				     || !ntfs_allowed_access(&security,
+						ni,accesstype))
+				res = -EACCES;
+		}
+		if (ntfs_inode_close(ni))
+			set_fuse_error(&res);
+	} else
+		res = -errno;
+	return res;
+}
+
+#endif
+
+static int ntfs_fuse_readdir(const char *path, void *buf,
+		fuse_fill_dir_t filler, off_t offset __attribute__((unused)),
+		struct fuse_file_info *fi __attribute__((unused)))
+{
+	ntfs_fuse_fill_context_t fill_ctx;
+	ntfs_inode *ni;
+	s64 pos = 0;
+	int err = 0;
+
+	fill_ctx.filler = filler;
+	fill_ctx.buf = buf;
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni)
+		return -errno;
+	if (ntfs_readdir(ni, &pos, &fill_ctx,
+			(ntfs_filldir_t)ntfs_fuse_filler))
+		err = -errno;
+	ntfs_fuse_update_times(ni, NTFS_UPDATE_ATIME);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&err);
+	return err;
+}
+
+static int ntfs_fuse_open(const char *org_path,
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+		struct fuse_file_info *fi)
+#else
+		struct fuse_file_info *fi __attribute__((unused)))
+#endif
+{
+	ntfs_inode *ni;
+	ntfs_attr *na;
+	int res = 0;
+	char *path = NULL;
+	ntfschar *stream_name;
+	int stream_name_len;
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	int accesstype;
+	struct SECURITY_CONTEXT security;
+#endif
+
+	stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);
+	if (stream_name_len < 0)
+		return stream_name_len;
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (ni) {
+		na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);
+		if (na) {
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+			if (ntfs_fuse_fill_security_context(&security)) {
+				if (fi->flags & O_WRONLY)
+					accesstype = S_IWRITE;
+				else
+					if (fi->flags & O_RDWR)
+						 accesstype = S_IWRITE | S_IREAD;
+					else
+						accesstype = S_IREAD;
+				/*
+				 * directory must be searchable
+				 * and requested access allowed
+				 */
+				if (!ntfs_allowed_dir_access(&security,
+					    path,(ntfs_inode*)NULL,ni,S_IEXEC)
+				  || !ntfs_allowed_access(&security,
+						ni,accesstype))
+					res = -EACCES;
+			}
+#endif
+			if ((res >= 0)
+			    && (fi->flags & (O_WRONLY | O_RDWR))) {
+			/* mark a future need to compress the last chunk */
+				if (na->data_flags & ATTR_COMPRESSION_MASK)
+					fi->fh |= CLOSE_COMPRESSED;
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+			/* mark a future need to fixup encrypted inode */
+				if (ctx->efs_raw
+				    && !(na->data_flags & ATTR_IS_ENCRYPTED)
+				    && (ni->flags & FILE_ATTR_ENCRYPTED))
+					fi->fh |= CLOSE_ENCRYPTED;
+#endif /* HAVE_SETXATTR */
+			/* mark a future need to update the mtime */
+				if (ctx->dmtime)
+					fi->fh |= CLOSE_DMTIME;
+			/* deny opening metadata files for writing */
+				if (ni->mft_no < FILE_first_user)
+					res = -EPERM;
+			}
+			ntfs_attr_close(na);
+		} else
+			res = -errno;
+		if (ntfs_inode_close(ni))
+			set_fuse_error(&res);
+	} else
+		res = -errno;
+	free(path);
+	if (stream_name_len)
+		free(stream_name);
+	return res;
+}
+
+static int ntfs_fuse_read(const char *org_path, char *buf, size_t size,
+		off_t offset, struct fuse_file_info *fi __attribute__((unused)))
+{
+	ntfs_inode *ni = NULL;
+	ntfs_attr *na = NULL;
+	char *path = NULL;
+	ntfschar *stream_name;
+	int stream_name_len, res;
+	s64 total = 0;
+	s64 max_read;
+
+	if (!size)
+		return 0;
+
+	stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);
+	if (stream_name_len < 0)
+		return stream_name_len;
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni) {
+		res = -errno;
+		goto exit;
+	}
+	na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);
+	if (!na) {
+		res = -errno;
+		goto exit;
+	}
+	max_read = na->data_size;
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+	/* limit reads at next 512 byte boundary for encrypted attributes */
+	if (ctx->efs_raw
+	    && max_read
+	    && (na->data_flags & ATTR_IS_ENCRYPTED)
+	    && NAttrNonResident(na)) {
+		max_read = ((na->data_size+511) & ~511) + 2;
+	}
+#endif /* HAVE_SETXATTR */
+	if (offset + (off_t)size > max_read) {
+		if (max_read < offset)
+			goto ok;
+		size = max_read - offset;
+	}
+	while (size > 0) {
+		s64 ret = ntfs_attr_pread(na, offset, size, buf + total);
+		if (ret != (s64)size)
+			ntfs_log_perror("ntfs_attr_pread error reading '%s' at "
+				"offset %lld: %lld <> %lld", org_path, 
+				(long long)offset, (long long)size, (long long)ret);
+		if (ret <= 0 || ret > (s64)size) {
+			res = (ret < 0) ? -errno : -EIO;
+			goto exit;
+		}
+		size -= ret;
+		offset += ret;
+		total += ret;
+	}
+ok:
+	ntfs_fuse_update_times(na->ni, NTFS_UPDATE_ATIME);
+	res = total;
+exit:
+	if (na)
+		ntfs_attr_close(na);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	free(path);
+	if (stream_name_len)
+		free(stream_name);
+	return res;
+}
+
+static int ntfs_fuse_write(const char *org_path, const char *buf, size_t size,
+		off_t offset, struct fuse_file_info *fi __attribute__((unused)))
+{
+	ntfs_inode *ni = NULL;
+	ntfs_attr *na = NULL;
+	char *path = NULL;
+	ntfschar *stream_name;
+	int stream_name_len, res, total = 0;
+
+	stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);
+	if (stream_name_len < 0) {
+		res = stream_name_len;
+		goto out;
+	}
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni) {
+		res = -errno;
+		goto exit;
+	}
+	na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);
+	if (!na) {
+		res = -errno;
+		goto exit;
+	}
+	while (size) {
+		s64 ret = ntfs_attr_pwrite(na, offset, size, buf + total);
+		if (ret <= 0) {
+			res = -errno;
+			goto exit;
+		}
+		size   -= ret;
+		offset += ret;
+		total  += ret;
+	}
+	res = total;
+	if ((res > 0)
+	    && (!ctx->dmtime
+		|| (le64_to_cpu(ntfs_current_time())
+		     - le64_to_cpu(ni->last_data_change_time)) > ctx->dmtime))
+		ntfs_fuse_update_times(na->ni, NTFS_UPDATE_MCTIME);
+exit:
+	if (na)
+		ntfs_attr_close(na);
+	if (total)
+		set_archive(ni);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	free(path);
+	if (stream_name_len)
+		free(stream_name);
+out:	
+	return res;
+}
+
+static int ntfs_fuse_release(const char *org_path,
+		struct fuse_file_info *fi)
+{
+	ntfs_inode *ni = NULL;
+	ntfs_attr *na = NULL;
+	char *path = NULL;
+	ntfschar *stream_name;
+	int stream_name_len, res;
+
+	/* Only for marked descriptors there is something to do */
+	if (!(fi->fh & (CLOSE_COMPRESSED | CLOSE_ENCRYPTED | CLOSE_DMTIME))) {
+		res = 0;
+		goto out;
+	}
+	stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);
+	if (stream_name_len < 0) {
+		res = stream_name_len;
+		goto out;
+	}
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni) {
+		res = -errno;
+		goto exit;
+	}
+	na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);
+	if (!na) {
+		res = -errno;
+		goto exit;
+	}
+	res = 0;
+	if (fi->fh & CLOSE_DMTIME)
+		ntfs_inode_update_times(na->ni,NTFS_UPDATE_MCTIME);
+	if (fi->fh & CLOSE_COMPRESSED)
+		res = ntfs_attr_pclose(na);
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+	if (fi->fh & CLOSE_ENCRYPTED)
+		res = ntfs_efs_fixup_attribute(NULL, na);
+#endif /* HAVE_SETXATTR */
+exit:
+	if (na)
+		ntfs_attr_close(na);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	free(path);
+	if (stream_name_len)
+		free(stream_name);
+out:	
+	return res;
+}
+
+/*
+ *	Common part for truncate() and ftruncate()
+ */
+
+static int ntfs_fuse_trunc(const char *org_path, off_t size,
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+			BOOL chkwrite)
+#else
+			BOOL chkwrite __attribute__((unused)))
+#endif
+{
+	ntfs_inode *ni = NULL;
+	ntfs_attr *na = NULL;
+	int res;
+	char *path = NULL;
+	ntfschar *stream_name;
+	int stream_name_len;
+	s64 oldsize;
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	struct SECURITY_CONTEXT security;
+#endif
+
+	stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);
+	if (stream_name_len < 0)
+		return stream_name_len;
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni)
+		goto exit;
+	/* deny truncating metadata files */
+	if (ni->mft_no < FILE_first_user) {
+		errno = EPERM;
+		goto exit;
+	}
+
+	na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);
+	if (!na)
+		goto exit;
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	/*
+	 * JPA deny truncation if cannot search in parent directory
+	 * or cannot write to file (already checked for ftruncate())
+	 */
+	if (ntfs_fuse_fill_security_context(&security)
+		&& (!ntfs_allowed_dir_access(&security, path,
+			 (ntfs_inode*)NULL, ni, S_IEXEC)
+	          || (chkwrite
+		     && !ntfs_allowed_access(&security, ni, S_IWRITE)))) {
+		errno = EACCES;
+		goto exit;
+	}
+#endif
+		/*
+		 * For compressed files, upsizing is done by inserting a final
+		 * zero, which is optimized as creating a hole when possible. 
+		 */
+	oldsize = na->data_size;
+	if ((na->data_flags & ATTR_COMPRESSION_MASK)
+	    && (size > na->initialized_size)) {
+		char zero = 0;
+		if (ntfs_attr_pwrite(na, size - 1, 1, &zero) <= 0)
+			goto exit;
+	} else
+		if (ntfs_attr_truncate(na, size))
+			goto exit;
+	if (oldsize != size)
+		set_archive(ni);
+	
+	ntfs_fuse_update_times(na->ni, NTFS_UPDATE_MCTIME);
+	errno = 0;
+exit:
+	res = -errno;
+	ntfs_attr_close(na);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	free(path);
+	if (stream_name_len)
+		free(stream_name);
+	return res;
+}
+
+static int ntfs_fuse_truncate(const char *org_path, off_t size)
+{
+	return ntfs_fuse_trunc(org_path, size, TRUE);
+}
+
+static int ntfs_fuse_ftruncate(const char *org_path, off_t size,
+			struct fuse_file_info *fi __attribute__((unused)))
+{
+	/*
+	 * in ->ftruncate() the file handle is guaranteed
+	 * to have been opened for write.
+	 */
+	return (ntfs_fuse_trunc(org_path, size, FALSE));
+}
+
+static int ntfs_fuse_chmod(const char *path,
+		mode_t mode)
+{
+	int res = 0;
+	ntfs_inode *ni;
+	struct SECURITY_CONTEXT security;
+
+	if (ntfs_fuse_is_named_data_stream(path))
+		return -EINVAL; /* n/a for named data streams. */
+
+		/*
+		 * Return unsupported if no user mapping has been defined
+		 * or enforcing Windows-type inheritance
+		 */
+	if (ctx->inherit
+	    || !ntfs_fuse_fill_security_context(&security)) {
+		if (ctx->silent)
+			res = 0;
+		else
+			res = -EOPNOTSUPP;
+	} else {
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+		   /* parent directory must be executable */
+		if (ntfs_allowed_dir_access(&security,path,
+				(ntfs_inode*)NULL,(ntfs_inode*)NULL,S_IEXEC)) {
+#endif
+			ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+			if (!ni)
+				res = -errno;
+			else {
+				if (ntfs_set_mode(&security,ni,mode))
+					res = -errno;
+				else
+					ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);
+				NInoSetDirty(ni);
+				if (ntfs_inode_close(ni))
+					set_fuse_error(&res);
+			}
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+		} else
+			res = -errno;
+#endif
+	}
+	return res;
+}
+
+static int ntfs_fuse_chown(const char *path, uid_t uid, gid_t gid)
+{
+	ntfs_inode *ni;
+	int res;
+	struct SECURITY_CONTEXT security;
+
+	if (ntfs_fuse_is_named_data_stream(path))
+		return -EINVAL; /* n/a for named data streams. */
+		/*
+		 * Return unsupported if no user mapping has been defined
+		 * or enforcing Windows-type inheritance
+		 */
+	if (ctx->inherit
+	    || !ntfs_fuse_fill_security_context(&security)) {
+		if (ctx->silent)
+			return 0;
+		if (uid == ctx->uid && gid == ctx->gid)
+			return 0;
+		return -EOPNOTSUPP;
+	} else {
+		res = 0;
+		if (((int)uid != -1) || ((int)gid != -1)) {
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+			   /* parent directory must be executable */
+		
+			if (ntfs_allowed_dir_access(&security,path,
+				(ntfs_inode*)NULL,(ntfs_inode*)NULL,S_IEXEC)) {
+#endif
+				ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+				if (!ni)
+					res = -errno;
+				else {
+					if (ntfs_set_owner(&security,
+							ni,uid,gid))
+						res = -errno;
+					else
+						ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);
+					if (ntfs_inode_close(ni))
+						set_fuse_error(&res);
+				}
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+			} else
+				res = -errno;
+#endif
+		}
+	}
+	return (res);
+}
+
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+
+static int ntfs_fuse_access(const char *path, int type)
+{
+	int res = 0;
+	int mode;
+	ntfs_inode *ni;
+	struct SECURITY_CONTEXT security;
+
+	if (ntfs_fuse_is_named_data_stream(path))
+		return -EINVAL; /* n/a for named data streams. */
+
+	  /* JPA return unsupported if no user mapping has been defined */
+	if (!ntfs_fuse_fill_security_context(&security)) {
+		if (ctx->silent)
+			res = 0;
+		else
+			res = -EOPNOTSUPP;
+	} else {
+		   /* parent directory must be seachable */
+		if (ntfs_allowed_dir_access(&security,path,(ntfs_inode*)NULL,
+				(ntfs_inode*)NULL,S_IEXEC)) {
+			ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+			if (!ni) {
+				res = -errno;
+			} else {
+				mode = 0;
+				if (type & (X_OK | W_OK | R_OK)) {
+					if (type & X_OK) mode += S_IEXEC;
+					if (type & W_OK) mode += S_IWRITE;
+					if (type & R_OK) mode += S_IREAD;
+					if (!ntfs_allowed_access(&security,
+							ni, mode))
+						res = -errno;
+				}
+				if (ntfs_inode_close(ni))
+					set_fuse_error(&res);
+			}
+		} else
+			res = -errno;
+	}
+	return (res);
+}
+
+#endif
+
+static int ntfs_fuse_create(const char *org_path, mode_t typemode, dev_t dev,
+		const char *target, struct fuse_file_info *fi)
+{
+	char *name;
+	ntfschar *uname = NULL, *utarget = NULL;
+	ntfs_inode *dir_ni = NULL, *ni;
+	char *dir_path;
+	le32 securid;
+	char *path = NULL;
+	gid_t gid;
+	mode_t dsetgid;
+	ntfschar *stream_name;
+	int stream_name_len;
+	mode_t type = typemode & ~07777;
+	mode_t perm;
+	struct SECURITY_CONTEXT security;
+	int res = 0, uname_len, utarget_len;
+
+	dir_path = strdup(org_path);
+	if (!dir_path)
+		return -errno;
+	/* Generate unicode filename. */
+	name = strrchr(dir_path, '/');
+	name++;
+	uname_len = ntfs_mbstoucs(name, &uname);
+	if ((uname_len < 0)
+	    || (ctx->windows_names
+		&& ntfs_forbidden_names(ctx->vol,uname,uname_len))) {
+		res = -errno;
+		goto exit;
+	}
+	stream_name_len = ntfs_fuse_parse_path(org_path,
+					 &path, &stream_name);
+		/* stream name validity has been checked previously */
+	if (stream_name_len < 0) {
+		res = stream_name_len;
+		goto exit;
+	}
+	/* Open parent directory. */
+	*--name = 0;
+	dir_ni = ntfs_pathname_to_inode(ctx->vol, NULL, dir_path);
+	if (!dir_ni) {
+		free(path);
+		res = -errno;
+		goto exit;
+	}
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+		/* make sure parent directory is writeable and executable */
+	if (!ntfs_fuse_fill_security_context(&security)
+	       || ntfs_allowed_create(&security,
+				dir_ni, &gid, &dsetgid)) {
+#else
+		ntfs_fuse_fill_security_context(&security);
+		ntfs_allowed_create(&security, dir_ni, &gid, &dsetgid);
+#endif
+		if (S_ISDIR(type))
+			perm = (typemode & ~ctx->dmask & 0777)
+				| (dsetgid & S_ISGID);
+		else
+			perm = typemode & ~ctx->fmask & 0777;
+			/*
+			 * Try to get a security id available for
+			 * file creation (from inheritance or argument).
+			 * This is not possible for NTFS 1.x, and we will
+			 * have to build a security attribute later.
+			 */
+		if (!ctx->security.mapping[MAPUSERS])
+			securid = 0;
+		else
+			if (ctx->inherit)
+				securid = ntfs_inherited_id(&security,
+					dir_ni, S_ISDIR(type));
+			else
+#if POSIXACLS
+				securid = ntfs_alloc_securid(&security,
+					security.uid, gid,
+					dir_ni, perm, S_ISDIR(type));
+#else
+				securid = ntfs_alloc_securid(&security,
+					security.uid, gid,
+					perm & ~security.umask, S_ISDIR(type));
+#endif
+		/* Create object specified in @type. */
+		switch (type) {
+			case S_IFCHR:
+			case S_IFBLK:
+				ni = ntfs_create_device(dir_ni, securid,
+						uname, uname_len, type,	dev);
+				break;
+			case S_IFLNK:
+				utarget_len = ntfs_mbstoucs(target, &utarget);
+				if (utarget_len < 0) {
+					res = -errno;
+					goto exit;
+				}
+				ni = ntfs_create_symlink(dir_ni, securid,
+						uname, uname_len,
+						utarget, utarget_len);
+				break;
+			default:
+				ni = ntfs_create(dir_ni, securid, uname,
+						uname_len, type);
+				break;
+		}
+		if (ni) {
+				/*
+				 * set the security attribute if a security id
+				 * could not be allocated (eg NTFS 1.x)
+				 */
+			if (ctx->security.mapping[MAPUSERS]) {
+#if POSIXACLS
+			   	if (!securid
+				   && ntfs_set_inherited_posix(&security, ni,
+					security.uid, gid,
+					dir_ni, perm) < 0)
+					set_fuse_error(&res);
+#else
+			   	if (!securid
+				   && ntfs_set_owner_mode(&security, ni,
+					security.uid, gid, 
+					perm & ~security.umask) < 0)
+					set_fuse_error(&res);
+#endif
+			}
+			set_archive(ni);
+			/* mark a need to compress the end of file */
+			if (fi && (ni->flags & FILE_ATTR_COMPRESSED)) {
+				fi->fh |= CLOSE_COMPRESSED;
+			}
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+			/* mark a future need to fixup encrypted inode */
+			if (fi
+			    && ctx->efs_raw
+			    && (ni->flags & FILE_ATTR_ENCRYPTED))
+				fi->fh |= CLOSE_ENCRYPTED;
+#endif /* HAVE_SETXATTR */
+			/* mark a need to update the mtime */
+			if (fi && ctx->dmtime)
+				fi->fh |= CLOSE_DMTIME;
+			NInoSetDirty(ni);
+			/*
+			 * closing ni requires access to dir_ni to
+			 * synchronize the index, avoid double opening.
+			 */
+			if (ntfs_inode_close_in_dir(ni, dir_ni))
+				set_fuse_error(&res);
+			ntfs_fuse_update_times(dir_ni, NTFS_UPDATE_MCTIME);
+		} else
+			res = -errno;
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	} else
+		res = -errno;
+#endif
+	free(path);
+
+exit:
+	free(uname);
+	if (ntfs_inode_close(dir_ni))
+		set_fuse_error(&res);
+	if (utarget)
+		free(utarget);
+	free(dir_path);
+	return res;
+}
+
+static int ntfs_fuse_create_stream(const char *path,
+		ntfschar *stream_name, const int stream_name_len,
+		struct fuse_file_info *fi)
+{
+	ntfs_inode *ni;
+	int res = 0;
+
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni) {
+		res = -errno;
+		if (res == -ENOENT) {
+			/*
+			 * If such file does not exist, create it and try once
+			 * again to add stream to it.
+			 * Note : no fuse_file_info for creation of main file
+			 */
+			res = ntfs_fuse_create(path, S_IFREG, 0, NULL,
+					(struct fuse_file_info*)NULL);
+			if (!res)
+				return ntfs_fuse_create_stream(path,
+						stream_name, stream_name_len,fi);
+			else
+				res = -errno;
+		}
+		return res;
+	}
+	if (ntfs_attr_add(ni, AT_DATA, stream_name, stream_name_len, NULL, 0))
+		res = -errno;
+	else
+		set_archive(ni);
+
+	if ((res >= 0)
+	    && fi
+	    && (fi->flags & (O_WRONLY | O_RDWR))) {
+		/* mark a future need to compress the last block */
+		if (ni->flags & FILE_ATTR_COMPRESSED)
+			fi->fh |= CLOSE_COMPRESSED;
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+		/* mark a future need to fixup encrypted inode */
+		if (ctx->efs_raw
+		    && (ni->flags & FILE_ATTR_ENCRYPTED))
+			fi->fh |= CLOSE_ENCRYPTED;
+#endif /* HAVE_SETXATTR */
+		if (ctx->dmtime)
+			fi->fh |= CLOSE_DMTIME;
+	}
+
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	return res;
+}
+
+static int ntfs_fuse_mknod_common(const char *org_path, mode_t mode, dev_t dev,
+				struct fuse_file_info *fi)
+{
+	char *path = NULL;
+	ntfschar *stream_name;
+	int stream_name_len;
+	int res = 0;
+
+	stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);
+	if (stream_name_len < 0)
+		return stream_name_len;
+	if (stream_name_len
+	    && (!S_ISREG(mode)
+		|| (ctx->windows_names
+		    && ntfs_forbidden_names(ctx->vol,stream_name,
+					stream_name_len)))) {
+		res = -EINVAL;
+		goto exit;
+	}
+	if (!stream_name_len)
+		res = ntfs_fuse_create(path, mode & (S_IFMT | 07777), dev, 
+					NULL,fi);
+	else
+		res = ntfs_fuse_create_stream(path, stream_name,
+				stream_name_len,fi);
+exit:
+	free(path);
+	if (stream_name_len)
+		free(stream_name);
+	return res;
+}
+
+static int ntfs_fuse_mknod(const char *path, mode_t mode, dev_t dev)
+{
+	return ntfs_fuse_mknod_common(path, mode, dev,
+			(struct fuse_file_info*)NULL);
+}
+
+static int ntfs_fuse_create_file(const char *path, mode_t mode,
+			    struct fuse_file_info *fi)
+{
+	return ntfs_fuse_mknod_common(path, mode, 0, fi);
+}
+
+static int ntfs_fuse_symlink(const char *to, const char *from)
+{
+	if (ntfs_fuse_is_named_data_stream(from))
+		return -EINVAL; /* n/a for named data streams. */
+	return ntfs_fuse_create(from, S_IFLNK, 0, to,
+			(struct fuse_file_info*)NULL);
+}
+
+static int ntfs_fuse_link(const char *old_path, const char *new_path)
+{
+	char *name;
+	ntfschar *uname = NULL;
+	ntfs_inode *dir_ni = NULL, *ni;
+	char *path;
+	int res = 0, uname_len;
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	BOOL samedir;
+	struct SECURITY_CONTEXT security;
+#endif
+
+	if (ntfs_fuse_is_named_data_stream(old_path))
+		return -EINVAL; /* n/a for named data streams. */
+	if (ntfs_fuse_is_named_data_stream(new_path))
+		return -EINVAL; /* n/a for named data streams. */
+	path = strdup(new_path);
+	if (!path)
+		return -errno;
+	/* Open file for which create hard link. */
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, old_path);
+	if (!ni) {
+		res = -errno;
+		goto exit;
+	}
+	
+	/* Generate unicode filename. */
+	name = strrchr(path, '/');
+	name++;
+	uname_len = ntfs_mbstoucs(name, &uname);
+	if ((uname_len < 0)
+	    || (ctx->windows_names
+		&& ntfs_forbidden_names(ctx->vol,uname,uname_len))) {
+		res = -errno;
+		goto exit;
+	}
+	/* Open parent directory. */
+	*--name = 0;
+	dir_ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!dir_ni) {
+		res = -errno;
+		goto exit;
+	}
+
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	samedir = !strncmp(old_path, path, strlen(path))
+			&& (old_path[strlen(path)] == '/');
+		/* JPA make sure the parent directories are writeable */
+	if (ntfs_fuse_fill_security_context(&security)
+	   && ((!samedir && !ntfs_allowed_dir_access(&security,old_path,
+			(ntfs_inode*)NULL,ni,S_IWRITE + S_IEXEC))
+	      || !ntfs_allowed_access(&security,dir_ni,S_IWRITE + S_IEXEC)))
+		res = -EACCES;
+	else
+#endif
+	{
+		if (ntfs_link(ni, dir_ni, uname, uname_len)) {
+				res = -errno;
+			goto exit;
+		}
+	
+		set_archive(ni);
+		ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);
+		ntfs_fuse_update_times(dir_ni, NTFS_UPDATE_MCTIME);
+	}
+exit:
+	/* 
+	 * Must close dir_ni first otherwise ntfs_inode_sync_file_name(ni)
+	 * may fail because ni may not be in parent's index on the disk yet.
+	 */
+	if (ntfs_inode_close(dir_ni))
+		set_fuse_error(&res);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	free(uname);
+	free(path);
+	return res;
+}
+
+static int ntfs_fuse_rm(const char *org_path)
+{
+	char *name;
+	ntfschar *uname = NULL;
+	ntfs_inode *dir_ni = NULL, *ni;
+	char *path;
+	int res = 0, uname_len;
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	struct SECURITY_CONTEXT security;
+#endif
+
+	path = strdup(org_path);
+	if (!path)
+		return -errno;
+	/* Open object for delete. */
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni) {
+		res = -errno;
+		goto exit;
+	}
+	/* deny unlinking metadata files */
+	if (ni->mft_no < FILE_first_user) {
+		errno = EPERM;
+		res = -errno;
+		goto exit;
+	}
+
+	/* Generate unicode filename. */
+	name = strrchr(path, '/');
+	name++;
+	uname_len = ntfs_mbstoucs(name, &uname);
+	if (uname_len < 0) {
+		res = -errno;
+		goto exit;
+	}
+	/* Open parent directory. */
+	*--name = 0;
+	dir_ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!dir_ni) {
+		res = -errno;
+		goto exit;
+	}
+	
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	/* JPA deny unlinking if directory is not writable and executable */
+	if (!ntfs_fuse_fill_security_context(&security)
+	    || ntfs_allowed_dir_access(&security, org_path, dir_ni, ni,
+				   S_IEXEC + S_IWRITE + S_ISVTX)) {
+#endif
+		if (ntfs_delete(ctx->vol, org_path, ni, dir_ni,
+				 uname, uname_len))
+			res = -errno;
+		/* ntfs_delete() always closes ni and dir_ni */
+		ni = dir_ni = NULL;
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	} else
+		res = -EACCES;
+#endif
+exit:
+	if (ntfs_inode_close(dir_ni))
+		set_fuse_error(&res);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	free(uname);
+	free(path);
+	return res;
+}
+
+static int ntfs_fuse_rm_stream(const char *path, ntfschar *stream_name,
+		const int stream_name_len)
+{
+	ntfs_inode *ni;
+	int res = 0;
+
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni)
+		return -errno;
+	
+	if (ntfs_attr_remove(ni, AT_DATA, stream_name, stream_name_len))
+		res = -errno;
+
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	return res;
+}
+
+static int ntfs_fuse_unlink(const char *org_path)
+{
+	char *path = NULL;
+	ntfschar *stream_name;
+	int stream_name_len;
+	int res = 0;
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	struct SECURITY_CONTEXT security;
+#endif
+
+	stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);
+	if (stream_name_len < 0)
+		return stream_name_len;
+	if (!stream_name_len)
+		res = ntfs_fuse_rm(path);
+	else {
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+			/*
+			 * JPA deny unlinking stream if directory is not
+			 * writable and executable (debatable)
+			 */
+		if (!ntfs_fuse_fill_security_context(&security)
+		   || ntfs_allowed_dir_access(&security, path,
+				(ntfs_inode*)NULL, (ntfs_inode*)NULL,
+				S_IEXEC + S_IWRITE + S_ISVTX))
+			res = ntfs_fuse_rm_stream(path, stream_name,
+					stream_name_len);
+		else
+			res = -errno;
+#else
+		res = ntfs_fuse_rm_stream(path, stream_name, stream_name_len);
+#endif
+	}
+	free(path);
+	if (stream_name_len)
+		free(stream_name);
+	return res;
+}
+
+static int ntfs_fuse_safe_rename(const char *old_path, 
+				 const char *new_path, 
+				 const char *tmp)
+{
+	int ret;
+
+	ntfs_log_trace("Entering\n");
+	
+	ret = ntfs_fuse_link(new_path, tmp);
+	if (ret)
+		return ret;
+	
+	ret = ntfs_fuse_unlink(new_path);
+	if (!ret) {
+		
+		ret = ntfs_fuse_link(old_path, new_path);
+		if (ret)
+			goto restore;
+		
+		ret = ntfs_fuse_unlink(old_path);
+		if (ret) {
+			if (ntfs_fuse_unlink(new_path))
+				goto err;
+			goto restore;
+		}
+	}
+	
+	goto cleanup;
+restore:
+	if (ntfs_fuse_link(tmp, new_path)) {
+err:
+		ntfs_log_perror("Rename failed. Existing file '%s' was renamed "
+				"to '%s'", new_path, tmp);
+	} else {
+cleanup:
+		/*
+		 * Condition for this unlink has already been checked in
+		 * "ntfs_fuse_rename_existing_dest()", so it should never
+		 * fail (unless concurrent access to directories when fuse
+		 * is multithreaded)
+		 */
+		if (ntfs_fuse_unlink(tmp) < 0)
+			ntfs_log_perror("Rename failed. Existing file '%s' still present "
+				"as '%s'", new_path, tmp);
+	}
+	return 	ret;
+}
+
+static int ntfs_fuse_rename_existing_dest(const char *old_path, const char *new_path)
+{
+	int ret, len;
+	char *tmp;
+	const char *ext = ".ntfs-3g-";
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	struct SECURITY_CONTEXT security;
+#endif
+
+	ntfs_log_trace("Entering\n");
+	
+	len = strlen(new_path) + strlen(ext) + 10 + 1; /* wc(str(2^32)) + \0 */
+	tmp = ntfs_malloc(len);
+	if (!tmp)
+		return -errno;
+	
+	ret = snprintf(tmp, len, "%s%s%010d", new_path, ext, ++ntfs_sequence);
+	if (ret != len - 1) {
+		ntfs_log_error("snprintf failed: %d != %d\n", ret, len - 1);
+		ret = -EOVERFLOW;
+	} else {
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+			/*
+			 * Make sure existing dest can be removed.
+			 * This is only needed if parent directory is
+			 * sticky, because in this situation condition
+			 * for unlinking is different from condition for
+			 * linking
+			 */
+		if (!ntfs_fuse_fill_security_context(&security)
+		  || ntfs_allowed_dir_access(&security, new_path,
+				(ntfs_inode*)NULL, (ntfs_inode*)NULL,
+				S_IEXEC + S_IWRITE + S_ISVTX))
+			ret = ntfs_fuse_safe_rename(old_path, new_path, tmp);
+		else
+			ret = -EACCES;
+#else
+		ret = ntfs_fuse_safe_rename(old_path, new_path, tmp);
+#endif
+	}
+	free(tmp);
+	return 	ret;
+}
+
+static int ntfs_fuse_rename(const char *old_path, const char *new_path)
+{
+	int ret, stream_name_len;
+	char *path = NULL;
+	ntfschar *stream_name;
+	ntfs_inode *ni;
+	u64 inum;
+	BOOL same;
+	
+	ntfs_log_debug("rename: old: '%s'  new: '%s'\n", old_path, new_path);
+	
+	/*
+	 *  FIXME: Rename should be atomic.
+	 */
+	stream_name_len = ntfs_fuse_parse_path(new_path, &path, &stream_name);
+	if (stream_name_len < 0)
+		return stream_name_len;
+	
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (ni) {
+		ret = ntfs_check_empty_dir(ni);
+		if (ret < 0) {
+			ret = -errno;
+			ntfs_inode_close(ni);
+			goto out;
+		}
+		
+		inum = ni->mft_no;
+		if (ntfs_inode_close(ni)) {
+			set_fuse_error(&ret);
+			goto out;
+		}
+
+		free(path);
+		path = (char*)NULL;
+		if (stream_name_len)
+			free(stream_name);
+
+			/* silently ignore a rename to same inode */
+		stream_name_len = ntfs_fuse_parse_path(old_path,
+						&path, &stream_name);
+		if (stream_name_len < 0)
+			return stream_name_len;
+	
+		ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+		if (ni) {
+			same = ni->mft_no == inum;
+			if (ntfs_inode_close(ni))
+				ret = -errno;
+			else
+				if (!same)
+					ret = ntfs_fuse_rename_existing_dest(
+							old_path, new_path);
+		} else
+			ret = -errno;
+		goto out;
+	}
+
+	ret = ntfs_fuse_link(old_path, new_path);
+	if (ret)
+		goto out;
+	
+	ret = ntfs_fuse_unlink(old_path);
+	if (ret)
+		ntfs_fuse_unlink(new_path);
+out:
+	free(path);
+	if (stream_name_len)
+		free(stream_name);
+	return ret;
+}
+
+static int ntfs_fuse_mkdir(const char *path,
+		mode_t mode)
+{
+	if (ntfs_fuse_is_named_data_stream(path))
+		return -EINVAL; /* n/a for named data streams. */
+	return ntfs_fuse_create(path, S_IFDIR | (mode & 07777), 0, NULL,
+			(struct fuse_file_info*)NULL);
+}
+
+static int ntfs_fuse_rmdir(const char *path)
+{
+	if (ntfs_fuse_is_named_data_stream(path))
+		return -EINVAL; /* n/a for named data streams. */
+	return ntfs_fuse_rm(path);
+}
+
+#ifdef HAVE_UTIMENSAT
+
+static int ntfs_fuse_utimens(const char *path, const struct timespec tv[2])
+{
+	ntfs_inode *ni;
+	int res = 0;
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	struct SECURITY_CONTEXT security;
+#endif
+
+	if (ntfs_fuse_is_named_data_stream(path))
+		return -EINVAL; /* n/a for named data streams. */
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+		   /* parent directory must be executable */
+	if (ntfs_fuse_fill_security_context(&security)
+	    && !ntfs_allowed_dir_access(&security,path,
+			(ntfs_inode*)NULL,(ntfs_inode*)NULL,S_IEXEC)) {
+		return (-errno);
+	}
+#endif
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni)
+		return -errno;
+
+			/* no check or update if both UTIME_OMIT */
+	if ((tv[0].tv_nsec != UTIME_OMIT) || (tv[1].tv_nsec != UTIME_OMIT)) {
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+		if (ntfs_allowed_as_owner(&security, ni)
+		    || ((tv[0].tv_nsec == UTIME_NOW)
+			&& (tv[1].tv_nsec == UTIME_NOW)
+			&& ntfs_allowed_access(&security, ni, S_IWRITE))) {
+#endif
+			ntfs_time_update_flags mask = NTFS_UPDATE_CTIME;
+
+			if (tv[0].tv_nsec == UTIME_NOW)
+				mask |= NTFS_UPDATE_ATIME;
+			else
+				if (tv[0].tv_nsec != UTIME_OMIT)
+					ni->last_access_time
+						= timespec2ntfs(tv[0]);
+			if (tv[1].tv_nsec == UTIME_NOW)
+				mask |= NTFS_UPDATE_MTIME;
+			else
+				if (tv[1].tv_nsec != UTIME_OMIT)
+					ni->last_data_change_time
+						= timespec2ntfs(tv[1]);
+			ntfs_inode_update_times(ni, mask);
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+		} else
+			res = -errno;
+#endif
+	}
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	return res;
+}
+
+#else /* HAVE_UTIMENSAT */
+
+static int ntfs_fuse_utime(const char *path, struct utimbuf *buf)
+{
+	ntfs_inode *ni;
+	int res = 0;
+	struct timespec actime;
+	struct timespec modtime;
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	BOOL ownerok;
+	BOOL writeok;
+	struct SECURITY_CONTEXT security;
+#endif
+
+	if (ntfs_fuse_is_named_data_stream(path))
+		return -EINVAL; /* n/a for named data streams. */
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+		   /* parent directory must be executable */
+	if (ntfs_fuse_fill_security_context(&security)
+	    && !ntfs_allowed_dir_access(&security,path,
+			(ntfs_inode*)NULL,(ntfs_inode*)NULL,S_IEXEC)) {
+		return (-errno);
+	}
+#endif
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni)
+		return -errno;
+	
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	ownerok = ntfs_allowed_as_owner(&security, ni);
+	if (buf) {
+		/*
+		 * fuse never calls with a NULL buf and we do not
+		 * know whether the specific condition can be applied
+		 * So we have to accept updating by a non-owner having
+		 * write access.
+		 */
+		writeok = !ownerok
+			&& (buf->actime == buf->modtime)
+			&& ntfs_allowed_access(&security, ni, S_IWRITE);
+			/* Must be owner */
+		if (!ownerok && !writeok)
+			res = (buf->actime == buf->modtime ? -EACCES : -EPERM);
+		else {
+			actime.tv_sec = buf->actime;
+			actime.tv_nsec = 0;
+			modtime.tv_sec = buf->modtime;
+			modtime.tv_nsec = 0;
+			ni->last_access_time = timespec2ntfs(actime);
+			ni->last_data_change_time = timespec2ntfs(modtime);
+			ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);
+		}
+	} else {
+			/* Must be owner or have write access */
+		writeok = !ownerok
+			&& ntfs_allowed_access(&security, ni, S_IWRITE);
+		if (!ownerok && !writeok)
+			res = -EACCES;
+		else
+			ntfs_inode_update_times(ni, NTFS_UPDATE_AMCTIME);
+	}
+#else
+	if (buf) {
+		actime.tv_sec = buf->actime;
+		actime.tv_nsec = 0;
+		modtime.tv_sec = buf->modtime;
+		modtime.tv_nsec = 0;
+		ni->last_access_time = timespec2ntfs(actime);
+		ni->last_data_change_time = timespec2ntfs(modtime);
+		ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);
+	} else
+		ntfs_inode_update_times(ni, NTFS_UPDATE_AMCTIME);
+#endif
+
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	return res;
+}
+
+#endif /* HAVE_UTIMENSAT */
+
+static int ntfs_fuse_fsync(const char *path __attribute__((unused)),
+			int type __attribute__((unused)),
+			struct fuse_file_info *fi __attribute__((unused)))
+{
+	int ret;
+
+		/* sync the full device */
+	ret = ntfs_device_sync(ctx->vol->dev);
+	if (ret)
+		ret = -errno;
+	return (ret);
+}
+
+#if defined(FUSE_INTERNAL) || (FUSE_VERSION >= 28)
+static int ntfs_fuse_ioctl(const char *path,
+			int cmd, void *arg,
+			struct fuse_file_info *fi __attribute__((unused)),
+			unsigned int flags, void *data)
+{
+	ntfs_inode *ni;
+	int ret;
+
+	if (flags & FUSE_IOCTL_COMPAT)
+		return -ENOSYS;
+
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni)
+		return -errno;
+
+	ret = ntfs_ioctl(ni, cmd, arg, flags, data);
+
+	if (ntfs_inode_close (ni))
+		set_fuse_error(&ret);
+	return ret;
+}
+#endif /* defined(FUSE_INTERNAL) || (FUSE_VERSION >= 28) */
+
+static int ntfs_fuse_bmap(const char *path, size_t blocksize, uint64_t *idx)
+{
+	ntfs_inode *ni;
+	ntfs_attr *na;
+	LCN lcn;
+	int ret = 0; 
+	int cl_per_bl = ctx->vol->cluster_size / blocksize;
+
+	if (blocksize > ctx->vol->cluster_size)
+		return -EINVAL;
+	
+	if (ntfs_fuse_is_named_data_stream(path))
+		return -EINVAL;
+	
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni)
+		return -errno;
+
+	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
+	if (!na) {
+		ret = -errno;
+		goto close_inode;
+	}
+	
+	if ((na->data_flags & (ATTR_COMPRESSION_MASK | ATTR_IS_ENCRYPTED))
+			 || !NAttrNonResident(na)) {
+		ret = -EINVAL;
+		goto close_attr;
+	}
+	
+	if (ntfs_attr_map_whole_runlist(na)) {
+		ret = -errno;
+		goto close_attr;
+	}
+	
+	lcn = ntfs_rl_vcn_to_lcn(na->rl, *idx / cl_per_bl);
+	*idx = (lcn > 0) ? lcn * cl_per_bl + *idx % cl_per_bl : 0;
+	
+close_attr:
+	ntfs_attr_close(na);
+close_inode:
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&ret);
+	return ret;
+}
+
+#ifdef HAVE_SETXATTR
+
+/*
+ *                Name space identifications and prefixes
+ */
+
+enum {
+	XATTRNS_NONE,
+	XATTRNS_USER,
+	XATTRNS_SYSTEM,
+	XATTRNS_SECURITY,
+	XATTRNS_TRUSTED,
+	XATTRNS_OPEN
+} ;
+
+/*
+ *		Check whether access to internal data as an extended
+ *	attribute in system name space is allowed
+ *
+ *	Returns pointer to inode if allowed,
+ *		NULL and errno set if not allowed
+ */
+
+static ntfs_inode *ntfs_check_access_xattr(struct SECURITY_CONTEXT *security,
+			const char *path, int attr, BOOL setting)
+{
+	ntfs_inode *ni;
+	BOOL foracl;
+	mode_t acctype;
+
+	ni = (ntfs_inode*)NULL;
+	if (ntfs_fuse_is_named_data_stream(path))
+		errno = EINVAL; /* n/a for named data streams. */
+	else {
+		foracl = (attr == XATTR_POSIX_ACC)
+			 || (attr == XATTR_POSIX_DEF);
+		/*
+		 * When accessing Posix ACL, return unsupported if ACL
+		 * were disabled or no user mapping has been defined,
+		 * or trying to change a Windows-inherited ACL.
+		 * However no error will be returned to getfacl
+		 */
+		if (((!ntfs_fuse_fill_security_context(security)
+			|| (ctx->secure_flags
+			    & ((1 << SECURITY_DEFAULT) | (1 << SECURITY_RAW))))
+			|| !(ctx->secure_flags & (1 << SECURITY_ACL))
+			|| (setting && ctx->inherit))
+		    && foracl) {
+			if (ctx->silent)
+				errno = 0;
+			else
+				errno = EOPNOTSUPP;
+		} else {
+				/*
+				 * parent directory must be executable, and
+				 * for setting a DOS name it must be writeable
+				 */
+			if (setting && (attr == XATTR_NTFS_DOS_NAME))
+				acctype = S_IEXEC | S_IWRITE;
+			else
+				acctype = S_IEXEC;
+			if ((attr == XATTR_NTFS_DOS_NAME)
+			    && !strcmp(path,"/"))
+				/* forbid getting/setting names on root */
+				errno = EPERM;
+			else
+				if (ntfs_allowed_real_dir_access(security, path,
+					   (ntfs_inode*)NULL ,acctype)) {
+					ni = ntfs_pathname_to_inode(ctx->vol,
+							NULL, path);
+			}
+		}
+	}
+	return (ni);
+}
+
+/*
+ *		Determine the name space of an extended attribute
+ */
+
+static int xattr_namespace(const char *name)
+{
+	int namespace;
+
+	if (ctx->streams == NF_STREAMS_INTERFACE_XATTR) {
+		namespace = XATTRNS_NONE;
+		if (!strncmp(name, nf_ns_user_prefix, 
+			nf_ns_user_prefix_len)
+		    && (strlen(name) != (size_t)nf_ns_user_prefix_len))
+			namespace = XATTRNS_USER;
+		else if (!strncmp(name, nf_ns_system_prefix, 
+			nf_ns_system_prefix_len)
+		    && (strlen(name) != (size_t)nf_ns_system_prefix_len))
+			namespace = XATTRNS_SYSTEM;
+		else if (!strncmp(name, nf_ns_security_prefix, 
+			nf_ns_security_prefix_len)
+		    && (strlen(name) != (size_t)nf_ns_security_prefix_len))
+			namespace = XATTRNS_SECURITY;
+		else if (!strncmp(name, nf_ns_trusted_prefix, 
+			nf_ns_trusted_prefix_len)
+		    && (strlen(name) != (size_t)nf_ns_trusted_prefix_len))
+			namespace = XATTRNS_TRUSTED;
+	} else
+		namespace = XATTRNS_OPEN;
+	return (namespace);
+}
+
+/*
+ *		Fix the prefix of an extended attribute
+ */
+
+static int fix_xattr_prefix(const char *name, int namespace, ntfschar **lename)
+{
+	int len;
+	char *prefixed;
+
+	*lename = (ntfschar*)NULL;
+	switch (namespace) {
+	case XATTRNS_USER :
+		/*
+		 * user name space : remove user prefix
+		 */
+		len = ntfs_mbstoucs(name + nf_ns_user_prefix_len, lename);
+		break;
+	case XATTRNS_SYSTEM :
+	case XATTRNS_SECURITY :
+	case XATTRNS_TRUSTED :
+		/*
+		 * security, trusted and unmapped system name spaces :
+		 * insert ntfs-3g prefix
+		 */
+		prefixed = ntfs_malloc(strlen(xattr_ntfs_3g)
+			 + strlen(name) + 1);
+		if (prefixed) {
+			strcpy(prefixed,xattr_ntfs_3g);
+			strcat(prefixed,name);
+			len = ntfs_mbstoucs(prefixed, lename);
+			free(prefixed);
+		} else
+			len = -1;
+		break;
+	case XATTRNS_OPEN :
+		/*
+		 * in open name space mode : do no fix prefix
+		 */
+		len = ntfs_mbstoucs(name, lename);
+		break;
+	default :
+		len = -1;
+	}
+	return (len);
+}
+
+static int ntfs_fuse_listxattr(const char *path, char *list, size_t size)
+{
+	ntfs_attr_search_ctx *actx = NULL;
+	ntfs_inode *ni;
+	int ret = 0;
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	struct SECURITY_CONTEXT security;
+#endif
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+		   /* parent directory must be executable */
+	if (ntfs_fuse_fill_security_context(&security)
+	    && !ntfs_allowed_dir_access(&security,path,(ntfs_inode*)NULL,
+			(ntfs_inode*)NULL,S_IEXEC)) {
+		return (-errno);
+	}
+#endif
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni)
+		return -errno;
+		/* Return with no result for symlinks, fifo, etc. */
+	if (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT))
+		goto exit;
+		/* otherwise file must be readable */
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	if (!ntfs_allowed_access(&security,ni,S_IREAD)) {
+		ret = -EACCES;
+		goto exit;
+	}
+#endif
+	actx = ntfs_attr_get_search_ctx(ni, NULL);
+	if (!actx) {
+		ret = -errno;
+		goto exit;
+	}
+
+	if ((ctx->streams == NF_STREAMS_INTERFACE_XATTR)
+	    || (ctx->streams == NF_STREAMS_INTERFACE_OPENXATTR)) {
+		ret = ntfs_fuse_listxattr_common(ni, actx, list, size,
+				ctx->streams == NF_STREAMS_INTERFACE_XATTR);
+		if (ret < 0)
+			goto exit;
+	}
+	if (errno != ENOENT)
+		ret = -errno;
+exit:
+	if (actx)
+		ntfs_attr_put_search_ctx(actx);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&ret);
+	return ret;
+}
+
+static int ntfs_fuse_getxattr_windows(const char *path, const char *name,
+				char *value, size_t size)
+{
+	ntfs_attr_search_ctx *actx = NULL;
+	ntfs_inode *ni;
+	char *to = value;
+	int ret = 0;
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	struct SECURITY_CONTEXT security;
+#endif
+
+	if (strcmp(name, "ntfs.streams.list"))
+		return -EOPNOTSUPP;
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+		   /* parent directory must be executable */
+	if (ntfs_fuse_fill_security_context(&security)
+	    && !ntfs_allowed_dir_access(&security,path,(ntfs_inode*)NULL,
+			(ntfs_inode*)NULL,S_IEXEC)) {
+		return (-errno);
+	}
+#endif
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni)
+		return -errno;
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	if (!ntfs_allowed_access(&security,ni,S_IREAD)) {
+		ret = -errno;
+		goto exit;
+	}
+#endif
+	actx = ntfs_attr_get_search_ctx(ni, NULL);
+	if (!actx) {
+		ret = -errno;
+		goto exit;
+	}
+	while (!ntfs_attr_lookup(AT_DATA, NULL, 0, CASE_SENSITIVE,
+				0, NULL, 0, actx)) {
+		char *tmp_name = NULL;
+		int tmp_name_len;
+
+		if (!actx->attr->name_length)
+			continue;
+		tmp_name_len = ntfs_ucstombs((ntfschar *)((u8*)actx->attr +
+				le16_to_cpu(actx->attr->name_offset)),
+				actx->attr->name_length, &tmp_name, 0);
+		if (tmp_name_len < 0) {
+			ret = -errno;
+			goto exit;
+		}
+		if (ret)
+			ret++; /* For space delimiter. */
+		ret += tmp_name_len;
+		if (size) {
+			if ((size_t)ret <= size) {
+				/* Don't add space to the beginning of line. */
+				if (to != value) {
+					*to = '\0';
+					to++;
+				}
+				strncpy(to, tmp_name, tmp_name_len);
+				to += tmp_name_len;
+			} else {
+				free(tmp_name);
+				ret = -ERANGE;
+				goto exit;
+			}
+		}
+		free(tmp_name);
+	}
+	if (errno != ENOENT)
+		ret = -errno;
+exit:
+	if (actx)
+		ntfs_attr_put_search_ctx(actx);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&ret);
+	return ret;
+}
+
+static int ntfs_fuse_getxattr(const char *path, const char *name,
+				char *value, size_t size)
+{
+	ntfs_inode *ni;
+	ntfs_inode *dir_ni;
+	ntfs_attr *na = NULL;
+	ntfschar *lename = NULL;
+	int res, lename_len;
+	s64 rsize;
+	enum SYSTEMXATTRS attr;
+	int namespace;
+	struct SECURITY_CONTEXT security;
+
+	attr = ntfs_xattr_system_type(name,ctx->vol);
+	if (attr != XATTR_UNMAPPED) {
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+			/*
+			 * hijack internal data and ACL retrieval, whatever
+			 * mode was selected for xattr (from the user's
+			 * point of view, ACLs are not xattr)
+			 */
+		ni = ntfs_check_access_xattr(&security, path, attr, FALSE);
+		if (ni) {
+			if (ntfs_allowed_access(&security,ni,S_IREAD)) {
+				if (attr == XATTR_NTFS_DOS_NAME)
+					dir_ni = get_parent_dir(path);
+				else
+					dir_ni = (ntfs_inode*)NULL;
+				res = ntfs_xattr_system_getxattr(&security,
+					attr, ni, dir_ni, value, size);
+				if (dir_ni && ntfs_inode_close(dir_ni))
+					set_fuse_error(&res);
+			} else {
+				res = -errno;
+                        }
+			if (ntfs_inode_close(ni))
+				set_fuse_error(&res);
+		} else
+			res = -errno;
+#else
+			/*
+			 * Only hijack NTFS ACL retrieval if POSIX ACLS
+			 * option is not selected
+			 * Access control is done by fuse
+			 */
+		if (ntfs_fuse_is_named_data_stream(path))
+			res = -EINVAL; /* n/a for named data streams. */
+		else {
+			ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+			if (ni) {
+					/* user mapping not mandatory */
+				ntfs_fuse_fill_security_context(&security);
+				if (attr == XATTR_NTFS_DOS_NAME)
+					dir_ni = get_parent_dir(path);
+				else
+					dir_ni = (ntfs_inode*)NULL;
+				res = ntfs_xattr_system_getxattr(&security,
+					attr, ni, dir_ni, value, size);
+				if (dir_ni && ntfs_inode_close(dir_ni))
+					set_fuse_error(&res);
+				if (ntfs_inode_close(ni))
+					set_fuse_error(&res);
+			} else
+				res = -errno;
+		}
+#endif
+		return (res);
+	}
+	if (ctx->streams == NF_STREAMS_INTERFACE_WINDOWS)
+		return ntfs_fuse_getxattr_windows(path, name, value, size);
+	if (ctx->streams == NF_STREAMS_INTERFACE_NONE)
+		return -EOPNOTSUPP;
+	namespace = xattr_namespace(name);
+	if (namespace == XATTRNS_NONE)
+		return -EOPNOTSUPP;
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+		   /* parent directory must be executable */
+	if (ntfs_fuse_fill_security_context(&security)
+	    && !ntfs_allowed_dir_access(&security,path,(ntfs_inode*)NULL,
+			(ntfs_inode*)NULL,S_IEXEC)) {
+		return (-errno);
+	}
+		/* trusted only readable by root */
+	if ((namespace == XATTRNS_TRUSTED)
+	    && security.uid)
+		    return -ENODATA;
+#endif
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni)
+		return -errno;
+		/* Return with no result for symlinks, fifo, etc. */
+	if (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT)) {
+		res = -ENODATA;
+		goto exit;
+	}
+		/* otherwise file must be readable */
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	if (!ntfs_allowed_access(&security, ni, S_IREAD)) {
+		res = -errno;
+		goto exit;
+	}
+#endif
+	lename_len = fix_xattr_prefix(name, namespace, &lename);
+	if (lename_len == -1) {
+		res = -errno;
+		goto exit;
+	}
+	na = ntfs_attr_open(ni, AT_DATA, lename, lename_len);
+	if (!na) {
+		res = -ENODATA;
+		goto exit;
+	}
+	rsize = na->data_size;
+	if (ctx->efs_raw
+	    && rsize
+	    && (na->data_flags & ATTR_IS_ENCRYPTED)
+	    && NAttrNonResident(na))
+		rsize = ((na->data_size + 511) & ~511) + 2;
+	if (size) {
+		if (size >= (size_t)rsize) {
+			res = ntfs_attr_pread(na, 0, rsize, value);
+			if (res != rsize)
+				res = -errno;
+		} else
+			res = -ERANGE;
+	} else
+		res = rsize;
+exit:
+	if (na)
+		ntfs_attr_close(na);
+	free(lename);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	return res;
+}
+
+static int ntfs_fuse_setxattr(const char *path, const char *name,
+				const char *value, size_t size, int flags)
+{
+	ntfs_inode *ni;
+	ntfs_inode *dir_ni;
+	ntfs_attr *na = NULL;
+	ntfschar *lename = NULL;
+	int res, lename_len;
+	size_t total;
+	s64 part;
+	enum SYSTEMXATTRS attr;
+	int namespace;
+	struct SECURITY_CONTEXT security;
+
+	attr = ntfs_xattr_system_type(name,ctx->vol);
+	if (attr != XATTR_UNMAPPED) {
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+			/*
+			 * hijack internal data and ACL setting, whatever
+			 * mode was selected for xattr (from the user's
+			 * point of view, ACLs are not xattr)
+			 * Note : ctime updated on successful settings
+			 */
+		ni = ntfs_check_access_xattr(&security,path,attr,TRUE);
+		if (ni) {
+			if (ntfs_allowed_as_owner(&security,ni)) {
+				if (attr == XATTR_NTFS_DOS_NAME)
+					dir_ni = get_parent_dir(path);
+				else
+					dir_ni = (ntfs_inode*)NULL;
+				res = ntfs_xattr_system_setxattr(&security,
+					attr, ni, dir_ni, value, size, flags);
+				/* never have to close dir_ni */
+				if (res)
+					res = -errno;
+			} else
+				res = -errno;
+			if (attr != XATTR_NTFS_DOS_NAME) {
+				if (!res)
+					ntfs_fuse_update_times(ni,
+							NTFS_UPDATE_CTIME);
+				if (ntfs_inode_close(ni))
+					set_fuse_error(&res);
+			}
+		} else
+			res = -errno;
+#else
+			/*
+			 * Only hijack NTFS ACL setting if POSIX ACLS
+			 * option is not selected
+			 * Access control is partially done by fuse
+			 */
+		if (ntfs_fuse_is_named_data_stream(path))
+			res = -EINVAL; /* n/a for named data streams. */
+		else {
+			/* creation of a new name is not controlled by fuse */
+			if (attr == XATTR_NTFS_DOS_NAME)
+				ni = ntfs_check_access_xattr(&security,path,attr,TRUE);
+			else
+				ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+			if (ni) {
+					/*
+					 * user mapping is not mandatory
+					 * if defined, only owner is allowed
+					 */
+				if (!ntfs_fuse_fill_security_context(&security)
+				   || ntfs_allowed_as_owner(&security,ni)) {
+					if (attr == XATTR_NTFS_DOS_NAME)
+						dir_ni = get_parent_dir(path);
+					else
+						dir_ni = (ntfs_inode*)NULL;
+					res = ntfs_xattr_system_setxattr(&security,
+						attr, ni, dir_ni, value,
+						size, flags);
+					/* never have to close dir_ni */
+					if (res)
+						res = -errno;
+				} else
+					res = -errno;
+				if (attr != XATTR_NTFS_DOS_NAME) {
+					if (!res)
+						ntfs_fuse_update_times(ni,
+							NTFS_UPDATE_CTIME);
+					if (ntfs_inode_close(ni))
+						set_fuse_error(&res);
+				}
+			} else
+				res = -errno;
+		}
+#endif
+		return (res);
+	}
+	if ((ctx->streams != NF_STREAMS_INTERFACE_XATTR)
+	    && (ctx->streams != NF_STREAMS_INTERFACE_OPENXATTR))
+		return -EOPNOTSUPP;
+	namespace = xattr_namespace(name);
+	if (namespace == XATTRNS_NONE)
+		return -EOPNOTSUPP;
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+		   /* parent directory must be executable */
+	if (ntfs_fuse_fill_security_context(&security)
+	    && !ntfs_allowed_dir_access(&security,path,(ntfs_inode*)NULL,
+			(ntfs_inode*)NULL,S_IEXEC)) {
+		return (-errno);
+	}
+		/* security and trusted only settable by root */
+	if (((namespace == XATTRNS_SECURITY)
+	   || (namespace == XATTRNS_TRUSTED))
+		&& security.uid)
+		    return -EPERM;
+#endif
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni)
+		return -errno;
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	switch (namespace) {
+	case XATTRNS_SECURITY :
+	case XATTRNS_TRUSTED :
+		if (security.uid) {
+			res = -EPERM;
+			goto exit;
+		}
+		break;
+	case XATTRNS_SYSTEM :
+		if (!ntfs_allowed_as_owner(&security,ni)) {
+			res = -EACCES;
+			goto exit;
+		}
+		break;
+	default :
+		/* User xattr not allowed for symlinks, fifo, etc. */
+		if (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT)) {
+			res = -EPERM;
+			goto exit;
+		}
+		if (!ntfs_allowed_access(&security,ni,S_IWRITE)) {
+			res = -EACCES;
+			goto exit;
+		}
+		break;
+	}
+#else
+		/* User xattr not allowed for symlinks, fifo, etc. */
+	if ((namespace == XATTRNS_USER)
+	    && (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT))) {
+		res = -EPERM;
+		goto exit;
+	}
+#endif
+	lename_len = fix_xattr_prefix(name, namespace, &lename);
+	if ((lename_len == -1)
+	    || (ctx->windows_names
+		&& ntfs_forbidden_chars(lename,lename_len))) {
+		res = -errno;
+		goto exit;
+	}
+	na = ntfs_attr_open(ni, AT_DATA, lename, lename_len);
+	if (na && flags == XATTR_CREATE) {
+		res = -EEXIST;
+		goto exit;
+	}
+	if (!na) {
+		if (flags == XATTR_REPLACE) {
+			res = -ENODATA;
+			goto exit;
+		}
+		if (ntfs_attr_add(ni, AT_DATA, lename, lename_len, NULL, 0)) {
+			res = -errno;
+			goto exit;
+		}
+		if (!(ni->flags & FILE_ATTR_ARCHIVE)) {
+			set_archive(ni);
+			NInoFileNameSetDirty(ni);
+		}
+		na = ntfs_attr_open(ni, AT_DATA, lename, lename_len);
+		if (!na) {
+			res = -errno;
+			goto exit;
+		}
+	} else {
+			/* currently compressed streams can only be wiped out */
+		if (ntfs_attr_truncate(na, (s64)0 /* size */)) {
+			res = -errno;
+			goto exit;
+		}
+	}
+	total = 0;
+	res = 0;
+	if (size) {
+		do {
+			part = ntfs_attr_pwrite(na, total, size - total,
+					 &value[total]);
+			if (part > 0)
+				total += part;
+		} while ((part > 0) && (total < size));
+	}
+	if ((total != size) || ntfs_attr_pclose(na))
+		res = -errno;
+	else {
+		if (ctx->efs_raw 
+		   && (ni->flags & FILE_ATTR_ENCRYPTED)) {
+			if (ntfs_efs_fixup_attribute(NULL,na))
+				res = -errno;
+		}
+	}
+	if (!res) {
+		ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);
+		if (!(ni->flags & FILE_ATTR_ARCHIVE)) {
+			set_archive(ni);
+			NInoFileNameSetDirty(ni);
+		}
+	}
+exit:
+	if (na)
+		ntfs_attr_close(na);
+	free(lename);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	return res;
+}
+
+static int ntfs_fuse_removexattr(const char *path, const char *name)
+{
+	ntfs_inode *ni;
+	ntfs_inode *dir_ni;
+	ntfschar *lename = NULL;
+	int res = 0, lename_len;
+	enum SYSTEMXATTRS attr;
+	int namespace;
+	struct SECURITY_CONTEXT security;
+
+	attr = ntfs_xattr_system_type(name,ctx->vol);
+	if (attr != XATTR_UNMAPPED) {
+		switch (attr) {
+			/*
+			 * Removal of NTFS ACL, ATTRIB, EFSINFO or TIMES
+			 * is never allowed
+			 */
+		case XATTR_NTFS_ACL :
+		case XATTR_NTFS_ATTRIB :
+		case XATTR_NTFS_ATTRIB_BE :
+		case XATTR_NTFS_EFSINFO :
+		case XATTR_NTFS_TIMES :
+		case XATTR_NTFS_TIMES_BE :
+		case XATTR_NTFS_CRTIME :
+		case XATTR_NTFS_CRTIME_BE :
+			res = -EPERM;
+			break;
+		default :
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+			/*
+			 * hijack internal data and ACL removal, whatever
+			 * mode was selected for xattr (from the user's
+			 * point of view, ACLs are not xattr)
+			 * Note : ctime updated on successful settings
+			 */
+			ni = ntfs_check_access_xattr(&security,path,attr,TRUE);
+			if (ni) {
+				if (ntfs_allowed_as_owner(&security,ni)) {
+					if (attr == XATTR_NTFS_DOS_NAME)
+						dir_ni = get_parent_dir(path);
+					else
+						dir_ni = (ntfs_inode*)NULL;
+					res = ntfs_xattr_system_removexattr(&security,
+						attr, ni, dir_ni);
+					/* never have to close dir_ni */
+					if (res)
+						res = -errno;
+				} else
+					res = -errno;
+				if (attr != XATTR_NTFS_DOS_NAME) {
+					if (!res)
+						ntfs_fuse_update_times(ni,
+							NTFS_UPDATE_CTIME);
+					if (ntfs_inode_close(ni))
+						set_fuse_error(&res);
+				}
+			} else
+				res = -errno;
+#else
+			/*
+			 * Only hijack NTFS ACL setting if POSIX ACLS
+			 * option is not selected
+			 * Access control is partially done by fuse
+			 */
+			/* creation of a new name is not controlled by fuse */
+			if (attr == XATTR_NTFS_DOS_NAME)
+				ni = ntfs_check_access_xattr(&security,
+							path, attr, TRUE);
+			else {
+				if (ntfs_fuse_is_named_data_stream(path)) {
+					ni = (ntfs_inode*)NULL;
+					errno = EINVAL; /* n/a for named data streams. */
+				} else
+					ni = ntfs_pathname_to_inode(ctx->vol,
+							NULL, path);
+			}
+			if (ni) {
+				/*
+				 * user mapping is not mandatory
+				 * if defined, only owner is allowed
+				 */
+				if (!ntfs_fuse_fill_security_context(&security)
+				   || ntfs_allowed_as_owner(&security,ni)) {
+					if (attr == XATTR_NTFS_DOS_NAME)
+						dir_ni = get_parent_dir(path);
+					else
+						dir_ni = (ntfs_inode*)NULL;
+					res = ntfs_xattr_system_removexattr(&security,
+						attr, ni, dir_ni);
+					/* never have to close dir_ni */
+					if (res)
+						res = -errno;
+				} else
+					res = -errno;
+				if (attr != XATTR_NTFS_DOS_NAME) {
+					if (!res)
+						ntfs_fuse_update_times(ni,
+							NTFS_UPDATE_CTIME);
+					if (ntfs_inode_close(ni))
+						set_fuse_error(&res);
+				}
+			} else
+				res = -errno;
+#endif
+			break;
+		}
+		return (res);
+	}
+	if ((ctx->streams != NF_STREAMS_INTERFACE_XATTR)
+	    && (ctx->streams != NF_STREAMS_INTERFACE_OPENXATTR))
+		return -EOPNOTSUPP;
+	namespace = xattr_namespace(name);
+	if (namespace == XATTRNS_NONE)
+		return -EOPNOTSUPP;
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+		   /* parent directory must be executable */
+	if (ntfs_fuse_fill_security_context(&security)
+	    && !ntfs_allowed_dir_access(&security,path,(ntfs_inode*)NULL,
+			(ntfs_inode*)NULL,S_IEXEC)) {
+		return (-errno);
+	}
+		/* security and trusted only settable by root */
+	if (((namespace == XATTRNS_SECURITY)
+	   || (namespace == XATTRNS_TRUSTED))
+		&& security.uid)
+		    return -EACCES;
+#endif
+	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+	if (!ni)
+		return -errno;
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	switch (namespace) {
+	case XATTRNS_SECURITY :
+	case XATTRNS_TRUSTED :
+		if (security.uid) {
+			res = -EPERM;
+			goto exit;
+		}
+		break;
+	case XATTRNS_SYSTEM :
+		if (!ntfs_allowed_as_owner(&security,ni)) {
+			res = -EACCES;
+			goto exit;
+		}
+		break;
+	default :
+		/* User xattr not allowed for symlinks, fifo, etc. */
+		if (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT)) {
+			res = -EPERM;
+			goto exit;
+		}
+		if (!ntfs_allowed_access(&security,ni,S_IWRITE)) {
+			res = -EACCES;
+			goto exit;
+		}
+		break;
+	}
+#else
+		/* User xattr not allowed for symlinks, fifo, etc. */
+	if ((namespace == XATTRNS_USER)
+	    && (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT))) {
+		res = -EPERM;
+		goto exit;
+	}
+#endif
+	lename_len = fix_xattr_prefix(name, namespace, &lename);
+	if (lename_len == -1) {
+		res = -errno;
+		goto exit;
+	}
+	if (ntfs_attr_remove(ni, AT_DATA, lename, lename_len)) {
+		if (errno == ENOENT)
+			errno = ENODATA;
+		res = -errno;
+	}
+	if (!res) {
+		ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);
+		if (!(ni->flags & FILE_ATTR_ARCHIVE)) {
+			set_archive(ni);
+			NInoFileNameSetDirty(ni);
+		}
+	}
+exit:
+	free(lename);
+	if (ntfs_inode_close(ni))
+		set_fuse_error(&res);
+	return res;
+}
+
+#else
+#if POSIXACLS
+#error "Option inconsistency : POSIXACLS requires SETXATTR"
+#endif
+#endif /* HAVE_SETXATTR */
+
+static void ntfs_close(void)
+{
+	struct SECURITY_CONTEXT security;
+
+	if (!ctx)
+		return;
+	
+	if (!ctx->vol)
+		return;
+	
+	if (ctx->mounted) {
+		ntfs_log_info("Unmounting %s (%s)\n", opts.device, 
+			      ctx->vol->vol_name);
+		if (ntfs_fuse_fill_security_context(&security)) {
+			if (ctx->seccache && ctx->seccache->head.p_reads) {
+				ntfs_log_info("Permissions cache : %lu writes, "
+				"%lu reads, %lu.%1lu%% hits\n",
+			      ctx->seccache->head.p_writes,
+			      ctx->seccache->head.p_reads,
+			      100 * ctx->seccache->head.p_hits
+			         / ctx->seccache->head.p_reads,
+			      1000 * ctx->seccache->head.p_hits
+			         / ctx->seccache->head.p_reads % 10);
+			}
+		}
+		ntfs_close_secure(&security);
+	}
+	
+	if (ntfs_umount(ctx->vol, FALSE))
+		ntfs_log_perror("Failed to close volume %s", opts.device);
+	
+	ctx->vol = NULL;
+}
+
+static void ntfs_fuse_destroy2(void *unused __attribute__((unused)))
+{
+	ntfs_close();
+}
+
+static struct fuse_operations ntfs_3g_ops = {
+	.getattr	= ntfs_fuse_getattr,
+	.readlink	= ntfs_fuse_readlink,
+	.readdir	= ntfs_fuse_readdir,
+	.open		= ntfs_fuse_open,
+	.release	= ntfs_fuse_release,
+	.read		= ntfs_fuse_read,
+	.write		= ntfs_fuse_write,
+	.truncate	= ntfs_fuse_truncate,
+	.ftruncate	= ntfs_fuse_ftruncate,
+	.statfs		= ntfs_fuse_statfs,
+	.chmod		= ntfs_fuse_chmod,
+	.chown		= ntfs_fuse_chown,
+	.create		= ntfs_fuse_create_file,
+	.mknod		= ntfs_fuse_mknod,
+	.symlink	= ntfs_fuse_symlink,
+	.link		= ntfs_fuse_link,
+	.unlink		= ntfs_fuse_unlink,
+	.rename		= ntfs_fuse_rename,
+	.mkdir		= ntfs_fuse_mkdir,
+	.rmdir		= ntfs_fuse_rmdir,
+#ifdef HAVE_UTIMENSAT
+	.utimens	= ntfs_fuse_utimens,
+#else
+	.utime		= ntfs_fuse_utime,
+#endif
+	.fsync		= ntfs_fuse_fsync,
+	.fsyncdir	= ntfs_fuse_fsync,
+	.bmap		= ntfs_fuse_bmap,
+	.destroy        = ntfs_fuse_destroy2,
+#if defined(FUSE_INTERNAL) || (FUSE_VERSION >= 28)
+        .ioctl		= ntfs_fuse_ioctl,
+#endif /* defined(FUSE_INTERNAL) || (FUSE_VERSION >= 28) */
+#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
+	.access		= ntfs_fuse_access,
+	.opendir	= ntfs_fuse_opendir,
+#endif
+#ifdef HAVE_SETXATTR
+	.getxattr	= ntfs_fuse_getxattr,
+	.setxattr	= ntfs_fuse_setxattr,
+	.removexattr	= ntfs_fuse_removexattr,
+	.listxattr	= ntfs_fuse_listxattr,
+#endif /* HAVE_SETXATTR */
+#if defined(__APPLE__) || defined(__DARWIN__)
+	/* MacFUSE extensions. */
+	.getxtimes	= ntfs_macfuse_getxtimes,
+	.setcrtime	= ntfs_macfuse_setcrtime,
+	.setbkuptime	= ntfs_macfuse_setbkuptime,
+	.setchgtime	= ntfs_macfuse_setchgtime,
+#endif /* defined(__APPLE__) || defined(__DARWIN__) */
+	.init		= ntfs_init
+};
+
+static int ntfs_fuse_init(void)
+{
+	ctx = ntfs_calloc(sizeof(ntfs_fuse_context_t));
+	if (!ctx)
+		return -1;
+	
+	*ctx = (ntfs_fuse_context_t) {
+		.uid     = getuid(),
+		.gid     = getgid(),
+#if defined(linux)			
+		.streams = NF_STREAMS_INTERFACE_XATTR,
+#else			
+		.streams = NF_STREAMS_INTERFACE_NONE,
+#endif			
+		.atime   = ATIME_RELATIVE,
+		.silent  = TRUE,
+		.recover = TRUE
+	};
+	return 0;
+}
+
+static int ntfs_open(const char *device)
+{
+	unsigned long flags = 0;
+	
+	if (!ctx->blkdev)
+		flags |= NTFS_MNT_EXCLUSIVE;
+	if (ctx->ro)
+		flags |= NTFS_MNT_RDONLY;
+	if (ctx->recover)
+		flags |= NTFS_MNT_RECOVER;
+	if (ctx->hiberfile)
+		flags |= NTFS_MNT_IGNORE_HIBERFILE;
+
+	ctx->vol = ntfs_mount(device, flags);
+	if (!ctx->vol) {
+		ntfs_log_perror("Failed to mount '%s'", device);
+		goto err_out;
+	}
+	if (ctx->sync && ctx->vol->dev)
+		NDevSetSync(ctx->vol->dev);
+	if (ctx->compression)
+		NVolSetCompression(ctx->vol);
+	else
+		NVolClearCompression(ctx->vol);
+#ifdef HAVE_SETXATTR
+			/* archivers must see hidden files */
+	if (ctx->efs_raw)
+		ctx->hide_hid_files = FALSE;
+#endif
+	if (ntfs_set_shown_files(ctx->vol, ctx->show_sys_files,
+				!ctx->hide_hid_files, ctx->hide_dot_files))
+		goto err_out;
+	
+	ctx->vol->free_clusters = ntfs_attr_get_free_bits(ctx->vol->lcnbmp_na);
+	if (ctx->vol->free_clusters < 0) {
+		ntfs_log_perror("Failed to read NTFS $Bitmap");
+		goto err_out;
+	}
+
+	ctx->vol->free_mft_records = ntfs_get_nr_free_mft_records(ctx->vol);
+	if (ctx->vol->free_mft_records < 0) {
+		ntfs_log_perror("Failed to calculate free MFT records");
+		goto err_out;
+	}
+
+	if (ctx->hiberfile && ntfs_volume_check_hiberfile(ctx->vol, 0)) {
+		if (errno != EPERM)
+			goto err_out;
+		if (ntfs_fuse_rm("/hiberfil.sys"))
+			goto err_out;
+	}
+	
+	errno = 0;
+err_out:
+	return ntfs_volume_error(errno);
+	
+}
+
+static void usage(void)
+{
+	ntfs_log_info(usage_msg, EXEC_NAME, VERSION, FUSE_TYPE, fuse_version(),
+			4 + POSIXACLS*6 - KERNELPERMS*3 + CACHEING,
+			EXEC_NAME, ntfs_home);
+}
+
+#if defined(linux) || defined(__uClinux__)
+
+static const char *dev_fuse_msg =
+"HINT: You should be root, or make ntfs-3g setuid root, or load the FUSE\n"
+"      kernel module as root ('modprobe fuse' or 'insmod <path_to>/fuse.ko'"
+"      or insmod <path_to>/fuse.o'). Make also sure that the fuse device"
+"      exists. It's usually either /dev/fuse or /dev/misc/fuse.";
+
+static const char *fuse26_kmod_msg =
+"WARNING: Deficient Linux kernel detected. Some driver features are\n"
+"         not available (swap file on NTFS, boot from NTFS by LILO), and\n"
+"         unmount is not safe unless it's made sure the ntfs-3g process\n"
+"         naturally terminates after calling 'umount'. If you wish this\n"
+"         message to disappear then you should upgrade to at least kernel\n"
+"         version 2.6.20, or request help from your distribution to fix\n"
+"         the kernel problem. The below web page has more information:\n"
+"         http://tuxera.com/community/ntfs-3g-faq/#fuse26\n"
+"\n";
+
+static void mknod_dev_fuse(const char *dev)
+{
+	struct stat st;
+	
+	if (stat(dev, &st) && (errno == ENOENT)) {
+		mode_t mask = umask(0); 
+		if (mknod(dev, S_IFCHR | 0666, makedev(10, 229))) {
+			ntfs_log_perror("Failed to create '%s'", dev);
+			if (errno == EPERM)
+				ntfs_log_error("%s", dev_fuse_msg);
+		}
+		umask(mask);
+	}
+}
+
+static void create_dev_fuse(void)
+{
+	mknod_dev_fuse("/dev/fuse");
+
+#ifdef __UCLIBC__
+	{
+		struct stat st;
+		/* The fuse device is under /dev/misc using devfs. */
+		if (stat("/dev/misc", &st) && (errno == ENOENT)) {
+			mode_t mask = umask(0); 
+			mkdir("/dev/misc", 0775);
+			umask(mask);
+		}
+		mknod_dev_fuse("/dev/misc/fuse");
+	}
+#endif
+}
+
+static fuse_fstype get_fuse_fstype(void)
+{
+	char buf[256];
+	fuse_fstype fstype = FSTYPE_NONE;
+	
+	FILE *f = fopen("/proc/filesystems", "r");
+	if (!f) {
+		ntfs_log_perror("Failed to open /proc/filesystems");
+		return FSTYPE_UNKNOWN;
+	}
+	
+	while (fgets(buf, sizeof(buf), f)) {
+		if (strstr(buf, "fuseblk\n")) {
+			fstype = FSTYPE_FUSEBLK;
+			break;
+		}
+		if (strstr(buf, "fuse\n"))
+			fstype = FSTYPE_FUSE;
+	}
+	
+	fclose(f);
+	return fstype;
+}
+
+static fuse_fstype load_fuse_module(void)
+{
+	int i;
+	struct stat st;
+	pid_t pid;
+	const char *cmd = "/sbin/modprobe";
+	struct timespec req = { 0, 100000000 };   /* 100 msec */
+	fuse_fstype fstype;
+	
+	if (!stat(cmd, &st) && !geteuid()) {
+		pid = fork();
+		if (!pid) {
+			execl(cmd, cmd, "fuse", NULL);
+			_exit(1);
+		} else if (pid != -1)
+			waitpid(pid, NULL, 0);
+	}
+	
+	for (i = 0; i < 10; i++) {
+		/* 
+		 * We sleep first because despite the detection of the loaded
+		 * FUSE kernel module, fuse_mount() can still fail if it's not 
+		 * fully functional/initialized. Note, of course this is still
+		 * unreliable but usually helps.
+		 */  
+		nanosleep(&req, NULL);
+		fstype = get_fuse_fstype();
+		if (fstype != FSTYPE_NONE)
+			break;
+	}
+	return fstype;
+}
+
+#endif
+
+static struct fuse_chan *try_fuse_mount(char *parsed_options)
+{
+	struct fuse_chan *fc = NULL;
+	struct fuse_args margs = FUSE_ARGS_INIT(0, NULL);
+	
+	/* The fuse_mount() options get modified, so we always rebuild it */
+	if ((fuse_opt_add_arg(&margs, EXEC_NAME) == -1 ||
+	     fuse_opt_add_arg(&margs, "-o") == -1 ||
+	     fuse_opt_add_arg(&margs, parsed_options) == -1)) {
+		ntfs_log_error("Failed to set FUSE options.\n");
+		goto free_args;
+	}
+	
+	fc = fuse_mount(opts.mnt_point, &margs);
+free_args:
+	fuse_opt_free_args(&margs);
+	return fc;
+		
+}
+		
+static int set_fuseblk_options(char **parsed_options)
+{
+	char options[64];
+	long pagesize; 
+	u32 blksize = ctx->vol->cluster_size;
+	
+	pagesize = sysconf(_SC_PAGESIZE);
+	if (pagesize < 1)
+		pagesize = 4096;
+	
+	if (blksize > (u32)pagesize)
+		blksize = pagesize;
+	
+	snprintf(options, sizeof(options), ",blkdev,blksize=%u", blksize);
+	if (ntfs_strappend(parsed_options, options))
+		return -1;
+	return 0;
+}
+
+static struct fuse *mount_fuse(char *parsed_options)
+{
+	struct fuse *fh = NULL;
+	struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
+	
+	ctx->fc = try_fuse_mount(parsed_options);
+	if (!ctx->fc)
+		return NULL;
+	
+	if (fuse_opt_add_arg(&args, "") == -1)
+		goto err;
+#if !CACHEING
+	if (fuse_opt_add_arg(&args, "-ouse_ino,kernel_cache,attr_timeout=0") == -1)
+		goto err;
+#else
+	if (fuse_opt_add_arg(&args, "-ouse_ino,kernel_cache,attr_timeout=1") == -1)
+		goto err;
+#endif
+	if (ctx->debug)
+		if (fuse_opt_add_arg(&args, "-odebug") == -1)
+			goto err;
+	
+	fh = fuse_new(ctx->fc, &args , &ntfs_3g_ops, sizeof(ntfs_3g_ops), NULL);
+	if (!fh)
+		goto err;
+	
+	if (fuse_set_signal_handlers(fuse_get_session(fh)))
+		goto err_destory;
+out:
+	fuse_opt_free_args(&args);
+	return fh;
+err_destory:
+	fuse_destroy(fh);
+	fh = NULL;
+err:	
+	fuse_unmount(opts.mnt_point, ctx->fc);
+	goto out;
+}
+
+static void setup_logging(char *parsed_options)
+{
+	if (!ctx->no_detach) {
+		if (daemon(0, ctx->debug))
+			ntfs_log_error("Failed to daemonize.\n");
+		else if (!ctx->debug) {
+#ifndef DEBUG
+			ntfs_log_set_handler(ntfs_log_handler_syslog);
+			/* Override default libntfs identify. */
+			openlog(EXEC_NAME, LOG_PID, LOG_DAEMON);
+#endif
+		}
+	}
+
+	ctx->seccache = (struct PERMISSIONS_CACHE*)NULL;
+
+	ntfs_log_info("Version %s %s %d\n", VERSION, FUSE_TYPE, fuse_version());
+	if (strcmp(opts.arg_device,opts.device))
+		ntfs_log_info("Requested device %s canonicalized as %s\n",
+				opts.arg_device,opts.device);
+	ntfs_log_info("Mounted %s (%s, label \"%s\", NTFS %d.%d)\n",
+			opts.device, (ctx->ro) ? "Read-Only" : "Read-Write",
+			ctx->vol->vol_name, ctx->vol->major_ver,
+			ctx->vol->minor_ver);
+	ntfs_log_info("Cmdline options: %s\n", opts.options ? opts.options : "");
+	ntfs_log_info("Mount options: %s\n", parsed_options);
+}
+
+int main(int argc, char *argv[])
+{
+	char *parsed_options = NULL;
+	struct fuse *fh;
+#if !(defined(__sun) && defined (__SVR4))
+	fuse_fstype fstype = FSTYPE_UNKNOWN;
+#endif
+	const char *permissions_mode = (const char*)NULL;
+	const char *failed_secure = (const char*)NULL;
+#if defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS)
+	struct XATTRMAPPING *xattr_mapping = (struct XATTRMAPPING*)NULL;
+#endif /* defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS) */
+	struct stat sbuf;
+	unsigned long existing_mount;
+	int err, fd;
+
+	/*
+	 * 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);
+
+#ifndef FUSE_INTERNAL
+	if ((getuid() != geteuid()) || (getgid() != getegid())) {
+		fprintf(stderr, "%s", setuid_msg);
+		return NTFS_VOLUME_INSECURE;
+	}
+#endif
+	if (drop_privs())
+		return NTFS_VOLUME_NO_PRIVILEGE;
+	
+	ntfs_set_locale();
+	ntfs_log_set_handler(ntfs_log_handler_stderr);
+
+	if (ntfs_parse_options(&opts, usage, argc, argv)) {
+		usage();
+		return NTFS_VOLUME_SYNTAX_ERROR;
+	}
+
+	if (ntfs_fuse_init()) {
+		err = NTFS_VOLUME_OUT_OF_MEMORY;
+		goto err2;
+	}
+	
+	parsed_options = parse_mount_options(ctx, &opts, FALSE);
+	if (!parsed_options) {
+		err = NTFS_VOLUME_SYNTAX_ERROR;
+		goto err_out;
+	}
+	if (!ntfs_check_if_mounted(opts.device,&existing_mount)
+	    && (existing_mount & NTFS_MF_MOUNTED)
+		/* accept multiple read-only mounts */
+	    && (!(existing_mount & NTFS_MF_READONLY) || !ctx->ro)) {
+		err = NTFS_VOLUME_LOCKED;
+		goto err_out;
+	}
+
+			/* need absolute mount point for junctions */
+	if (opts.mnt_point[0] == '/')
+		ctx->abs_mnt_point = strdup(opts.mnt_point);
+	else {
+		ctx->abs_mnt_point = (char*)ntfs_malloc(PATH_MAX);
+		if (ctx->abs_mnt_point) {
+			if (getcwd(ctx->abs_mnt_point,
+				     PATH_MAX - strlen(opts.mnt_point) - 1)) {
+				strcat(ctx->abs_mnt_point, "/");
+				strcat(ctx->abs_mnt_point, opts.mnt_point);
+#if defined(__sun) && defined (__SVR4)
+			/* Solaris also wants the absolute mount point */
+				opts.mnt_point = ctx->abs_mnt_point;
+#endif /* defined(__sun) && defined (__SVR4) */
+			}
+		}
+	}
+	if (!ctx->abs_mnt_point) {
+		err = NTFS_VOLUME_OUT_OF_MEMORY;
+		goto err_out;
+	}
+
+	ctx->security.uid = 0;
+	ctx->security.gid = 0;
+	if ((opts.mnt_point[0] == '/')
+	   && !stat(opts.mnt_point,&sbuf)) {
+		/* collect owner of mount point, useful for default mapping */
+		ctx->security.uid = sbuf.st_uid;
+		ctx->security.gid = sbuf.st_gid;
+	}
+
+#if defined(linux) || defined(__uClinux__)
+	fstype = get_fuse_fstype();
+
+	err = NTFS_VOLUME_NO_PRIVILEGE;
+	if (restore_privs())
+		goto err_out;
+
+	if (fstype == FSTYPE_NONE || fstype == FSTYPE_UNKNOWN)
+		fstype = load_fuse_module();
+	create_dev_fuse();
+
+	if (drop_privs())
+		goto err_out;
+#endif	
+	if (stat(opts.device, &sbuf)) {
+		ntfs_log_perror("Failed to access '%s'", opts.device);
+		err = NTFS_VOLUME_NO_PRIVILEGE;
+		goto err_out;
+	}
+
+#if !(defined(__sun) && defined (__SVR4))
+	/* Always use fuseblk for block devices unless it's surely missing. */
+	if (S_ISBLK(sbuf.st_mode) && (fstype != FSTYPE_FUSE))
+		ctx->blkdev = TRUE;
+#endif
+
+#ifndef FUSE_INTERNAL
+	if (getuid() && ctx->blkdev) {
+		ntfs_log_error("%s", unpriv_fuseblk_msg);
+		err = NTFS_VOLUME_NO_PRIVILEGE;
+		goto err2;
+	}
+#endif
+	err = ntfs_open(opts.device);
+	if (err)
+		goto err_out;
+	
+	/* Force read-only mount if the device was found read-only */
+	if (!ctx->ro && NVolReadOnly(ctx->vol)) {
+		ctx->ro = TRUE;
+		if (ntfs_strinsert(&parsed_options, ",ro")) 
+                	goto err_out;
+	}
+	/* We must do this after ntfs_open() to be able to set the blksize */
+	if (ctx->blkdev && set_fuseblk_options(&parsed_options))
+		goto err_out;
+
+	ctx->security.vol = ctx->vol;
+	ctx->vol->secure_flags = ctx->secure_flags;
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+	ctx->vol->efs_raw = ctx->efs_raw;
+#endif /* HAVE_SETXATTR */
+		/* JPA open $Secure, (whatever NTFS version !) */
+		/* to initialize security data */
+	if (ntfs_open_secure(ctx->vol) && (ctx->vol->major_ver >= 3))
+		failed_secure = "Could not open file $Secure";
+	if (!ntfs_build_mapping(&ctx->security,ctx->usermap_path,
+		(ctx->vol->secure_flags
+			& ((1 << SECURITY_DEFAULT) | (1 << SECURITY_ACL)))
+		&& !ctx->inherit
+		&& !(ctx->vol->secure_flags & (1 << SECURITY_WANTED)))) {
+#if POSIXACLS
+		/* use basic permissions if requested */
+		if (ctx->vol->secure_flags & (1 << SECURITY_DEFAULT))
+			permissions_mode = "User mapping built, Posix ACLs not used";
+		else {
+			permissions_mode = "User mapping built, Posix ACLs in use";
+#if KERNELACLS
+			if (ntfs_strinsert(&parsed_options, ",default_permissions,acl")) {
+				err = NTFS_VOLUME_SYNTAX_ERROR;
+				goto err_out;
+			}
+#endif /* KERNELACLS */
+		}
+#else /* POSIXACLS */
+#if KERNELPERMS
+		if (!(ctx->vol->secure_flags
+			& ((1 << SECURITY_DEFAULT) | (1 << SECURITY_ACL)))) {
+			/*
+			 * No explicit option but user mapping found
+			 * force default security
+			 */
+			ctx->vol->secure_flags |= (1 << SECURITY_DEFAULT);
+			if (ntfs_strinsert(&parsed_options, ",default_permissions")) {
+				err = NTFS_VOLUME_SYNTAX_ERROR;
+				goto err_out;
+			}
+		}
+#endif /* KERNELPERMS */
+		permissions_mode = "User mapping built";
+#endif /* POSIXACLS */
+		ctx->dmask = ctx->fmask = 0;
+	} else {
+		ctx->security.uid = ctx->uid;
+		ctx->security.gid = ctx->gid;
+		/* same ownership/permissions for all files */
+		ctx->security.mapping[MAPUSERS] = (struct MAPPING*)NULL;
+		ctx->security.mapping[MAPGROUPS] = (struct MAPPING*)NULL;
+		if ((ctx->vol->secure_flags & (1 << SECURITY_WANTED))
+		   && !(ctx->vol->secure_flags & (1 << SECURITY_DEFAULT))) {
+			ctx->vol->secure_flags |= (1 << SECURITY_DEFAULT);
+			if (ntfs_strinsert(&parsed_options, ",default_permissions")) {
+				err = NTFS_VOLUME_SYNTAX_ERROR;
+				goto err_out;
+			}
+		}
+		if (ctx->vol->secure_flags & (1 << SECURITY_DEFAULT)) {
+			ctx->vol->secure_flags |= (1 << SECURITY_RAW);
+			permissions_mode = "Global ownership and permissions enforced";
+		} else {
+			ctx->vol->secure_flags &= ~(1 << SECURITY_RAW);
+			permissions_mode = "Ownership and permissions disabled";
+		}
+	}
+	if (ctx->usermap_path)
+		free (ctx->usermap_path);
+
+#if defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS)
+	xattr_mapping = ntfs_xattr_build_mapping(ctx->vol,
+				ctx->xattrmap_path);
+	ctx->vol->xattr_mapping = xattr_mapping;
+	/*
+	 * Errors are logged, do not refuse mounting, it would be
+	 * too difficult to fix the unmountable mapping file.
+	 */
+	if (ctx->xattrmap_path)
+		free(ctx->xattrmap_path);
+#endif /* defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS) */
+
+	fh = mount_fuse(parsed_options);
+	if (!fh) {
+		err = NTFS_VOLUME_FUSE_ERROR;
+		goto err_out;
+	}
+	
+	ctx->mounted = TRUE;
+
+#if defined(linux) || defined(__uClinux__)
+	if (S_ISBLK(sbuf.st_mode) && (fstype == FSTYPE_FUSE))
+		ntfs_log_info("%s", fuse26_kmod_msg);
+#endif	
+	setup_logging(parsed_options);
+	if (failed_secure)
+	        ntfs_log_info("%s\n",failed_secure);
+	if (permissions_mode)
+	        ntfs_log_info("%s, configuration type %d\n",permissions_mode,
+			4 + POSIXACLS*6 - KERNELPERMS*3 + CACHEING);
+	if ((ctx->vol->secure_flags & (1 << SECURITY_RAW))
+	    && !ctx->uid && ctx->gid)
+		ntfs_log_error("Warning : using problematic uid==0 and gid!=0\n");
+	
+	fuse_loop(fh);
+	
+	err = 0;
+
+	fuse_unmount(opts.mnt_point, ctx->fc);
+	fuse_destroy(fh);
+err_out:
+	ntfs_mount_error(opts.device, opts.mnt_point, err);
+	if (ctx->abs_mnt_point)
+		free(ctx->abs_mnt_point);
+#if defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS)
+	ntfs_xattr_free_mapping(xattr_mapping);
+#endif /* defined(HAVE_SETXATTR) && defined(XATTR_MAPPINGS) */
+err2:
+	ntfs_close();
+	free(ctx);
+	free(parsed_options);
+	free(opts.options);
+	free(opts.device);
+	return err;
+}
diff --git a/src/ntfs-3g.probe.8 b/src/ntfs-3g.probe.8
new file mode 100755
index 0000000000000000000000000000000000000000..5215f8a0a507a68bf3c883e078e8a45526876e74
--- /dev/null
+++ b/src/ntfs-3g.probe.8
@@ -0,0 +1,81 @@
+.\" Copyright (c) 2008 Szabolcs Szakacsits.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFS-3G.PROBE 8 "January 2008" "ntfs-3g.probe 2015.3.14"
+.SH NAME
+ntfs-3g.probe \- Probe an NTFS volume mountability
+.SH SYNOPSIS
+.B ntfs-3g.probe
+.I <\-\-readonly|\-\-readwrite>
+.I volume 
+.br
+.SH DESCRIPTION
+The \fBntfs-3g.probe\fR utility tests a volume if it's NTFS mountable 
+read-only or read-write, and exits with a status value accordingly. 
+The \fIvolume\fR can be a block device or image file.
+.SH OPTIONS
+Below is a summary of the options that \fBntfs-3g.probe\fR accepts.
+.TP
+.B \-r, \-\-readonly
+Test if the volume can be mounted read-only.
+.TP
+.B \-w, \-\-readwrite
+Test if the volume can be mounted read-write.
+.TP
+.B \-h, \-\-help
+Display help and exit.
+.SH EXAMPLE
+Test if /dev/sda1 can be mounted read-write:
+.RS
+.sp
+.B ntfs-3g.probe --readwrite /dev/sda1
+.sp
+.RE
+.SH EXIT CODES
+The exit codes are as follows:
+.IP 0
+Volume is mountable.
+.IP 11
+Syntax error, command line parsing failed.
+.IP 12
+The volume doesn't have a valid NTFS.
+.IP 13
+Inconsistent NTFS, hardware or device driver fault, or unsetup 
+SoftRAID/FakeRAID hardware. 
+.IP 14
+The NTFS partition is hibernated.
+.IP 15
+The volume was not cleanly unmounted. 
+.IP 16
+The volume is already exclusively opened and in use by a kernel
+driver or software.
+.IP 17
+Unsetup SoftRAID/FakeRAID hardware.
+.IP 18
+Unknown reason.
+.IP 19
+Not enough privilege to mount.
+.IP 20
+Out of memory.
+.IP 21
+Unclassified FUSE error.
+.SH KNOWN ISSUES
+Please see 
+.RS
+.sp
+http://tuxera.com/community/ntfs-3g-faq/
+.sp
+.RE
+for common questions and known issues.
+If you think you have found an undocumented problem in the latest release of
+the software then please send an email describing it in detail. 
+You can contact the development team on the ntfs\-3g\-devel@lists.sf.net
+address.
+.SH AUTHORS
+.B ntfs-3g.probe 
+was written by Szabolcs Szakacsits. 
+.SH THANKS
+Alon Bar-Lev has integrated the utility into the NTFS-3G build process and 
+tested it with Erik Larsson before the public release.
+.SH SEE ALSO
+.BR ntfs-3g (8)
diff --git a/src/ntfs-3g.probe.8.in b/src/ntfs-3g.probe.8.in
new file mode 100755
index 0000000000000000000000000000000000000000..62ce57e5e50d54e41f844db8f979912ca499f60d
--- /dev/null
+++ b/src/ntfs-3g.probe.8.in
@@ -0,0 +1,81 @@
+.\" Copyright (c) 2008 Szabolcs Szakacsits.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFS-3G.PROBE 8 "January 2008" "ntfs-3g.probe @VERSION@"
+.SH NAME
+ntfs-3g.probe \- Probe an NTFS volume mountability
+.SH SYNOPSIS
+.B ntfs-3g.probe
+.I <\-\-readonly|\-\-readwrite>
+.I volume 
+.br
+.SH DESCRIPTION
+The \fBntfs-3g.probe\fR utility tests a volume if it's NTFS mountable 
+read-only or read-write, and exits with a status value accordingly. 
+The \fIvolume\fR can be a block device or image file.
+.SH OPTIONS
+Below is a summary of the options that \fBntfs-3g.probe\fR accepts.
+.TP
+.B \-r, \-\-readonly
+Test if the volume can be mounted read-only.
+.TP
+.B \-w, \-\-readwrite
+Test if the volume can be mounted read-write.
+.TP
+.B \-h, \-\-help
+Display help and exit.
+.SH EXAMPLE
+Test if /dev/sda1 can be mounted read-write:
+.RS
+.sp
+.B ntfs-3g.probe --readwrite /dev/sda1
+.sp
+.RE
+.SH EXIT CODES
+The exit codes are as follows:
+.IP 0
+Volume is mountable.
+.IP 11
+Syntax error, command line parsing failed.
+.IP 12
+The volume doesn't have a valid NTFS.
+.IP 13
+Inconsistent NTFS, hardware or device driver fault, or unsetup 
+SoftRAID/FakeRAID hardware. 
+.IP 14
+The NTFS partition is hibernated.
+.IP 15
+The volume was not cleanly unmounted. 
+.IP 16
+The volume is already exclusively opened and in use by a kernel
+driver or software.
+.IP 17
+Unsetup SoftRAID/FakeRAID hardware.
+.IP 18
+Unknown reason.
+.IP 19
+Not enough privilege to mount.
+.IP 20
+Out of memory.
+.IP 21
+Unclassified FUSE error.
+.SH KNOWN ISSUES
+Please see 
+.RS
+.sp
+http://tuxera.com/community/ntfs-3g-faq/
+.sp
+.RE
+for common questions and known issues.
+If you think you have found an undocumented problem in the latest release of
+the software then please send an email describing it in detail. 
+You can contact the development team on the ntfs\-3g\-devel@lists.sf.net
+address.
+.SH AUTHORS
+.B ntfs-3g.probe 
+was written by Szabolcs Szakacsits. 
+.SH THANKS
+Alon Bar-Lev has integrated the utility into the NTFS-3G build process and 
+tested it with Erik Larsson before the public release.
+.SH SEE ALSO
+.BR ntfs-3g (8)
diff --git a/src/ntfs-3g.probe.c b/src/ntfs-3g.probe.c
new file mode 100755
index 0000000000000000000000000000000000000000..cb73aee416b70a47ee65a42f2c0ac857c8c4fe87
--- /dev/null
+++ b/src/ntfs-3g.probe.c
@@ -0,0 +1,166 @@
+/**
+ * ntfs-3g.probe - Probe NTFS volume mountability
+ *
+ * Copyright (c) 2007-2009 Szabolcs Szakacsits
+ *
+ * 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
+ */
+
+#include "config.h"
+
+#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 <getopt.h>
+
+#include "compat.h"
+#include "volume.h"
+#include "misc.h"
+
+typedef enum {
+	PROBE_UNSET,
+	PROBE_READONLY,
+	PROBE_READWRITE
+} probe_t;
+
+static struct options {
+	probe_t  probetype;
+	char	 *device;
+} opts;
+
+static const char *EXEC_NAME = "ntfs-3g.probe";
+
+static const char *usage_msg = 
+"\n"
+"%s %s - Probe NTFS volume mountability\n"
+"\n"
+"Copyright (C) 2007 Szabolcs Szakacsits\n"
+"\n"
+"Usage:    %s <--readonly|--readwrite> <device|image_file>\n"
+"\n"
+"Example:  ntfs-3g.probe --readwrite /dev/sda1\n"
+"\n"
+"%s";
+
+static int ntfs_open(const char *device)
+{
+	ntfs_volume *vol;
+	unsigned long flags = 0;
+	int ret = NTFS_VOLUME_OK;
+	
+	if (opts.probetype == PROBE_READONLY)
+		flags |= NTFS_MNT_RDONLY;
+
+	vol = ntfs_mount(device, flags);
+	if (!vol)
+		ret = ntfs_volume_error(errno);
+
+	if (ret == 0 && ntfs_umount(vol, FALSE) == -1)
+		ret = ntfs_volume_error(errno);
+
+	return ret;
+}
+
+static void usage(void)
+{
+	ntfs_log_info(usage_msg, EXEC_NAME, VERSION, EXEC_NAME, ntfs_home);
+}
+
+static int parse_options(int argc, char *argv[])
+{
+	int c;
+
+	static const char *sopt = "-hrw";
+	static const struct option lopt[] = {
+		{ "readonly",	no_argument,	NULL, 'r' },
+		{ "readwrite",	no_argument,	NULL, 'w' },
+		{ "help",	no_argument,	NULL, 'h' },
+		{ NULL,		0,		NULL,  0  }
+	};
+
+	opterr = 0; /* We handle errors. */
+	opts.probetype = PROBE_UNSET;
+
+	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
+		switch (c) {
+		case 1:	/* A non-option argument */
+			if (!opts.device) {
+				opts.device = ntfs_malloc(PATH_MAX + 1);
+				if (!opts.device)
+					return -1;
+				
+				strncpy(opts.device, optarg, PATH_MAX);
+				opts.device[PATH_MAX] = 0;
+			} else {
+				ntfs_log_error("%s: You must specify exactly "
+					       "one device\n", EXEC_NAME);
+				return -1;
+			}
+			break;
+		case 'h':
+			usage();
+			exit(0);
+		case 'r':
+			opts.probetype = PROBE_READONLY;
+			break;
+		case 'w':
+			opts.probetype = PROBE_READWRITE;
+			break;
+		default:
+			ntfs_log_error("%s: Unknown option '%s'.\n", EXEC_NAME,
+				       argv[optind - 1]);
+			return -1;
+		}
+	}
+
+	if (!opts.device) {
+		ntfs_log_error("ERROR: %s: Device is missing\n", EXEC_NAME);
+		return -1;
+	}
+
+	if (opts.probetype == PROBE_UNSET) {
+		ntfs_log_error("ERROR: %s: Probe type is missing\n", EXEC_NAME);
+		return -1;
+	}
+
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	int err;
+
+	ntfs_log_set_handler(ntfs_log_handler_stderr);
+
+	if (parse_options(argc, argv)) {
+		usage();
+		exit(NTFS_VOLUME_SYNTAX_ERROR);
+	}
+
+	err = ntfs_open(opts.device);
+
+	free(opts.device);
+	if (err)
+		exit(err);
+	return (0);
+}
+
diff --git a/src/ntfs-3g.secaudit.8 b/src/ntfs-3g.secaudit.8
new file mode 100755
index 0000000000000000000000000000000000000000..669828e5432c1d7869768e5c95bec8aa81619eaa
--- /dev/null
+++ b/src/ntfs-3g.secaudit.8
@@ -0,0 +1,184 @@
+.\" Copyright (c) 2007-2009 Jean-Pierre André.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFS-3G.SECAUDIT 8 "February 2010" "ntfs-3g.secaudit 1.4.1"
+.SH NAME
+ntfs-3g.secaudit \- NTFS Security Data Auditing
+.SH SYNOPSIS
+.B ntfs-3g.secaudit
+\fB[\fIoptions\fP\fB]\fR
+.I args
+.PP
+Where \fIoptions\fP is a combination of :
+.RS
+-a full auditing of security data (Linux only)
+.RE
+.RS
+-b backup ACLs
+.RE
+.RS
+-e setting extra backed-up parameters (in conjunction with -s)
+.RE
+.RS
+-h displaying hexadecimal security descriptors saved in a file
+.RE
+.RS
+-r recursing in a directory
+.RE
+.RS
+-s setting backed-up ACLs
+.RE
+.RS
+-u getting a user mapping proposal
+.RE
+.RS
+-v verbose (very verbose if set twice)
+.RE
+.PP
+and args define the parameters and the set of files acted upon.
+.PP
+Typing secaudit with no args will display a summary of available options.
+.SH DESCRIPTION
+\fBntfs-3g.secaudit\fR
+displays the ownership and permissions of a set of files on an NTFS
+file system, and checks their consistency. It can be started in terminal
+mode only (no graphical user interface is available.)
+.PP
+When a \fIvolume\fR is required, it has to be unmounted, and the command
+has to be issued as \fBroot\fP. The \fIvolume\fR can be either a block
+device (i.e. a disk partition) or an image file.
+.PP
+When acting on a directory or volume, the command may produce a lot
+of information. It is therefore advisable to redirect the output to
+a file or pipe it to a text editor for examination.
+.SH OPTIONS
+Below are the valid combinations of options and arguments that
+\fBntfs-3g.secaudit\fR accepts. All the indicated arguments are
+mandatory and must be unique (if wildcards are used, they must
+resolve to a single name.)
+.TP
+\fB-h\fP \fIfile\fP
+Displays in an human readable form the hexadecimal security descriptors
+saved in \fIfile\fP. This can be used to turn a verbose output into a very
+verbose output.
+.TP
+\fB-a[rv]\fP \fIvolume\fP
+Audits the volume : all the global security data on \fIvolume\fP are scanned
+and errors are displayed. If option \fB-r\fP is present, all files and
+directories are also scanned and their relations to global security data
+are checked. This can produce a lot of data.
+
+This option is not effective on volumes formatted for old NTFS versions (pre
+NTFS 3.0). Such volumes have no global security data.
+
+When errors are signalled, it is advisable to repair the volume with an
+appropriate tool (such as \fBchkdsk\fP on Windows.)
+.TP
+\fB[-v]\fP \fIvolume\fP \fIfile\fP
+Displays the security parameters of \fIfile\fP : its interpreted Linux mode
+(rwx flags in octal) and Posix ACL[1], its security key if any, and its
+security descriptor if verbose output.
+.TP
+\fB-r[v]\fP \fIvolume\fP \fIdirectory\fP
+displays the security parameters of all files and subdirectories in
+\fIdirectory\fP : their interpreted Linux mode (rwx flags in octal) and Posix
+ACL[1], their security key if any, and their security descriptor if
+verbose output.
+.TP
+.B -b[v] \fIvolume\fP \fI[directory]\fP
+Recursively extracts to standard output the NTFS ACLs of files in \fIvolume\fP
+and \fIdirectory\fP.
+.TP
+\fB-s[ev]\fP \fIvolume\fP \fI[backup-file]\fP
+Sets the NTFS ACLS as indicated in \fIbackup-file\fP or standard input. The
+input data must have been created on Linux. With option \fB-e\fP, also sets
+extra parameters (currently Windows attrib).
+.TP
+\fIvolume\fP \fIperms\fP \fIfile\fP
+Sets the security parameters of file to perms. Perms is the Linux
+requested mode (rwx flags, expressed in octal form as in chmod) or
+a Posix ACL[1] (expressed like in setfacl -m). This sets a new ACL
+which is effective for Linux and Windows.
+.TP
+\fB-r[v]\fP \fIvolume\fP \fIperms\fP \fIdirectory\fP
+Sets the security parameters of all files and subdirectories in
+\fIdirectory\fP to \fIperms\fP. Perms is the Linux requested mode (rwx flags,
+expressed in octal form as in \fBchmod\fP), or a Posix ACL[1] (expressed like
+in \fBsetfacl -m\fP.) This sets new ACLs which are effective for Linux and
+Windows.
+.TP
+\fB[-v]\fP \fImounted-file\fP
+Displays the security parameters of \fImounted-file\fP : its interpreted
+Linux mode (rwx flags in octal) and Posix ACL[1], its security key if any,
+and its security descriptor if verbose output. This is a special case which
+acts on a mounted file (or directory) and does not require being root. The
+Posix ACL interpretation can only be displayed if the full path to
+\fImounted-file\fP from the root of the global file tree is provided.
+.TP
+\fB-u[v]\fP \fImounted-file\fP
+Displays a proposed contents for a user mapping file, based on the
+ownership parameters set by Windows on \fImounted-file\fP, assuming
+this file was created on Windows by the user who should be mapped to the
+current Linux user. The displayed information has to be copied to the
+file \fB.NTFS-3G/UserMapping\fP where \fB.NTFS-3G\fP is a hidden
+subdirectory of the root of the partition for which the mapping is to
+be defined. This will cause the ownership of files created on that
+partition to be the same as the original \fImounted-file\fP.
+.SH NOTE
+[1] provided the POSIX ACL option was selected at compile time. A Posix ACL
+specification looks like "\fB[d:]{ugmo}:[id]:[perms],...\fP" where id is a
+numeric user or group id, and perms an octal digit or a set from the letters
+r, w and x.
+.RS
+Example : "\fBu::7,g::5,o:0,u:510:rwx,g:500:5,d:u:510:7\fP"
+.SH EXAMPLES
+Audit the global security data on /dev/sda1
+.RS
+.sp
+.B ntfs-3g.secaudit -ar /dev/sda1
+.sp
+.RE
+Display the ownership and permissions parameters for files in directory
+/audio/music on device /dev/sda5, excluding sub-directories :
+.RS
+.sp
+.B ntfs-3g.secaudit /dev/sda5 /audio/music
+.sp
+.RE
+Set all files in directory /audio/music on device /dev/sda5 as writeable
+by owner and read-only for everybody :
+.RS
+.sp
+.B ntfs-3g.secaudit -r /dev/sda5 644 /audio/music
+.sp
+.RE
+.SH EXIT CODES
+.B ntfs-3g.secaudit
+exits with a value of 0 when no error was detected, and with a value
+of 1 when an error was detected.
+.SH KNOWN ISSUES
+Please see 
+.RS
+.sp
+http://www.tuxera.com/community/ntfs-3g-faq/
+.sp
+.RE
+for common questions and known issues.
+If you would find a new one in the latest release of
+the software then please send an email describing it
+in detail. You can contact the 
+development team on the ntfs\-3g\-devel@lists.sf.net
+address.
+.SH AUTHORS
+.B ntfs-3g.secaudit
+has been developed by Jean-Pierre André.
+.SH THANKS
+Several people made heroic efforts, often over five or more
+years which resulted the ntfs-3g driver. Most importantly they are 
+Anton Altaparmakov, Richard Russon, Szabolcs Szakacsits, Yura Pakhuchiy,
+Yuval Fledel, and the author of the groundbreaking FUSE filesystem development 
+framework, Miklos Szeredi.
+.SH SEE ALSO
+.BR ntfsprogs (8),
+.BR attr (5),
+.BR getfattr (1)
diff --git a/src/ntfs-3g.secaudit.8.in b/src/ntfs-3g.secaudit.8.in
new file mode 100755
index 0000000000000000000000000000000000000000..669828e5432c1d7869768e5c95bec8aa81619eaa
--- /dev/null
+++ b/src/ntfs-3g.secaudit.8.in
@@ -0,0 +1,184 @@
+.\" Copyright (c) 2007-2009 Jean-Pierre André.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFS-3G.SECAUDIT 8 "February 2010" "ntfs-3g.secaudit 1.4.1"
+.SH NAME
+ntfs-3g.secaudit \- NTFS Security Data Auditing
+.SH SYNOPSIS
+.B ntfs-3g.secaudit
+\fB[\fIoptions\fP\fB]\fR
+.I args
+.PP
+Where \fIoptions\fP is a combination of :
+.RS
+-a full auditing of security data (Linux only)
+.RE
+.RS
+-b backup ACLs
+.RE
+.RS
+-e setting extra backed-up parameters (in conjunction with -s)
+.RE
+.RS
+-h displaying hexadecimal security descriptors saved in a file
+.RE
+.RS
+-r recursing in a directory
+.RE
+.RS
+-s setting backed-up ACLs
+.RE
+.RS
+-u getting a user mapping proposal
+.RE
+.RS
+-v verbose (very verbose if set twice)
+.RE
+.PP
+and args define the parameters and the set of files acted upon.
+.PP
+Typing secaudit with no args will display a summary of available options.
+.SH DESCRIPTION
+\fBntfs-3g.secaudit\fR
+displays the ownership and permissions of a set of files on an NTFS
+file system, and checks their consistency. It can be started in terminal
+mode only (no graphical user interface is available.)
+.PP
+When a \fIvolume\fR is required, it has to be unmounted, and the command
+has to be issued as \fBroot\fP. The \fIvolume\fR can be either a block
+device (i.e. a disk partition) or an image file.
+.PP
+When acting on a directory or volume, the command may produce a lot
+of information. It is therefore advisable to redirect the output to
+a file or pipe it to a text editor for examination.
+.SH OPTIONS
+Below are the valid combinations of options and arguments that
+\fBntfs-3g.secaudit\fR accepts. All the indicated arguments are
+mandatory and must be unique (if wildcards are used, they must
+resolve to a single name.)
+.TP
+\fB-h\fP \fIfile\fP
+Displays in an human readable form the hexadecimal security descriptors
+saved in \fIfile\fP. This can be used to turn a verbose output into a very
+verbose output.
+.TP
+\fB-a[rv]\fP \fIvolume\fP
+Audits the volume : all the global security data on \fIvolume\fP are scanned
+and errors are displayed. If option \fB-r\fP is present, all files and
+directories are also scanned and their relations to global security data
+are checked. This can produce a lot of data.
+
+This option is not effective on volumes formatted for old NTFS versions (pre
+NTFS 3.0). Such volumes have no global security data.
+
+When errors are signalled, it is advisable to repair the volume with an
+appropriate tool (such as \fBchkdsk\fP on Windows.)
+.TP
+\fB[-v]\fP \fIvolume\fP \fIfile\fP
+Displays the security parameters of \fIfile\fP : its interpreted Linux mode
+(rwx flags in octal) and Posix ACL[1], its security key if any, and its
+security descriptor if verbose output.
+.TP
+\fB-r[v]\fP \fIvolume\fP \fIdirectory\fP
+displays the security parameters of all files and subdirectories in
+\fIdirectory\fP : their interpreted Linux mode (rwx flags in octal) and Posix
+ACL[1], their security key if any, and their security descriptor if
+verbose output.
+.TP
+.B -b[v] \fIvolume\fP \fI[directory]\fP
+Recursively extracts to standard output the NTFS ACLs of files in \fIvolume\fP
+and \fIdirectory\fP.
+.TP
+\fB-s[ev]\fP \fIvolume\fP \fI[backup-file]\fP
+Sets the NTFS ACLS as indicated in \fIbackup-file\fP or standard input. The
+input data must have been created on Linux. With option \fB-e\fP, also sets
+extra parameters (currently Windows attrib).
+.TP
+\fIvolume\fP \fIperms\fP \fIfile\fP
+Sets the security parameters of file to perms. Perms is the Linux
+requested mode (rwx flags, expressed in octal form as in chmod) or
+a Posix ACL[1] (expressed like in setfacl -m). This sets a new ACL
+which is effective for Linux and Windows.
+.TP
+\fB-r[v]\fP \fIvolume\fP \fIperms\fP \fIdirectory\fP
+Sets the security parameters of all files and subdirectories in
+\fIdirectory\fP to \fIperms\fP. Perms is the Linux requested mode (rwx flags,
+expressed in octal form as in \fBchmod\fP), or a Posix ACL[1] (expressed like
+in \fBsetfacl -m\fP.) This sets new ACLs which are effective for Linux and
+Windows.
+.TP
+\fB[-v]\fP \fImounted-file\fP
+Displays the security parameters of \fImounted-file\fP : its interpreted
+Linux mode (rwx flags in octal) and Posix ACL[1], its security key if any,
+and its security descriptor if verbose output. This is a special case which
+acts on a mounted file (or directory) and does not require being root. The
+Posix ACL interpretation can only be displayed if the full path to
+\fImounted-file\fP from the root of the global file tree is provided.
+.TP
+\fB-u[v]\fP \fImounted-file\fP
+Displays a proposed contents for a user mapping file, based on the
+ownership parameters set by Windows on \fImounted-file\fP, assuming
+this file was created on Windows by the user who should be mapped to the
+current Linux user. The displayed information has to be copied to the
+file \fB.NTFS-3G/UserMapping\fP where \fB.NTFS-3G\fP is a hidden
+subdirectory of the root of the partition for which the mapping is to
+be defined. This will cause the ownership of files created on that
+partition to be the same as the original \fImounted-file\fP.
+.SH NOTE
+[1] provided the POSIX ACL option was selected at compile time. A Posix ACL
+specification looks like "\fB[d:]{ugmo}:[id]:[perms],...\fP" where id is a
+numeric user or group id, and perms an octal digit or a set from the letters
+r, w and x.
+.RS
+Example : "\fBu::7,g::5,o:0,u:510:rwx,g:500:5,d:u:510:7\fP"
+.SH EXAMPLES
+Audit the global security data on /dev/sda1
+.RS
+.sp
+.B ntfs-3g.secaudit -ar /dev/sda1
+.sp
+.RE
+Display the ownership and permissions parameters for files in directory
+/audio/music on device /dev/sda5, excluding sub-directories :
+.RS
+.sp
+.B ntfs-3g.secaudit /dev/sda5 /audio/music
+.sp
+.RE
+Set all files in directory /audio/music on device /dev/sda5 as writeable
+by owner and read-only for everybody :
+.RS
+.sp
+.B ntfs-3g.secaudit -r /dev/sda5 644 /audio/music
+.sp
+.RE
+.SH EXIT CODES
+.B ntfs-3g.secaudit
+exits with a value of 0 when no error was detected, and with a value
+of 1 when an error was detected.
+.SH KNOWN ISSUES
+Please see 
+.RS
+.sp
+http://www.tuxera.com/community/ntfs-3g-faq/
+.sp
+.RE
+for common questions and known issues.
+If you would find a new one in the latest release of
+the software then please send an email describing it
+in detail. You can contact the 
+development team on the ntfs\-3g\-devel@lists.sf.net
+address.
+.SH AUTHORS
+.B ntfs-3g.secaudit
+has been developed by Jean-Pierre André.
+.SH THANKS
+Several people made heroic efforts, often over five or more
+years which resulted the ntfs-3g driver. Most importantly they are 
+Anton Altaparmakov, Richard Russon, Szabolcs Szakacsits, Yura Pakhuchiy,
+Yuval Fledel, and the author of the groundbreaking FUSE filesystem development 
+framework, Miklos Szeredi.
+.SH SEE ALSO
+.BR ntfsprogs (8),
+.BR attr (5),
+.BR getfattr (1)
diff --git a/src/ntfs-3g.usermap.8 b/src/ntfs-3g.usermap.8
new file mode 100755
index 0000000000000000000000000000000000000000..6efd47b9d1f31bc0b7d1159b547d144114d01d12
--- /dev/null
+++ b/src/ntfs-3g.usermap.8
@@ -0,0 +1,96 @@
+.\" Copyright (c) 2007-2009 Jean-Pierre André.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFS-3G.USERMAP 8 "February 2010" "ntfs-3g.usermap 1.1.2"
+.SH NAME
+ntfs-3g.usermap \- NTFS Building a User Mapping File
+.SH SYNOPSIS
+.B ntfs-3g.usermap
+\fIwindows-system-device\fP
+\fB[\fIother-ntfs-device\fP...\fB]\fR
+.PP
+Where \fIwindows-system-device\fP is the device containing the Windows system
+whose users are to be mapped to current Linux system.
+.PP
+And \fIother-ntfs-device\fP is another device containing files which are
+to be accessed both by the Windows mentioned above and current Linux system.
+.PP
+the ntfs-3g.usermap command must be started as root, and the designated devices
+must not be mounted.
+.PP
+Typing ntfs-3g.usermap with no args will display a summary of command
+arguments.
+.SH DESCRIPTION
+\fBntfs-3g.usermap\fR
+creates the file defining the mapping of Windows accounts to Linux logins for
+users who owns files which should be visible from both Windows and
+Linux.
+.PP
+It relies on existing files which were created on Windows, trying
+to locate significant files and asking which Linux user or group should
+own them. When a Linux owner or group is requested, the reply may be :
+.PP
+- the uid or gid (numeric or symbolic) of Linux owner or group of the file.
+.RS
+In that situation, no more file with the same Windows owner will be selected.
+.RE
+- or no answer, when not able to define the owner or group.
+.RS
+In that situation another file owned by the same Windows user or group
+may be selected later so that a mapping can be defined.
+.RE
+.PP
+The mappings for standard Windows users, such as "Administrator" or
+"All Users" are defined implicitly. As a consequence a user mapping should
+never be defined as Linux root.
+.PP
+When there are no more significant files, ntfs-3g.usermap create the
+mapping file into the file UserMapping in the current directory. This
+file has to be moved to the hidden directory .NTFS-3G in the root of
+all the NTFS file systems to be shared between Windows and Linux. This
+requires the file system to be mounted, but the created file will not
+be taken into account if not present at mount time, which means the
+file system has to be unmounted and mounted again for the new mapping
+file to be taken into account.
+.SH OPTIONS
+No option is defined for ntfs-3g.usermap.
+.SH EXAMPLES
+Map the users defined on the Windows system present on /dev/sda1 :
+.RS
+.sp
+.B ntfs-3g.usermap /dev/sda1
+.sp
+.RE
+.PP
+A detailed example, with screen displays is available on
+http://pagesperso-orange.fr/b.andre/usermap.html
+.SH EXIT CODES
+.B ntfs-3g.usermap
+exits with a value of 0 when no error was detected, and with a value
+of 1 when an error was detected.
+.SH KNOWN ISSUES
+Please see 
+.RS
+.sp
+http://www.tuxera.com/community/ntfs-3g-faq/
+.sp
+.RE
+for common questions and known issues.
+If you would find a new one in the latest release of
+the software then please send an email describing it
+in detail. You can contact the 
+development team on the ntfs\-3g\-devel@lists.sf.net
+address.
+.SH AUTHORS
+.B ntfs-3g.secaudit
+has been developed by Jean-Pierre André.
+.SH THANKS
+Several people made heroic efforts, often over five or more
+years which resulted the ntfs-3g driver. Most importantly they are 
+Anton Altaparmakov, Richard Russon, Szabolcs Szakacsits, Yura Pakhuchiy,
+Yuval Fledel, and the author of the groundbreaking FUSE filesystem development 
+framework, Miklos Szeredi.
+.SH SEE ALSO
+.BR ntfsprogs (8),
+.BR attr (5),
+.BR getfattr (1)
diff --git a/src/ntfs-3g.usermap.8.in b/src/ntfs-3g.usermap.8.in
new file mode 100755
index 0000000000000000000000000000000000000000..6efd47b9d1f31bc0b7d1159b547d144114d01d12
--- /dev/null
+++ b/src/ntfs-3g.usermap.8.in
@@ -0,0 +1,96 @@
+.\" Copyright (c) 2007-2009 Jean-Pierre André.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH NTFS-3G.USERMAP 8 "February 2010" "ntfs-3g.usermap 1.1.2"
+.SH NAME
+ntfs-3g.usermap \- NTFS Building a User Mapping File
+.SH SYNOPSIS
+.B ntfs-3g.usermap
+\fIwindows-system-device\fP
+\fB[\fIother-ntfs-device\fP...\fB]\fR
+.PP
+Where \fIwindows-system-device\fP is the device containing the Windows system
+whose users are to be mapped to current Linux system.
+.PP
+And \fIother-ntfs-device\fP is another device containing files which are
+to be accessed both by the Windows mentioned above and current Linux system.
+.PP
+the ntfs-3g.usermap command must be started as root, and the designated devices
+must not be mounted.
+.PP
+Typing ntfs-3g.usermap with no args will display a summary of command
+arguments.
+.SH DESCRIPTION
+\fBntfs-3g.usermap\fR
+creates the file defining the mapping of Windows accounts to Linux logins for
+users who owns files which should be visible from both Windows and
+Linux.
+.PP
+It relies on existing files which were created on Windows, trying
+to locate significant files and asking which Linux user or group should
+own them. When a Linux owner or group is requested, the reply may be :
+.PP
+- the uid or gid (numeric or symbolic) of Linux owner or group of the file.
+.RS
+In that situation, no more file with the same Windows owner will be selected.
+.RE
+- or no answer, when not able to define the owner or group.
+.RS
+In that situation another file owned by the same Windows user or group
+may be selected later so that a mapping can be defined.
+.RE
+.PP
+The mappings for standard Windows users, such as "Administrator" or
+"All Users" are defined implicitly. As a consequence a user mapping should
+never be defined as Linux root.
+.PP
+When there are no more significant files, ntfs-3g.usermap create the
+mapping file into the file UserMapping in the current directory. This
+file has to be moved to the hidden directory .NTFS-3G in the root of
+all the NTFS file systems to be shared between Windows and Linux. This
+requires the file system to be mounted, but the created file will not
+be taken into account if not present at mount time, which means the
+file system has to be unmounted and mounted again for the new mapping
+file to be taken into account.
+.SH OPTIONS
+No option is defined for ntfs-3g.usermap.
+.SH EXAMPLES
+Map the users defined on the Windows system present on /dev/sda1 :
+.RS
+.sp
+.B ntfs-3g.usermap /dev/sda1
+.sp
+.RE
+.PP
+A detailed example, with screen displays is available on
+http://pagesperso-orange.fr/b.andre/usermap.html
+.SH EXIT CODES
+.B ntfs-3g.usermap
+exits with a value of 0 when no error was detected, and with a value
+of 1 when an error was detected.
+.SH KNOWN ISSUES
+Please see 
+.RS
+.sp
+http://www.tuxera.com/community/ntfs-3g-faq/
+.sp
+.RE
+for common questions and known issues.
+If you would find a new one in the latest release of
+the software then please send an email describing it
+in detail. You can contact the 
+development team on the ntfs\-3g\-devel@lists.sf.net
+address.
+.SH AUTHORS
+.B ntfs-3g.secaudit
+has been developed by Jean-Pierre André.
+.SH THANKS
+Several people made heroic efforts, often over five or more
+years which resulted the ntfs-3g driver. Most importantly they are 
+Anton Altaparmakov, Richard Russon, Szabolcs Szakacsits, Yura Pakhuchiy,
+Yuval Fledel, and the author of the groundbreaking FUSE filesystem development 
+framework, Miklos Szeredi.
+.SH SEE ALSO
+.BR ntfsprogs (8),
+.BR attr (5),
+.BR getfattr (1)
diff --git a/src/ntfs-3g_common.c b/src/ntfs-3g_common.c
new file mode 100755
index 0000000000000000000000000000000000000000..d6e2942d8b48ab298382afe1a0dca54ed1c2fb6e
--- /dev/null
+++ b/src/ntfs-3g_common.c
@@ -0,0 +1,762 @@
+/**
+ * ntfs-3g_common.c - Common definitions for ntfs-3g and lowntfs-3g.
+ *
+ * Copyright (c) 2010-2015 Jean-Pierre Andre
+ * Copyright (c) 2010      Erik Larsson
+ *
+ * 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
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include <getopt.h>
+#include <fuse.h>
+
+#include "inode.h"
+#include "security.h"
+#include "xattrs.h"
+#include "ntfs-3g_common.h"
+#include "realpath.h"
+#include "misc.h"
+
+const char xattr_ntfs_3g[] = "ntfs-3g.";
+
+const char nf_ns_user_prefix[] = "user.";
+const int nf_ns_user_prefix_len = sizeof(nf_ns_user_prefix) - 1;
+const char nf_ns_system_prefix[] = "system.";
+const int nf_ns_system_prefix_len = sizeof(nf_ns_system_prefix) - 1;
+const char nf_ns_security_prefix[] = "security.";
+const int nf_ns_security_prefix_len = sizeof(nf_ns_security_prefix) - 1;
+const char nf_ns_trusted_prefix[] = "trusted.";
+const int nf_ns_trusted_prefix_len = sizeof(nf_ns_trusted_prefix) - 1;
+
+static const char nf_ns_alt_xattr_efsinfo[] = "user.ntfs.efsinfo";
+
+static const char def_opts[] = "allow_other,nonempty,";
+
+	/*
+	 *	 Table of recognized options
+	 * Their order may be significant
+	 * The options invalid in some configuration should still
+	 * be present, so that an error can be returned
+	 */
+const struct DEFOPTION optionlist[] = {
+	{ "ro", OPT_RO, FLGOPT_APPEND | FLGOPT_BOGUS },
+	{ "noatime", OPT_NOATIME, FLGOPT_BOGUS },
+	{ "atime", OPT_ATIME, FLGOPT_BOGUS },
+	{ "relatime", OPT_RELATIME, FLGOPT_BOGUS },
+	{ "delay_mtime", OPT_DMTIME, FLGOPT_DECIMAL | FLGOPT_OPTIONAL },
+	{ "fake_rw", OPT_FAKE_RW, FLGOPT_BOGUS },
+	{ "fsname", OPT_FSNAME, FLGOPT_NOSUPPORT },
+	{ "no_def_opts", OPT_NO_DEF_OPTS, FLGOPT_BOGUS },
+	{ "default_permissions", OPT_DEFAULT_PERMISSIONS, FLGOPT_BOGUS },
+	{ "permissions", OPT_PERMISSIONS, FLGOPT_BOGUS },
+	{ "acl", OPT_ACL, FLGOPT_BOGUS },
+	{ "umask", OPT_UMASK, FLGOPT_OCTAL },
+	{ "fmask", OPT_FMASK, FLGOPT_OCTAL },
+	{ "dmask", OPT_DMASK, FLGOPT_OCTAL },
+	{ "uid", OPT_UID, FLGOPT_DECIMAL },
+	{ "gid", OPT_GID, FLGOPT_DECIMAL },
+	{ "show_sys_files", OPT_SHOW_SYS_FILES, FLGOPT_BOGUS },
+	{ "hide_hid_files", OPT_HIDE_HID_FILES, FLGOPT_BOGUS },
+	{ "hide_dot_files", OPT_HIDE_DOT_FILES, FLGOPT_BOGUS },
+	{ "ignore_case", OPT_IGNORE_CASE, FLGOPT_BOGUS },
+	{ "windows_names", OPT_WINDOWS_NAMES, FLGOPT_BOGUS },
+	{ "compression", OPT_COMPRESSION, FLGOPT_BOGUS },
+	{ "nocompression", OPT_NOCOMPRESSION, FLGOPT_BOGUS },
+	{ "silent", OPT_SILENT, FLGOPT_BOGUS },
+	{ "recover", OPT_RECOVER, FLGOPT_BOGUS },
+	{ "norecover", OPT_NORECOVER, FLGOPT_BOGUS },
+	{ "remove_hiberfile", OPT_REMOVE_HIBERFILE, FLGOPT_BOGUS },
+	{ "sync", OPT_SYNC, FLGOPT_BOGUS | FLGOPT_APPEND },
+	{ "big_writes", OPT_BIG_WRITES, FLGOPT_BOGUS },
+	{ "locale", OPT_LOCALE, FLGOPT_STRING },
+	{ "nfconv", OPT_NFCONV, FLGOPT_BOGUS },
+	{ "nonfconv", OPT_NONFCONV, FLGOPT_BOGUS },
+	{ "streams_interface", OPT_STREAMS_INTERFACE, FLGOPT_STRING },
+	{ "user_xattr", OPT_USER_XATTR, FLGOPT_BOGUS },
+	{ "noauto", OPT_NOAUTO, FLGOPT_BOGUS },
+	{ "debug", OPT_DEBUG, FLGOPT_BOGUS },
+	{ "no_detach", OPT_NO_DETACH, FLGOPT_BOGUS },
+	{ "remount", OPT_REMOUNT, FLGOPT_BOGUS },
+	{ "blksize", OPT_BLKSIZE, FLGOPT_STRING },
+	{ "inherit", OPT_INHERIT, FLGOPT_BOGUS },
+	{ "addsecurids", OPT_ADDSECURIDS, FLGOPT_BOGUS },
+	{ "staticgrps", OPT_STATICGRPS, FLGOPT_BOGUS },
+	{ "usermapping", OPT_USERMAPPING, FLGOPT_STRING },
+	{ "xattrmapping", OPT_XATTRMAPPING, FLGOPT_STRING },
+	{ "efs_raw", OPT_EFS_RAW, FLGOPT_BOGUS },
+	{ (const char*)NULL, 0, 0 } /* end marker */
+} ;
+
+#define STRAPPEND_MAX_INSIZE   8192
+#define strappend_is_large(x) ((x) > STRAPPEND_MAX_INSIZE)
+
+int ntfs_strappend(char **dest, const char *append)
+{
+	char *p;
+	size_t size_append, size_dest = 0;
+	
+	if (!dest)
+		return -1;
+	if (!append)
+		return 0;
+
+	size_append = strlen(append);
+	if (*dest)
+		size_dest = strlen(*dest);
+	
+	if (strappend_is_large(size_dest) || strappend_is_large(size_append)) {
+		errno = EOVERFLOW;
+		ntfs_log_perror("%s: Too large input buffer", EXEC_NAME);
+		return -1;
+	}
+	
+	p = (char*)realloc(*dest, size_dest + size_append + 1);
+    	if (!p) {
+		ntfs_log_perror("%s: Memory realloction failed", EXEC_NAME);
+		return -1;
+	}
+	
+	*dest = p;
+	strcpy(*dest + size_dest, append);
+	
+	return 0;
+}
+
+/*
+ *		Insert an option before ",fsname="
+ *	This is for keeping "fsname" as the last option, because on
+ *	Solaris device names may contain commas.
+ */
+
+int ntfs_strinsert(char **dest, const char *append)
+{
+	char *p, *q;
+	size_t size_append, size_dest = 0;
+	
+	if (!dest)
+		return -1;
+	if (!append)
+		return 0;
+
+	size_append = strlen(append);
+	if (*dest)
+		size_dest = strlen(*dest);
+	
+	if (strappend_is_large(size_dest) || strappend_is_large(size_append)) {
+		errno = EOVERFLOW;
+		ntfs_log_perror("%s: Too large input buffer", EXEC_NAME);
+		return -1;
+	}
+	
+	p = (char*)malloc(size_dest + size_append + 1);
+	if (!p) {
+		ntfs_log_perror("%s: Memory reallocation failed", EXEC_NAME);
+		return -1;
+	}
+	strcpy(p, *dest);
+	q = strstr(p, ",fsname=");
+	if (q) {
+		strcpy(q, append);
+		q = strstr(*dest, ",fsname=");
+		if (q)
+			strcat(p, q);
+		free(*dest);
+		*dest = p;
+	} else {
+		free(*dest);
+		*dest = p;
+		strcpy(*dest + size_dest, append);
+	}
+	return 0;
+}
+
+static int bogus_option_value(char *val, const char *s)
+{
+	if (val) {
+		ntfs_log_error("'%s' option shouldn't have value.\n", s);
+		return -1;
+	}
+	return 0;
+}
+
+static int missing_option_value(char *val, const char *s)
+{
+	if (!val) {
+		ntfs_log_error("'%s' option should have a value.\n", s);
+		return -1;
+	}
+	return 0;
+}
+
+char *parse_mount_options(ntfs_fuse_context_t *ctx,
+			const struct ntfs_options *popts, BOOL low_fuse)
+{
+	char *options, *s, *opt, *val, *ret = NULL;
+     char *sz_device = NULL;
+	const char *orig_opts = popts->options;
+	BOOL no_def_opts = FALSE;
+	int default_permissions = 0;
+	int permissions = 0;
+	int acl = 0;
+	int want_permissions = 0;
+	int intarg;
+	const struct DEFOPTION *poptl;
+
+	ctx->secure_flags = 0;
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+	ctx->efs_raw = FALSE;
+#endif /* HAVE_SETXATTR */
+	ctx->compression = DEFAULT_COMPRESSION;
+	options = strdup(orig_opts ? orig_opts : "");
+	if (!options) {
+		ntfs_log_perror("%s: strdup failed", EXEC_NAME);
+		return NULL;
+	}
+	
+	s = options;
+	while (s && *s && (val = strsep(&s, ","))) {
+		opt = strsep(&val, "=");
+		poptl = optionlist;
+		while (poptl->name && strcmp(poptl->name,opt))
+			poptl++;
+		if (poptl->name) {
+			if ((poptl->flags & FLGOPT_BOGUS)
+			    && bogus_option_value(val, opt))
+				goto err_exit;
+			if ((poptl->flags & FLGOPT_OCTAL)
+			    && (!val
+				|| !sscanf(val, "%o", &intarg))) {
+				ntfs_log_error("'%s' option needs an octal value\n",
+					opt);
+				goto err_exit;
+			}
+			if (poptl->flags & FLGOPT_DECIMAL) {
+				if ((poptl->flags & FLGOPT_OPTIONAL) && !val)
+					intarg = 0;
+				else
+					if (!val
+					    || !sscanf(val, "%i", &intarg)) {
+						ntfs_log_error("'%s' option "
+						     "needs a decimal value\n",
+							opt);
+						goto err_exit;
+					}
+			}
+			if ((poptl->flags & FLGOPT_STRING)
+			    && missing_option_value(val, opt))
+				goto err_exit;
+
+			switch (poptl->type) {
+			case OPT_RO :
+			case OPT_FAKE_RW :
+				ctx->ro = TRUE;
+				break;
+			case OPT_NOATIME :
+				ctx->atime = ATIME_DISABLED;
+				break;
+			case OPT_ATIME :
+				ctx->atime = ATIME_ENABLED;
+				break;
+			case OPT_RELATIME :
+				ctx->atime = ATIME_RELATIVE;
+				break;
+			case OPT_DMTIME :
+				if (!intarg)
+					intarg = DEFAULT_DMTIME;
+				ctx->dmtime = intarg*10000000LL;
+				break;
+			case OPT_NO_DEF_OPTS :
+				no_def_opts = TRUE; /* Don't add default options. */
+				ctx->silent = FALSE; /* cancel default silent */
+				break;
+			case OPT_DEFAULT_PERMISSIONS :
+				default_permissions = 1;
+				break;
+			case OPT_PERMISSIONS :
+				permissions = 1;
+				break;
+#if POSIXACLS
+			case OPT_ACL :
+				acl = 1;
+				break;
+#endif
+			case OPT_UMASK :
+				ctx->dmask = ctx->fmask = intarg;
+				want_permissions = 1;
+				break;
+			case OPT_FMASK :
+				ctx->fmask = intarg;
+			       	want_permissions = 1;
+				break;
+			case OPT_DMASK :
+				ctx->dmask = intarg;
+			       	want_permissions = 1;
+				break;
+			case OPT_UID :
+				ctx->uid = intarg;
+			       	want_permissions = 1;
+				break;
+			case OPT_GID :
+				ctx->gid = intarg;
+				want_permissions = 1;
+				break;
+			case OPT_SHOW_SYS_FILES :
+				ctx->show_sys_files = TRUE;
+				break;
+			case OPT_HIDE_HID_FILES :
+				ctx->hide_hid_files = TRUE;
+				break;
+			case OPT_HIDE_DOT_FILES :
+				ctx->hide_dot_files = TRUE;
+				break;
+			case OPT_WINDOWS_NAMES :
+				ctx->windows_names = TRUE;
+				break;
+			case OPT_IGNORE_CASE :
+				if (low_fuse)
+					ctx->ignore_case = TRUE;
+				else {
+					ntfs_log_error("'%s' is an unsupported option.\n",
+						poptl->name);
+					goto err_exit;
+				}
+				break;
+			case OPT_COMPRESSION :
+				ctx->compression = TRUE;
+				break;
+			case OPT_NOCOMPRESSION :
+				ctx->compression = FALSE;
+				break;
+			case OPT_SILENT :
+				ctx->silent = TRUE;
+				break;
+			case OPT_RECOVER :
+				ctx->recover = TRUE;
+				break;
+			case OPT_NORECOVER :
+				ctx->recover = FALSE;
+				break;
+			case OPT_REMOVE_HIBERFILE :
+				ctx->hiberfile = TRUE;
+				break;
+			case OPT_SYNC :
+				ctx->sync = TRUE;
+				break;
+#ifdef FUSE_CAP_BIG_WRITES
+			case OPT_BIG_WRITES :
+				ctx->big_writes = TRUE;
+				break;
+#endif
+			case OPT_LOCALE :
+				ntfs_set_char_encoding(val);
+				break;
+#if defined(__APPLE__) || defined(__DARWIN__)
+#ifdef ENABLE_NFCONV
+			case OPT_NFCONV :
+				if (ntfs_macosx_normalize_filenames(1)) {
+					ntfs_log_error("ntfs_macosx_normalize_filenames(1) failed!\n");
+					goto err_exit;
+				}
+				break;
+			case OPT_NONFCONV :
+				if (ntfs_macosx_normalize_filenames(0)) {
+					ntfs_log_error("ntfs_macosx_normalize_filenames(0) failed!\n");
+					goto err_exit;
+				}
+				break;
+#endif /* ENABLE_NFCONV */
+#endif /* defined(__APPLE__) || defined(__DARWIN__) */
+			case OPT_STREAMS_INTERFACE :
+				if (!strcmp(val, "none"))
+					ctx->streams = NF_STREAMS_INTERFACE_NONE;
+				else if (!strcmp(val, "xattr"))
+					ctx->streams = NF_STREAMS_INTERFACE_XATTR;
+				else if (!strcmp(val, "openxattr"))
+					ctx->streams = NF_STREAMS_INTERFACE_OPENXATTR;
+				else if (!low_fuse && !strcmp(val, "windows"))
+					ctx->streams = NF_STREAMS_INTERFACE_WINDOWS;
+				else {
+					ntfs_log_error("Invalid named data streams "
+						"access interface.\n");
+					goto err_exit;
+				}
+				break;
+			case OPT_USER_XATTR :
+				ctx->streams = NF_STREAMS_INTERFACE_XATTR;
+				break;
+			case OPT_NOAUTO :
+				/* Don't pass noauto option to fuse. */
+				break;
+			case OPT_DEBUG :
+				ctx->debug = TRUE;
+				ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG);
+				ntfs_log_set_levels(NTFS_LOG_LEVEL_TRACE);
+				break;
+			case OPT_NO_DETACH :
+				ctx->no_detach = TRUE;
+				break;
+			case OPT_REMOUNT :
+				ntfs_log_error("Remounting is not supported at present."
+					" You have to umount volume and then "
+					"mount it once again.\n");
+				goto err_exit;
+			case OPT_BLKSIZE :
+				ntfs_log_info("WARNING: blksize option is ignored "
+				      "because ntfs-3g must calculate it.\n");
+				break;
+			case OPT_INHERIT :
+				/*
+				 * do not overwrite inherited permissions
+				 * in create()
+				 */
+				ctx->inherit = TRUE;
+				break;
+			case OPT_ADDSECURIDS :
+				/*
+				 * create security ids for files being read
+				 * with an individual security attribute
+				 */
+				ctx->secure_flags |= (1 << SECURITY_ADDSECURIDS);
+				break;
+			case OPT_STATICGRPS :
+				/*
+				 * use static definition of groups
+				 * for file access control
+				 */
+				ctx->secure_flags |= (1 << SECURITY_STATICGRPS);
+				break;
+			case OPT_USERMAPPING :
+				ctx->usermap_path = strdup(val);
+				if (!ctx->usermap_path) {
+					ntfs_log_error("no more memory to store "
+						"'usermapping' option.\n");
+					goto err_exit;
+				}
+				break;
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+#ifdef XATTR_MAPPINGS
+			case OPT_XATTRMAPPING :
+				ctx->xattrmap_path = strdup(val);
+				if (!ctx->xattrmap_path) {
+					ntfs_log_error("no more memory to store "
+						"'xattrmapping' option.\n");
+					goto err_exit;
+				}
+				break;
+#endif /* XATTR_MAPPINGS */
+			case OPT_EFS_RAW :
+				ctx->efs_raw = TRUE;
+				break;
+#endif /* HAVE_SETXATTR */
+			case OPT_FSNAME : /* Filesystem name. */
+			/*
+			 * We need this to be able to check whether filesystem
+			 * mounted or not.
+			 *      (falling through to default)
+			 */
+			default :
+				ntfs_log_error("'%s' is an unsupported option.\n",
+					poptl->name);
+				goto err_exit;
+			}
+			if ((poptl->flags & FLGOPT_APPEND)
+			    && (ntfs_strappend(&ret, poptl->name)
+				    || ntfs_strappend(&ret, ",")))
+				goto err_exit;
+		} else { /* Probably FUSE option. */
+			if (ntfs_strappend(&ret, opt))
+				goto err_exit;
+			if (val) {
+				if (ntfs_strappend(&ret, "="))
+					goto err_exit;
+				if (ntfs_strappend(&ret, val))
+					goto err_exit;
+			}
+			if (ntfs_strappend(&ret, ","))
+				goto err_exit;
+		}
+	}
+	if (!no_def_opts && ntfs_strappend(&ret, def_opts))
+		goto err_exit;
+	if ((default_permissions || (permissions && !acl))
+			&& ntfs_strappend(&ret, "default_permissions,"))
+		goto err_exit;
+			/* The atime options exclude each other */
+	if (ctx->atime == ATIME_RELATIVE && ntfs_strappend(&ret, "relatime,"))
+		goto err_exit;
+	else if (ctx->atime == ATIME_ENABLED && ntfs_strappend(&ret, "atime,"))
+		goto err_exit;
+	else if (ctx->atime == ATIME_DISABLED && ntfs_strappend(&ret, "noatime,"))
+		goto err_exit;
+	
+	if (ntfs_strappend(&ret, "fsname="))
+		goto err_exit;
+    sz_device = malloc(strlen(popts->device) + 1);
+    if (!sz_device)
+         goto err_exit;
+    strcpy(sz_device, popts->device);
+    char *r_device = strchr(sz_device, ',');
+    if (r_device)
+        r_device[0] = '@';
+    if (ntfs_strappend(&ret, sz_device))
+		goto err_exit;
+	if (permissions && !acl)
+		ctx->secure_flags |= (1 << SECURITY_DEFAULT);
+	if (acl)
+		ctx->secure_flags |= (1 << SECURITY_ACL);
+	if (want_permissions)
+		ctx->secure_flags |= (1 << SECURITY_WANTED);
+	if (ctx->ro) {
+		ctx->secure_flags &= ~(1 << SECURITY_ADDSECURIDS);
+		ctx->hiberfile = FALSE;
+	}
+exit:
+    if (sz_device)
+        free(sz_device);
+	free(options);
+	return ret;
+err_exit:
+	free(ret);
+	ret = NULL;
+	goto exit;
+}
+
+/**
+ * parse_options - Read and validate the programs command line
+ * Read the command line, verify the syntax and parse the options.
+ *
+ * Return:   0 success, -1 error.
+ */
+int ntfs_parse_options(struct ntfs_options *popts, void (*usage)(void),
+			int argc, char *argv[])
+{
+	int c;
+
+	static const char *sopt = "-o:hnsvV";
+	static const struct option lopt[] = {
+		{ "options",	 required_argument,	NULL, 'o' },
+		{ "help",	 no_argument,		NULL, 'h' },
+		{ "no-mtab",	 no_argument,		NULL, 'n' },
+		{ "verbose",	 no_argument,		NULL, 'v' },
+		{ "version",	 no_argument,		NULL, 'V' },
+		{ NULL,		 0,			NULL,  0  }
+	};
+
+	opterr = 0; /* We'll handle the errors, thank you. */
+
+	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
+		switch (c) {
+		case 1:	/* A non-option argument */
+			if (!popts->device) {
+				popts->device = ntfs_malloc(PATH_MAX + 1);
+				if (!popts->device)
+					return -1;
+				
+				/* Canonicalize device name (mtab, etc) */
+				popts->arg_device = optarg;
+				if (!ntfs_realpath_canonicalize(optarg,
+						popts->device)) {
+					ntfs_log_perror("%s: Failed to access "
+					     "volume '%s'", EXEC_NAME, optarg);
+					free(popts->device);
+					popts->device = NULL;
+					return -1;
+				}
+			} else if (!popts->mnt_point) {
+				popts->mnt_point = optarg;
+			} else {
+				ntfs_log_error("%s: You must specify exactly one "
+						"device and exactly one mount "
+						"point.\n", EXEC_NAME);
+				return -1;
+			}
+			break;
+		case 'o':
+			if (popts->options)
+				if (ntfs_strappend(&popts->options, ","))
+					return -1;
+			if (ntfs_strappend(&popts->options, optarg))
+				return -1;
+			break;
+		case 'h':
+			usage();
+			exit(9);
+		case 'n':
+			/*
+			 * no effect - automount passes it, meaning 'no-mtab'
+			 */
+			break;
+		case 's':
+			/*
+			 * no effect - automount passes it, meaning sloppy
+			 */
+			break;
+		case 'v':
+			/*
+			 * We must handle the 'verbose' option even if
+			 * we don't use it because mount(8) passes it.
+			 */
+			break;
+		case 'V':
+			ntfs_log_info("%s %s %s %d\n", EXEC_NAME, VERSION, 
+				      FUSE_TYPE, fuse_version());
+			exit(0);
+		default:
+			ntfs_log_error("%s: Unknown option '%s'.\n", EXEC_NAME,
+				       argv[optind - 1]);
+			return -1;
+		}
+	}
+
+	if (!popts->device) {
+		ntfs_log_error("%s: No device is specified.\n", EXEC_NAME);
+		return -1;
+	}
+	if (!popts->mnt_point) {
+		ntfs_log_error("%s: No mountpoint is specified.\n", EXEC_NAME);
+		return -1;
+	}
+
+	return 0;
+}
+
+#ifdef HAVE_SETXATTR
+
+int ntfs_fuse_listxattr_common(ntfs_inode *ni, ntfs_attr_search_ctx *actx,
+			char *list, size_t size, BOOL prefixing)
+{
+	int ret = 0;
+	char *to = list;
+#ifdef XATTR_MAPPINGS
+	BOOL accepted;
+	const struct XATTRMAPPING *item;
+#endif /* XATTR_MAPPINGS */
+
+		/* first list the regular user attributes (ADS) */
+	while (!ntfs_attr_lookup(AT_DATA, NULL, 0, CASE_SENSITIVE,
+				0, NULL, 0, actx)) {
+		char *tmp_name = NULL;
+		int tmp_name_len;
+
+		if (!actx->attr->name_length)
+			continue;
+		tmp_name_len = ntfs_ucstombs(
+			(ntfschar *)((u8*)actx->attr +
+				le16_to_cpu(actx->attr->name_offset)),
+			actx->attr->name_length, &tmp_name, 0);
+		if (tmp_name_len < 0) {
+			ret = -errno;
+			goto exit;
+		}
+				/*
+				 * When using name spaces, do not return
+				 * security, trusted or system attributes
+				 * (filtered elsewhere anyway)
+				 * otherwise insert "user." prefix
+				 */
+		if (prefixing) {
+			if ((strlen(tmp_name) > sizeof(xattr_ntfs_3g))
+			  && !strncmp(tmp_name,xattr_ntfs_3g,
+				sizeof(xattr_ntfs_3g)-1))
+				tmp_name_len = 0;
+			else
+				ret += tmp_name_len
+					 + nf_ns_user_prefix_len + 1;
+		} else
+			ret += tmp_name_len + 1;
+		if (size && tmp_name_len) {
+			if ((size_t)ret <= size) {
+				if (prefixing) {
+					strcpy(to, nf_ns_user_prefix);
+					to += nf_ns_user_prefix_len;
+				}
+				strncpy(to, tmp_name, tmp_name_len);
+				to += tmp_name_len;
+				*to = 0;
+				to++;
+			} else {
+				free(tmp_name);
+				ret = -ERANGE;
+				goto exit;
+			}
+		}
+		free(tmp_name);
+	}
+#ifdef XATTR_MAPPINGS
+		/* now append the system attributes mapped to user space */
+	for (item=ni->vol->xattr_mapping; item; item=item->next) {
+		switch (item->xattr) {
+		case XATTR_NTFS_EFSINFO :
+			accepted = ni->vol->efs_raw
+				&& (ni->flags & FILE_ATTR_ENCRYPTED);
+			break;
+		case XATTR_NTFS_REPARSE_DATA :
+			accepted = (ni->flags & FILE_ATTR_REPARSE_POINT)
+					!= const_cpu_to_le32(0);
+			break;
+// TODO : we are supposed to only return xattrs which are set
+// this is more complex for OBJECT_ID and DOS_NAME
+		default : accepted = TRUE;
+			break;
+		}
+		if (accepted) {
+			ret += strlen(item->name) + 1;
+			if (size) {
+				if ((size_t)ret <= size) {
+					strcpy(to, item->name);
+					to += strlen(item->name);
+					*to++ = 0;
+				} else {
+					ret = -ERANGE;
+					goto exit;
+				}
+			}
+#else /* XATTR_MAPPINGS */
+		/* List efs info xattr for encrypted files */
+	if (ni->vol->efs_raw && (ni->flags & FILE_ATTR_ENCRYPTED)) {
+		ret += sizeof(nf_ns_alt_xattr_efsinfo);
+		if ((size_t)ret <= size) {
+			memcpy(to, nf_ns_alt_xattr_efsinfo,
+				sizeof(nf_ns_alt_xattr_efsinfo));
+			to += sizeof(nf_ns_alt_xattr_efsinfo);
+#endif /* XATTR_MAPPINGS */
+		}
+	}
+exit :
+	return (ret);
+}
+
+#endif /* HAVE_SETXATTR */
diff --git a/src/ntfs-3g_common.h b/src/ntfs-3g_common.h
new file mode 100755
index 0000000000000000000000000000000000000000..e68c699226d8f0a873ab3629499754b042c0e885
--- /dev/null
+++ b/src/ntfs-3g_common.h
@@ -0,0 +1,185 @@
+/*
+ * ntfs-3g_common.h - Common declarations for ntfs-3g and lowntfs-3g.
+ *
+ * Copyright (c) 2010-2011 Jean-Pierre Andre
+ * Copyright (c) 2010      Erik Larsson
+ *
+ * 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_3G_COMMON_H
+#define _NTFS_3G_COMMON_H
+
+#include "inode.h"
+
+struct ntfs_options {
+        char    *mnt_point;     /* Mount point */    
+        char    *options;       /* Mount options */  
+        char    *device;        /* Device to mount */
+	char	*arg_device;	/* Device requested in argv */
+} ;
+
+typedef enum {
+	NF_STREAMS_INTERFACE_NONE,	/* No access to named data streams. */
+	NF_STREAMS_INTERFACE_XATTR,	/* Map named data streams to xattrs. */
+	NF_STREAMS_INTERFACE_OPENXATTR,	/* Same, not limited to "user." */
+	NF_STREAMS_INTERFACE_WINDOWS,	/* "file:stream" interface. */
+} ntfs_fuse_streams_interface;
+
+struct DEFOPTION {
+	const char *name;
+	int type;
+	int flags;
+} ;
+			/* Options, order not significant */
+enum {
+	OPT_RO,
+	OPT_NOATIME,
+	OPT_ATIME,
+	OPT_RELATIME,
+	OPT_DMTIME,
+	OPT_FAKE_RW,
+	OPT_FSNAME,
+	OPT_NO_DEF_OPTS,
+	OPT_DEFAULT_PERMISSIONS,
+	OPT_PERMISSIONS,
+	OPT_ACL,
+	OPT_UMASK,
+	OPT_FMASK,
+	OPT_DMASK,
+	OPT_UID,
+	OPT_GID,
+	OPT_SHOW_SYS_FILES,
+	OPT_HIDE_HID_FILES,
+	OPT_HIDE_DOT_FILES,
+	OPT_IGNORE_CASE,
+	OPT_WINDOWS_NAMES,
+	OPT_COMPRESSION,
+	OPT_NOCOMPRESSION,
+	OPT_SILENT,
+	OPT_RECOVER,
+	OPT_NORECOVER,
+	OPT_REMOVE_HIBERFILE,
+	OPT_SYNC,
+	OPT_BIG_WRITES,
+	OPT_LOCALE,
+	OPT_NFCONV,
+	OPT_NONFCONV,
+	OPT_STREAMS_INTERFACE,
+	OPT_USER_XATTR,
+	OPT_NOAUTO,
+	OPT_DEBUG,
+	OPT_NO_DETACH,
+	OPT_REMOUNT,
+	OPT_BLKSIZE,
+	OPT_INHERIT,
+	OPT_ADDSECURIDS,
+	OPT_STATICGRPS,
+	OPT_USERMAPPING,
+	OPT_XATTRMAPPING,
+	OPT_EFS_RAW,
+} ;
+
+			/* Option flags */
+enum {
+	FLGOPT_BOGUS = 1,
+	FLGOPT_STRING = 2,
+	FLGOPT_OCTAL = 4,
+	FLGOPT_DECIMAL = 8,
+	FLGOPT_APPEND = 16,
+	FLGOPT_NOSUPPORT = 32,
+	FLGOPT_OPTIONAL = 64
+} ;
+
+typedef enum {
+	ATIME_ENABLED,
+	ATIME_DISABLED,
+	ATIME_RELATIVE
+} ntfs_atime_t;
+
+typedef struct {
+	ntfs_volume *vol;
+	unsigned int uid;
+	unsigned int gid;
+	unsigned int fmask;
+	unsigned int dmask;
+	ntfs_fuse_streams_interface streams;
+	ntfs_atime_t atime;
+	u64 dmtime;
+	BOOL ro;
+	BOOL show_sys_files;
+	BOOL hide_hid_files;
+	BOOL hide_dot_files;
+	BOOL windows_names;
+	BOOL ignore_case;
+	BOOL compression;
+	BOOL acl;
+	BOOL silent;
+	BOOL recover;
+	BOOL hiberfile;
+	BOOL sync;
+	BOOL big_writes;
+	BOOL debug;
+	BOOL no_detach;
+	BOOL blkdev;
+	BOOL mounted;
+#ifdef HAVE_SETXATTR	/* extended attributes interface required */
+	BOOL efs_raw;
+#ifdef XATTR_MAPPINGS
+	char *xattrmap_path;
+#endif /* XATTR_MAPPINGS */
+#endif /* HAVE_SETXATTR */
+	struct fuse_chan *fc;
+	BOOL inherit;
+	unsigned int secure_flags;
+	char *usermap_path;
+	char *abs_mnt_point;
+	struct PERMISSIONS_CACHE *seccache;
+	struct SECURITY_CONTEXT security;
+	struct open_file *open_files; /* only defined in lowntfs-3g */
+	u64 latest_ghost;
+} ntfs_fuse_context_t;
+
+extern const char *EXEC_NAME;
+
+#ifdef FUSE_INTERNAL
+#define FUSE_TYPE	"integrated FUSE"
+#else
+#define FUSE_TYPE	"external FUSE"
+#endif
+
+extern const char xattr_ntfs_3g[];
+
+extern const char nf_ns_user_prefix[];
+extern const int nf_ns_user_prefix_len;
+extern const char nf_ns_system_prefix[];
+extern const int nf_ns_system_prefix_len;
+extern const char nf_ns_security_prefix[];
+extern const int nf_ns_security_prefix_len;
+extern const char nf_ns_trusted_prefix[];
+extern const int nf_ns_trusted_prefix_len;
+
+int ntfs_strappend(char **dest, const char *append);
+int ntfs_strinsert(char **dest, const char *append);
+char *parse_mount_options(ntfs_fuse_context_t *ctx,
+			const struct ntfs_options *popts, BOOL low_fuse);
+int ntfs_parse_options(struct ntfs_options *popts, void (*usage)(void),
+			int argc, char *argv[]);
+
+int ntfs_fuse_listxattr_common(ntfs_inode *ni, ntfs_attr_search_ctx *actx,
+ 			char *list, size_t size, BOOL prefixing);
+
+#endif /* _NTFS_3G_COMMON_H */
diff --git a/src/secaudit.c b/src/secaudit.c
new file mode 100755
index 0000000000000000000000000000000000000000..8ffb2a912d571cb90ae0fce90df7319a9fe5049e
--- /dev/null
+++ b/src/secaudit.c
@@ -0,0 +1,7777 @@
+/*
+ *		 Display and audit security attributes in an NTFS volume
+ *
+ * Copyright (c) 2007-2014 Jean-Pierre Andre
+ * 
+ *	Options :
+ *		-a auditing security data
+ *		-b backing up NTFS ACLs
+ *		-e set extra backed-up parameters (in conjunction with -s)
+ *		-h displaying hexadecimal security descriptors within a file
+ *		-r recursing in a directory
+ *		-s setting backed-up NTFS ACLs
+ *		-u getting a user mapping proposal
+ *		-v verbose (very verbose if set twice)
+ *	   also, if compile-time option is set
+ *		-t run internal tests (with no access to storage)
+ *
+ *	On Linux (being root, with volume not mounted) :
+ *		secaudit -h [file]
+ *			display the security descriptors found in file
+ *		secaudit -a[rv] volume
+ *			audit the volume
+ *		secaudit [-v] volume file
+ *			display the security parameters of file
+ *		secaudit -r[v] volume directory
+ *			display the security parameters of files in directory
+ *		secaudit -b[v] volume [directory]
+ *			backup the security parameters of files in directory
+ *		secaudit -s[ve] volume [backupfile]
+ *			set the security parameters as indicated in backup
+ *			with -e set extra parameters (Windows attrib)
+ *		secaudit volume perms file
+ *			set the security parameters of file to perms (mode or acl)
+ *		secaudit -r[v] volume perms directory
+ *			set the security parameters of files in directory to perms
+ *          special case, does not require being root :
+ *		secaudit [-v] mounted-file
+ *			display the security parameters of mounted file
+ *
+ *
+ *	On Windows (the volume being part of file name)
+ *		secaudit -h [file]
+ *			display the security descriptors found in file
+ *		secaudit [-v] file
+ *			display the security parameters of file
+ *		secaudit -r[v] directory
+ *			display the security parameters of files in directory
+ *		secaudit -b[v] directory
+ *			backup the security parameters of files in directory
+ *		secaudit -s[v] [backupfile]
+ *			set the security parameters as indicated in backup
+ *			with -e set extra parameters (Windows attrib)
+ *		secaudit perms file
+ *			set the security parameters of file to perms (mode or acl)
+ *		secaudit -r[v] perms directory
+ *			set the security parameters of files in directory to perms
+ */
+
+/*	History
+ *
+ *  Nov 2007
+ *     - first version, by concatenating miscellaneous utilities
+ *
+ *  Jan 2008, version 1.0.1
+ *     - fixed mode displaying
+ *     - added a global severe errors count
+ *
+ *  Feb 2008, version 1.0.2
+ *     - implemented conversions for big-endian machines
+ *
+ *  Mar 2008, version 1.0.3
+ *     - avoided consistency checks on $Secure when there is no such file
+ *
+ *  Mar 2008, version 1.0.4
+ *     - changed ordering of ACE's
+ *     - changed representation for special flags
+ *     - defaulted to stdin for option -h
+ *     - added self tests (compile time option)
+ *     - fixed errors specific to big-endian computers
+ *
+ *  Apr 2008, version 1.1.0
+ *     - developped Posix ACLs to NTFS ACLs conversions
+ *     - developped NTFS ACLs backup and restore
+ *
+ *  Apr 2008, version 1.1.1
+ *     - fixed an error specific to big-endian computers
+ *     - checked hash value and fixed error report in restore
+ *     - improved display in showhex() and restore()
+ *
+ *  Apr 2008, version 1.1.2
+ *     - improved and fixed Posix ACLs to NTFS ACLs conversions
+ *
+ *  Apr 2008, version 1.1.3
+ *     - reenabled recursion for setting a new mode or ACL
+ *     - processed Unicode file names and displayed them as UTF-8
+ *     - allocated dynamically memory for file names when recursing
+ *
+ *  May 2008, version 1.1.4
+ *     - all Unicode/UTF-8 strings checked and processed
+ *
+ *  Jul 2008, version 1.1.5
+ *     - made Windows owner consistent with Linux owner when changing mode
+ *     - allowed owner change on Windows when it does not match Linux owner
+ *     - skipped currently unused code
+ *
+ *  Aug 2008, version 1.2.0
+ *     - processed \.NTFS-3G\UserMapping on Windows
+ *     - made use of user mappings through the security API or direct access
+ *     - fixed a bug in restore
+ *     - fixed UTF-8 conversions
+ *
+ *  Sep 2008, version 1.3.0
+ *     - split the code to have part of it shared with ntfs-3g library
+ *     - fixed testing for end of SDS block
+ *     - added samples checking in selftest for easier debugging
+ *
+ *  Oct 2008, version 1.3.1
+ *     - fixed outputting long long data when testing on a Palm organizer
+ *
+ *  Dec 2008, version 1.3.2
+ *     - fixed restoring ACLs
+ *     - added optional logging of ACL hashes to facilitate restore checks
+ *     - fixed collecting SACLs
+ *     - fixed setting special control flags
+ *     - fixed clearing existing SACLs (Linux only) and DACLs
+ *     - changed the sequencing of items when quering a security descriptor
+ *     - avoided recursing on junctions and symlinks on Windows
+ *
+ *  Jan 2009, version 1.3.3
+ *     - save/restore Windows attributes (code from Faisal)
+ *
+ *  Mar 2009, version 1.3.4
+ *     - enabled displaying attributes of a mounted file over Linux
+ *
+ *  Apr 2009, version 1.3.5
+ *     - fixed initialisation of stand-alone user mapping
+ *     - fixed POSIXACL redefinition when included in the ntfs-3g package
+ *     - fixed displaying of options
+ *     - fixed a dependency on the shared library version used
+ *
+ *  May 2009, version 1.3.6
+ *     - added new samples for self testing
+ *
+ *  Jun 2009, version 1.3.7
+ *     - fixed displaying owner and group of a mounted file over Linux
+ *
+ *  Jul 2009, version 1.3.8
+ *     - fixed again displaying owner and group of a mounted file over Linux
+ *     - cleaned some code to avoid warnings
+ *
+ *  Nov 2009, version 1.3.9
+ *     - allowed security descriptors up to 64K
+ *
+ *  Nov 2009, version 1.3.10
+ *     - applied patches for MacOSX from Erik Larsson
+ *
+ *  Nov 2009, version 1.3.11
+ *     - replace <attr/xattr.h> by <sys/xattr.h> (provided by glibc)
+ *
+ *  Dec 2009, version 1.3.12
+ *     - worked around "const" possibly redefined in config.h
+ *
+ *  Dec 2009, version 1.3.13
+ *     - fixed the return code of dorestore()
+ *
+ *  Dec 2009, version 1.3.14
+ *     - adapted to opensolaris
+ *
+ *  Jan 2010, version 1.3.15
+ *     - more adaptations to opensolaris
+ *     - removed the fix for return code of dorestore()
+ *
+ *  Jan 2010, version 1.3.16
+ *     - repeated the fix for return code of dorestore()
+ *
+ *  Mar 2010, version 1.3.17
+ *     - adapted to new default user mapping
+ *     - fixed #ifdef'd code for selftest
+ *
+ *  May 2010, version 1.3.18
+ *     - redefined early error logging
+ *
+ *  Mar 2011, version 1.3.19
+ *     - fixed interface to ntfs_initialize_file_security()
+ *
+ *  Apr 2011, version 1.3.20
+ *     - fixed false memory leak detection
+ *
+ *  Jun 2011, version 1.3.21
+ *     - cleaned a few unneeded variables
+ *
+ *  Nov 2011, version 1.3.22
+ *     - added a distinctive prefix to owner and group SID
+ *     - fixed a false memory leak detection
+ *
+ *  Jun 2012, version 1.3.23
+ *     - added support for SACL (nickgarvey)
+ *
+ *  Jul 2012, version 1.3.24
+ *     - added self-tests for authenticated users
+ *     - added display of ace-inherited flag
+ *     - made runnable on OpenIndiana
+ *
+ *  Aug 2012, version 1.4.0
+ *     - added an option for user mapping proposal
+ *
+ *  Sep 2013, version 1.4.1
+ *     - silenced an aliasing warning by gcc >= 4.8
+ *
+ *  May 2014, version 1.4.2
+ *     - decoded GENERIC_ALL permissions
+ *     - decoded more "well-known" and generic SIDs
+ *     - showed Windows ownership in verbose situations
+ *     - fixed apparent const violations
+ */
+
+/*
+ * 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
+ */
+
+/*
+ *		General parameters which may have to be adapted to needs
+ */
+
+#define AUDT_VERSION "1.4.2"
+
+#define GET_FILE_SECURITY "ntfs_get_file_security"
+#define SET_FILE_SECURITY "ntfs_set_file_security"
+#define GET_FILE_ATTRIBUTES "ntfs_get_file_attributes"
+#define SET_FILE_ATTRIBUTES "ntfs_set_file_attributes"
+#define READ_DIRECTORY "ntfs_read_directory"
+#define READ_SDS "ntfs_read_sds"
+#define READ_SII "ntfs_read_sii"
+#define READ_SDH "ntfs_read_sdh"
+#define GET_USER "ntfs_get_user"
+#define GET_GROUP "ntfs_get_group"
+#define GET_USID "ntfs_get_usid"
+#define GET_GSID "ntfs_get_gsid"
+#define INIT_FILE_SECURITY "ntfs_initialize_file_security"
+#define LEAVE_FILE_SECURITY "ntfs_leave_file_security"
+
+/*
+ *			External declarations
+ */
+
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdarg.h>
+
+				/*
+				 * integration into secaudit, check whether Win32,
+				 * may have to be adapted to compiler or something else
+				 */
+
+#ifndef WIN32
+#if defined(__WIN32) | defined(__WIN32__) | defined(WNSC)
+#define WIN32 1
+#endif
+#endif
+
+				/*
+				 * integration into secaudit/Win32
+				 */
+#ifdef WIN32
+#include <windows.h>
+#define __LITTLE_ENDIAN 1234
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#else
+				/*
+				 * integration into secaudit/STSC
+				 */
+#ifdef STSC
+#include <stat.h>
+#undef __BYTE_ORDER
+#define __BYTE_ORDER __BIG_ENDIAN
+#else
+				/*
+				 * integration into secaudit/Linux
+				 */
+
+#include <sys/stat.h>
+#ifdef HAVE_ENDIAN_H
+#include <endian.h>
+#endif
+#ifdef HAVE_MACHINE_ENDIAN_H
+#include <machine/endian.h>
+#endif
+#include <unistd.h>
+#include <dlfcn.h>
+#endif /* STSC */
+#endif /* WIN32 */
+#include "secaudit.h"
+
+#ifndef WIN32
+
+#ifndef STSC
+
+#if !defined(HAVE_CONFIG_H) && POSIXACLS && !defined(__SVR4)
+      /* require <sys/xattr.h> if not integrated into ntfs-3g package */
+#define HAVE_SETXATTR 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#ifdef _FILE_OFFSET_BITS
+#undef _FILE_OFFSET_BITS  /* work around "_FILE_OFFSET_BITS" possibly already defined */
+#endif
+      /* <sys/xattr.h> according to config.h if integrated into ntfs-3g package */
+#include "config.h"
+#ifdef const /* work around "const" possibly redefined in config.h */
+#undef const
+#endif
+#ifndef POSIXACLS
+#define POSIXACLS 0
+#endif
+#endif /* HAVE_CONFIG_H */
+
+#ifdef HAVE_SETXATTR
+#include <sys/xattr.h>
+#else
+#warning "The extended attribute package is not available"
+#endif /* HAVE_SETXATTR */
+
+#endif /* STSC */
+
+#define NTFS_MNT_NONE 0    /* no flag for mounting the device */
+#define NTFS_MNT_RDONLY 1  /* flag for mounting the device read-only */
+
+struct CALLBACK;
+
+typedef int (*dircallback)(struct CALLBACK *context, char *ntfsname,
+	int length, int type, long long pos, u64 mft_ref,
+	unsigned int dt_type);
+
+#ifndef HAVE_SYSLOG_H
+void ntfs_log_early_error(const char *format, ...)
+			__attribute__((format(printf, 1, 2)));
+#endif
+
+#if USESTUBS | defined(STSC)
+
+int ntfs_get_file_security(void *scapi,
+		const char *path, DWORD selection,
+		char *buf, DWORD buflen, LPDWORD psize);
+BOOL ntfs_set_file_security(void *scapi,
+		const char *path, DWORD selection, const char *attr);
+int ntfs_get_file_attributes(void *scapi,
+		const char *path);
+BOOL ntfs_set_file_attributes(void *scapi,
+		const char *path, DWORD attrib);
+BOOL ntfs_read_directory(void *scapi,
+		const char *path, dircallback callback, void *context);
+int ntfs_read_sds(void *scapi,
+		char *buf, DWORD buflen, DWORD offset);
+void *ntfs_read_sii(void *scapi, void *entry);
+void *ntfs_read_sdh(void *scapi, void *entry);
+
+int ntfs_get_usid(void *scapi, uid_t uid, char *buf);
+int ntfs_get_gsid(void *scapi, gid_t gid, char *buf);
+int ntfs_get_user(void *scapi, const char *usid);
+int ntfs_get_group(void *scapi, const char *gsid);
+
+void *ntfs_initialize_file_security(const char *device, unsigned long flags);
+BOOL ntfs_leave_file_security(void *scapi);
+
+#else
+
+typedef int (*type_get_file_security)(void *scapi,
+		const char *path, DWORD selection,
+		char *buf, DWORD buflen, LPDWORD psize);
+typedef BOOL (*type_set_file_security)(void *scapi,
+		const char *path, DWORD selection, const char *attr);
+typedef int (*type_get_file_attributes)(void *scapi,
+		const char *path);
+typedef BOOL (*type_set_file_attributes)(void *scapi,
+		const char *path, DWORD attrib);
+typedef BOOL (*type_read_directory)(void *scapi,
+		const char *path, dircallback callback, void *context);
+typedef int (*type_read_sds)(void *scapi,
+		char *buf, DWORD buflen, DWORD offset);
+typedef void *(*type_read_sii)(void *scapi, void *entry);
+typedef void *(*type_read_sdh)(void *scapi, void *entry);
+
+typedef int (*type_get_usid)(void *scapi, uid_t uid, char *buf);
+typedef int (*type_get_gsid)(void *scapi, gid_t gid, char *buf);
+typedef int (*type_get_user)(void *scapi, const char *usid);
+typedef int (*type_get_group)(void *scapi, const char *gsid);
+
+typedef void *(*type_initialize_file_security)(const char *device,
+				unsigned long flags);
+typedef BOOL (*type_leave_file_security)(void *scapi);
+
+type_get_file_security ntfs_get_file_security;
+type_set_file_security ntfs_set_file_security;
+type_get_file_attributes ntfs_get_file_attributes;
+type_set_file_attributes ntfs_set_file_attributes;
+type_read_directory ntfs_read_directory;
+type_read_sds ntfs_read_sds;
+type_read_sii ntfs_read_sii;
+type_read_sdh ntfs_read_sdh;
+
+type_get_usid ntfs_get_usid;
+type_get_gsid ntfs_get_gsid;
+type_get_user ntfs_get_user;
+type_get_group ntfs_get_group;
+
+type_initialize_file_security ntfs_initialize_file_security;
+type_leave_file_security ntfs_leave_file_security;
+
+
+#endif /* USESTUBS | defined(STSC) */
+#endif /* WIN32 */
+
+#define ACCOUNTSIZE 256  /* maximum size of an account name */
+
+/*
+ *		Prototypes for local functions
+ */
+
+BOOL open_security_api(void);
+BOOL close_security_api(void);
+#ifndef WIN32
+BOOL open_volume(const char*, unsigned long flags);
+BOOL close_volume(const char*);
+#endif
+unsigned int get2l(const char*, int);
+unsigned long get4l(const char*, int);
+u64 get6l(const char*, int);
+u64 get6h(const char*, int);
+u64 get8l(const char*, int);
+void set2l(char*, unsigned int);
+void set4l(char*, unsigned long);
+void hexdump(const char*, int, int);
+u32 hash(const le32*, int);
+unsigned int utf8size(const char*, int);
+unsigned int makeutf8(char*, const char*, int);
+unsigned int utf16size(const char*);
+unsigned int makeutf16(char*, const char*);
+unsigned int utf16len(const char*);
+void printname(FILE*, const char*);
+void printerror(FILE*);
+BOOL guess_dir(const char*);
+void showsid(const char*, int, const char*, int);
+void showusid(const char*, int);
+void showgsid(const char*, int);
+void showownership(const char*);
+void showheader(const char*, int);
+void showace(const char*, int, int, int);
+void showacl(const char*, int, int, int);
+void showdacl(const char*, int, int);
+void showsacl(const char*, int, int);
+void showall(const char*, int);
+void showposix(const struct POSIX_SECURITY*);
+int linux_permissions(const char*, BOOL);
+uid_t linux_owner(const char*);
+gid_t linux_group(const char*);
+int basicread(void*, char*, size_t, off_t);
+int dummyread(void*, char*, size_t, off_t);
+int local_build_mapping(struct MAPPING *[], const char*);
+void newblock(s32);
+void freeblocks(void);
+u32 getmsbhex(const char*);
+u32 getlsbhex(const char*);
+BOOL ishexdump(const char*, int, int);
+void showhex(FILE*);
+void showfull(const char*, BOOL);
+BOOL applyattr(const char*, const char*, BOOL, int, s32);
+BOOL restore(FILE*);
+BOOL dorestore(const char*, FILE*);
+u32 merge_rights(const struct POSIX_SECURITY*, BOOL);
+void tryposix(struct POSIX_SECURITY*);
+void check_samples(void);
+void basictest(int, BOOL, const SID*, const SID*);
+void posixtest(int, BOOL, const SID*, const SID*);
+void selftests(void);
+unsigned int getfull(char*, const char*);
+BOOL updatefull(const char *name, DWORD flags, char *attr);
+BOOL setfull(const char*, int, BOOL);
+BOOL singleshow(const char*);
+BOOL proposal(const char*, const char*);
+BOOL showmounted(const char*);
+BOOL processmounted(const char*);
+BOOL recurseshow(const char*);
+BOOL singleset(const char*, int);
+BOOL recurseset(const char*, int);
+#ifdef WIN32
+BOOL backup(const char*);
+BOOL listfiles(const char*);
+#if POSIXACLS
+BOOL iterate(RECURSE, const char*, const struct POSIX_SECURITY*);
+#else
+BOOL iterate(RECURSE, const char*, mode_t);
+#endif
+#else
+BOOL backup(const char*, const char*);
+BOOL listfiles(const char*, const char*);
+BOOL mapproposal(const char*, const char*);
+#endif
+#if POSIXACLS
+BOOL setfull_posix(const char *, const struct POSIX_SECURITY*, BOOL);
+struct POSIX_SECURITY *linux_permissions_posix(const char*, BOOL);
+BOOL recurseset_posix(const char*, const struct POSIX_SECURITY*);
+BOOL singleset_posix(const char*, const struct POSIX_SECURITY*);
+struct POSIX_SECURITY *encode_posix_acl(const char*);
+#endif
+static void *stdmalloc(size_t);
+static void stdfree(void*);
+
+BOOL valid_sds(const char*, unsigned int, unsigned int,
+		unsigned int, u32, BOOL);
+BOOL valid_sii(const char*, u32);
+BOOL valid_sdh(const char*, u32, u32);
+int consist_sds(const char*, unsigned int, unsigned int, BOOL);
+int consist_sii(const char*);
+int consist_sdh(const char*);
+int audit_sds(BOOL);
+int audit_sii(void);
+int audit_sdh(void);
+void audit_summary(void);
+BOOL audit(const char*);
+int getoptions(int, char*[]);
+
+#ifndef WIN32
+
+/*
+ *		Structures for collecting directory contents (Linux only)
+ */
+
+struct LINK {
+	struct LINK *next;
+	char name[1];
+} ;
+
+struct CALLBACK {
+	struct LINK *head;
+	const char *dir;
+} ;
+
+int callback(struct CALLBACK *context, char *ntfsname,
+	int length, int type, long long pos, u64 mft_ref,
+	unsigned int dt_type);
+#endif
+
+/*
+ *		  Global constants
+ */
+
+#define BANNER "secaudit " AUDT_VERSION " : NTFS security data auditing"
+
+#if SELFTESTS & !USESTUBS
+
+/*
+ *		Dummy mapping file (self tests only)
+ */
+
+#define DUMMYAUTH "S-1-5-21-3141592653-589793238-462843383-"
+char dummymapping[] =	"500::" DUMMYAUTH "1000\n"
+			"501::" DUMMYAUTH "1001\n"
+			"502::" DUMMYAUTH "1002\n"
+			"503::" DUMMYAUTH "1003\n"
+			"516::" DUMMYAUTH "1016\n"
+			":500:" DUMMYAUTH "513\r\n"
+			":511:S-1-5-21-1607551490-981732888-1819828000-513\n"
+			":516:" DUMMYAUTH "1012\r\n"
+			"::"	DUMMYAUTH "10000\n";
+
+/*
+ *		SID for world  (S-1-1-0)
+ */
+
+static const char worldsidbytes[] = {
+		1,		/* revision */
+		1,		/* auth count */
+		0, 0, 0, 0, 0, 1,	/* base */
+		0, 0, 0, 0	/* 1st level */
+} ;
+static const SID *worldsid = (const SID*)worldsidbytes;
+
+/*	        
+ *		SID for authenticated user (S-1-5-11)
+ */
+	        
+static const char authsidbytes[] = {
+		1,		/* revision */ 
+		1,		/* auth count */
+		0, 0, 0, 0, 0, 5,	/* base */
+		11, 0, 0, 0	/* 1st level */
+};
+  
+static const SID *authsid = (const SID*)authsidbytes;
+
+/*
+ *		SID for administrator (S-1-5-32-544)
+ */
+
+static const char adminsidbytes[] = {
+		1,		/* revision */
+		2,		/* auth count */
+		0, 0, 0, 0, 0, 5,	/* base */
+		32, 0, 0, 0,	/* 1st level */
+		32, 2, 0, 0	/* 2nd level */
+};
+
+static const SID *adminsid = (const SID*)adminsidbytes;
+
+/*
+ *		SID for local users (S-1-5-32-545)
+ */
+
+static const char localsidbytes[] = {
+		1,		/* revision */
+		2,		/* auth count */
+		0, 0, 0, 0, 0, 5,	/* base */
+		32, 0, 0, 0,	/* 1st level */
+		33, 2, 0, 0	/* 2nd level */
+};
+
+static const SID *localsid = (const SID*)localsidbytes;
+
+/*	        
+ *		SID for system (S-1-5-18)
+ */
+	        
+static const char systemsidbytes[] = {
+		1,		/* revision */ 
+		1,		/* auth count */
+		0, 0, 0, 0, 0, 5,	/* base */
+		18, 0, 0, 0	/* 1st level */
+	};
+  
+static const SID *systemsid = (const SID*)systemsidbytes;
+
+#endif
+
+/*
+ *		  Global variables
+ */
+
+BOOL opt_a;	/* audit security data */
+BOOL opt_b;	/* backup NTFS ACLs */
+BOOL opt_e;	/* restore extra (currently windows attribs) */
+BOOL opt_h;	/* display an hexadecimal descriptor in a file */
+BOOL opt_r;	/* recursively apply to subdirectories */
+BOOL opt_s;	/* restore NTFS ACLs */
+BOOL opt_u;	/* user mapping proposal */
+#if SELFTESTS & !USESTUBS
+BOOL opt_t;	/* run self-tests */
+#endif
+int opt_v;  /* verbose or very verbose*/
+struct SECURITY_DATA *securdata[(MAXSECURID + (1 << SECBLKSZ) - 1)/(1 << SECBLKSZ)];
+#if FORCEMASK
+BOOL opt_m;	/* force a mask - dangerous */
+u32 forcemsk /* mask to force */
+#endif
+unsigned int errors; /* number of severe errors */
+unsigned int warnings; /* number of non-severe errors */
+
+struct CHKALLOC *firstalloc;
+struct SECURITY_CONTEXT context;
+MAPTYPE mappingtype;
+
+#ifdef STSC
+#define static
+#endif
+
+#ifndef WIN32
+
+void *ntfs_handle;
+void *ntfs_context = (void*)NULL;
+
+/*
+ *		Open and close the security API (platform dependent)
+ */
+
+BOOL open_security_api(void)
+{
+#if USESTUBS | defined(STSC)
+	return (TRUE);
+#else
+	char *error;
+	BOOL err;
+	const char *libfile;
+
+	err = TRUE;
+	libfile = getenv(ENVNTFS3G);
+	if (!libfile)
+		libfile = (sizeof(char*) == 8 ? LIBFILE64 : LIBFILE);
+#ifdef __SVR4
+		/* do not override library functions by caller ones */
+	ntfs_handle = dlopen(libfile,RTLD_LAZY | RTLD_GROUP);
+#else
+	ntfs_handle = dlopen(libfile,RTLD_LAZY);
+#endif
+	if (ntfs_handle) {
+		ntfs_initialize_file_security = (type_initialize_file_security)
+				dlsym(ntfs_handle,INIT_FILE_SECURITY);
+		error = dlerror();
+		if (error)
+			fprintf(stderr," %s\n",error);
+		else {
+			ntfs_leave_file_security = (type_leave_file_security)
+					dlsym(ntfs_handle,LEAVE_FILE_SECURITY);
+			ntfs_get_file_security = (type_get_file_security)
+					dlsym(ntfs_handle,GET_FILE_SECURITY);
+			ntfs_set_file_security = (type_set_file_security)
+					dlsym(ntfs_handle,SET_FILE_SECURITY);
+			ntfs_get_file_attributes = (type_get_file_attributes)
+					dlsym(ntfs_handle,GET_FILE_ATTRIBUTES);
+			ntfs_set_file_attributes = (type_set_file_attributes)
+					dlsym(ntfs_handle,SET_FILE_ATTRIBUTES);
+			ntfs_read_directory = (type_read_directory)
+					dlsym(ntfs_handle,READ_DIRECTORY);
+			ntfs_read_sds = (type_read_sds)
+					dlsym(ntfs_handle,READ_SDS);
+			ntfs_read_sii = (type_read_sii)
+					dlsym(ntfs_handle,READ_SII);
+			ntfs_read_sdh = (type_read_sdh)
+					dlsym(ntfs_handle,READ_SDH);
+			ntfs_get_user = (type_get_user)
+					dlsym(ntfs_handle,GET_USER);
+			ntfs_get_group = (type_get_group)
+					dlsym(ntfs_handle,GET_GROUP);
+			ntfs_get_usid = (type_get_usid)
+					dlsym(ntfs_handle,GET_USID);
+			ntfs_get_gsid = (type_get_gsid)
+					dlsym(ntfs_handle,GET_GSID);
+			err = !ntfs_initialize_file_security
+				|| !ntfs_leave_file_security
+				|| !ntfs_get_file_security
+				|| !ntfs_set_file_security
+				|| !ntfs_get_file_attributes
+				|| !ntfs_set_file_attributes
+				|| !ntfs_read_directory
+				|| !ntfs_read_sds
+				|| !ntfs_read_sii
+				|| !ntfs_read_sdh
+				|| !ntfs_get_user
+				|| !ntfs_get_group
+				|| !ntfs_get_usid
+				|| !ntfs_get_gsid;
+
+			if (error)
+				fprintf(stderr,"ntfs-3g API not available\n");
+		}
+	} else {
+		fprintf(stderr,"Could not open ntfs-3g library\n");
+		fprintf(stderr,"\nPlease set environment variable \"" ENVNTFS3G "\"\n");
+		fprintf(stderr,"to appropriate path and retry\n");
+	}
+	return (!err);
+#endif /* USESTUBS | defined(STSC) */
+}
+
+BOOL close_security_api(void)
+{
+#if USESTUBS | defined(STSC)
+	return (0);
+#else
+	return (!dlclose(ntfs_handle));
+#endif /* USESTUBS | defined(STSC) */
+}
+
+/*
+ *		Open and close a volume (platform dependent)
+ *	Assumes a single volume is opened
+ */
+
+BOOL open_volume(const char *volume, unsigned long flags)
+{
+	BOOL ok;
+
+	ok = FALSE;
+	if (!ntfs_context) {
+		ntfs_context = ntfs_initialize_file_security(volume,flags);
+		if (ntfs_context) {
+			if (*(u32*)ntfs_context != MAGIC_API) {
+				fprintf(stderr,"Versions of ntfs-3g and secaudit"
+						" are not compatible\n");
+			} else {
+				fprintf(stderr,"\"%s\" opened\n",volume);
+				mappingtype = MAPEXTERN;
+				ok = TRUE;
+			}
+		} else {
+			fprintf(stderr,"Could not open \"%s\"\n",volume);
+			fprintf(stderr,"Make sure \"%s\" is not mounted\n",volume);
+		}
+	} else
+		fprintf(stderr,"A volume is already open\n");
+	return (ok);
+}
+
+BOOL close_volume(const char *volume)
+{
+	BOOL r;
+
+	r = ntfs_leave_file_security(ntfs_context);
+	if (r)
+		fprintf(stderr,"\"%s\" closed\n",volume);
+	else
+		fprintf(stderr,"Could not close \"%s\"\n",volume);
+	ntfs_context = (void*)NULL;
+	return (r);
+}
+
+#endif /* WIN32 */
+
+/*
+ *		Extract small or big endian data from an array of bytes
+ */
+
+unsigned int get2l(const char *attr, int p)
+{
+	int i;
+	unsigned int v;
+
+	v = 0;
+	for (i=0; i<2; i++)
+		v += (attr[p+i] & 255) << (8*i);
+	return (v);
+}
+
+unsigned long get4l(const char *attr, int p)
+{
+	int i;
+	unsigned long v;
+
+	v = 0;
+	for (i=0; i<4; i++)
+		v += ((long)(attr[p+i] & 255)) << (8*i);
+	return (v);
+}
+
+u64 get6l(const char *attr, int p)
+{
+	int i;
+	u64 v;
+
+	v = 0;
+	for (i=0; i<6; i++)
+		v += ((long long)(attr[p+i] & 255)) << (8*i);
+	return (v);
+}
+
+u64 get6h(const char *attr, int p)
+{
+	int i;
+	u64 v;
+
+	v = 0;
+	for (i=0; i<6; i++)
+		v = (v << 8) + (attr[p+i] & 255);
+	return (v);
+}
+
+u64 get8l(const char *attr, int p)
+{
+	int i;
+	u64 v;
+
+	v = 0;
+	for (i=0; i<8; i++)
+		v += ((long long)(attr[p+i] & 255)) << (8*i);
+	return (v);
+}
+
+/*
+ *		Set small or big endian data into an array of bytes
+ */
+
+void set2l(char *p, unsigned int v)
+{
+	int i;
+
+	for (i=0; i<2; i++)
+		p[i] = ((v >> 8*i) & 255);
+}
+
+void set4l(char *p, unsigned long v)
+{
+	int i;
+
+	for (i=0; i<4; i++)
+		p[i] = ((v >> 8*i) & 255);
+}
+
+
+/*
+ *		hexadecimal dump of an array of bytes
+ */
+
+void hexdump(const char *attr, int size, int level)
+{
+	int i,j;
+
+	for (i=0; i<size; i+=16) {
+		if (level)
+			printf("%*c",level,' ');
+		printf("%06x ",i);
+		for (j=i; (j<(i+16)) && (j<size); j++)
+			printf((j & 3 ? "%02x" : " %02x"),attr[j] & 255);
+		printf("\n");
+	}
+}
+
+u32 hash(const le32 *buf, int size /* bytes */)
+{
+	u32 h;
+	int i;
+
+	h = 0;
+	for (i=0; 4*i<size; i++)
+		h = le32_to_cpu(buf[i]) + (h << 3) + ((h >> 29) & 7);
+	return (h);
+}
+
+/*
+ *		Evaluate the size of UTS-8 conversion of a UTF-16LE text
+ *	trailing '\0' not accounted for
+ *	Returns 0 for invalid input
+ */
+
+unsigned int utf8size(const char *utf16, int length)
+{
+	int i;
+	unsigned int size;
+	enum { BASE, SURR, ERR } state;
+
+	size = 0;
+	state = BASE;
+	for (i=0; i<2*length; i+=2) {
+		switch (state) {
+		case BASE :
+			if (utf16[i+1] & 0xf8) {
+				if ((utf16[i+1] & 0xf8) == 0xd8)
+					state = (utf16[i+1] & 4 ? ERR : SURR);
+				else
+#if NOREVBOM
+					if (((utf16[i+1] & 0xff) == 0xff)
+					  && ((utf16[i] & 0xfe) == 0xfe))
+						state = ERR;
+					else
+						size += 3;
+#else
+					size += 3;
+#endif
+			} else
+				if ((utf16[i] & 0x80) || utf16[i+1])
+					size += 2;
+				else
+					size++;
+			break;
+		case SURR :
+			if ((utf16[i+1] & 0xfc) == 0xdc) {
+				state = BASE;
+				size += 4;
+			} else
+				state = ERR;
+			break;
+		case ERR :
+			break;
+		}
+	}
+	if (state != BASE)
+		size = 0;
+	return (size);
+}
+
+/*
+ *		Convert a UTF-16LE text to UTF-8
+ *	Note : wcstombs() not used because on Linux it fails for characters
+ *	not present in current locale
+ *	Returns size or zero for invalid input
+ */
+
+unsigned int makeutf8(char *utf8, const char *utf16, int length)
+{
+	int i;
+	unsigned int size;
+	unsigned int rem;
+	enum { BASE, SURR, ERR } state;
+
+	size = 0;
+	rem = 0;
+	state = BASE;
+	for (i=0; i<2*length; i+=2) {
+		switch (state) {
+		case BASE :
+			if (utf16[i+1] & 0xf8) {
+				if ((utf16[i+1] & 0xf8) == 0xd8) {
+					if (utf16[i+1] & 4)
+						state = ERR;
+					else {
+						utf8[size++] = 0xf0 + (utf16[i+1] & 7)
+                                                                    + ((utf16[i] & 0xc0) == 0xc0);
+						utf8[size++] = 0x80 + (((utf16[i] + 64) >> 2) & 63);
+						rem = utf16[i] & 3;
+						state = SURR;
+					}
+				} else {
+#if NOREVBOM
+					if (((utf16[i+1] & 0xff) == 0xff)
+					  && ((utf16[i] & 0xfe) == 0xfe))
+						state = ERR;
+					else {
+						utf8[size++] = 0xe0 + ((utf16[i+1] >> 4) & 15);
+						utf8[size++] = 0x80
+							+ ((utf16[i+1] & 15) << 2)
+							+ ((utf16[i] >> 6) & 3);
+						utf8[size++] = 0x80 + (utf16[i] & 63);
+					}
+#else
+					utf8[size++] = 0xe0 + ((utf16[i+1] >> 4) & 15);
+					utf8[size++] = 0x80
+						+ ((utf16[i+1] & 15) << 2)
+						+ ((utf16[i] >> 6) & 3);
+					utf8[size++] = 0x80 + (utf16[i] & 63);
+#endif
+				}
+			} else
+				if ((utf16[i] & 0x80) || utf16[i+1]) {
+					utf8[size++] = 0xc0
+						+ ((utf16[i+1] & 15) << 2)
+						+ ((utf16[i] >> 6) & 3);
+					utf8[size++] = 0x80 + (utf16[i] & 63);
+				} else
+					utf8[size++] = utf16[i];
+			break;
+		case SURR :
+			if ((utf16[i+1] & 0xfc) == 0xdc) {
+				utf8[size++] = 0x80 + (rem << 4)
+						 + ((utf16[i+1] & 3) << 2)
+						 + ((utf16[i] >> 6) & 3);
+				utf8[size++] = 0x80 + (utf16[i] & 63);
+				state = BASE;
+			} else
+				state = ERR;
+			break;
+		case ERR :
+			break;
+		}
+	}
+	utf8[size] = 0;
+	if (state != BASE)
+		state = ERR;
+	return (state == ERR ? 0 : size);
+}
+
+#ifdef WIN32
+
+/*
+ *		Evaluate the size of UTF-16LE conversion of a UTF-8 text
+ *	(basic conversions only)
+ *	trailing '\0' not accounted for
+ */
+
+unsigned int utf16size(const char *utf8)
+{
+	unsigned int size;
+	const char *p;
+	int c;
+	unsigned int code;
+	enum { BASE, TWO, THREE, THREE2, THREE3, FOUR, ERR } state;
+
+	p = utf8;
+	size = 0;
+	state = BASE;
+	while (*p) {
+		c = *p++ & 255;
+		switch (state) {
+		case BASE :
+			if (!(c & 0x80))
+				size++;
+			else
+				if (c < 0xc2)
+					state = ERR;
+				else
+					if (c < 0xe0)
+						state = TWO;
+					else
+						if (c < 0xf0) {
+							if (c == 0xe0)
+								state = THREE2;
+							else
+								if (c == 0xed)
+									state = THREE3;
+								else
+									state = THREE;
+						} else
+							if (c < 0xf8) {
+								state = FOUR;
+								code = c & 7;
+							} else
+								state = ERR;
+			break;
+		case TWO :
+			if ((c & 0xc0) != 0x80)
+				state = ERR;
+			else {
+				size++;
+				state = BASE;
+			}
+			break;
+		case THREE :
+			if ((c & 0xc0) != 0x80)
+				state = ERR;
+			else
+				state = TWO;
+			break;
+		case THREE2 :
+			if ((c & 0xe0) != 0xa0)
+				state = ERR;
+			else
+				state = TWO;
+			break;
+		case THREE3 :
+			if ((c & 0xe0) != 0x80)
+				state = ERR;
+			else
+				state = TWO;
+			break;
+		case FOUR :
+			if ((((code << 6) + (c & 63)) > 0x10f)
+			  || (((code << 6) + (c & 63)) < 0x10))
+				state = ERR;
+			else {
+				size++;
+				state = THREE;
+			}
+			break;
+		case ERR :
+			break;
+		}
+	}
+	if (state != BASE) size = 0;
+	return (size);
+}
+
+/*
+ *		Convert a UTF8 text to UTF-16LE
+ *	(basic conversions only)
+ *	Note : mbstowcs() not used because on Linux it fails for characters
+ *	not present in current locale
+ */
+
+unsigned int makeutf16(char *target, const char *utf8)
+{
+	unsigned int size;
+	unsigned int code;
+	const char *p;
+	int c;
+	enum { BASE, TWO, THREE, THREE2, THREE3, FOUR, FOUR2, FOUR3, ERR } state;
+
+	p = utf8;
+	size = 0;
+	c = 0;
+	state = BASE;
+	while (*p) {
+		c = *p++ & 255;
+		switch (state) {
+		case BASE :
+			if (!(c & 0x80)) {
+				target[2*size] = c;
+				target[2*size + 1] = 0;
+				size++;
+			} else {
+				if (c < 0xc2)
+					state = ERR;
+				else
+					if (c < 0xe0) {
+						code = c & 31;
+						state = TWO;
+					} else
+						if (c < 0xf0) {
+							code = c & 15;
+							if (c == 0xe0)
+								state = THREE2;
+							else
+								if (c == 0xed)
+									state = THREE3;
+								else
+									state = THREE;
+						} else
+							if (c < 0xf8) {
+								code = c & 7;
+								state = FOUR;
+							} else
+								state = ERR;
+			}
+			break;
+		case TWO :
+#if NOREVBOM
+			if (((c & 0xc0) != 0x80)
+			  || ((code == 0x3ff) && (c >= 0xbe)))
+#else
+			if ((c & 0xc0) != 0x80)
+#endif
+				state = ERR;
+			else {
+				target[2*size] = ((code & 3) << 6) + (c & 63);
+				target[2*size + 1] = ((code >> 2) & 255);
+				size++;
+				state = BASE;
+			}
+			break;
+		case THREE :
+			if ((c & 0xc0) != 0x80)
+				state = ERR;
+			else {
+				code = ((code & 15) << 6) + (c & 63);
+				state = TWO;
+			}
+			break;
+		case THREE2 :
+			if ((c & 0xe0) != 0xa0)
+				state = ERR;
+			else {
+				code = ((code & 15) << 6) + (c & 63);
+				state = TWO;
+			}
+			break;
+		case THREE3 :
+			if ((c & 0xe0) != 0x80)
+				state = ERR;
+			else {
+				code = ((code & 15) << 6) + (c & 63);
+				state = TWO;
+			}
+			break;
+		case FOUR :
+			if ((c & 0xc0) != 0x80)
+				state = ERR;
+			else {
+				code = (code << 6) + (c & 63);
+				state = FOUR2;
+			}
+			break;
+		case FOUR2 :
+			if ((c & 0xc0) != 0x80)
+				state = ERR;
+			else {
+				code = (code << 6) + (c & 63);
+				state = FOUR3;
+			}
+			break;
+		case FOUR3 :
+			if ((code > 0x43ff)
+			 || (code < 0x400)
+			 || ((c & 0xc0) != 0x80))
+				state = ERR;
+			else {
+				target[2*size] = ((code - 0x400) >> 4) & 255;
+				target[2*size+1] = 0xd8 + (((code - 0x400) >> 12) & 3);
+				target[2*size+2] = ((code & 3) << 6) + (c & 63);
+				target[2*size+3] = 0xdc + ((code >> 2) & 3);
+				size += 2;
+				state = BASE;
+			}
+			break;
+		case ERR :
+			break;
+		}
+	}
+	if (state != BASE)
+		size = 0;
+	target[2*size] = 0;
+	target[2*size + 1] = 0;
+	return (size);
+}
+
+unsigned int utf16len(const char *str)
+{
+	unsigned int len;
+
+	len = 0;
+	while (str[2*len] || str[2*len+1]) len++;
+	return (len);
+}
+
+#endif
+
+/*
+ *		Print a file name
+ *	on Windows it prints UTF-16LE names as UTF-8
+ */
+
+void printname(FILE *file, const char *name)
+{
+#ifdef WIN32
+	char utf8name[MAXFILENAME];
+
+	makeutf8(utf8name,name,utf16len(name));
+	fprintf(file,"%s",utf8name);	
+#else
+	fprintf(file,"%s",name);
+#endif
+}
+
+/*
+ *		Print the last error code
+ */
+
+void printerror(FILE *file)
+{
+#ifdef WIN32
+	int err;
+	const char *txt;
+
+	err = GetLastError();
+	switch (err) {
+	case 5 :
+		txt = "Access to security descriptor was denied";
+		break;
+	case 1307 :
+		txt = "This SID may not be assigned as the owner of this object";
+		break;
+	case 1308 :
+		txt = "This SID may not be assigned as the group of this object";
+		break;
+	case 1314 :
+		txt = "You do not have the privilege to change this SID";
+		break;
+	default :
+		txt = (const char*)NULL;
+		break;
+	}
+	if (txt)
+		fprintf(file,"Error %d : %s\n",err,txt);
+	else
+		fprintf(file,"Error %d\n",err);
+#else
+#ifdef STSC
+	if (errno) fprintf(file,"Error code %d\n",errno);
+#else
+	if (errno) fprintf(file,"Error code %d : %s\n",errno,strerror(errno));
+#endif
+#endif
+}
+
+#ifndef HAVE_SYSLOG_H
+
+/*
+ *		Redefine early error messages in stand-alone situations
+ */
+
+void ntfs_log_early_error(const char *format, ...)
+{
+	va_list args;
+
+	va_start(args, format);
+	vfprintf(stderr,format,args);
+	va_end(args);
+}
+
+#endif
+
+/*
+ *	Guess whether a security attribute is intended for a directory
+ *	based on the presence of inheritable ACE
+ *	(not 100% reliable)
+ */
+
+BOOL guess_dir(const char *attr)
+{
+	int off;
+	int isdir;
+	int cnt;
+	int i;
+	int x;
+
+	isdir = 0;
+	off = get4l(attr,16);
+	if (off) {
+		cnt = get2l(attr,off+4);
+		x = 8;
+		for (i=0; i<cnt; i++) {
+			if (attr[off + x + 1] & 3)
+				isdir = 1;
+			x += get2l(attr,off + x + 2);
+		}
+	}
+	return (isdir);
+}
+
+/*
+ *		   Display a SID
+ *   See http://msdn2.microsoft.com/en-us/library/aa379649.aspx
+ */
+
+void showsid(const char *attr, int off, const char *prefix, int level)
+{
+	int cnt;
+	int i;
+	BOOL known;
+	u64 auth;
+	unsigned long first;
+	unsigned long second;
+	unsigned long last;
+	char marker;
+
+	if (opt_b)
+		marker = '#';
+	else
+		marker = ' ';
+	cnt = attr[off+1] & 255;
+	auth = get6h(attr,off+2);
+	first = get4l(attr,off+8);
+	known = FALSE;
+	if ((attr[off] == 1) /* revision */
+	     && (auth < 100))
+		switch (cnt) {
+		case 0 : /* no level (error) */
+			break;
+		case 1 : /* single level */
+			switch (auth) {
+			case 0 :
+				if (first == 0) {
+					known = TRUE;
+					printf("%*cNull SID\n",-level,marker);
+				}
+				break;
+			case 1 :
+				if (first == 0) {
+					known = TRUE;
+					printf("%*cWorld SID\n",-level,marker);
+				}
+				break;
+			case 3 :
+				switch (first) {
+				case 0 :
+					known = TRUE;
+					printf("%*cCreator owner SID\n",-level,marker);
+					break;
+				case 1 :
+					known = TRUE;
+					printf("%*cCreator group SID\n",-level,marker);
+					break;
+				}
+				break;
+			case 5 :
+				switch (first) {
+				case 1 :
+					known = TRUE;
+					printf("%*cDialup SID\n",-level,marker);
+					break;
+				case 2 :
+					known = TRUE;
+					printf("%*cNetwork SID\n",-level,marker);
+					break;
+				case 3 :
+					known = TRUE;
+					printf("%*cBatch SID\n",-level,marker);
+					break;
+				case 4 :
+					known = TRUE;
+					printf("%*cInteractive SID\n",-level,marker);
+					break;
+				case 6 :
+					known = TRUE;
+					printf("%*cService SID\n",-level,marker);
+					break;
+				case 7 :
+					known = TRUE;
+					printf("%*cAnonymous logon SID\n",-level,marker);
+					break;
+				case 11 :
+					known = TRUE;
+					printf("%*cAuthenticated user SID\n",-level,marker);
+					break;
+				case 13 :
+					known = TRUE;
+					printf("%*cLocal service SID\n",-level,marker);
+					break;
+				case 14 :
+					known = TRUE;
+					printf("%*cNetwork service SID\n",-level,marker);
+					break;
+				case 18 :
+					known = TRUE;
+					printf("%*cNT System SID\n",-level,marker);
+					break;
+				}
+				break;
+			}
+			break;
+		case 2 : /* double level */
+			second = get4l(attr,off+12);
+			switch (auth) {
+			case 5 :
+				if (first == 32) {
+					known = TRUE;
+					switch (second) {
+					case 544 :
+						printf("%*cLocal admins SID\n",-level,marker);
+						break;
+					case 545 :
+						printf("%*cLocal users SID\n",-level,marker);
+						break;
+					case 546 :
+						printf("%*cLocal guests SID\n",-level,marker);
+						break;
+					default :
+						printf("%*cSome domain SID\n",-level,marker);
+						break;
+					}
+				}
+				break;
+			}
+		default : /* three levels or more */
+			second = get4l(attr,off+12);
+			last = get4l(attr,off+4+4*cnt);
+			switch (auth) {
+			case 5 :
+				if (first == 21) {
+					known = TRUE;
+					switch (last) {
+						case 500 :
+							printf("%*cSystem admin SID\n",-level,marker);
+							break;
+						case 501 :
+							printf("%*cGuest SID\n",-level,marker);
+							break;
+						case 512 :
+							printf("%*cLocal admins SID\n",-level,marker);
+							break;
+						case 513 :
+							printf("%*cLocal users SID\n",-level,marker);
+							break;
+						case 514 :
+							printf("%*cLocal guests SID\n",-level,marker);
+							break;
+						default :
+							printf("%*cLocal user-%lu SID\n",-level,marker,last);
+							break;
+					}
+				}
+				break;
+			}
+		}
+	if (!known)
+		printf("%*cUnknown SID\n",-level,marker);
+	printf("%*c%shex S-%d-",-level,marker,prefix,attr[off] & 255);
+	printf("%llx",auth);
+	for (i=0; i<cnt; i++)
+		printf("-%lx",get4l(attr,off+8+4*i));
+	printf("\n");
+	printf("%*c%sdec S-%d-",-level,marker,prefix,attr[off] & 255);
+	printf("%llu",auth);
+	for (i=0; i<cnt; i++)
+		printf("-%lu",get4l(attr,off+8+4*i));
+	printf("\n");
+}
+
+void showusid(const char *attr, int level)
+{
+	int off;
+	char marker;
+
+	if (opt_b)
+		marker = '#';
+	else
+		marker = ' ';
+	if (level)
+		printf("%*c",-level,marker);
+	printf("Owner SID\n");
+	off = get4l(attr,4);
+	showsid(attr,off,"O:",level+4);
+}
+
+void showgsid(const char *attr, int level)
+{
+	int off;
+	char marker;
+
+	if (opt_b)
+		marker = '#';
+	else
+		marker = ' ';
+	if (level)
+		printf("%*c",-level,marker);
+	printf("Group SID\n");
+	off = get4l(attr,8);
+	showsid(attr,off,"G:",level+4);
+}
+
+void showownership(const char *attr)
+{
+#ifdef WIN32
+	char account[ACCOUNTSIZE];
+	BIGSID sidcopy;
+	SID_NAME_USE use;
+	unsigned long accountsz;
+	unsigned long domainsz;
+#endif
+	enum { SHOWOWN, SHOWGRP, SHOWINT } shown;
+	const char *sid;
+	const char *prefix;
+	u64 auth;
+	int cnt;
+	int off;
+	int i;
+
+	for (shown=SHOWOWN; shown<=SHOWINT; shown++) {
+		switch (shown) {
+		case SHOWOWN :
+			off = get4l(attr,4);
+			sid = &attr[off];
+			prefix = "Windows owner";
+			break;
+		case SHOWGRP :
+			off = get4l(attr,8);
+			sid = &attr[off];
+			prefix = "Windows group";
+			break;
+#if OWNERFROMACL
+		case SHOWINT :
+			off = get4l(attr,4);
+			prefix = "Interpreted owner";
+			sid = (const char*)ntfs_acl_owner((const char*)attr);
+			if (ntfs_same_sid((const SID*)sid,
+						(const SID*)&attr[off]))
+				sid = (const char*)NULL;
+			break;
+#endif
+		default :
+			sid = (const char*)NULL;
+			prefix = (const char*)NULL;
+			break;
+		}
+		if (sid) {
+			cnt = sid[1] & 255;
+			auth = get6h(sid,2);
+			if (opt_b)
+				printf("# %s S-%d-",prefix,sid[0] & 255);
+			else
+				printf("%s S-%d-",prefix,sid[0] & 255);
+			printf("%llu",auth);
+			for (i=0; i<cnt; i++)
+				printf("-%lu",get4l(sid,8+4*i));
+#ifdef WIN32
+			memcpy(sidcopy,sid,ntfs_sid_size((const SID*)sid));
+			accountsz = ACCOUNTSIZE;
+			domainsz = ACCOUNTSIZE;
+			if (LookupAccountSidA((const char*)NULL, sidcopy,
+					account, &accountsz,
+					(char*)NULL, &domainsz, &use))
+				printf(" (%s)", account);
+#endif
+			printf("\n");
+		}
+	}
+}
+
+void showheader(const char *attr, int level)
+{
+	int flags;
+	char marker;
+
+	if (opt_b)
+		marker = '#';
+	else
+		marker = ' ';
+	if (level)
+		printf("%*c",-level,marker);
+	printf("Global header\n");
+	printf("%*crevision %d\n",-level-4,marker,attr[0]);
+	flags = get2l(attr,2);
+	printf("%*cflags    0x%x\n",-level-4,marker,flags);
+	if (flags & 1)
+		printf("%*c    owner is defaulted\n",-level-4,marker);
+	if (flags & 2)
+		printf("%*c    group is defaulted\n",-level-4,marker);
+	if (flags & 4)
+		printf("%*c    DACL present\n",-level-4,marker);
+	if (flags & 8)
+		printf("%*c    DACL is defaulted\n",-level-4,marker);
+	if (flags & 0x10)
+		printf("%*c    SACL present\n",-level-4,marker);
+	if (flags & 0x20)
+		printf("%*c    SACL is defaulted\n",-level-4,marker);
+	if (flags & 0x100)
+		printf("%*c    DACL inheritance is requested\n",-level-4,marker);
+	if (flags & 0x200)
+		printf("%*c    SACL inheritance is requested\n",-level-4,marker);
+	if (flags & 0x400)
+		printf("%*c    DACL was inherited automatically\n",-level-4,marker);
+	if (flags & 0x800)
+		printf("%*c    SACL was inherited automatically\n",-level-4,marker);
+	if (flags & 0x1000)
+		printf("%*c    DACL cannot be modified by inheritable ACEs\n",-level-4,marker);
+	if (flags & 0x2000)
+		printf("%*c    SACL cannot be modified by inheritable ACEs\n",-level-4,marker);
+	if (flags & 0x8000)
+		printf("%*c    self relative descriptor\n",-level-4,marker);
+	if (flags & 0x43eb)
+		printf("%*c    unknown flags 0x%x present\n",-level-4,marker,
+				flags & 0x43eb);
+	printf("%*cOff USID 0x%x\n",-level-4,marker,(int)get4l(attr,4));
+	printf("%*cOff GSID 0x%x\n",-level-4,marker,(int)get4l(attr,8));
+	printf("%*cOff SACL 0x%x\n",-level-4,marker,(int)get4l(attr,12));
+	printf("%*cOff DACL 0x%x\n",-level-4,marker,(int)get4l(attr,16));
+}
+
+void showace(const char *attr, int off, int isdir, int level)
+{
+	int flags;
+	u32 rights;
+	char marker;
+
+	if (opt_b)
+		marker = '#';
+	else
+		marker = ' ';
+	printf("%*ctype     %d\n",-level,marker,attr[off]);
+	switch (attr[off]) {
+	case 0 :
+		printf("%*cAccess allowed\n",-level-4,marker);
+		break;
+	case 1 :
+		printf("%*cAccess denied\n",-level-4,marker);
+		break;
+	case 2 :
+		printf("%*cSystem audit\n",-level-4,marker);
+		break;
+	default :
+		printf("%*cunknown\n",-level-4,marker);
+		break;
+	}
+	flags = attr[off+1] & 255;
+	printf("%*cflags    0x%x\n",-level,marker,flags);
+	if (flags & 1)
+		printf("%*cObject inherits ACE\n",-level-4,marker);
+	if (flags & 2)
+		printf("%*cContainer inherits ACE\n",-level-4,marker);
+	if (flags & 4)
+		printf("%*cDon\'t propagate inherits ACE\n",-level-4,marker);
+	if (flags & 8)
+		printf("%*cInherit only ACE\n",-level-4,marker);
+	if (flags & 0x10)
+		printf("%*cACE was inherited\n",-level-4,marker);
+	if (flags & 0x40)
+		printf("%*cAudit on success\n",-level-4,marker);
+	if (flags & 0x80)
+		printf("%*cAudit on failure\n",-level-4,marker);
+
+	printf("%*cSize     0x%x\n",-level,marker,get2l(attr,off+2));
+
+	rights = get4l(attr,off+4);
+	printf("%*cAcc rgts 0x%lx\n",-level,marker,(long)rights);
+	printf("%*cObj specific acc rgts 0x%lx\n",-level-4,marker,(long)rights & 65535);
+	if (isdir) /* a directory */ {
+		if (rights & 0x01)
+			printf("%*cList directory\n",-level-8,marker);
+		if (rights & 0x02)
+			printf("%*cAdd file\n",-level-8,marker);
+		if (rights & 0x04)
+			printf("%*cAdd subdirectory\n",-level-8,marker);
+		if (rights & 0x08)
+			printf("%*cRead EA\n",-level-8,marker);
+		if (rights & 0x10)
+			printf("%*cWrite EA\n",-level-8,marker);
+		if (rights & 0x20)
+			printf("%*cTraverse\n",-level-8,marker);
+		if (rights & 0x40)
+			printf("%*cDelete child\n",-level-8,marker);
+		if (rights & 0x80)
+			printf("%*cRead attributes\n",-level-8,marker);
+		if (rights & 0x100)
+			printf("%*cWrite attributes\n",-level-8,marker);
+	}
+	else {
+	     /* see FILE_READ_DATA etc in winnt.h */
+		if (rights & 0x01)
+			printf("%*cRead data\n",-level-8,marker);
+		if (rights & 0x02)
+			printf("%*cWrite data\n",-level-8,marker);
+		if (rights & 0x04)
+			printf("%*cAppend data\n",-level-8,marker);
+		if (rights & 0x08)
+			printf("%*cRead EA\n",-level-8,marker);
+		if (rights & 0x10)
+			printf("%*cWrite EA\n",-level-8,marker);
+		if (rights & 0x20)
+			printf("%*cExecute\n",-level-8,marker);
+		if (rights & 0x80)
+			printf("%*cRead attributes\n",-level-8,marker);
+		if (rights & 0x100)
+			printf("%*cWrite attributes\n",-level-8,marker);
+	}
+	printf("%*cstandard acc rgts 0x%lx\n",-level-4,marker,(long)(rights >> 16) & 127);
+	if (rights & 0x10000)
+		printf("%*cDelete\n",-level-8,marker);
+	if (rights & 0x20000)
+		printf("%*cRead control\n",-level-8,marker);
+	if (rights & 0x40000)
+		printf("%*cWrite DAC\n",-level-8,marker);
+	if (rights & 0x80000)
+		printf("%*cWrite owner\n",-level-8,marker);
+	if (rights & 0x100000)
+		printf("%*cSynchronize\n",-level-8,marker);
+	if (rights & 0x800000)
+		printf("%*cCan access security ACL\n",-level-4,marker);
+	if (rights & 0x10000000)
+		printf("%*cGeneric all\n",-level-4,marker);
+	if (rights & 0x20000000)
+		printf("%*cGeneric execute\n",-level-4,marker);
+	if (rights & 0x40000000)
+		printf("%*cGeneric write\n",-level-4,marker);
+	if (rights & 0x80000000)
+		printf("%*cGeneric read\n",-level-4,marker);
+
+	printf("%*cSID at 0x%x\n",-level,marker,off+8);
+	showsid(attr,off+8,"",level+4);
+	printf("%*cSummary :",-level,marker);
+	if (attr[off] == 0)
+		printf(" grant");
+	if (attr[off] == 1)
+		printf(" deny");
+	if (rights & le32_to_cpu(FILE_GREAD | FILE_GWRITE | FILE_GEXEC)) {
+		printf(" ");
+		if (rights & le32_to_cpu(FILE_GREAD))
+			printf("r");
+		if (rights & le32_to_cpu(FILE_GWRITE))
+			printf("w");
+		if (rights & le32_to_cpu(FILE_GEXEC))
+			printf("x");
+	} else
+		printf(" none");
+	if (flags & 11)
+		printf(" inherited");
+	if (!(flags & 8)) {
+		int sz;
+
+		printf(" applied");
+		sz = attr[off+9]*4 + 8;
+		if (!memcmp(&attr[off+8],&attr[get4l(attr,4)],sz))
+			printf(" to owner");
+		if (!memcmp(&attr[off+8],&attr[get4l(attr,8)],sz))
+			printf(" to group");
+	}
+	printf("\n");
+
+}
+
+void showacl(const char *attr, int off, int isdir, int level)
+{
+	int i;
+	int cnt;
+	int size;
+	int x;
+	char marker;
+
+	if (opt_b)
+		marker = '#';
+	else
+		marker = ' ';
+	size = get2l(attr,off+2);
+	printf("%*crevision %d\n",-level,marker,attr[off]);
+	printf("%*cACL size %d\n",-level,marker,size);
+	cnt = get2l(attr,off+4);
+	printf("%*cACE cnt  %d\n",-level,marker,cnt);
+	x = 8;
+	for (i=0; (i<cnt) && (x < size); i++) {
+		printf("%*cACE %d at 0x%x\n",-level,marker,i + 1,off+x);
+		showace(attr,off + x,isdir,level+4);
+		x += get2l(attr,off + x + 2);
+	}
+}
+
+void showdacl(const char *attr, int isdir, int level)
+{
+	int off;
+	char marker;
+
+	if (opt_b)
+		marker = '#';
+	else
+		marker = ' ';
+	off = get4l(attr,16);
+	if (off) {
+		if (level)
+			printf("%*c",-level,marker);
+		printf("DACL\n");
+		showacl(attr,off,isdir,level+4);
+	} else {
+		if (level)
+			printf("%*c",-level,marker);
+		printf("No DACL\n");
+	}
+}
+
+void showsacl(const char *attr, int isdir, int level)
+{
+	int off;
+	char marker;
+
+	if (opt_b)
+		marker = '#';
+	else
+		marker = ' ';
+	off = get4l(attr,12);
+	if (off) {
+		if (level)
+			printf("%*c",-level,marker);
+		printf("SACL\n");
+		showacl(attr,off,isdir,level+4);
+	}
+	else {
+		if (level)
+			printf("%*c",-level,marker);
+		printf("No SACL\n");
+	}
+}
+
+void showall(const char *attr, int level)
+{
+	BOOL isdir;
+
+	isdir = guess_dir(attr);
+	showheader(attr,level);
+	showusid(attr,level);
+	showgsid(attr,level);
+	showdacl(attr,isdir,level);
+	showsacl(attr,isdir,level);
+}
+
+#if POSIXACLS
+/*
+ *		Display a Posix descriptor
+ */
+
+void showposix(const struct POSIX_SECURITY *pxdesc)
+{
+	char txperm[4];
+	const char *txtag;
+	const char *txtype;
+	const struct POSIX_ACL *acl;
+	const struct POSIX_ACE *pxace;
+	int acccnt;
+	int defcnt;
+	int firstdef;
+	int perms;
+	u16 tag;
+	s32 id;
+	int k,l;
+
+	if (pxdesc) {
+		acccnt = pxdesc->acccnt;
+		defcnt = pxdesc->defcnt;
+		firstdef = pxdesc->firstdef;
+		acl = &pxdesc->acl;
+		printf("Posix descriptor :\n");
+		printf("    acccnt %d\n",acccnt);
+		printf("    defcnt %d\n",defcnt);
+		printf("    firstdef %d\n",firstdef);
+		printf("    mode : 0%03o\n",(int)pxdesc->mode);
+		printf("    tagsset : 0x%02x\n",(int)pxdesc->tagsset);
+		printf("Posix ACL :\n");
+		printf("    version %d\n",(int)acl->version);
+		printf("    flags 0x%02x\n",(int)acl->flags);
+		for (k=0; k<(acccnt + defcnt); k++) {
+			if (k < acccnt)
+				l = k;
+			else
+				l = firstdef + k - acccnt;
+			pxace = &acl->ace[l];
+			tag = pxace->tag;
+			perms = pxace->perms;
+			if (tag == POSIX_ACL_SPECIAL) {
+				txperm[0] = (perms & S_ISVTX ? 's' : '-');
+				txperm[1] = (perms & S_ISUID ? 'u' : '-');
+				txperm[2] = (perms & S_ISGID ? 'g' : '-');
+			} else {
+				txperm[0] = (perms & 4 ? 'r' : '-');
+				txperm[1] = (perms & 2 ? 'w' : '-');
+				txperm[2] = (perms & 1 ? 'x' : '-');
+			}
+			txperm[3] = 0;
+			if (k >= acccnt)
+				txtype = "default";
+			else
+				txtype = "access ";
+			switch (tag) {
+			case POSIX_ACL_USER :
+				txtag = "USER ";
+				break;
+			case POSIX_ACL_USER_OBJ :
+				txtag = "USR-O";
+				break;
+			case POSIX_ACL_GROUP :
+				txtag = "GROUP";
+				break;
+			case POSIX_ACL_GROUP_OBJ :
+				txtag = "GRP-O";
+				break;
+			case POSIX_ACL_MASK :
+				txtag = "MASK ";
+				break;
+			case POSIX_ACL_OTHER :
+				txtag = "OTHER";
+				break;
+			case POSIX_ACL_SPECIAL :
+				txtag = "SPECL";
+				break;
+			default :
+				txtag = "UNKWN";
+				break;
+			}
+			id = pxace->id;
+			printf("ace %d : %s %s %4ld perms 0%03o %s\n",
+				l,txtype,txtag,(long)id,
+				perms,txperm);
+		}
+	} else
+		printf("** NULL ACL\n");
+}
+
+#endif /* POSIXACLS */
+
+#if defined(WIN32) | defined(STSC)
+
+#else
+
+/*
+ *		Relay to get usid as defined during mounting
+ */
+
+const SID *relay_find_usid(const struct MAPPING *usermapping __attribute__((unused)),
+		uid_t uid, SID *defusid)
+{
+	return (ntfs_get_usid(ntfs_context,uid,(char*)defusid) ?
+			defusid : (SID*)NULL);
+}
+
+/*
+ *		Relay to get gsid as defined during mounting
+ */
+
+const SID *relay_find_gsid(const struct MAPPING *groupmapping __attribute__((unused)),
+		uid_t gid, SID *defgsid)
+{
+	return (ntfs_get_usid(ntfs_context,gid,(char*)defgsid) ?
+			defgsid : (SID*)NULL);
+}
+
+/*
+ *		Relay to get uid as defined during mounting
+ */
+
+uid_t relay_find_user(const struct MAPPING *mapping __attribute__((unused)),
+			const SID *usid)
+{
+	int uid;
+
+	uid = ntfs_get_user(ntfs_context,(const char*)usid);
+	return (uid < 0 ? 0 : uid);
+}
+
+/*
+ *		Relay to get gid as defined during mounting
+ */
+
+gid_t relay_find_group(const struct MAPPING *mapping __attribute__((unused)),
+			const SID *gsid)
+{
+	int gid;
+
+	gid = ntfs_get_group(ntfs_context,(const char*)gsid);
+	return (gid < 0 ? 0 : gid);
+}
+
+#endif
+
+#if defined(WIN32) | defined(STSC)
+
+/*
+ *		Dummy get uid from user name, out of a Linux environment
+ */
+
+struct passwd *getpwnam(const char *user)
+{
+	ntfs_log_error("Cannot interpret id \"%s\"", user);
+	ntfs_log_error("please use numeric uids in UserMapping file\n");
+	return ((struct passwd*)NULL);
+}
+
+/*
+ *		Dummy get gid from group name, out of a Linux environment
+ */
+
+struct group *getgrnam(const char *group)
+{
+	ntfs_log_error("Cannot interpret id \"%s\"", group);
+	ntfs_log_error("please use numeric gids in UserMapping file\n");
+	return ((struct group*)NULL);
+}
+
+#endif /* defined(WIN32) | defined(STSC) */
+
+#if POSIXACLS
+
+struct POSIX_SECURITY *linux_permissions_posix(const char *attr, BOOL isdir)
+{
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+#if OWNERFROMACL
+	const SID *osid;
+#endif
+	const SID *usid;
+	const SID *gsid;
+	struct POSIX_SECURITY *posix_desc;
+
+	phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr;
+	gsid = (const SID*)&attr[le32_to_cpu(phead->group)];
+#if OWNERFROMACL
+	osid = (const SID*)&attr[le32_to_cpu(phead->owner)];
+	usid = ntfs_acl_owner((const char*)attr);
+#if SELFTESTS & !USESTUBS
+	if (!opt_t && !ntfs_same_sid(usid,osid))
+		printf("== Linux owner is different from Windows owner\n"); 
+#else
+	if (!ntfs_same_sid(usid,osid))
+		printf("== Linux owner is different from Windows owner\n"); 
+#endif
+#else
+	usid = (const SID*)&attr[le32_to_cpu(phead->owner)];
+#endif
+	posix_desc = ntfs_build_permissions_posix(context.mapping,
+			(const char*)attr, usid, gsid, isdir);
+	if (!posix_desc) {
+		printf("** Failed to build a Posix descriptor\n");
+		errors++;
+	}
+	return (posix_desc);
+}
+
+#endif /* POSIXACLS */
+
+int linux_permissions(const char *attr, BOOL isdir)
+{
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+#if OWNERFROMACL
+	const SID *osid;
+#endif
+	const SID *usid;
+	const SID *gsid;
+	int perm;
+
+	phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr;
+	gsid = (const SID*)&attr[le32_to_cpu(phead->group)];
+#if OWNERFROMACL
+	osid = (const SID*)&attr[le32_to_cpu(phead->owner)];
+	usid = ntfs_acl_owner((const char*)attr);
+#if SELFTESTS & !USESTUBS
+	if (!opt_t && !ntfs_same_sid(usid,osid))
+		printf("== Linux owner is different from Windows owner\n"); 
+#else
+	if (!ntfs_same_sid(usid,osid))
+		printf("== Linux owner is different from Windows owner\n"); 
+#endif
+#else
+	usid = (const SID*)&attr[le32_to_cpu(phead->owner)];
+#endif
+	perm = ntfs_build_permissions((const char*)attr, usid, gsid, isdir);
+	if (perm < 0) {
+		printf("** Failed to build permissions\n");
+		errors++;
+	}
+	return (perm);
+}
+
+uid_t linux_owner(const char *attr)
+{
+	const SID *usid;
+	uid_t uid;
+
+#if OWNERFROMACL
+	usid = ntfs_acl_owner((const char*)attr);
+#else
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+
+	phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr;
+	usid = (const SID*)&attr[le32_to_cpu(phead->owner)];
+#endif
+#if defined(WIN32) | defined(STSC)
+	uid = ntfs_find_user(context.mapping[MAPUSERS],usid);
+#else
+	if (mappingtype == MAPEXTERN)
+		uid = relay_find_user(context.mapping[MAPUSERS],usid);
+	else
+		uid = ntfs_find_user(context.mapping[MAPUSERS],usid);
+#endif
+	return (uid);
+}
+
+gid_t linux_group(const char *attr)
+{
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	const SID *gsid;
+	gid_t gid;
+
+	phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr;
+	gsid = (const SID*)&attr[le32_to_cpu(phead->group)];
+#if defined(WIN32) | defined(STSC)
+	gid = ntfs_find_group(context.mapping[MAPGROUPS],gsid);
+#else
+	if (mappingtype == MAPEXTERN)
+		gid = relay_find_group(context.mapping[MAPGROUPS],gsid);
+	else
+		gid = ntfs_find_group(context.mapping[MAPGROUPS],gsid);
+#endif
+	return (gid);
+}
+
+void newblock(s32 key)
+{
+	struct SECURITY_DATA *psecurdata;
+	int i;
+
+	if ((key > 0) && (key < MAXSECURID) && !securdata[key >> SECBLKSZ]) {
+		securdata[key >> SECBLKSZ] =
+			(struct SECURITY_DATA*)malloc((1 << SECBLKSZ)*sizeof(struct SECURITY_DATA));
+		if (securdata[key >> SECBLKSZ])
+			for (i=0; i<(1 << SECBLKSZ); i++) {
+				psecurdata = &securdata[key >> SECBLKSZ][i];
+				psecurdata->filecount = 0;
+				psecurdata->mode = 0;
+				psecurdata->flags = 0;
+				psecurdata->attr = (char*)NULL;
+			}
+	}
+}
+
+void freeblocks(void)
+{
+	int i,j;
+	struct SECURITY_DATA *psecurdata;
+
+	for (i=0; i<(MAXSECURID + (1 << SECBLKSZ) - 1)/(1 << SECBLKSZ); i++)
+		if (securdata[i]) {
+			for (j=0; j<(1 << SECBLKSZ); j++) {
+				psecurdata = &securdata[i][j];
+				if (psecurdata->attr)
+					free(psecurdata->attr);
+			}
+			free(securdata[i]);
+		}
+}
+
+/*
+ *		Basic read from a user mapping file (Win32)
+ */
+
+int basicread(void *fileid, char *buf, size_t size,
+		off_t pos __attribute__((unused)))
+{
+	return (read(*(int*)fileid, buf, size));
+}
+
+#if SELFTESTS & !USESTUBS
+
+/*
+ *		Read a dummy mapping file for tests
+ */
+
+int dummyread(void *fileid  __attribute__((unused)),
+		char *buf, size_t size, off_t pos)
+{
+	size_t sz;
+
+	if (pos >= (off_t)(sizeof(dummymapping) - 1))
+		sz = 0;
+	else
+		if ((size + pos) >= (sizeof(dummymapping) - 1))
+			sz = sizeof(dummymapping) - 1 - pos;
+		else
+			sz = size;
+	if (sz > 0)
+		memcpy(buf,&dummymapping[pos],sz);
+	return (sz);
+}
+
+#endif /* POSIXACLS & SELFTESTS & !USESTUBS */
+
+/*
+ *		Apply default single user mapping
+ *	returns zero if successful
+ */
+
+static int do_default_mapping(struct MAPPING *mapping[],
+			 const SID *usid)
+{
+	struct MAPPING *usermapping;
+	struct MAPPING *groupmapping;
+	SID *sid;
+	int sidsz;
+	int res;
+
+	res = -1;
+	sidsz = ntfs_sid_size(usid);
+#if USESTUBS
+	sid = (SID*)stdmalloc(sidsz); /* will be freed within the library */
+#else
+	sid = (SID*)ntfs_malloc(sidsz);
+#endif
+	if (sid) {
+		memcpy(sid,usid,sidsz);
+#if USESTUBS
+		usermapping = (struct MAPPING*)stdmalloc(sizeof(struct MAPPING));
+#else
+		usermapping = (struct MAPPING*)ntfs_malloc(sizeof(struct MAPPING));
+#endif
+		if (usermapping) {
+#if USESTUBS
+			groupmapping = (struct MAPPING*)stdmalloc(sizeof(struct MAPPING));
+#else
+			groupmapping = (struct MAPPING*)ntfs_malloc(sizeof(struct MAPPING));
+#endif
+			if (groupmapping) {
+				usermapping->sid = sid;
+				usermapping->xid = 0;
+				usermapping->next = (struct MAPPING*)NULL;
+				groupmapping->sid = sid;
+				groupmapping->xid = 0;
+				groupmapping->next = (struct MAPPING*)NULL;
+				mapping[MAPUSERS] = usermapping;
+				mapping[MAPGROUPS] = groupmapping;
+				res = 0;
+			}
+		}
+	}
+	return (res);
+}
+
+/*
+ *		Build the user mapping
+ *	- according to a mapping file if defined (or default present),
+ *	- or try default single user mapping if possible
+ *
+ *	The mapping is specific to a mounted device
+ *	No locking done, mounting assumed non multithreaded
+ *
+ *	returns zero if mapping is successful
+ *	(failure should not be interpreted as an error)
+ */
+
+int local_build_mapping(struct MAPPING *mapping[], const char *usermap_path)
+{
+#ifdef WIN32
+	char mapfile[sizeof(MAPDIR) + sizeof(MAPFILE) + 6];
+	char currpath[261];
+#else
+	char *mapfile;
+	char *p;
+#endif
+	int fd;
+	struct MAPLIST *item;
+	struct MAPLIST *firstitem = (struct MAPLIST*)NULL;
+	struct MAPPING *usermapping;
+	struct MAPPING *groupmapping;
+	static struct {
+		u8 revision;
+		u8 levels;
+		be16 highbase;
+		be32 lowbase;
+		le32 level1;
+		le32 level2;
+		le32 level3;
+		le32 level4;
+		le32 level5;
+	} defmap = {
+		1, 5, const_cpu_to_be16(0), const_cpu_to_be32(5),
+		const_cpu_to_le32(21),
+		const_cpu_to_le32(DEFSECAUTH1), const_cpu_to_le32(DEFSECAUTH2),
+		const_cpu_to_le32(DEFSECAUTH3), const_cpu_to_le32(DEFSECBASE)
+	} ;
+
+	/* be sure not to map anything until done */
+	mapping[MAPUSERS] = (struct MAPPING*)NULL;
+	mapping[MAPGROUPS] = (struct MAPPING*)NULL;
+
+	if (usermap_path) {
+#ifdef WIN32
+/* TODO : check whether the device can store acls */
+		strcpy(mapfile,"x:\\" MAPDIR "\\" MAPFILE);
+		if (((const le16*)usermap_path)[1] == ':')
+  			mapfile[0] = usermap_path[0];
+		else {
+			GetModuleFileName(NULL, currpath, 261);
+			mapfile[0] = currpath[0];
+		}
+		fd = open(mapfile,O_RDONLY);
+#else
+		fd = 0;
+		mapfile = (char*)malloc(MAXFILENAME);
+		if (mapfile) {
+			/* build a full path to locate the mapping file */
+			if ((usermap_path[0] != '/')
+			   && getcwd(mapfile,MAXFILENAME)) {
+				strcat(mapfile,"/");
+				strcat(mapfile,usermap_path);
+			} else
+				strcpy(mapfile,usermap_path);
+			p = strrchr(mapfile,'/');
+			if (p)
+				do {
+					strcpy(p,"/" MAPDIR "/" MAPFILE);
+					fd = open(mapfile,O_RDONLY);
+					if (fd <= 0) {
+						*p = 0;
+						p = strrchr(mapfile,'/');
+						if (p == mapfile)
+							p = (char*)NULL;
+					}
+				} while ((fd <= 0) && p);
+			free(mapfile);
+			if (!p) {
+				printf("** Could not find the user mapping file\n");
+				if (usermap_path[0] != '/')
+					printf("   Retry with full path of file\n");
+				errors++;
+			}
+		}
+#endif
+		if (fd > 0) {
+			firstitem = ntfs_read_mapping(basicread, (void*)&fd);
+			close(fd);
+		}
+	} else {
+#if SELFTESTS & !USESTUBS
+		firstitem = ntfs_read_mapping(dummyread, (void*)NULL);
+#endif
+	}
+
+	if (firstitem) {
+		usermapping = ntfs_do_user_mapping(firstitem);
+		groupmapping = ntfs_do_group_mapping(firstitem);
+		if (usermapping && groupmapping) {
+			mapping[MAPUSERS] = usermapping;
+			mapping[MAPGROUPS] = groupmapping;
+		} else
+			ntfs_log_error("There were no valid user or no valid group\n");
+		/* now we can free the memory copy of input text */
+		/* and rely on internal representation */
+		while (firstitem) {
+			item = firstitem->next;
+#if USESTUBS
+			stdfree(firstitem); /* allocated within library */
+#else
+			free(firstitem);
+#endif
+			firstitem = item;
+		}
+	} else {
+		do_default_mapping(mapping,(const SID*)&defmap);
+	}
+	if (mapping[MAPUSERS])
+		mappingtype = MAPLOCAL;
+	return (!mapping[MAPUSERS]);
+}
+
+/*
+ *		Get an hexadecimal number (source with MSB first)
+ */
+
+u32 getmsbhex(const char *text)
+{
+	u32 v;
+	int b;
+	BOOL ok;
+
+	v = 0;
+	ok = TRUE;
+	do {
+		b = *text++;
+		if ((b >= '0') && (b <= '9'))
+			v = (v << 4) + b - '0';
+		else
+			if ((b >= 'a') && (b <= 'f'))
+				v = (v << 4) + b - 'a' + 10;
+			else
+				if ((b >= 'A') && (b <= 'F'))
+					v = (v << 4) + b - 'A' + 10;
+				else ok = FALSE;
+	} while (ok);
+	return (v);
+}
+
+
+/*
+ *		Get an hexadecimal number (source with LSB first)
+ *	An odd number of digits might yield a strange result
+ */
+
+u32 getlsbhex(const char *text)
+{
+	u32 v;
+	int b;
+	BOOL ok;
+	int pos;
+
+	v = 0;
+	ok = TRUE;
+	pos = 0;
+	do {
+		b = *text++;
+		if ((b >= '0') && (b <= '9'))
+			v |= (u32)(b - '0') << (pos ^ 4);
+		else
+			if ((b >= 'a') && (b <= 'f'))
+				v |= (u32)(b - 'a' + 10) << (pos ^ 4);
+			else
+				if ((b >= 'A') && (b <= 'F'))
+					v |= (u32)(b - 'A' + 10) << (pos ^ 4);
+				else ok = FALSE;
+		pos += 4;
+	} while (ok);
+	return (v);
+}
+
+
+/*
+ *		Check whether a line looks like an hex dump
+ */
+
+BOOL ishexdump(const char *line, int first, int lth)
+{
+	BOOL ok;
+	int i;
+	int b;
+
+	ok = (first >= 0) && (lth >= (first + 16));
+	for (i=0; ((first+i)<lth) && ok; i++) {
+		b = line[first + i];
+		if ((i == 6)
+		    || (i == 7)
+		    || (i == 16)
+		    || (i == 25)
+		    || (i == 34)
+		    || (i == 43))
+			ok = (b == ' ') || (b == '\n');
+		else
+			ok = ((b >= '0') && (b <= '9'))
+			    || ((b >= 'a') && (b <= 'f'))
+			    || ((b >= 'A') && (b <= 'F'));
+	}
+	return (ok);
+}
+
+
+/*
+ *		Display security descriptors from a file
+ *	This is typically to convert a verbose output to a very verbose one
+ */
+
+void showhex(FILE *fd)
+{
+	static char attr[MAXATTRSZ];
+	char line[MAXLINE+1];
+#if POSIXACLS
+	struct POSIX_SECURITY *pxdesc;
+#endif
+	int lth;
+	int first;
+	unsigned int pos;
+	u32 v;
+	int c;
+	int isdir;
+	int mode;
+	unsigned int off;
+	int i;
+	le32 *pattr;
+	BOOL isdump;
+	BOOL done;
+
+	pos = 0;
+	off = 0;
+	done = FALSE;
+	do {
+			/* input a (partial) line without displaying */
+		lth = 0;
+		first = -1;
+		do {
+			c = getc(fd);
+			if ((c != ' ') && (first < 0))
+				first = lth;
+			if (c == EOF)
+				done = TRUE;
+			else
+				if (c != '\r')
+					line[lth++] = c;
+		} while (!done && (c != '\n') && (lth < MAXLINE));
+			/* check whether this looks like an hexadecimal dump */
+		isdump = ishexdump(line, first, lth);
+		if (isdump) off = getmsbhex(&line[first]);
+			/* line is not an hexadecimal dump */
+			/* display what we have in store */
+		if ((!isdump || !off) && pos && ntfs_valid_descr((char*)attr,pos)) {
+			printf("	Computed hash : 0x%08lx\n",
+				    (unsigned long)hash((le32*)attr,
+				    ntfs_attr_size(attr)));
+			isdir = guess_dir(attr);
+			printf("    Estimated type : %s\n",(isdir ? "directory" : "file"));
+			showheader(attr,4);
+			showusid(attr,4);
+			showgsid(attr,4);
+			showdacl(attr,isdir,4);
+			showsacl(attr,isdir,4);
+			showownership(attr);
+			mode = linux_permissions(attr,isdir);
+			printf("Interpreted Unix mode 0%03o\n",mode);
+#if POSIXACLS
+				/*
+				 * Posix display not possible when user
+				 * mapping is not available (option -h)
+				 */
+			if (mappingtype != MAPNONE) {
+				pxdesc = linux_permissions_posix(attr,isdir);
+				if (pxdesc) {
+					showposix(pxdesc);
+					free(pxdesc);
+				}
+			}
+#endif
+			pos = 0;
+		}
+		if (isdump && !off)
+			pos = off;
+			/* line looks like an hexadecimal dump */
+			/* decode it into attribute */
+		if (isdump && (off == pos)) {
+			for (i=first+8; i<lth; i+=9) {
+				pattr = (le32*)&attr[pos];
+				v = getlsbhex(&line[i]);
+				*pattr = cpu_to_le32(v);
+				pos += 4;
+			}
+		}
+			/* display (full) current line */
+		if (lth) printf("! ");
+		for (i=0; i<lth; i++) {
+			c = line[i];
+			putchar(c);
+		}
+		while (!done && (c != '\n')) {
+			c = getc(fd);
+			if (c == EOF)
+				done = TRUE;
+			else
+				putchar(c);
+		}
+	} while (!done);
+}
+
+BOOL applyattr(const char *fullname, const char *attr,
+			BOOL withattr, int attrib, s32 key)
+{
+	struct SECURITY_DATA *psecurdata;
+	const char *curattr;
+	char *newattr;
+	int selection;
+	BOOL bad;
+	BOOL badattrib;
+	BOOL err;
+#ifdef WIN32
+	HANDLE htoken;
+	TOKEN_PRIVILEGES tkp;
+#endif
+
+	err = FALSE;
+	psecurdata = (struct SECURITY_DATA*)NULL;
+	curattr = (const char*)NULL;
+	newattr = (char*)NULL;
+	if ((key > 0) && (key < MAXSECURID)) {
+		if (!securdata[key >> SECBLKSZ])
+			newblock(key);
+		if (securdata[key >> SECBLKSZ]) {
+			psecurdata = &securdata[key >> SECBLKSZ]
+					[key & ((1 << SECBLKSZ) - 1)];
+		}
+	}
+
+			/* If we have a usable attrib value. Try applying */
+	badattrib = FALSE;
+	if (opt_e && (attrib != INVALID_FILE_ATTRIBUTES)) {
+#ifdef WIN32
+		badattrib = !SetFileAttributesW((LPCWSTR)fullname, attrib);
+#else
+		badattrib = !ntfs_set_file_attributes(ntfs_context, fullname, attrib);
+#endif
+		if (badattrib) {
+			printf("** Could not set Windows attrib of ");
+			printname(stdout,fullname);
+			printf(" to 0x%x\n", attrib);
+			printerror(stdout);
+			warnings++;
+		}
+	}
+
+	if (withattr) {
+		if (psecurdata) {
+			newattr = (char*)malloc(ntfs_attr_size(attr));
+			if (newattr) {
+				memcpy(newattr,attr,ntfs_attr_size(attr));
+				psecurdata->attr = newattr;
+			}
+		}
+		curattr = attr;
+	} else
+		/*
+		 * No explicit attr in backup, use attr defined
+		 * previously for the same id
+		 */
+		if (psecurdata)
+			curattr = psecurdata->attr;
+       
+
+	if (curattr) {
+#ifdef WIN32
+		selection = OWNER_SECURITY_INFORMATION
+			| GROUP_SECURITY_INFORMATION
+			| DACL_SECURITY_INFORMATION;
+		if (OpenProcessToken(GetCurrentProcess(), 
+				TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &htoken)) {
+			if (LookupPrivilegeValue(NULL, SE_SECURITY_NAME,
+					&tkp.Privileges[0].Luid)) {
+				tkp.PrivilegeCount = 1;
+				tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+				if (AdjustTokenPrivileges(htoken, FALSE, &tkp, 0, NULL, 0)) {
+					selection |= SACL_SECURITY_INFORMATION;
+				}
+			}
+		}
+		/* const missing from stupid prototype */
+		bad = !SetFileSecurityW((LPCWSTR)fullname,
+			selection, (PSECURITY_DESCRIPTOR)(LONG_PTR)curattr);
+		if (bad)
+			switch (GetLastError()) {
+			case 1307 :
+			case 1314 :
+				printf("** Could not set owner or SACL of ");
+				printname(stdout,fullname);
+				printf(", retrying with no owner or SACL setting\n");
+				warnings++;
+				/* const missing from stupid prototype */
+				bad = !SetFileSecurityW((LPCWSTR)fullname,
+					selection & ~OWNER_SECURITY_INFORMATION
+					& ~SACL_SECURITY_INFORMATION,
+					(PSECURITY_DESCRIPTOR)
+							(LONG_PTR)curattr);
+				break;
+			default :
+				break;
+			}
+		/* Release privileges once we are done*/
+		if (selection ^ SACL_SECURITY_INFORMATION) {
+			tkp.Privileges[0].Attributes = 0;
+			AdjustTokenPrivileges(htoken, FALSE, &tkp, 0, NULL, 0);
+		}
+#else
+		selection = OWNER_SECURITY_INFORMATION
+			| GROUP_SECURITY_INFORMATION
+			| DACL_SECURITY_INFORMATION
+			| SACL_SECURITY_INFORMATION;
+		bad = !ntfs_set_file_security(ntfs_context,fullname,
+			selection, (const char*)curattr);
+#endif
+		if (bad) {
+			printf("** Could not set the ACL of ");
+			printname(stdout,fullname);
+			printf("\n");
+			printerror(stdout);
+			err = TRUE;
+		} else
+			if (opt_v) {
+				if (opt_e && !badattrib)
+					printf("ACL and attrib have been applied to ");
+				else
+					printf("ACL has been applied to ");
+				printname(stdout,fullname);
+				printf("\n");
+
+			}
+	} else {
+		printf("** There was no valid ACL for ");
+		printname(stdout,fullname);
+		printf("\n");
+		err = TRUE;
+	}
+	return (!err);
+}
+
+/*
+ *		Restore security descriptors from a file
+ */
+
+BOOL restore(FILE *fd)
+{
+	static char attr[MAXATTRSZ];
+	char line[MAXFILENAME+25];
+	char fullname[MAXFILENAME+25];
+	SECURITY_DESCRIPTOR_RELATIVE *phead;
+	int lth;
+	int first;
+	unsigned int pos;
+	int c;
+	int isdir;
+	int mode;
+	s32 key;
+	BOOL isdump;
+	unsigned int off;
+	u32 v;
+	u32 oldhash;
+	int i;
+	int count;
+	int attrib;
+	le32 *pattr;
+	BOOL withattr;
+	BOOL done;
+
+	pos = 0;
+	off = 0;
+	done = FALSE;
+	withattr = FALSE;
+	oldhash = 0;
+	key = 0;
+	errors = 0;
+	count = 0;
+	fullname[0] = 0;
+	attrib = INVALID_FILE_ATTRIBUTES;
+	do {
+			/* input a (partial) line without processing */
+		lth = 0;
+		first = -1;
+		do {
+			c = getc(fd);
+			if ((c != ' ') && (first < 0))
+				first = lth;
+			if (c == EOF)
+				done = TRUE;
+			else
+				if (c != '\r')
+					line[lth++] = c;
+		} while (!done && (c != '\n') && (lth < (MAXFILENAME + 24)));
+			/* check whether this looks like an hexadecimal dump */
+		isdump = ishexdump(line, first, lth);
+		if (isdump) off = getmsbhex(&line[first]);
+			/* line is not an hexadecimal dump */
+			/* apply what we have in store */
+		if ((!isdump || !off) && pos && ntfs_valid_descr((char*)attr,pos)) {
+			withattr = TRUE;
+			if (opt_v >= 2) {
+				printf("	Computed hash : 0x%08lx\n",
+					    (unsigned long)hash((le32*)attr,
+					    ntfs_attr_size(attr)));
+				isdir = guess_dir(attr);
+				printf("    Estimated type : %s\n",(isdir ? "directory" : "file"));
+				showheader(attr,4);
+				showusid(attr,4);
+				showgsid(attr,4);
+				showdacl(attr,isdir,4);
+				showsacl(attr,isdir,4);
+				mode = linux_permissions(attr,isdir);
+				showownership(attr);
+				printf("Interpreted Unix mode 0%03o\n",mode);
+			}
+			pos = 0;
+		}
+		if (isdump && !off)
+			pos = off;
+			/* line looks like an hexadecimal dump */
+			/* decode it into attribute */
+		if (isdump && (off == pos)) {
+			for (i=first+8; i<lth; i+=9) {
+				pattr = (le32*)&attr[pos];
+				v = getlsbhex(&line[i]);
+				*pattr = cpu_to_le32(v);
+				pos += 4;
+			}
+		}
+			/* display (full) current line unless dump or verbose */
+		if (!isdump || opt_v) {
+			if(lth) printf("! ");
+			for (i=0; i<lth; i++) {
+				c = line[i];
+				putchar(c);
+			}
+		}
+		while (!done && (c != '\n')) {
+			c = getc(fd);
+			if (c == EOF)
+				done = TRUE;
+			else
+				if (!isdump || opt_v)
+					putchar(c);
+		}
+
+		line[lth] = 0;
+		while ((lth > 0)
+		    && ((line[lth-1] == '\n') || (line[lth-1] == '\r')))
+			line[--lth] = 0;
+		if (!strncmp(line,"Computed hash : 0x",18))
+			oldhash = getmsbhex(&line[18]);
+		if (!strncmp(line,"Security key : 0x",17))
+			key = getmsbhex(&line[17]);
+		if (!strncmp(line,"Windows attrib : 0x",19))
+			attrib = getmsbhex(&line[19]);
+		if (done
+		    || !strncmp(line,"File ",5)
+		    || !strncmp(line,"Directory ",10)) {
+			/*
+			 *  New file or directory (or end of file) :
+			 *  apply attribute just collected
+			 *  or apply attribute defined from current key
+			 */
+
+			if (withattr
+			    && oldhash
+			    && (hash((const le32*)attr,ntfs_attr_size(attr)) != oldhash)) {
+				printf("** ACL rejected, its hash is not as expected\n");
+				errors++;
+			} else
+				if (fullname[0]) {
+					phead = (SECURITY_DESCRIPTOR_RELATIVE*)attr;
+					/* set the request for auto-inheritance */
+					if (phead->control & SE_DACL_AUTO_INHERITED)
+						phead->control |= SE_DACL_AUTO_INHERIT_REQ;
+					if (!applyattr(fullname,attr,withattr,
+							attrib,key))
+						errors++;
+					else
+						count++;
+				}
+			/* save current file or directory name */
+			withattr = FALSE;
+			key = 0;
+			oldhash = 0;
+			attrib = INVALID_FILE_ATTRIBUTES;
+			if (!done) {
+#ifdef WIN32
+				if (!strncmp(line,"File ",5))
+					makeutf16(fullname,&line[5]);
+				else
+					makeutf16(fullname,&line[10]);
+#else
+				if (!strncmp(line,"File ",5))
+					strcpy(fullname,&line[5]);
+				else
+					strcpy(fullname,&line[10]);
+#endif
+			}
+		}
+	} while (!done);
+	printf("%d ACLs have been applied\n",count);
+	return (FALSE);
+}
+
+/*
+ *		Open the security API in rw mode for an ACL restoration
+ */
+
+#ifdef WIN32
+#else
+BOOL dorestore(const char *volume, FILE *fd)
+{
+	BOOL err;
+
+	err = FALSE;
+	if (!getuid()) {
+ 		if (open_security_api()) {
+			if (open_volume(volume,NTFS_MNT_NONE)) {
+				if (restore(fd)) err = TRUE;
+				close_volume(volume);
+			} else {
+				fprintf(stderr,"Could not open volume %s\n",volume);
+				printerror(stderr);
+				err = TRUE;
+			}
+			close_security_api();
+		} else {
+			fprintf(stderr,"Could not open security API\n");
+			printerror(stderr);
+			err = TRUE;
+		}
+	} else {
+		fprintf(stderr,"Restore is only possible as root\n");
+		err = TRUE;
+	}
+	return (err);
+}
+#endif /* WIN32 */
+
+#if POSIXACLS & SELFTESTS & !USESTUBS
+
+/*
+ *		Merge Posix ACL rights into an u32 (self test only)
+ *
+ *	Result format : -----rwxrwxrwxrwxrwx---rwxrwxrwx
+ *                           U1 U2 G1 G2  M     o  g  w
+ *
+ *	Only two users (U1, U2) and two groups (G1, G2) taken into account
+ */
+u32 merge_rights(const struct POSIX_SECURITY *pxdesc, BOOL def)
+{
+	const struct POSIX_ACE *pxace;
+	int i;
+	int users;
+	int groups;
+	int first;
+	int last;
+	u32 rights;
+
+	rights = 0;
+	users = 0;
+	groups = 0;
+	if (def) {
+		first = pxdesc->firstdef;
+		last = pxdesc->firstdef + pxdesc->defcnt - 1;
+	} else {
+		first = 0;
+		last = pxdesc->acccnt - 1;
+	}
+	pxace = pxdesc->acl.ace;
+	for (i=first; i<=last; i++) {
+		switch (pxace[i].tag) {
+		case POSIX_ACL_USER_OBJ :
+			rights |= (pxace[i].perms & 7) << 6;
+			break;
+		case POSIX_ACL_USER :
+			if (users < 2)
+				rights |= ((u32)pxace[i].perms & 7) << (24 - 3*users);
+			users++;
+			break;
+		case POSIX_ACL_GROUP_OBJ :
+			rights |= (pxace[i].perms & 7) << 3;
+			break;
+		case POSIX_ACL_GROUP :
+			if (groups < 2)
+				rights |= ((u32)pxace[i].perms & 7) << (18 - 3*groups);
+			groups++;
+			break;
+		case POSIX_ACL_MASK :
+			rights |= ((u32)pxace[i].perms & 7) << 12;
+			break;
+		case POSIX_ACL_OTHER :
+			rights |= (pxace[i].perms & 7);
+			break;
+		default :
+			break;
+		}
+	}
+	return (rights);
+}
+
+void tryposix(struct POSIX_SECURITY *pxdesc)
+{
+	le32 owner_sid[] = /* S-1-5-21-3141592653-589793238-462843383-1016 */
+		{
+		cpu_to_le32(0x501), cpu_to_le32(0x05000000), cpu_to_le32(21),
+		cpu_to_le32(DEFSECAUTH1), cpu_to_le32(DEFSECAUTH2),
+		cpu_to_le32(DEFSECAUTH3), cpu_to_le32(1016)
+		} ;
+	le32 group_sid[] = /* S-1-5-21-3141592653-589793238-462843383-513 */
+		{
+		cpu_to_le32(0x501), cpu_to_le32(0x05000000), cpu_to_le32(21),
+		cpu_to_le32(DEFSECAUTH1), cpu_to_le32(DEFSECAUTH2),
+		cpu_to_le32(DEFSECAUTH3), cpu_to_le32(513)
+		} ;
+
+	char *attr;
+	BOOL isdir;
+	mode_t mode;
+	struct POSIX_SECURITY *newpxdesc;
+	struct POSIX_SECURITY *oldpxdesc;
+	static char *oldattr = (char*)NULL;
+
+	isdir = FALSE;
+	if (oldattr) {
+		oldpxdesc = linux_permissions_posix(oldattr, isdir);
+		newpxdesc = ntfs_merge_descr_posix(pxdesc, oldpxdesc);
+		if (!newpxdesc)
+			newpxdesc = pxdesc;
+		free(oldpxdesc);
+		if (opt_v) {
+			printf("merged descriptors :\n");
+			showposix(newpxdesc);
+		}
+	} else
+		newpxdesc = pxdesc;
+	attr = ntfs_build_descr_posix(context.mapping,newpxdesc,
+			isdir,(SID*)owner_sid,(SID*)group_sid);
+	if (attr && ntfs_valid_descr(attr, ntfs_attr_size(attr))) {
+		if (opt_v)
+			hexdump(attr,ntfs_attr_size(attr),8);
+		if (opt_v >= 2) {
+			showheader(attr,4);
+			showusid(attr,4);
+			showgsid(attr,4);
+			showdacl(attr,isdir,4);
+			showsacl(attr,isdir,4);
+			mode = linux_permissions(attr,isdir);
+			printf("Interpreted Unix mode 0%03o\n",mode);
+			printf("Interpreted back Posix descriptor :\n");
+			newpxdesc = linux_permissions_posix(attr,isdir);
+			showposix(newpxdesc);
+			free(newpxdesc);
+		}
+		if (oldattr) free(oldattr);
+		oldattr = attr;
+	}
+}
+
+static BOOL same_posix(struct POSIX_SECURITY *pxdesc1,
+			struct POSIX_SECURITY *pxdesc2)
+{
+	BOOL same;
+	int i;
+
+	same = pxdesc1
+		&& pxdesc2
+		&& (pxdesc1->mode == pxdesc2->mode)
+		&& (pxdesc1->acccnt == pxdesc2->acccnt)
+		&& (pxdesc1->defcnt == pxdesc2->defcnt)
+		&& (pxdesc1->firstdef == pxdesc2->firstdef)
+		&& (pxdesc1->tagsset == pxdesc2->tagsset)
+		&& (pxdesc1->acl.version == pxdesc2->acl.version)
+		&& (pxdesc1->acl.flags == pxdesc2->acl.flags);
+	i = 0;
+	while (same && (i < pxdesc1->acccnt)) {
+		same = (pxdesc1->acl.ace[i].tag == pxdesc2->acl.ace[i].tag)
+		   && (pxdesc1->acl.ace[i].perms == pxdesc2->acl.ace[i].perms)
+		   && (pxdesc1->acl.ace[i].id == pxdesc2->acl.ace[i].id);
+		i++;
+	}
+	i = pxdesc1->firstdef;
+	while (same && (i < pxdesc1->firstdef + pxdesc1->defcnt)) {
+		same = (pxdesc1->acl.ace[i].tag == pxdesc2->acl.ace[i].tag)
+		   && (pxdesc1->acl.ace[i].perms == pxdesc2->acl.ace[i].perms)
+		   && (pxdesc1->acl.ace[i].id == pxdesc2->acl.ace[i].id);
+		i++;
+	}
+	return (same);
+}
+
+#endif /* POSIXACLS & SELFTESTS & !USESTUBS */
+
+#if SELFTESTS & !USESTUBS
+
+/*
+ *		Build a dummy security descriptor
+ *	returns descriptor in allocated memory, must free() after use
+ */
+
+static char *build_dummy_descr(BOOL isdir __attribute__((unused)),
+			const SID *usid, const SID *gsid,
+			int cnt, 
+			 /* seq of int allow, SID *sid, int flags, u32 mask */
+			...)
+{
+	char *attr;
+	int attrsz;
+	SECURITY_DESCRIPTOR_RELATIVE *pnhead;
+	ACL *pacl;
+	ACCESS_ALLOWED_ACE *pace;
+	va_list ap;
+	const SID *sid;
+	u32 umask;
+	le32 mask;
+	int flags;
+	BOOL allow;
+	int pos;
+	int usidsz;
+	int gsidsz;
+	int sidsz;
+	int aclsz;
+	int i;
+
+	if (usid)
+		usidsz = ntfs_sid_size(usid);
+	else
+		usidsz = 0;
+	if (gsid)
+		gsidsz = ntfs_sid_size(gsid);
+	else
+		gsidsz = 0;
+
+
+	/* allocate enough space for the new security attribute */
+	attrsz = sizeof(SECURITY_DESCRIPTOR_RELATIVE)	/* header */
+	    + usidsz + gsidsz	/* usid and gsid */
+	    + sizeof(ACL)	/* acl header */
+	    + cnt*40;
+
+	attr = (char*)ntfs_malloc(attrsz);
+	if (attr) {
+		/* build the main header part */
+		pnhead = (SECURITY_DESCRIPTOR_RELATIVE*) attr;
+		pnhead->revision = SECURITY_DESCRIPTOR_REVISION;
+		pnhead->alignment = 0;
+			/*
+			 * The flag SE_DACL_PROTECTED prevents the ACL
+			 * to be changed in an inheritance after creation
+			 */
+		pnhead->control = SE_DACL_PRESENT | SE_DACL_PROTECTED
+				    | SE_SELF_RELATIVE;
+			/*
+			 * Windows prefers ACL first, do the same to
+			 * get the same hash value and avoid duplication
+			 */
+		/* build the ACL header */
+		pos = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
+		pacl = (ACL*)&attr[pos];
+		pacl->revision = ACL_REVISION;
+		pacl->alignment1 = 0;
+		pacl->size = cpu_to_le16(0); /* fixed later */
+		pacl->ace_count = cpu_to_le16(cnt);
+		pacl->alignment2 = cpu_to_le16(0);
+
+		/* enter the ACEs */
+
+		pos += sizeof(ACL);
+		aclsz = sizeof(ACL);
+		va_start(ap,cnt);
+		for (i=0; i<cnt; i++) {
+			pace = (ACCESS_ALLOWED_ACE*)&attr[pos];
+			allow = va_arg(ap,int);
+			sid = va_arg(ap,SID*);
+			flags = va_arg(ap,int);
+			umask = va_arg(ap,u32);
+			mask = cpu_to_le32(umask);
+			sidsz = ntfs_sid_size(sid);
+			pace->type = (allow ? ACCESS_ALLOWED_ACE_TYPE : ACCESS_DENIED_ACE_TYPE);
+			pace->flags = flags;
+			pace->size = cpu_to_le16(sidsz + 8);
+			pace->mask = mask;
+			memcpy(&pace->sid,sid,sidsz);
+			aclsz += sidsz + 8;
+			pos += sidsz + 8;
+		}
+		va_end(ap);
+
+		/* append usid and gsid if defined */
+		/* positions of ACL, USID and GSID into header */
+		pnhead->owner = cpu_to_le32(0);
+		pnhead->group = cpu_to_le32(0);
+		if (usid) {
+			memcpy(&attr[pos], usid, usidsz);
+			pnhead->owner = cpu_to_le32(pos);
+		}
+		if (gsid) {
+			memcpy(&attr[pos + usidsz], gsid, gsidsz);
+			pnhead->group = cpu_to_le32(pos + usidsz);
+		}
+		/* positions of DACL and SACL into header */
+		pnhead->sacl = cpu_to_le32(0);
+		if (cnt) {
+			pacl->size = cpu_to_le16(aclsz);
+			pnhead->dacl =
+			    cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE));
+		} else
+			pnhead->dacl = cpu_to_le32(0);
+		if (!ntfs_valid_descr(attr,pos+usidsz+gsidsz)) {
+			printf("** Bad sample descriptor\n");
+			free(attr);
+			attr = (char*)NULL;
+			errors++;
+		}
+	} else
+		errno = ENOMEM;
+	return (attr);
+}
+
+/*
+ *		Check a few samples with special conditions
+ */
+
+void check_samples()
+{
+	char *descr = (char*)NULL;
+	BOOL isdir = FALSE;
+	mode_t perms;
+	mode_t expect = 0;
+	int cnt;
+	u32 expectacc;
+	u32 expectdef;
+#if POSIXACLS
+	u32 accrights;
+	u32 defrights;
+	mode_t mixmode;
+	struct POSIX_SECURITY *pxdesc;
+	struct POSIX_SECURITY *pxsample;
+	const char *txsample;
+#endif
+	le32 owner1[] = /* S-1-5-21-1833069642-4243175381-1340018762-1003 */
+		{
+		cpu_to_le32(0x501), cpu_to_le32(0x05000000), cpu_to_le32(21),
+		cpu_to_le32(1833069642), cpu_to_le32(4243175381),
+		cpu_to_le32(1340018762), cpu_to_le32(1003)
+		} ;
+	le32 group1[] = /* S-1-5-21-1833069642-4243175381-1340018762-513 */
+		{
+		cpu_to_le32(0x501), cpu_to_le32(0x05000000), cpu_to_le32(21),
+		cpu_to_le32(1833069642), cpu_to_le32(4243175381),
+		cpu_to_le32(1340018762), cpu_to_le32(513)
+		} ;
+	le32 group2[] = /* S-1-5-21-1607551490-981732888-1819828000-513 */
+		{
+		cpu_to_le32(0x501), cpu_to_le32(0x05000000), cpu_to_le32(21),
+		cpu_to_le32(1607551490), cpu_to_le32(981732888),
+		cpu_to_le32(1819828000), cpu_to_le32(513)
+		} ;
+	le32 owner3[] = /* S-1-5-21-3141592653-589793238-462843383-1016 */
+		{
+		cpu_to_le32(0x501), cpu_to_le32(0x05000000), cpu_to_le32(21),
+		cpu_to_le32(DEFSECAUTH1), cpu_to_le32(DEFSECAUTH2),
+		cpu_to_le32(DEFSECAUTH3), cpu_to_le32(1016)
+		} ;
+	le32 group3[] = /* S-1-5-21-3141592653-589793238-462843383-513 */
+		{
+		cpu_to_le32(0x501), cpu_to_le32(0x05000000), cpu_to_le32(21),
+		cpu_to_le32(DEFSECAUTH1), cpu_to_le32(DEFSECAUTH2),
+		cpu_to_le32(DEFSECAUTH3), cpu_to_le32(513)
+		} ;
+
+#if POSIXACLS
+	struct {
+		struct POSIX_SECURITY head;
+		struct POSIX_ACE ace[4];
+	} sampletry1 =
+	{
+		{ 0645, 4, 0, 4, 0x35,
+			{ POSIX_VERSION, 0, 0 }
+		},
+		{
+			{ 1, 6, -1 },
+			{ 4, 5, -1 },
+			{ 16, 4, -1 },
+			{ 32, 5, -1 }
+		}
+	} ;
+
+	struct {
+		struct POSIX_SECURITY head;
+		struct POSIX_ACE ace[6];
+	} sampletry3 =
+	{
+		{ 0100, 6, 0, 6, 0x3f,
+			{ POSIX_VERSION, 0, 0 }
+		},
+		{
+			{ 1, 1, -1 },
+			{ 2, 3, 1000 },
+			{ 4, 1, -1 },
+			{ 8, 3, 1002 },
+			{ 16, 0, -1 },
+			{ 32, 0, -1 }
+		}
+	} ;
+
+	struct {
+		struct POSIX_SECURITY head;
+		struct POSIX_ACE ace[8];
+	} sampletry4 =
+	{
+		{ 0140, 8, 0, 8, 0x3f,
+			{ POSIX_VERSION, 0, 0 }
+		},
+		{
+			{ 1, 1, -1 },
+			{ 2, 3, 516 },
+			{ 2, 6, 1000 },
+			{ 4, 1, -1 },
+			{ 8, 6, 500 },
+			{ 8, 3, 1002 },
+			{ 16, 4, -1 },
+			{ 32, 0, -1 }
+		}
+	} ;
+
+	struct {
+		struct POSIX_SECURITY head;
+		struct POSIX_ACE ace[6];
+	} sampletry5 =
+	{
+		{ 0454, 6, 0, 6, 0x3f,
+			{ POSIX_VERSION, 0, 0 }
+		},
+		{
+			{ 1, 4, -1 },
+			{ 2, 5, 516 },
+			{ 4, 4, -1 },
+			{ 8, 6, 500 },
+			{ 16, 5, -1 },
+			{ 32, 4, -1 }
+		}
+	} ;
+
+	struct {
+		struct POSIX_SECURITY head;
+		struct POSIX_ACE ace[8];
+	} sampletry6 =
+	{
+		{ 0332, 8, 0, 8, 0x3f,
+			{ POSIX_VERSION, 0, 0 }
+		},
+		{
+			{ 1, 3, -1 },
+			{ 2, 1,  0 },
+			{ 2, 2,  1000 },
+			{ 4, 6, -1 },
+			{ 8, 4,  0 },
+			{ 8, 5,  1002 },
+			{ 16, 3, -1 },
+			{ 32, 2, -1 }
+		}
+	} ;
+
+	struct {
+		struct POSIX_SECURITY head;
+		struct POSIX_ACE ace[4];
+	} sampletry8 =
+	{
+		{ 0677, 4, 0, 4, 0x35,
+			{ POSIX_VERSION, 0, 0 }
+		},
+		{
+			{ 1, 6, -1 },
+			{ 4, 7, -1 },
+			{ 16, 7, -1 },
+			{ 32, 7, -1 }
+		}
+	} ;
+
+#endif /* POSIXACLS */
+
+
+#if POSIXACLS
+	for (cnt=1; cnt<=8; cnt++) {
+		switch (cnt) {
+		case 1 :
+			pxsample = &sampletry1.head;
+			txsample = "sampletry1-a";
+			isdir = FALSE;
+			descr = ntfs_build_descr_posix(context.mapping,&sampletry1.head,
+				isdir, (const SID*)owner3, (const SID*)group3);
+			break;
+		case 2 :
+			pxsample = &sampletry1.head;
+			txsample = "sampletry1-b";
+			isdir = FALSE;
+			descr = ntfs_build_descr_posix(context.mapping,&sampletry1.head,
+				isdir, (const SID*)adminsid, (const SID*)group3);
+			break;
+		case 3 :
+			isdir = FALSE;
+			pxsample = &sampletry3.head;
+			txsample = "sampletry3";
+			descr = ntfs_build_descr_posix(context.mapping,pxsample,
+				isdir, (const SID*)group3, (const SID*)group3);
+			break;
+		case 4 :
+			isdir = FALSE;
+			pxsample = &sampletry4.head;
+			txsample = "sampletry4";
+			descr = ntfs_build_descr_posix(context.mapping,pxsample,
+				isdir, (const SID*)owner3, (const SID*)group3);
+			break;
+		case 5 :
+			isdir = FALSE;
+			pxsample = &sampletry5.head;
+			txsample = "sampletry5";
+			descr = ntfs_build_descr_posix(context.mapping,pxsample,
+				isdir, (const SID*)owner3, (const SID*)group3);
+			break;
+		case 6 :
+			isdir = FALSE;
+			pxsample = &sampletry6.head;
+			txsample = "sampletry6-a";
+			descr = ntfs_build_descr_posix(context.mapping,pxsample,
+				isdir, (const SID*)owner3, (const SID*)group3);
+			break;
+		case 7 :
+			isdir = FALSE;
+			pxsample = &sampletry6.head;
+			txsample = "sampletry6-b";
+			descr = ntfs_build_descr_posix(context.mapping,pxsample,
+				isdir, (const SID*)adminsid, (const SID*)adminsid);
+			break;
+		case 8 :
+			pxsample = &sampletry8.head;
+			txsample = "sampletry8";
+			isdir = FALSE;
+			descr = ntfs_build_descr_posix(context.mapping,&sampletry8.head,
+				isdir, (const SID*)owner3, (const SID*)group3);
+			break;
+		default :
+			pxsample = (struct POSIX_SECURITY*)NULL;
+			txsample = (const char*)NULL;
+		}
+				/* check we get original back */
+		if (descr)
+			pxdesc = linux_permissions_posix(descr, isdir);
+		else
+			pxdesc = (struct POSIX_SECURITY*)NULL;
+		if (!descr || !pxdesc || !same_posix(pxsample,pxdesc)) {
+			printf("** Error in %s\n",txsample);
+			showposix(pxsample);
+			showall(descr,0);
+			showposix(pxdesc);
+			errors++;
+		}
+		free(descr);
+		free(pxdesc);
+	}
+
+#endif /* POSIXACLS */
+
+
+		/*
+		 *		Check a few samples built by Windows,
+		 *	which cannot be generated by Linux
+		 */
+
+	for (cnt=1; cnt<=10; cnt++) {
+		switch(cnt) {
+		case 1 :  /* hp/tmp */
+			isdir = TRUE;
+			descr = build_dummy_descr(isdir,
+				(const SID*)owner1, (const SID*)group1,
+				1,
+				(int)TRUE, worldsid, (int)0x3, (u32)0x1f01ff);
+			expectacc = expect = 0777;
+			expectdef = 0;
+			break;
+		case 2 :  /* swsetup */
+			isdir = TRUE;
+			descr = build_dummy_descr(isdir, adminsid, (const SID*)group2,
+				2,
+				(int)TRUE, worldsid, (int)0x0, (u32)0x1f01ff,
+				(int)TRUE, worldsid, (int)0xb, (u32)0x1f01ff);
+			expectacc = expect = 0777;
+			expectdef = 0777;
+			break;
+		case 3 :  /* Dr Watson */
+			isdir = TRUE;
+			descr = build_dummy_descr(isdir, (const SID*)owner3, (const SID*)group3,
+				0);
+			expectacc = expect = 0700;
+			expectdef = 0;
+			break;
+		case 4 :
+			isdir = FALSE;
+			descr = build_dummy_descr(isdir,
+				(const SID*)owner3, (const SID*)group3,
+				4,
+				(int)TRUE, (const SID*)owner3, 0, 
+					le32_to_cpu(FILE_READ_DATA | OWNER_RIGHTS),
+				(int)TRUE, (const SID*)group3, 0,
+					le32_to_cpu(FILE_WRITE_DATA),
+				(int)TRUE, (const SID*)group2, 0,
+					le32_to_cpu(FILE_WRITE_DATA | FILE_READ_DATA),
+				(int)TRUE, (const SID*)worldsid, 0,
+					le32_to_cpu(FILE_EXECUTE));
+			expect = 0731;
+			expectacc = 07070731;
+			expectdef = 0;
+			break;
+		case 5 :  /* Vista/JP */
+			isdir = TRUE;
+			descr = build_dummy_descr(isdir, systemsid, systemsid,
+				6,
+				(int)TRUE, owner1, (int)0x0, (u32)0x1f01ff,
+				(int)TRUE, systemsid, (int)0x0, (u32)0x1f01ff,
+				(int)TRUE, adminsid, (int)0x0, (u32)0x1f01ff,
+				(int)TRUE, owner1, (int)0xb, (u32)0x10000000,
+				(int)TRUE, systemsid, (int)0xb, (u32)0x10000000,
+				(int)TRUE, adminsid, (int)0xb, (u32)0x10000000);
+			expectacc = expect = 0700;
+			expectdef = 0700;
+			break;
+		case 6 :  /* Vista/JP2 */
+			isdir = TRUE;
+			descr = build_dummy_descr(isdir, systemsid, systemsid,
+				7,
+				(int)TRUE, owner1,    (int)0x0, (u32)0x1f01ff,
+				(int)TRUE, systemsid, (int)0x0, (u32)0x1f01ff,
+				(int)TRUE, adminsid,  (int)0x0, (u32)0x1f01ff,
+				(int)TRUE, owner1,    (int)0xb, (u32)0x1f01ff,
+				(int)TRUE, systemsid, (int)0xb, (u32)0x1f01ff,
+				(int)TRUE, adminsid,  (int)0xb, (u32)0x1f01ff,
+				(int)TRUE, owner3,    (int)0x3, (u32)0x1200a9);
+			expectacc = 0500070700;
+			expectdef = 0700;
+			expect = 0700;
+			break;
+		case 7 :  /* WinXP/JP */
+			isdir = TRUE;
+			descr = build_dummy_descr(isdir, adminsid, systemsid,
+				6,
+				(int)TRUE, owner1, (int)0x0, (u32)0x1f01ff,
+				(int)TRUE, systemsid, (int)0x0, (u32)0x1f01ff,
+				(int)TRUE, adminsid, (int)0x0, (u32)0x1f01ff,
+				(int)TRUE, owner1, (int)0xb, (u32)0x10000000,
+				(int)TRUE, systemsid, (int)0xb, (u32)0x10000000,
+				(int)TRUE, adminsid, (int)0xb, (u32)0x10000000);
+			expectacc = expect = 0700;
+			expectdef = 0700;
+			break;
+		case 8 :  /* WinXP/JP2 */
+			isdir = TRUE;
+			descr = build_dummy_descr(isdir, adminsid, systemsid,
+				6,
+				(int)TRUE, owner1,    (int)0x0, (u32)0x1f01ff,
+				(int)TRUE, systemsid, (int)0x0, (u32)0x1f01ff,
+				(int)TRUE, adminsid,  (int)0x0, (u32)0x1f01ff,
+				(int)TRUE, owner1,    (int)0xb, (u32)0x10000000,
+				(int)TRUE, systemsid, (int)0xb, (u32)0x10000000,
+				(int)TRUE, adminsid,  (int)0xb, (u32)0x10000000);
+			expectacc = expect = 0700;
+			expectdef = 0700;
+			break;
+		case 9 :  /* Win8/bin */
+			isdir = TRUE;
+			descr = build_dummy_descr(isdir,
+				(const SID*)owner3, (const SID*)owner3,
+				6,
+				(int)TRUE, authsid,   (int)0x3,  (u32)0x1f01ff,
+				(int)TRUE, adminsid,  (int)0x13, (u32)0x1f01ff,
+				(int)TRUE, systemsid, (int)0x13, (u32)0x1f01ff,
+				(int)TRUE, localsid,  (int)0x13, (u32)0x1200a9,
+				(int)TRUE, authsid,   (int)0x10, (u32)0x1301bf,
+				(int)TRUE, authsid,   (int)0x1b, (u32)0xe0010000);
+			expectacc = expect = 0777;
+			expectdef = 0777;
+			break;
+		case 10 :  /* Win8/bin/linem.exe */
+			isdir = FALSE;
+			descr = build_dummy_descr(isdir,
+				(const SID*)owner3, (const SID*)owner3,
+				4,
+				(int)TRUE, authsid,   (int)0x10, (u32)0x1f01ff,
+				(int)TRUE, adminsid,  (int)0x10, (u32)0x1f01ff,
+				(int)TRUE, systemsid, (int)0x10, (u32)0x1ff,
+				(int)TRUE, localsid,  (int)0x10, (u32)0x1200a9);
+			expectacc = expect = 0777;
+			expectdef = 0;
+			break;
+		default :
+			expectacc = expectdef = 0;
+			break;
+		}
+		if (descr) {
+			perms = linux_permissions(descr, isdir);
+			if (perms != expect) {
+				printf("** Error in sample %d, perms 0%03o expected 0%03o\n",
+					cnt,perms,expect);
+				showall(descr,0);
+				errors++;
+			} else {
+#if POSIXACLS
+				pxdesc = linux_permissions_posix(descr, isdir);
+				if (pxdesc) {
+					accrights = merge_rights(pxdesc,FALSE);
+					defrights = merge_rights(pxdesc,TRUE);
+					if (!(pxdesc->tagsset & ~(POSIX_ACL_USER_OBJ | POSIX_ACL_GROUP_OBJ | POSIX_ACL_OTHER)))
+						mixmode = expect;
+					else
+						mixmode = (expect & 07707) | ((accrights >> 9) & 070);
+					if ((pxdesc->mode != mixmode)
+					  || (accrights != expectacc)
+					  || (defrights != expectdef)) {
+						printf("** Error in sample %d : mode %03o expected 0%03o\n",
+							cnt,pxdesc->mode,mixmode);
+						printf("     Posix access rights 0%03lo expected 0%03lo\n",
+							(long)accrights,(long)expectacc);
+						printf("          default rights 0%03lo expected 0%03lo\n",
+							(long)defrights,(long)expectdef);
+						showall(descr,0);
+						showposix(pxdesc);
+exit(1);
+					}
+					free(pxdesc);
+				}
+#endif
+			}
+		free(descr);
+		}
+	}
+}
+
+
+/*
+ *		Check whether any basic permission setting is interpreted
+ *	back exactly as set
+ */
+
+void basictest(int kind, BOOL isdir, const SID *owner, const SID *group)
+{
+	char *attr;
+	mode_t perm;
+	mode_t gotback;
+	u32 count;
+	u32 acecount;
+	u32 globhash;
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	const ACL *pacl;
+	enum { ERRNO,
+		ERRMA, ERRPA, /* error converting mode or Posix ACL to NTFS */
+		ERRAM, ERRAP, /* error converting NTFS to mode or Posix ACL */
+	} err;
+	u32 expectcnt[] = {
+		27800, 31896,
+		24064, 28160,
+		24064, 28160,
+		24064, 28160,
+		25416, 29512
+	} ;
+	u32 expecthash[] = {
+		0x8f80865b, 0x7bc7960,
+		0x8fd9ecfe, 0xddd4db0,
+		0xa8b07400, 0xa189c20,
+		0xc5689a00, 0xb6c09000,
+		0x94bfb419, 0xa4311791
+	} ;
+#if POSIXACLS
+	struct POSIX_SECURITY *pxdesc;
+	char *pxattr;
+	u32 pxcount;
+	u32 pxacecount;
+	u32 pxglobhash;
+#endif
+
+	count = 0;
+	acecount = 0;
+	globhash = 0;
+#if POSIXACLS
+	pxcount = 0;
+	pxacecount = 0;
+	pxglobhash = 0;
+#endif
+	for (perm=0; (perm<=07777) && (errors < 10); perm++) {
+		err = ERRNO;
+		/* file owned by plain user and group */
+		attr = ntfs_build_descr(perm,isdir,owner,(const SID*)group);
+		if (attr && ntfs_valid_descr(attr, ntfs_attr_size(attr))) {
+			phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr;
+			pacl = (const ACL*)&attr[le32_to_cpu(phead->dacl)];
+			acecount += le16_to_cpu(pacl->ace_count);
+			globhash += hash((const le32*)attr,ntfs_attr_size(attr));
+			count++;
+#if POSIXACLS
+			/*
+			 * Build a NTFS ACL from a mode, and
+			 * decode to a Posix ACL, expecting to
+			 * get the original mode back.
+			 */
+			pxdesc = linux_permissions_posix(attr, isdir);
+			if (!pxdesc || (pxdesc->mode != perm)) {
+				err = ERRAP;
+				if (pxdesc)
+					gotback = pxdesc->mode;
+				else
+					gotback = 0;
+			} else {
+			/*
+			 * Build a NTFS ACL from the Posix ACL, expecting to
+			 * get exactly the same NTFS ACL, then decode to a
+			 * mode, expecting to get the original mode back.
+			 */
+				pxattr = ntfs_build_descr_posix(context.mapping,
+						pxdesc,isdir,owner,
+						(const SID*)group);
+				if (pxattr && !memcmp(pxattr,attr,
+						 ntfs_attr_size(attr))) {
+					phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr;
+					pacl = (const ACL*)&attr[le32_to_cpu(phead->dacl)];
+					pxacecount += le16_to_cpu(pacl->ace_count);
+					pxglobhash += hash((const le32*)attr,ntfs_attr_size(attr));
+					pxcount++;
+					gotback = linux_permissions(pxattr, isdir);
+					if (gotback != perm)
+						err = ERRAM;
+					else
+						free(pxattr);
+				} else
+					err = ERRPA;
+				free(attr);
+			}
+			free(pxdesc);
+#else
+			gotback = linux_permissions(attr, isdir);
+			if (gotback != perm)
+				err = ERRAM;
+			else
+				free(attr);
+#endif /* POSIXACLS */
+		} else
+			err = ERRMA;
+
+		switch (err) {
+		case ERRMA :
+			printf("** no or wrong permission settings "
+				"for kind %d perm %03o\n",kind,perm);
+			if (attr && opt_v)
+				hexdump(attr,ntfs_attr_size(attr),8);
+			if (attr && (opt_v >= 2)) {
+				showheader(attr,4);
+				showusid(attr,4);
+				showgsid(attr,4);
+				showdacl(attr,isdir,4);
+				showsacl(attr,isdir,4);
+			}
+			errors++;
+			break;
+		case ERRPA :
+			printf("** no or wrong permission settings from PX "
+				"for kind %d perm %03o\n",kind,perm);
+			errors++;
+			break;
+#if POSIXACLS
+		case ERRAM :
+			printf("** wrong permission settings, "
+				"kind %d perm 0%03o, gotback %03o\n",
+				kind, perm, gotback);
+			if (opt_v)
+				hexdump(pxattr,ntfs_attr_size(pxattr),8);
+			if (opt_v >= 2) {
+				showheader(pxattr,4);
+				showusid(pxattr,4);
+				showgsid(pxattr,4);
+				showdacl(pxattr,isdir,4);
+				showsacl(pxattr,isdir,4);
+			}
+			errors++;
+			break;
+		case ERRAP :
+			/* continued */
+#else
+		case ERRAM :
+		case ERRAP :
+#endif /* POSIXACLS */
+			printf("** wrong permission settings, "
+				"kind %d perm 0%03o, gotback %03o\n",
+				kind, perm, gotback);
+			if (opt_v)
+				hexdump(attr,ntfs_attr_size(attr),8);
+			if (opt_v >= 2) {
+				showheader(attr,4);
+				showusid(attr,4);
+				showgsid(attr,4);
+				showdacl(attr,isdir,4);
+				showsacl(attr,isdir,4);
+			}
+			errors++;
+			free(attr);
+			break;
+		default :
+			break;
+		}
+	}
+	printf("%lu ACLs built from mode, %lu ACE built, mean count %lu.%02lu\n",
+		(unsigned long)count,(unsigned long)acecount,
+		(unsigned long)acecount/count,acecount*100L/count%100L);
+	if (acecount != expectcnt[kind]) {
+		printf("** Error : expected ACE count %lu\n",
+			(unsigned long)expectcnt[kind]);
+		errors++;
+	}
+	if (globhash != expecthash[kind]) {
+		printf("** Error : wrong global hash 0x%lx instead of 0x%lx\n",
+			(unsigned long)globhash, (unsigned long)expecthash[kind]);
+		errors++;
+	}
+#if POSIXACLS
+	printf("%lu ACLs built from Posix ACLs, %lu ACE built, mean count %lu.%02lu\n",
+		(unsigned long)pxcount,(unsigned long)pxacecount,
+		(unsigned long)pxacecount/pxcount,pxacecount*100L/pxcount%100L);
+	if (pxacecount != expectcnt[kind]) {
+		printf("** Error : expected ACE count %lu\n",
+			(unsigned long)expectcnt[kind]);
+		errors++;
+	}
+	if (pxglobhash != expecthash[kind]) {
+		printf("** Error : wrong global hash 0x%lx instead of 0x%lx\n",
+			(unsigned long)pxglobhash, (unsigned long)expecthash[kind]);
+		errors++;
+	}
+#endif /* POSIXACLS */
+}
+
+#if POSIXACLS
+
+/*
+ *		Check whether Posix ACL settings are interpreted
+ *	back exactly as set
+ */
+
+void posixtest(int kind, BOOL isdir,
+			const SID *owner, const SID *group)
+{
+	struct POSIX_SECURITY *pxdesc;
+	struct {
+		struct POSIX_SECURITY pxdesc;
+		struct POSIX_ACE aces[10];
+	} desc;
+	int ownobj;
+	int grpobj;
+	int usr;
+	int grp;
+	int wrld;
+	int mask;
+	int mindes, maxdes;
+	int minmsk, maxmsk;
+	char *pxattr;
+	u32 count;
+	u32 acecount;
+	u32 globhash;
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	const ACL *pacl;
+	struct POSIX_SECURITY *gotback;
+	enum { ERRNO,
+		ERRMA, ERRPA, /* error converting mode or Posix ACL to NTFS */
+		ERRAM, ERRAP, /* error converting NTFS to mode or Posix ACL */
+	} err;
+	u32 expectcnt[] = {
+#ifdef STSC
+		32400, 34992,
+		25920, 28512,
+		25920, 28512,
+		25920, 28512,
+		26460, 29052,
+		0, 0,
+		0, 0,
+		0, 0,
+		24516, 27108,
+		20736, 23328,
+		20736, 23328,
+		20736, 23328,
+		21060, 23652,
+#else
+		252720, 273456,
+		199584, 220320,
+		199584, 220320,
+		199584, 220320,
+		203904, 224640,
+		0, 0,
+		0, 0,
+		0, 0,
+		196452, 217188,
+		165888, 186624,
+		165888, 186624,
+		165888, 186624,
+		168480, 189216,
+#endif
+		0, 0,
+		0, 0,
+		0, 0,
+		16368, 18672,
+		0, 0,
+		13824, 0,
+		0, 0,
+		14640, 0
+	} ;
+	u32 expecthash[] = {
+#ifdef STSC
+		0xf9f82115, 0x40666647,
+		0xde826d30, 0xa181b660,
+		0x952d4500, 0x8ac49450,
+		0xf80acee0, 0xbd9ec6c0,
+		0xfe09b868, 0xde24e84d,
+		0, 0,
+		0, 0,
+		0, 0,
+		0x2381438d, 0x3ab42dc6,
+		0x7cccf6f8, 0x108ad430,
+		0x5e448840, 0x83ab6c40,
+		0x9b037100, 0x8f7c3b40,
+		0x04a359dc, 0xa4619609,
+#else
+		0x1808a6cd, 0xd82f7c60,
+		0x5ad29e85, 0x518c7620,
+		0x188ce270, 0x7e44e590,
+		0x48a64800, 0x5bdf0030,
+		0x1c64aec6, 0x8b0168fa,
+		0, 0,
+		0, 0,
+		0, 0,
+		0x169fb80e, 0x382d9a59,
+		0xf9c28164, 0x1855d352,
+		0xf9685700, 0x44d16700,
+		0x587ebe90, 0xf7c51480,
+		0x2cb1b518, 0x52408df6,
+#endif
+		0, 0,
+		0, 0,
+		0, 0,
+		0x905f2e38, 0xd40c22f0,
+		0, 0,
+		0xdd76da00, 0,
+		0, 0,
+		0x718e34a0, 0
+	};
+
+	count = 0;
+	acecount = 0;
+	globhash = 0;
+				/* fill headers */
+	pxdesc = &desc.pxdesc;
+	pxdesc->mode = 0;
+	pxdesc->defcnt = 0;
+	if (kind & 32) {
+		pxdesc->acccnt = 4;
+		pxdesc->firstdef = 4;
+		pxdesc->tagsset = 0x35;
+	} else {
+		pxdesc->acccnt = 6;;
+		pxdesc->firstdef = 6;
+		pxdesc->tagsset = 0x3f;
+	}
+	pxdesc->acl.version = POSIX_VERSION;
+	pxdesc->acl.flags = 0;
+	pxdesc->acl.filler = 0;
+				/* prefill aces */
+	pxdesc->acl.ace[0].tag = POSIX_ACL_USER_OBJ;
+	pxdesc->acl.ace[0].id = -1;
+	if (kind & 32) {
+		pxdesc->acl.ace[1].tag = POSIX_ACL_GROUP_OBJ;
+		pxdesc->acl.ace[1].id = -1;
+		pxdesc->acl.ace[2].tag = POSIX_ACL_MASK;
+		pxdesc->acl.ace[2].id = -1;
+		pxdesc->acl.ace[3].tag = POSIX_ACL_OTHER;
+		pxdesc->acl.ace[3].id = -1;
+	} else {
+		pxdesc->acl.ace[1].tag = POSIX_ACL_USER;
+		pxdesc->acl.ace[1].id = (kind & 16 ? 0 : 1000);
+		pxdesc->acl.ace[2].tag = POSIX_ACL_GROUP_OBJ;
+		pxdesc->acl.ace[2].id = -1;
+		pxdesc->acl.ace[3].tag = POSIX_ACL_GROUP;
+		pxdesc->acl.ace[3].id = (kind & 16 ? 0 : 1002);
+		pxdesc->acl.ace[4].tag = POSIX_ACL_MASK;
+		pxdesc->acl.ace[4].id = -1;
+		pxdesc->acl.ace[5].tag = POSIX_ACL_OTHER;
+		pxdesc->acl.ace[5].id = -1;
+	}
+
+	mindes = 3;
+	maxdes = (kind & 32 ? mindes : 6);
+#ifdef STSC
+	minmsk = (kind & 32 ? 0 : 3);
+	maxmsk = (kind & 32 ? 7 : 3);
+#else
+	minmsk = 0;
+	maxmsk = 7;
+#endif
+	for (mask=minmsk; mask<=maxmsk; mask++)
+	for (ownobj=1; ownobj<7; ownobj++)
+	for (grpobj=1; grpobj<7; grpobj++)
+	for (wrld=0; wrld<8; wrld++)
+	for (usr=mindes; usr<=maxdes; usr++)
+	if (usr != 4)
+	for (grp=mindes; grp<=maxdes; grp++)
+	if (grp != 4) {
+		pxdesc->mode = (ownobj << 6) | (mask << 3) | wrld;
+
+		pxdesc->acl.ace[0].perms = ownobj;
+		if (kind & 32) {
+			pxdesc->acl.ace[1].perms = grpobj;
+			pxdesc->acl.ace[2].perms = mask;
+			pxdesc->acl.ace[3].perms = wrld;
+		} else {
+			pxdesc->acl.ace[1].perms = usr;
+			pxdesc->acl.ace[2].perms = grpobj;
+			pxdesc->acl.ace[3].perms = grp;
+			pxdesc->acl.ace[4].perms = mask;
+			pxdesc->acl.ace[5].perms = wrld;
+		}
+
+		err = ERRNO;
+		gotback = (struct POSIX_SECURITY*)NULL;
+		pxattr = ntfs_build_descr_posix(context.mapping,
+				pxdesc,isdir,owner,group);
+		if (pxattr && ntfs_valid_descr(pxattr, ntfs_attr_size(pxattr))) {
+			phead = (const SECURITY_DESCRIPTOR_RELATIVE*)pxattr;
+			pacl = (const ACL*)&pxattr[le32_to_cpu(phead->dacl)];
+			acecount += le16_to_cpu(pacl->ace_count);
+			globhash += hash((const le32*)pxattr,ntfs_attr_size(pxattr));
+			count++;
+			gotback = linux_permissions_posix(pxattr, isdir);
+			if (gotback) {
+				if (ntfs_valid_posix(gotback)) {
+					if (!same_posix(pxdesc,gotback)) {
+						printf("Non matching got back Posix ACL\n");
+						printf("input ACL\n");
+						showposix(pxdesc);
+						printf("NTFS owner\n");
+						showusid(pxattr,4);
+						printf("NTFS group\n");
+						showgsid(pxattr,4);
+						printf("NTFS DACL\n");
+						showdacl(pxattr,isdir,4);
+						printf("gotback ACL\n");
+						showposix(gotback);
+						errors++;
+exit(1);
+					}
+				} else {
+					printf("Got back an invalid Posix ACL\n");
+					errors++;
+				}
+				free(gotback);
+			} else {
+				printf("Could not get Posix ACL back\n");
+				errors++;
+			}
+
+		} else {
+			printf("NTFS ACL incorrect or not build\n");
+			printf("input ACL\n");
+			showposix(pxdesc);
+			printf("NTFS DACL\n");
+			if (pxattr)
+				showdacl(pxattr,isdir,4);
+			else
+				printf("   (none)\n");
+			if (gotback) {
+				printf("gotback ACL\n");
+				showposix(gotback);
+			} else
+				printf("no gotback ACL\n");
+			errors++;
+		}
+		if (pxattr)
+			free(pxattr);
+	}
+	printf("%lu ACLs built from Posix ACLs, %lu ACE built, mean count %lu.%02lu\n",
+		(unsigned long)count,(unsigned long)acecount,
+		(unsigned long)acecount/count,acecount*100L/count%100L);
+	if (acecount != expectcnt[kind]) {
+		printf("** Error ! expected ACE count %lu\n",
+			(unsigned long)expectcnt[kind]);
+		errors++;
+	}
+	if (globhash != expecthash[kind]) {
+		printf("** Error : wrong global hash 0x%lx instead of 0x%lx\n",
+			(unsigned long)globhash, (unsigned long)expecthash[kind]);
+		errors++;
+	}
+}
+
+#endif /* POSIXACLS */
+
+void selftests(void)
+{
+	le32 owner_sid[] = /* S-1-5-21-3141592653-589793238-462843383-1016 */
+		{
+		cpu_to_le32(0x501), cpu_to_le32(0x05000000), cpu_to_le32(21),
+		cpu_to_le32(DEFSECAUTH1), cpu_to_le32(DEFSECAUTH2),
+		cpu_to_le32(DEFSECAUTH3), cpu_to_le32(1016)
+		} ;
+	le32 group_sid[] = /* S-1-5-21-3141592653-589793238-462843383-513 */
+		{
+		cpu_to_le32(0x501), cpu_to_le32(0x05000000), cpu_to_le32(21),
+		cpu_to_le32(DEFSECAUTH1), cpu_to_le32(DEFSECAUTH2),
+		cpu_to_le32(DEFSECAUTH3), cpu_to_le32(513)
+		} ;
+#if POSIXACLS
+#ifdef STSC
+	unsigned char kindlist[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+			   16, 17, 18, 20, 22, 24,
+			   32, 33, 36, 40 } ;
+#else
+	unsigned char kindlist[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+			   16, 17, 18, 20, 22, 24, 19, 21, 23, 25,
+			   32, 33, 36, 40 } ;
+#endif
+	unsigned int k;
+#endif /* POSIXACLS */
+	int kind;
+	const SID *owner;
+	const SID *group;
+	BOOL isdir;
+
+#if POSIXACLS
+	local_build_mapping(context.mapping, (const char*)NULL);
+#endif
+			/* first check samples */
+	mappingtype = MAPDUMMY;
+	check_samples();
+if (errors) exit(1);
+		/*
+		 * kind is oring of :
+		 *   1 : directory
+		 *   2 : owner is root
+		 *   4 : group is root
+		 *   8 : group is owner
+		 *  16 : root is designated user/group
+		 *  32 : mask present with no designated user/group
+		 */
+	for (kind=0; (kind<10) && (errors<10); kind++) {
+		isdir = kind & 1;
+		if (kind & 8)
+			owner = (const SID*)group_sid;
+		else
+			owner = (kind & 2 ? adminsid : (const SID*)owner_sid);
+		group = (kind & 4 ? adminsid : (const SID*)group_sid);
+		basictest(kind, isdir, owner, group);
+	}
+#if POSIXACLS
+	for (k=0; (k<sizeof(kindlist)) && (errors<10); k++) {
+		kind = kindlist[k];
+		isdir = kind & 1;
+		if (kind & 8)
+			owner = (const SID*)group_sid;
+		else
+			owner = (kind & 2 ? adminsid : (const SID*)owner_sid);
+		group = (kind & 4 ? adminsid : (const SID*)group_sid);
+		posixtest(kind, isdir, owner, group);
+	}
+	ntfs_free_mapping(context.mapping);
+#endif
+	if (errors >= 10)
+		printf("** too many errors, test aborted\n");
+}
+#endif /* SELFTESTS & !USESTUBS */
+
+#ifdef WIN32
+
+/*
+ *		   Get the security descriptor of a file (Windows version)
+ */
+
+unsigned int getfull(char *attr, const char *fullname)
+{
+	static char part[MAXATTRSZ];
+	BIGSID ownsid;
+	int xowner;
+	int ownersz;
+	u16 ownerfl;
+	ULONG attrsz;
+	ULONG partsz;
+	BOOL overflow;
+	HANDLE htoken;
+	TOKEN_PRIVILEGES tkp;
+	BOOL saclsuccess;
+
+	attrsz = 0;
+	partsz = 0;
+	overflow = FALSE;
+	if (GetFileSecurityW((LPCWSTR)fullname,OWNER_SECURITY_INFORMATION,
+				(char*)part,MAXATTRSZ,&partsz)) {
+		xowner = get4l(part,4);
+		if (xowner) {
+			ownerfl = get2l(part,2);
+			ownersz = ntfs_sid_size((SID*)&part[xowner]);
+			if (ownersz <= (int)sizeof(BIGSID))
+				memcpy(ownsid,&part[xowner],ownersz);
+			else
+				overflow = TRUE;
+		} else {
+			ownerfl = 0;
+			ownersz = 0;
+		}
+			/*
+			 *  SACL : just feed in or clean
+			 *  This requires the SE_SECURITY_NAME privilege
+			 */
+		saclsuccess = FALSE;
+		if (OpenProcessToken(GetCurrentProcess(), 
+				TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &htoken)) {
+			if (LookupPrivilegeValue(NULL, SE_SECURITY_NAME,
+					&tkp.Privileges[0].Luid)) {
+				tkp.PrivilegeCount = 1;
+				tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+				if (AdjustTokenPrivileges(htoken, FALSE, &tkp, 0, NULL, 0)) {
+					if (GetFileSecurityW((LPCWSTR)fullname,
+							SACL_SECURITY_INFORMATION,
+							(char*)attr,MAXATTRSZ,&attrsz)) {
+						saclsuccess = TRUE;
+					}
+					tkp.Privileges[0].Attributes = 0;
+					AdjustTokenPrivileges(htoken, FALSE, &tkp, 0, NULL, 0);
+				}
+			}
+		}		
+		if (!saclsuccess) {
+			attrsz = 20;
+			set4l(attr,0);
+			attr[0] = SECURITY_DESCRIPTOR_REVISION;
+			set4l(&attr[12],0);
+			if (opt_v >= 2)
+				printf("   No SACL\n");
+		}
+			/*
+			 *  append DACL and merge its flags
+			 */
+		partsz = 0;
+		set4l(&attr[16],0);
+		if (GetFileSecurityW((LPCWSTR)fullname,DACL_SECURITY_INFORMATION,
+			    (char*)part,MAXATTRSZ,&partsz)) {
+			if ((attrsz + partsz - 20) <= MAXATTRSZ) {
+				memcpy(&attr[attrsz],&part[20],partsz-20);
+				set4l(&attr[16],(partsz > 20 ? attrsz : 0));
+				set2l(&attr[2],get2l(attr,2) | (get2l(part,2)
+					& const_le16_to_cpu(SE_DACL_PROTECTED
+						   | SE_DACL_AUTO_INHERITED
+						   | SE_DACL_PRESENT)));
+				attrsz += partsz - 20;
+			} else
+				overflow = TRUE;
+		} else
+			if (partsz > MAXATTRSZ)
+				overflow = TRUE;
+			else {
+				if (opt_b)
+					printf("#   No discretionary access control list\n");
+				else
+					printf("   No discretionary access control list\n");
+				warnings++;
+			}
+
+			/*
+			 *  append owner and merge its flag
+			 */
+		if (xowner && !overflow) {
+			memcpy(&attr[attrsz],ownsid,ownersz);
+			set4l(&attr[4],attrsz);
+			set2l(&attr[2],get2l(attr,2)
+			   | (ownerfl & const_le16_to_cpu(SE_OWNER_DEFAULTED)));
+			attrsz += ownersz;
+		} else
+			set4l(&attr[4],0);
+			/*
+			 * append group
+			 */
+		partsz = 0;
+		set4l(&attr[8],0);
+		if (GetFileSecurityW((LPCWSTR)fullname,GROUP_SECURITY_INFORMATION,
+			    (char*)part,MAXATTRSZ,&partsz)) {
+			if ((attrsz + partsz - 20) <= MAXATTRSZ) {
+				memcpy(&attr[attrsz],&part[20],partsz-20);
+				set4l(&attr[8],(partsz > 20 ? attrsz : 0));
+				set2l(&attr[2],get2l(attr,2) | (get2l(part,2)
+					& const_le16_to_cpu(SE_GROUP_DEFAULTED)));
+				attrsz += partsz - 20;
+			} else
+				overflow = TRUE;
+		} else
+			if (partsz > MAXATTRSZ)
+				overflow = TRUE;
+			else {
+				printf("**   No group SID\n");
+				warnings++;
+			}
+		set2l(&attr[2],get2l(attr,2)
+					| const_le16_to_cpu(SE_SELF_RELATIVE));
+		if (overflow) {
+			printf("** Descriptor was too long (> %d)\n",MAXATTRSZ);
+			warnings++;
+			attrsz = 0;
+		} else
+			if (!ntfs_valid_descr((char*)attr,attrsz)) {
+				printf("** Descriptor for ");
+				printname(stdout,fullname);
+				printf(" is not valid\n");
+				errors++;
+				attrsz = 0;
+			}
+
+	} else {
+		printf("** Could not get owner of ");
+		printname(stdout,fullname);
+		printf(", partsz %d\n",partsz);
+		printerror(stdout);
+		warnings++;
+		attrsz = 0;		
+	}
+	return (attrsz);
+}
+
+/*
+ *		Update a security descriptor (Windows version)
+ */
+
+BOOL updatefull(const char *name, DWORD flags, char *attr)
+{
+	BOOL bad;
+
+	bad = !SetFileSecurityW((LPCWSTR)name, flags, attr);
+	if (bad
+	  && (flags & OWNER_SECURITY_INFORMATION)
+	  && (GetLastError() == 1307)) {
+		printf("** Could not set owner of ");
+		printname(stdout,name);
+		printf(", retrying with no owner setting\n");
+		warnings++;
+		bad = !SetFileSecurityW((LPCWSTR)name,
+			flags & ~OWNER_SECURITY_INFORMATION, (char*)attr);
+	}
+	if (bad) {
+		printf("** Could not change attributes of ");
+		printname(stdout,name);
+		printf("\n");
+		printerror(stdout);
+		errors++;
+	}
+	return (!bad);
+}
+
+#else
+
+/*
+ *		   Get the security descriptor of a file (Linux version)
+ */
+
+unsigned int getfull(char *attr, const char *fullname)
+{
+	static char part[MAXATTRSZ];
+	BIGSID ownsid;
+	int xowner;
+	int ownersz;
+	u16 ownerfl;
+	u32 attrsz;
+	u32 partsz;
+	BOOL overflow;
+
+	attrsz = 0;
+	partsz = 0;
+	overflow = FALSE;
+	if (ntfs_get_file_security(ntfs_context,fullname,
+				OWNER_SECURITY_INFORMATION,
+				(char*)part,MAXATTRSZ,&partsz)) {
+		xowner = get4l(part,4);
+		if (xowner) {
+			ownerfl = get2l(part,2);
+			ownersz = ntfs_sid_size((SID*)&part[xowner]);
+			if (ownersz <= (int)sizeof(BIGSID))
+				memcpy(ownsid,&part[xowner],ownersz);
+			else
+				overflow = TRUE;
+		} else {
+			ownerfl = 0;
+			ownersz = 0;
+		}
+			/*
+			 *  SACL : just feed in or clean
+			 */
+		if (!ntfs_get_file_security(ntfs_context,fullname,
+				SACL_SECURITY_INFORMATION,
+				(char*)attr,MAXATTRSZ,&attrsz)) {
+			attrsz = 20;
+			set4l(attr,0);
+			attr[0] = SECURITY_DESCRIPTOR_REVISION;
+			set4l(&attr[12],0);
+			if (opt_v >= 2)
+				printf("   No SACL\n");
+		}
+			/*
+			 *  append DACL and merge its flags
+			 */
+		partsz = 0;
+		set4l(&attr[16],0);
+		if (ntfs_get_file_security(ntfs_context,fullname,
+		    DACL_SECURITY_INFORMATION,
+		    (char*)part,MAXATTRSZ,&partsz)) {
+			if ((attrsz + partsz - 20) <= MAXATTRSZ) {
+				memcpy(&attr[attrsz],&part[20],partsz-20);
+				set4l(&attr[16],(partsz > 20 ? attrsz : 0));
+				set2l(&attr[2],get2l(attr,2) | (get2l(part,2)
+					& const_le16_to_cpu(SE_DACL_PROTECTED
+						   | SE_DACL_AUTO_INHERITED
+						   | SE_DACL_PRESENT)));
+				attrsz += partsz - 20;
+			} else
+				overflow = TRUE;
+		} else
+			if (partsz > MAXATTRSZ)
+				overflow = TRUE;
+			else {
+				if (opt_b)
+					printf("#   No discretionary access control list\n");
+				else
+					printf("   No discretionary access control list\n");
+				warnings++;
+			}
+
+			/*
+			 *  append owner and merge its flag
+			 */
+		if (xowner && !overflow) {
+			memcpy(&attr[attrsz],ownsid,ownersz);
+			set4l(&attr[4],attrsz);
+			set2l(&attr[2],get2l(attr,2)
+			   | (ownerfl & const_le16_to_cpu(SE_OWNER_DEFAULTED)));
+			attrsz += ownersz;
+		} else
+			set4l(&attr[4],0);
+			/*
+			 * append group
+			 */
+		partsz = 0;
+		set4l(&attr[8],0);
+		if (ntfs_get_file_security(ntfs_context,fullname,
+		    GROUP_SECURITY_INFORMATION,
+		    (char*)part,MAXATTRSZ,&partsz)) {
+			if ((attrsz + partsz - 20) <= MAXATTRSZ) {
+				memcpy(&attr[attrsz],&part[20],partsz-20);
+				set4l(&attr[8],(partsz > 20 ? attrsz : 0));
+				set2l(&attr[2],get2l(attr,2) | (get2l(part,2)
+					& const_le16_to_cpu(SE_GROUP_DEFAULTED)));
+				attrsz += partsz - 20;
+			} else
+				overflow = TRUE;
+		} else
+			if (partsz > MAXATTRSZ)
+				overflow = TRUE;
+			else {
+				printf("**   No group SID\n");
+				warnings++;
+			}
+		if (overflow) {
+			printf("** Descriptor was too long (> %d)\n",MAXATTRSZ);
+			warnings++;
+			attrsz = 0;
+		} else
+			if (!ntfs_valid_descr((char*)attr,attrsz)) {
+				printf("** Descriptor for %s is not valid\n",fullname);
+				errors++;
+				attrsz = 0;
+			}
+
+	} else {
+		printf("** Could not get owner of %s\n",fullname);
+		warnings++;
+		attrsz = 0;		
+	}
+	return (attrsz);
+}
+
+/*
+ *		Update a security descriptor (Linux version)
+ */
+
+BOOL updatefull(const char *name, DWORD flags, char *attr)
+{
+	BOOL ok;
+
+	ok = !ntfs_set_file_security(ntfs_context, name, flags, attr);
+	if (ok) {
+		printf("** Could not change attributes of %s\n",name);
+		printerror(stdout);
+		errors++;
+	}
+	return (ok);
+}
+
+
+#endif
+
+#if POSIXACLS
+
+/*
+ *		   Set all the parameters associated to a file
+ */
+
+BOOL setfull_posix(const char *fullname, const struct POSIX_SECURITY *pxdesc,
+			BOOL isdir)
+{
+	static char attr[MAXATTRSZ];
+	struct POSIX_SECURITY *oldpxdesc;
+	struct POSIX_SECURITY *newpxdesc;
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	char *newattr;
+	int err;
+	unsigned int attrsz;
+	int newattrsz;
+	const SID *usid;
+	const SID *gsid;
+#if OWNERFROMACL
+	const SID *osid;
+#endif
+
+	printf("%s ",(isdir ? "Directory" : "File"));
+	printname(stdout,fullname);
+	if (pxdesc->acccnt)
+		printf("\n");
+	else
+		printf(" mode 0%03o\n",pxdesc->mode);
+
+	err = FALSE;
+	attrsz = getfull(attr, fullname);
+	if (attrsz) {
+		oldpxdesc = linux_permissions_posix(attr, isdir);
+		if (opt_v >= 2) {
+			printf("Posix equivalent of old ACL :\n");
+			showposix(oldpxdesc);
+		}
+		if (oldpxdesc) {
+			if (!pxdesc->defcnt
+			   && !(pxdesc->tagsset &
+			     (POSIX_ACL_USER | POSIX_ACL_GROUP | POSIX_ACL_MASK))) {
+				if (!ntfs_merge_mode_posix(oldpxdesc,pxdesc->mode))
+					newpxdesc = oldpxdesc;
+				else {
+					newpxdesc = (struct POSIX_SECURITY*)NULL;
+					free(oldpxdesc);
+				}
+			} else {
+				newpxdesc = ntfs_merge_descr_posix(pxdesc, oldpxdesc);
+				free(oldpxdesc);
+			}
+			if (opt_v) {
+				printf("New Posix ACL :\n");
+				showposix(newpxdesc);
+			}
+		} else
+			newpxdesc = (struct POSIX_SECURITY*)NULL;
+		if (newpxdesc) {
+			phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr;
+			gsid = (const SID*)&attr[le32_to_cpu(phead->group)];
+#if OWNERFROMACL
+			osid = (const SID*)&attr[le32_to_cpu(phead->owner)];
+			usid = ntfs_acl_owner((const char*)attr);
+			if (!ntfs_same_sid(usid,osid))
+				printf("== Windows owner might change\n"); 
+#else
+			usid = (const SID*)&attr[le32_to_cpu(phead->owner)];
+#endif
+			newattr = ntfs_build_descr_posix(context.mapping,
+				newpxdesc,isdir,usid,gsid);
+			free(newpxdesc);
+		} else
+			newattr = (char*)NULL;
+		if (newattr) {
+			newattrsz = ntfs_attr_size(newattr);
+			if (opt_v) {
+				printf("New NTFS security descriptor\n");
+				hexdump(newattr,newattrsz,4);
+			}
+			if (opt_v >= 2) {
+				printf("Expected hash : 0x%08lx\n",
+					(unsigned long)hash((le32*)newattr,ntfs_attr_size(newattr)));
+				showheader(newattr,0);
+				showusid(newattr,0);
+				showgsid(newattr,0);
+				showdacl(newattr,isdir,0);
+				showsacl(newattr,isdir,0);
+			}
+
+#ifdef WIN32
+			/*
+			 * avoid getting a set owner error on Windows
+			 * owner should not be changed anyway
+			 */
+			if (!updatefull(fullname,
+				DACL_SECURITY_INFORMATION
+				| GROUP_SECURITY_INFORMATION
+				| OWNER_SECURITY_INFORMATION,
+					newattr))
+#else
+			if (!updatefull(fullname,
+				DACL_SECURITY_INFORMATION
+				| GROUP_SECURITY_INFORMATION
+				| OWNER_SECURITY_INFORMATION,
+					newattr))
+#endif
+				err = TRUE;
+/*
+{
+struct POSIX_SECURITY *interp;
+printf("Reinterpreted new Posix :\n");
+interp = linux_permissions_posix(newattr,isdir);
+showposix(interp);
+free(interp);
+}
+*/
+			free(newattr);
+		} else
+			err = TRUE;
+	} else
+		err = TRUE;
+	return (!err);
+}
+
+#endif
+
+BOOL setfull(const char *fullname, int mode, BOOL isdir)
+{
+	static char attr[MAXATTRSZ];
+	const SECURITY_DESCRIPTOR_RELATIVE *phead;
+	char *newattr;
+	int err;
+	unsigned int attrsz;
+	int newattrsz;
+	const SID *usid;
+	const SID *gsid;
+#if OWNERFROMACL
+	const SID *osid;
+#endif
+
+	printf("%s ",(isdir ? "Directory" : "File"));
+	printname(stdout,fullname);
+	printf(" mode 0%03o\n",mode);
+	attrsz = getfull(attr, fullname);
+	err = FALSE;
+	if (attrsz) {
+		phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr;
+		gsid = (const SID*)&attr[le32_to_cpu(phead->group)];
+#if OWNERFROMACL
+		osid = (const SID*)&attr[le32_to_cpu(phead->owner)];
+		usid = ntfs_acl_owner((const char*)attr);
+		if (!ntfs_same_sid(usid,osid))
+			printf("== Windows owner might change\n"); 
+#else
+		usid = (const SID*)&attr[le32_to_cpu(phead->owner)];
+#endif
+		newattr = ntfs_build_descr(mode,isdir,usid,gsid);
+		if (newattr) {
+			newattrsz = ntfs_attr_size(newattr);
+			if (opt_v) {
+				printf("Security descriptor\n");
+				hexdump(newattr,newattrsz,4);
+			}
+			if (opt_v >= 2) {
+				printf("Expected hash : 0x%08lx\n",
+					(unsigned long)hash((le32*)newattr,ntfs_attr_size(newattr)));
+				showheader(newattr,0);
+				showusid(newattr,0);
+				showgsid(newattr,0);
+				showdacl(newattr,isdir,0);
+				showsacl(newattr,isdir,0);
+			}
+
+#ifdef WIN32
+			/*
+			 * avoid getting a set owner error on Windows
+			 * owner should not be changed anyway
+			 */
+			if (!updatefull(fullname,
+				DACL_SECURITY_INFORMATION
+				| GROUP_SECURITY_INFORMATION
+				| OWNER_SECURITY_INFORMATION,
+					newattr))
+#else
+			if (!updatefull(fullname,
+				DACL_SECURITY_INFORMATION
+				| GROUP_SECURITY_INFORMATION
+				| OWNER_SECURITY_INFORMATION,
+					newattr))
+#endif
+				err = TRUE;
+			free(newattr);
+		}
+		
+	} else
+		err = TRUE;
+	return (err);
+}
+
+BOOL proposal(const char *name, const char *attr)
+{
+	char fullname[MAXFILENAME];
+	int uoff, goff;
+	int i;
+	u64 uauth, gauth;
+	int ucnt, gcnt;
+	int uid, gid;
+	BOOL err;
+#ifdef WIN32
+	char driveletter;
+#else
+	struct stat st;
+	char *p,*q;
+#endif
+
+	err = FALSE;
+#ifdef WIN32
+	uid = gid = 0;
+#else
+	uid = getuid();
+	gid = getgid();
+#endif
+	uoff = get4l(attr,4);
+	uauth = get6h(attr,uoff+2);
+	ucnt = attr[uoff+1] & 255;
+	goff = get4l(attr,8);
+	gauth = get6h(attr,goff+2);
+	gcnt = attr[goff+1] & 255;
+
+	if ((ucnt == 5) && (gcnt == 5)
+	    && (uauth == 5) && (gauth == 5)
+	    && (get4l(attr,uoff+8) == 21) && (get4l(attr,goff+8) == 21)) {
+		printf("# User mapping proposal :\n");
+		printf("# -------------------- cut here -------------------\n");
+		if (uid)
+			printf("%d::",uid);
+		else
+			printf("user::");
+		printf("S-%d-%llu",attr[uoff] & 255,uauth);
+		for (i=0; i<ucnt; i++)
+			printf("-%lu",get4l(attr,uoff+8+4*i));
+		printf("\n");
+		if (gid)
+			printf(":%d:",gid);
+		else
+			printf(":group:");
+		printf("S-%d-%llu",attr[goff] & 255,gauth);
+		for (i=0; i<gcnt; i++)
+			printf("-%lu",get4l(attr,goff+8+4*i));
+		printf("\n");
+			/* generic rule, based on group */
+		printf("::S-%d-%llu",attr[goff] & 255,gauth);
+		for (i=0; i<gcnt-1; i++)
+			printf("-%lu",get4l(attr,goff+8+4*i));
+		printf("-10000\n");
+		printf("# -------------------- cut here -------------------\n");
+		if (!uid || !gid) {
+			printf("# Please replace \"user\" and \"group\" above by the uid\n");
+			printf("# and gid of the Linux owner and group of ");
+			printname(stdout,name);
+			printf(", then\n");
+			printf("# insert the modified lines into .NTFS-3G/Usermapping, with .NTFS-3G\n");
+		} else
+			printf("# Insert the above lines into .NTFS-3G/Usermapping, with .NTFS-3G\n");
+#ifdef WIN32
+		printf("# being a directory of the root of the NTFS file system.\n");
+
+		/* Get the drive letter to the file system */
+		driveletter = 0;
+		if ((((name[0] >= 'a') && (name[0] <= 'z'))
+			|| ((name[0] >= 'A') && (name[0] <= 'Z')))
+		    && (name[1] == ':'))
+			driveletter = name[0];
+		else {
+			if (GetCurrentDirectoryA(MAXFILENAME, fullname)
+					&& (fullname[1] == ':'))
+				driveletter = fullname[0];
+		}
+		if (driveletter) {
+			printf("# Example : %c:\\.NTFS-3G\\UserMapping\n",
+				driveletter);
+		}
+#else
+		printf("# being a hidden subdirectory of the root of the NTFS file system.\n");
+
+		/* Get the path to the root of the file system */
+		if (name[0] != '/') {
+			p = getcwd(fullname,MAXFILENAME);
+			if (p) {
+				strcat(fullname,"/");
+				strcat(fullname,name);
+			}
+		} else {
+			strcpy(fullname,name);
+			p = fullname;
+		}
+		if (p) {
+			/* go down the path to inode 5 (fails on symlinks) */
+			do {
+				lstat(fullname,&st);
+				q = strrchr(p,'/');
+				if (q && (st.st_ino != 5))
+					*q = 0;
+			} while (strchr(p,'/') && (st.st_ino != 5));
+		}
+		if (p && (st.st_ino == 5)) {
+			printf("# Example : ");
+			printname(stdout,p);
+			printf("/.NTFS-3G/UserMapping\n");
+		}
+#endif
+	} else {
+		printf("** Not possible : ");
+		printname(stdout,name);
+		printf(" was not created by a Windows user\n");
+		err = TRUE;
+	}
+	return (err);
+}
+
+#ifdef WIN32
+
+/*
+ *		Check whether a directory with reparse data is a junction
+ *	or a symbolic link
+ */
+
+BOOL islink(const char *filename)
+{
+	WIN32_FIND_DATAW found;
+	HANDLE search;
+	BOOL link;
+
+	link = FALSE;
+	search = FindFirstFileW((LPCWSTR)filename, &found);
+	if (search != INVALID_HANDLE_VALUE) {
+		link = (found.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT)
+		   || (found.dwReserved0 == IO_REPARSE_TAG_SYMLINK);
+		FindClose(search);
+	}
+	return (link);
+}
+
+#if POSIXACLS
+BOOL iterate(RECURSE call, const char *fullname, const struct POSIX_SECURITY *pxdesc)
+#else
+BOOL iterate(RECURSE call, const char *fullname, mode_t mode)
+#endif
+{
+	WIN32_FIND_DATAW found;
+	HANDLE search;
+	BOOL err;
+	unsigned int len;
+	char *filter;
+	char *inner;
+
+	err = FALSE;
+	filter = (char*)malloc(MAXFILENAME);
+	inner = (char*)malloc(MAXFILENAME);
+	if (filter && inner) {
+		len = utf16len(fullname);
+		memcpy(filter, fullname, 2*len);
+		makeutf16(&filter[2*len],"\\*.*");
+		search = FindFirstFileW((LPCWSTR)filter, &found);
+		if (search != INVALID_HANDLE_VALUE) {
+			do {
+				if (found.cFileName[0] != UNICODE('.')) {
+					memcpy(inner, fullname, 2*len);
+					inner[2*len] = '\\';
+					inner[2*len+1] = 0;
+					memcpy(&inner[2*len+2],found.cFileName,
+						2*utf16len((char*)found.cFileName)+2);
+					if (opt_v)
+						if (opt_b)
+							printf("#\n#\n");
+						else
+							printf("\n\n");
+					switch (call) {
+					case RECSHOW :
+						if (recurseshow(inner))
+							err = TRUE;
+						break;
+#if POSIXACLS
+					case RECSETPOSIX :
+						if (recurseset_posix(inner,pxdesc))
+							err = TRUE;
+						break;
+#else
+					case RECSET :
+						if (recurseset(inner,mode))
+							err = TRUE;
+						break;
+#endif
+					default :
+						err = TRUE;
+					}
+				}
+			} while (FindNextFileW(search, &found));
+			FindClose(search);
+		}
+		free(filter);
+		free(inner);
+	} else {
+		printf("** Cannot process deeper : not enough memory\n");
+		errors++;
+		err = TRUE;
+	}
+	return (err);
+}
+
+
+
+/*
+ *		   Display all the parameters associated to a file (Windows version)
+ */
+
+void showfull(const char *fullname, BOOL isdir)
+{
+	static char attr[MAXATTRSZ];
+#if POSIXACLS
+	struct POSIX_SECURITY *pxdesc;
+#endif
+	ULONG attrsz;
+	int mode;
+	uid_t uid;
+	gid_t gid;
+	int attrib;
+	int level;
+
+	printf("%s ",(isdir ? "Directory" : "File"));
+	printname(stdout,fullname);
+	printf("\n");
+
+       /* get individual parameters, as when trying to get them */
+       /* all, and one (typically SACL) is missing, we get none, */
+       /* and concatenate them, to be able to compute the hash code */
+
+	attrsz = getfull(attr, fullname);
+	if (attrsz) {
+			if (opt_v || opt_b) {
+				hexdump(attr,attrsz,8);
+				printf("Computed hash : 0x%08lx\n",
+					(unsigned long)hash((le32*)attr,attrsz));
+			}
+			if (opt_v && opt_b) {
+				printf("# %s ",(isdir ? "Directory" : "File"));
+				printname(stdout,fullname);
+				printf(" hash 0x%lx\n",
+					(unsigned long)hash((le32*)attr,attrsz));
+			}
+			attrib = GetFileAttributesW((LPCWSTR)fullname);
+			if (attrib == INVALID_FILE_ATTRIBUTES) {
+				printf("** Could not get file attrib\n");
+				errors++;
+			} else
+				printf("Windows attrib : 0x%x\n",attrib);
+			if (ntfs_valid_descr(attr,attrsz)) {
+#if POSIXACLS
+				pxdesc = linux_permissions_posix(attr,isdir);
+				if (pxdesc)
+					mode = pxdesc->mode;
+				else
+					mode = 0;
+#else
+				mode = linux_permissions(attr,isdir);
+#endif
+				if (opt_v >= 2) {
+					level = (opt_b ? 4 : 0);
+					showheader(attr,level);
+					showusid(attr,level);
+					showgsid(attr,level);
+					showdacl(attr,isdir,level);
+					showsacl(attr,isdir,level);
+				}
+				uid = linux_owner(attr);
+				gid = linux_group(attr);
+				if (opt_b) {
+				        showownership(attr);
+					printf("# Interpreted Unix owner %d, group %d, mode 0%03o\n",
+						(int)uid,(int)gid,mode);
+				} else {
+				        showownership(attr);
+					printf("Interpreted Unix owner %d, group %d, mode 0%03o\n",
+						(int)uid,(int)gid,mode);
+				}
+#if POSIXACLS
+				if (pxdesc) {
+					if (!opt_b
+					    && (pxdesc->defcnt
+						|| (pxdesc->tagsset
+						    & (POSIX_ACL_USER
+							| POSIX_ACL_GROUP
+							| POSIX_ACL_MASK))))
+						showposix(pxdesc);
+					free(pxdesc);
+				}
+#endif
+			} else
+				if (opt_b)
+					printf("# Descriptor fails sanity check\n");
+				else
+					printf("Descriptor fails sanity check\n");
+	}
+}
+
+BOOL recurseshow(const char *fullname)
+{
+	int attrib;
+	int err;
+	BOOL isdir;
+
+	err = FALSE;
+	attrib = GetFileAttributesW((LPCWSTR)fullname);
+	if (attrib != INVALID_FILE_ATTRIBUTES) {
+		isdir = (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0;
+		showfull(fullname,isdir);
+		if (isdir
+		   && !((attrib & FILE_ATTRIBUTE_REPARSE_POINT)
+			&& islink(fullname))) {
+#if POSIXACLS
+			err = iterate(RECSHOW, fullname, (struct POSIX_SECURITY*)NULL);
+#else
+			err = iterate(RECSHOW, fullname, 0);
+#endif
+		}
+	} else {
+		printf("** Could not access ");
+		printname(stdout,fullname);
+		printf("\n");
+		printerror(stdout);
+		errors++;
+		err = TRUE;
+	}
+	return (err);
+}
+
+
+BOOL singleshow(const char *fullname)
+{
+	int attrib;
+	int err;
+	BOOL isdir;
+
+	err = FALSE;
+	attrib = GetFileAttributesW((LPCWSTR)fullname);
+	if (attrib != INVALID_FILE_ATTRIBUTES) {
+		isdir = (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0;
+		showfull(fullname,isdir);
+	} else { 
+		printf("** Could not access ");
+		printname(stdout,fullname);
+		printf("\n");
+		printerror(stdout);
+		errors++;
+		err = TRUE;
+	}
+	return (err);
+}
+
+BOOL mapproposal(const char *fullname)
+{
+	char attr[256];
+	ULONG attrsz;
+	int attrib;
+	int err;
+
+	err = FALSE;
+	attrsz = 0;
+	attrib = GetFileAttributesW((LPCWSTR)fullname);
+	if ((attrib != INVALID_FILE_ATTRIBUTES)
+	    && GetFileSecurityW((LPCWSTR)fullname,
+				OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION,
+				(char*)attr,256,&attrsz)) {
+		err = proposal(fullname,attr);
+	} else { 
+		printf("** Could not access ");
+		printname(stdout,fullname);
+		printf("\n");
+		printerror(stdout);
+		err = TRUE;
+	}
+	return (err);
+}
+
+#if POSIXACLS
+
+BOOL recurseset_posix(const char *fullname, const struct POSIX_SECURITY *pxdesc)
+{
+	int attrib;
+	int err;
+	BOOL isdir;
+
+	err = FALSE;
+	attrib = GetFileAttributesW((LPCWSTR)fullname);
+	if (attrib != INVALID_FILE_ATTRIBUTES) {
+		isdir = (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0;
+		err = !setfull_posix(fullname,pxdesc,isdir);
+		if (err) {
+			printf("** Failed to update ");
+			printname(stdout,fullname);
+			printf("\n");
+			errors++;
+		} else
+			if (isdir
+			   && !((attrib & FILE_ATTRIBUTE_REPARSE_POINT)
+				&& islink(fullname)))
+				iterate(RECSETPOSIX, fullname, pxdesc);
+	} else { 
+		err = GetLastError();
+		printf("** Could not access ");
+		printname(stdout,fullname);
+		printf("\n");
+		printerror(stdout);
+		err = TRUE;
+		errors++;
+	}
+	return (err);
+}
+
+#else
+
+BOOL recurseset(const char *fullname, int mode)
+{
+	int attrib;
+	int err;
+	BOOL isdir;
+
+	err = FALSE;
+	attrib = GetFileAttributesW((LPCWSTR)fullname);
+	if (attrib != INVALID_FILE_ATTRIBUTES) {
+		isdir = (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0;
+		setfull(fullname,mode,isdir);
+		if (isdir
+		   && !((attrib & FILE_ATTRIBUTE_REPARSE_POINT)
+			&& islink(fullname)))
+			iterate(RECSETPOSIX, fullname, mode);
+	} else { 
+		err = GetLastError();
+		printf("** Could not access ");
+		printname(stdout,fullname);
+		printf("\n");
+		printerror(stdout);
+		err = TRUE;
+		errors++;
+	}
+	return (err);
+}
+
+#endif
+
+#if POSIXACLS
+
+BOOL singleset_posix(const char *path, const struct POSIX_SECURITY *pxdesc)
+{
+	BOOL isdir;
+	BOOL err;
+	int attrib;
+
+	err = FALSE;
+	attrib = GetFileAttributesW((LPCWSTR)path);
+	if (attrib != INVALID_FILE_ATTRIBUTES) {
+		isdir = (attrib & FILE_ATTRIBUTE_DIRECTORY);
+		err = !setfull_posix(path,pxdesc,isdir);
+		if (err) {
+			printf("** Failed to update ");
+			printname(stdout,path);
+			printf("\n");
+			errors++;
+		}
+	} else {
+		printf("** Could not access ");
+		printname(stdout,path);
+		printf("\n");
+		printerror(stdout);
+		errors++;
+		err = TRUE;
+	}
+	return (!err);
+}
+
+#endif
+
+BOOL singleset(const char *path, int mode)
+{
+	BOOL isdir;
+	BOOL err;
+	int attrib;
+
+	err = FALSE;
+	attrib = GetFileAttributesW((LPCWSTR)path);
+	if (attrib != INVALID_FILE_ATTRIBUTES) {
+		isdir = (attrib & FILE_ATTRIBUTE_DIRECTORY);
+		setfull(path,mode,isdir);
+	} else {
+		printf("** Could not access ");
+		printname(stdout,path);
+		printf("\n");
+		printerror(stdout);
+		errors++;
+		err = TRUE;
+	}
+	return (!err);
+}
+
+#else
+
+/*
+ *		   Display all the parameters associated to a file (Linux version)
+ */
+
+void showfull(const char *fullname, BOOL isdir)
+{
+	static char attr[MAXATTRSZ];
+	static char part[MAXATTRSZ];
+#if POSIXACLS
+	struct POSIX_SECURITY *pxdesc;
+#endif
+	struct SECURITY_DATA *psecurdata;
+	char *newattr;
+	int securindex;
+	int mode;
+	int level;
+	int attrib;
+	u32 attrsz;
+	u32 partsz;
+	uid_t uid;
+	gid_t gid;
+
+	if (opt_v || opt_b)
+		printf("%s %s\n",(isdir ? "Directory" : "File"),fullname);
+
+       /* get individual parameters, as when trying to get them */
+       /* all, and one (typically SACL) is missing, we get none */
+       /* and concatenate them, to be able to compute the checksum */
+
+	partsz = 0;
+	securindex = ntfs_get_file_security(ntfs_context,fullname,
+				OWNER_SECURITY_INFORMATION,
+				(char*)part,MAXATTRSZ,&partsz);
+
+	attrib = ntfs_get_file_attributes(ntfs_context, fullname);
+	if (attrib == INVALID_FILE_ATTRIBUTES) {
+		printf("** Could not get file attrib\n");
+		errors++;
+	}
+	if ((securindex < 0)
+	    || (securindex >= MAXSECURID)
+	    || ((securindex > 0)
+		&& ((!opt_r && !opt_b)
+		   || !securdata[securindex >> SECBLKSZ]
+		   || !securdata[securindex >> SECBLKSZ][securindex & ((1 << SECBLKSZ) - 1)].filecount)))
+		{
+		if (opt_v || opt_b) {
+			if ((securindex < -1) || (securindex >= MAXSECURID))
+				printf("Security key : 0x%x out of range\n",securindex);
+			else
+				if (securindex == -1)
+					printf("Security key : none\n");
+				else
+					printf("Security key : 0x%x\n",securindex);
+		} else {
+			printf("%s %s",(isdir ? "Directory" : "File"),fullname);
+			if ((securindex < -1) || (securindex >= MAXSECURID))
+					printf(" : key 0x%x out of range\n",securindex);
+			else
+				if (securindex == -1)
+					printf(" : no key\n");
+				else
+					printf(" : key 0x%x\n",securindex);
+		}
+
+		attrsz = getfull(attr, fullname);
+		if (attrsz) {
+			psecurdata = (struct SECURITY_DATA*)NULL;
+			if ((securindex < MAXSECURID) && (securindex > 0)) {
+				if (!securdata[securindex >> SECBLKSZ])
+					newblock(securindex);
+				if (securdata[securindex >> SECBLKSZ])
+					psecurdata = &securdata[securindex >> SECBLKSZ]
+					   [securindex & ((1 << SECBLKSZ) - 1)];
+			}
+			if (opt_v && (opt_a || opt_b) && psecurdata) {
+				newattr = (char*)malloc(attrsz);
+				printf("# %s %s hash 0x%lx\n",(isdir ? "Directory" : "File"),
+					fullname,
+					(unsigned long)hash((le32*)attr,attrsz));
+				if (newattr) {
+					memcpy(newattr,attr,attrsz);
+					psecurdata->attr = newattr;
+				}
+			}
+			if ((opt_v || opt_b)
+				&& ((securindex >= MAXSECURID)
+				   || (securindex <= 0)
+				   || !psecurdata
+				   || (!psecurdata->filecount
+					&& !psecurdata->flags))) {
+				hexdump(attr,attrsz,8);
+				printf("Computed hash : 0x%08lx\n",
+					(unsigned long)hash((le32*)attr,attrsz));
+			}
+			if (ntfs_valid_descr((char*)attr,attrsz)) {
+#if POSIXACLS
+				pxdesc = linux_permissions_posix(attr,isdir);
+				if (pxdesc)
+					mode = pxdesc->mode;
+				else
+					mode = 0;
+#else
+				mode = linux_permissions(attr,isdir);
+#endif
+				attrib = ntfs_get_file_attributes(ntfs_context,fullname);
+				if (opt_v >= 2) {
+					level = (opt_b ? 4 : 0);
+					showheader(attr,level);
+					showusid(attr,level);
+					showgsid(attr,level);
+					showdacl(attr,isdir,level);
+					showsacl(attr,isdir,level);
+				}
+				if (attrib != INVALID_FILE_ATTRIBUTES)
+					printf("Windows attrib : 0x%x\n",attrib);
+				uid = linux_owner(attr);
+				gid = linux_group(attr);
+				if (opt_b) {
+				        showownership(attr);
+					printf("# Interpreted Unix owner %d, group %d, mode 0%03o\n",
+						(int)uid,(int)gid,mode);
+				} else {
+				        showownership(attr);
+					printf("Interpreted Unix owner %d, group %d, mode 0%03o\n",
+						(int)uid,(int)gid,mode);
+				}
+#if POSIXACLS
+				if (pxdesc) {
+					if (!opt_b
+					    && (pxdesc->defcnt
+					       || (pxdesc->tagsset
+						   & (POSIX_ACL_USER
+							| POSIX_ACL_GROUP
+							| POSIX_ACL_MASK))))
+						showposix(pxdesc);
+#if USESTUBS
+					stdfree(pxdesc); /* allocated within library */
+#else
+					free(pxdesc);
+#endif
+				}
+#endif
+				if ((opt_r || opt_b) && (securindex < MAXSECURID)
+				    && (securindex > 0) && psecurdata) {
+					psecurdata->filecount++;
+					psecurdata->mode = mode;
+				}
+			} else {
+				printf("** Descriptor fails sanity check\n");
+				errors++;
+			}
+		}
+	} else
+		if (securindex > 0) {
+			if (securdata[securindex >> SECBLKSZ]) {
+				psecurdata = &securdata[securindex >> SECBLKSZ]
+					[securindex & ((1 << SECBLKSZ) - 1)];
+				psecurdata->filecount++;
+				if (opt_b || opt_r) {
+					if (!opt_b && !opt_v)
+						printf("%s %s\n",(isdir ? "Directory" : "File"),fullname);
+					printf("Security key : 0x%x mode %03o (already displayed)\n",
+						securindex,psecurdata->mode);
+					if (attrib != INVALID_FILE_ATTRIBUTES)
+						printf("Windows attrib : 0x%x\n",attrib);
+				} else {
+					printf("%s %s",(isdir ? "Directory" : "File"),fullname);
+					printf(" : key 0x%x\n",securindex);
+				}
+				if ((opt_a || opt_b) && opt_v
+				    && psecurdata && psecurdata->attr) {
+					printf("# %s %s hash 0x%lx\n",(isdir ? "Directory" : "File"),
+						fullname,
+						(unsigned long)hash((le32*)psecurdata->attr,
+							ntfs_attr_size(psecurdata->attr)));
+				}
+			}
+		} else {
+			if (!opt_v && !opt_b)
+				printf("%s %s",(isdir ? "Directory" : "File"),fullname);
+			printf("   (Failed)\n");
+			printf("** Could not get security data of %s, partsz %d\n",
+				fullname,partsz);
+			printerror(stdout);
+			errors++;
+		}
+}
+
+BOOL recurseshow(const char *path)
+{
+	struct CALLBACK dircontext;
+	struct LINK *current;
+	BOOL isdir;
+	BOOL err;
+
+	err = FALSE;
+	dircontext.head = (struct LINK*)NULL;
+	dircontext.dir = path;
+	isdir = ntfs_read_directory(ntfs_context, path,
+			callback, &dircontext);
+	if (isdir) {
+		showfull(path,TRUE);
+		if (opt_v) {
+			if (opt_b)
+				printf("#\n#\n");
+			else
+				printf("\n\n");
+		}
+		while (dircontext.head) {
+			current = dircontext.head;
+			if (recurseshow(current->name)) err = TRUE;
+			dircontext.head = dircontext.head->next;
+			free(current);
+		}
+	} else
+		if (errno == ENOTDIR) {
+			showfull(path,FALSE);
+			if (opt_v) {
+				if (opt_b)
+					printf("#\n#\n");
+				else
+					printf("\n\n");
+			}
+		} else {
+			printf("** Could not access %s\n",path);
+			printerror(stdout);
+			errors++;
+			err = TRUE;
+		}
+	return (!err);
+}
+
+
+BOOL singleshow(const char *path)
+{
+	BOOL isdir;
+	BOOL err;
+
+	err = FALSE;
+	isdir = ntfs_read_directory(ntfs_context, path,
+			callback, (struct CALLBACK*)NULL);
+	if (isdir || (errno == ENOTDIR))
+		showfull(path,isdir);
+	else {
+		printf("** Could not access %s\n",path);
+		printerror(stdout);
+		errors++;
+		err = TRUE;
+	}
+	return (err);
+}
+
+#ifdef HAVE_SETXATTR
+
+static ssize_t ntfs_getxattr(const char *path, const char *name, void *value, size_t size)
+{
+#if defined(__APPLE__) || defined(__DARWIN__)
+    return getxattr(path, name, value, size, 0, 0);
+#else
+    return getxattr(path, name, value, size);
+#endif
+}
+
+/*
+ *		   Display all the parameters associated to a mounted file
+ */
+
+BOOL showmounted(const char *fullname)
+{
+
+	static char attr[MAXATTRSZ];
+	struct stat st;
+#if POSIXACLS
+	struct POSIX_SECURITY *pxdesc;
+#endif
+	BOOL mapped;
+	int attrsz;
+	int mode;
+	uid_t uid;
+	gid_t gid;
+	u32 attrib;
+	int level;
+	BOOL isdir;
+	BOOL err;
+
+	err = FALSE;
+	if (!stat(fullname,&st)) {
+		isdir = S_ISDIR(st.st_mode);
+		printf("%s ",(isdir ? "Directory" : "File"));
+		printname(stdout,fullname);
+		printf("\n");
+
+		attrsz = ntfs_getxattr(fullname,"system.ntfs_acl",attr,MAXATTRSZ);
+		if (attrsz > 0) {
+			if (opt_v) {
+				hexdump(attr,attrsz,8);
+				printf("Computed hash : 0x%08lx\n",
+					(unsigned long)hash((le32*)attr,attrsz));
+			}
+			if (ntfs_getxattr(fullname,"system.ntfs_attrib",&attrib,4) != 4) {
+				printf("** Could not get file attrib\n");
+				errors++;
+			} else
+				printf("Windows attrib : 0x%x\n",(int)attrib);
+			if (ntfs_valid_descr(attr,attrsz)) {
+				mapped = !local_build_mapping(context.mapping,fullname);
+#if POSIXACLS
+				if (mapped) {
+					pxdesc = linux_permissions_posix(attr,isdir);
+					if (pxdesc)
+						mode = pxdesc->mode;
+					else
+						mode = 0;
+				} else {
+					pxdesc = (struct POSIX_SECURITY*)NULL;
+					mode = linux_permissions(attr,isdir);
+					printf("No user mapping : "
+						"cannot display the Posix ACL\n");
+				}
+#else
+				mode = linux_permissions(attr,isdir);
+#endif
+				if (opt_v >= 2) {
+					level = (opt_b ? 4 : 0);
+					showheader(attr,level);
+					showusid(attr,level);
+					showgsid(attr,level);
+					showdacl(attr,isdir,level);
+					showsacl(attr,isdir,level);
+				}
+			        showownership(attr);
+				if (mapped) {
+					uid = linux_owner(attr);
+					gid = linux_group(attr);
+					printf("Interpreted Unix owner %d, group %d, mode 0%03o\n",
+						(int)uid,(int)gid,mode);
+				} else {
+					printf("Interpreted Unix mode 0%03o (owner and group are unmapped)\n",
+						mode);
+				}
+#if POSIXACLS
+				if (pxdesc) {
+					if ((pxdesc->defcnt
+						|| (pxdesc->tagsset
+						    & (POSIX_ACL_USER
+							| POSIX_ACL_GROUP
+							| POSIX_ACL_MASK))))
+						showposix(pxdesc);
+#if USESTUBS
+					stdfree(pxdesc); /* allocated within library */
+#else
+					free(pxdesc);
+#endif
+				}
+				if (mapped)
+					ntfs_free_mapping(context.mapping);
+#endif
+			} else {
+				printf("Descriptor fails sanity check\n");
+				errors++;
+			}
+		} else {
+			printf("** Could not get the NTFS ACL, check whether file is on NTFS\n");
+			errors++;
+		}
+	} else {
+		printf("%s not found\n",fullname);
+		err = TRUE;
+	}
+	return (err);
+}
+
+BOOL processmounted(const char *fullname)
+{
+
+	static char attr[MAXATTRSZ];
+	struct stat st;
+	int attrsz;
+	BOOL err;
+
+	err = FALSE;
+	if (!opt_u)
+		err = showmounted(fullname);
+	else
+	if (!stat(fullname,&st)) {
+		attrsz = ntfs_getxattr(fullname,"system.ntfs_acl",attr,MAXATTRSZ);
+		if (attrsz > 0) {
+			if (opt_v) {
+				hexdump(attr,attrsz,8);
+				printf("Computed hash : 0x%08lx\n",
+					(unsigned long)hash((le32*)attr,attrsz));
+			}
+			if (ntfs_valid_descr(attr,attrsz)) {
+				err = proposal(fullname, attr);
+			} else {
+				printf("*** Descriptor fails sanity check\n");
+				errors++;
+			}
+		} else {
+			printf("** Could not get the NTFS ACL, check whether file is on NTFS\n");
+			errors++;
+		}
+	} else {
+		printf("%s not found\n",fullname);
+		err = TRUE;
+	}
+	return (err);
+}
+
+#else /* HAVE_SETXATTR */
+
+BOOL processmounted(const char *fullname __attribute__((unused)))
+{
+	fprintf(stderr,"Not possible on this configuration,\n");
+	fprintf(stderr,"you have to use an unmounted partition\n");
+	return (TRUE);
+}
+
+#endif /* HAVE_SETXATTR */
+
+#if POSIXACLS
+
+BOOL recurseset_posix(const char *path, const struct POSIX_SECURITY *pxdesc)
+{
+	struct CALLBACK dircontext;
+	struct LINK *current;
+	BOOL isdir;
+	BOOL err;
+
+	err = FALSE;
+	dircontext.head = (struct LINK*)NULL;
+	dircontext.dir = path;
+	isdir = ntfs_read_directory(ntfs_context, path,
+			callback, &dircontext);
+	if (isdir) {
+		err = !setfull_posix(path,pxdesc,TRUE);
+		if (err) {
+			printf("** Failed to update %s\n",path);
+			printerror(stdout);
+			errors++;
+		} else {
+			if (opt_b)
+				printf("#\n#\n");
+			else
+				printf("\n\n");
+			while (dircontext.head) {
+				current = dircontext.head;
+				recurseset_posix(current->name,pxdesc);
+				dircontext.head = dircontext.head->next;
+				free(current);
+			}
+		}
+	} else
+		if (errno == ENOTDIR) {
+			err = !setfull_posix(path,pxdesc,FALSE);
+			if (err) {
+				printf("** Failed to update %s\n",path);
+				printerror(stdout);
+				errors++;
+			}
+		} else {
+			printf("** Could not access %s\n",path);
+			printerror(stdout);
+			errors++;
+			err = TRUE;
+		}
+	return (!err);
+}
+
+#else
+
+BOOL recurseset(const char *path, int mode)
+{
+	struct CALLBACK dircontext;
+	struct LINK *current;
+	BOOL isdir;
+	BOOL err;
+
+	err = FALSE;
+	dircontext.head = (struct LINK*)NULL;
+	dircontext.dir = path;
+	isdir = ntfs_read_directory(ntfs_context, path,
+			callback, &dircontext);
+	if (isdir) {
+		setfull(path,mode,TRUE);
+		if (opt_b)
+			printf("#\n#\n");
+		else
+			printf("\n\n");
+		while (dircontext.head) {
+			current = dircontext.head;
+			recurseset(current->name,mode);
+			dircontext.head = dircontext.head->next;
+			free(current);
+		}
+	} else
+		if (errno == ENOTDIR)
+			setfull(path,mode,FALSE);
+		else {
+			printf("** Could not access %s\n",path);
+			printerror(stdout);
+			errors++;
+			err = TRUE;
+		}
+	return (!err);
+}
+
+#endif
+
+#if POSIXACLS
+
+BOOL singleset_posix(const char *path, const struct POSIX_SECURITY *pxdesc)
+{
+	BOOL isdir;
+	BOOL err;
+
+	err = FALSE;
+	isdir = ntfs_read_directory(ntfs_context, path,
+			callback, (struct CALLBACK*)NULL);
+	if (isdir || (errno == ENOTDIR)) {
+		err = !setfull_posix(path,pxdesc,isdir);
+		if (err) {
+			printf("** Failed to update %s\n",path);
+			printerror(stdout);
+			errors++;
+		}
+	} else {
+		printf("** Could not access %s\n",path);
+		printerror(stdout);
+		errors++;
+		err = TRUE;
+	}
+	return (!err);
+}
+
+#endif
+
+BOOL singleset(const char *path, int mode)
+{
+	BOOL isdir;
+	BOOL err;
+
+	err = FALSE;
+	isdir = ntfs_read_directory(ntfs_context, path,
+			callback, (struct CALLBACK*)NULL);
+	if (isdir || (errno == ENOTDIR))
+		setfull(path,mode,isdir);
+	else {
+		printf("** Could not access %s\n",path);
+		printerror(stdout);
+		errors++;
+		err = TRUE;
+	}
+	return (!err);
+}
+
+int callback(struct CALLBACK *dircontext, char *ntfsname,
+	int length, int type,
+	long long pos  __attribute__((unused)), u64 mft_ref __attribute__((unused)),
+	unsigned int dt_type __attribute__((unused)))
+{
+	struct LINK *linkage;
+	char *name;
+	int newlth;
+	int size;
+
+	size = utf8size(ntfsname,length);
+	if (dircontext
+	    && (type != 2)     /* 2 : dos name (8+3) */
+	    && (size > 0)      /* chars convertible to utf8 */
+	    && ((length > 2)
+		|| (ntfsname[0] != '.')
+		|| (ntfsname[1] != '\0')
+		|| ((ntfsname[2] || ntfsname[3])
+		   && ((ntfsname[2] != '.') || (ntfsname[3] != '\0'))))) {
+		linkage = (struct LINK*)malloc(sizeof(struct LINK) 
+				+ strlen(dircontext->dir)
+				+ size + 2);
+		if (linkage) {
+		/* may find ".fuse_hidden*" files */
+		/* recommendation is not to hide them, so that */
+		/* the user has a clue to delete them */
+			strcpy(linkage->name,dircontext->dir);
+			if (linkage->name[strlen(linkage->name) - 1] != '/')
+				strcat(linkage->name,"/");
+			name = &linkage->name[strlen(linkage->name)];
+			newlth = makeutf8(name,ntfsname,length);
+			name[newlth] = 0;
+			linkage->next = dircontext->head;
+			dircontext->head = linkage;
+		}
+	}
+	return (0);
+}
+
+#endif
+
+#ifdef WIN32
+
+/*
+ *		 Backup security descriptors in a directory tree (Windows mode)
+ */
+
+BOOL backup(const char *root)
+{
+	BOOL err;
+	time_t now;
+	const char *txtime;
+
+	now = time((time_t*)NULL);
+	txtime = ctime(&now);
+	printf("#\n# Recursive ACL collection on %s#\n",txtime);
+	err = recurseshow(root);
+	return (err);
+}
+
+#else
+
+/*
+ *		 Backup security descriptors in a directory tree (Linux mode)
+ */
+
+BOOL backup(const char *volume, const char *root)
+{
+	BOOL err;
+	int count;
+	int i,j;
+	time_t now;
+	const char *txtime;
+
+	now = time((time_t*)NULL);
+	txtime = ctime(&now);
+	if (!getuid() && open_security_api()) {
+		if (open_volume(volume,NTFS_MNT_RDONLY)) {
+			printf("#\n# Recursive ACL collection on %s#\n",txtime);
+			err = recurseshow(root);
+			count = 0;
+			for (i=0; i<(MAXSECURID + (1 << SECBLKSZ) - 1)/(1 << SECBLKSZ); i++)
+				if (securdata[i])
+					for (j=0; j<(1 << SECBLKSZ); j++)
+						if (securdata[i][j].filecount) {
+							count++;
+						}
+			printf("# %d security keys\n",count);
+			close_volume(volume);
+		} else {
+			fprintf(stderr,"Could not open volume %s\n",volume);
+			printerror(stdout);
+			err = TRUE;
+		}
+		close_security_api();
+	} else {
+		if (getuid())
+			fprintf(stderr,"This is only possible as root\n");
+		else
+			fprintf(stderr,"Could not open security API\n");
+		err = TRUE;
+	}
+	return (err);
+}
+
+#endif
+
+#ifdef WIN32
+
+/*
+ *		 List security descriptors in a directory tree (Windows mode)
+ */
+
+BOOL listfiles(const char *root)
+{
+	BOOL err;
+
+	if (opt_r) {
+		printf("\nRecursive file check\n");
+		err = recurseshow(root);
+	} else
+		err = singleshow(root);
+	return (err);
+}
+
+#else
+
+/*
+ *		 List security descriptors in a directory tree (Linux mode)
+ */
+
+BOOL listfiles(const char *volume, const char *root)
+{
+	BOOL err;
+	int i,j;
+	int count;
+
+	if (!getuid() && open_security_api()) {
+		if (open_volume(volume,NTFS_MNT_RDONLY)) {
+			if (opt_r) {
+				printf("\nRecursive file check\n");
+				err = recurseshow(root);
+				printf("Summary\n");
+				count = 0;
+				for (i=0; i<(MAXSECURID + (1 << SECBLKSZ) - 1)/(1 << SECBLKSZ); i++)
+					if (securdata[i])
+						for (j=0; j<(1 << SECBLKSZ); j++)
+							if (securdata[i][j].filecount) {
+								printf("Key 0x%x : %d files, mode 0%03o\n",
+									i*(1 << SECBLKSZ)+j,securdata[i][j].filecount,
+									securdata[i][j].mode);
+								count++;
+							}
+				printf("%d security keys\n",count);
+			} else
+				err = singleshow(root);
+			close_volume(volume);
+		} else {
+			fprintf(stderr,"Could not open volume %s\n",volume);
+			printerror(stdout);
+			err = TRUE;
+		}
+		close_security_api();
+	} else {
+		if (getuid())
+			fprintf(stderr,"This is only possible as root\n");
+		else
+			fprintf(stderr,"Could not open security API\n");
+		err = TRUE;
+	}
+	return (err);
+}
+
+BOOL mapproposal(const char *volume, const char *name)
+{
+	BOOL err;
+	u32 attrsz;
+	int securindex;
+	char attr[256]; /* header (20) and a couple of SIDs (max 40 each) */
+
+	err = FALSE;
+	if (!getuid() && open_security_api()) {
+		if (open_volume(volume,NTFS_MNT_RDONLY)) {
+
+			attrsz = 0;
+			securindex = ntfs_get_file_security(ntfs_context,name,
+					OWNER_SECURITY_INFORMATION
+					    | GROUP_SECURITY_INFORMATION,
+					(char*)attr,MAXATTRSZ,&attrsz);
+			if (securindex)
+				err = proposal(name,attr);
+			else {
+				fprintf(stderr,"*** Could not get the ACL of %s\n",
+						name);
+				printerror(stdout);
+				errors++;
+			}
+			close_volume(volume);
+		} else {
+			fprintf(stderr,"Could not open volume %s\n",volume);
+			printerror(stdout);
+			err = TRUE;
+		}
+		close_security_api();
+	} else {
+		if (getuid())
+			fprintf(stderr,"This is only possible as root\n");
+		else
+			fprintf(stderr,"Could not open security API\n");
+		err = TRUE;
+	}
+	return (err);
+}
+
+#endif
+
+#ifndef WIN32
+
+/*
+ *		Check whether a SDS entry is valid
+ */
+
+BOOL valid_sds(const char *attr, unsigned int offset,
+		unsigned int entrysz, unsigned int size, u32 prevkey,
+		BOOL second)
+{
+	BOOL unsane;
+	u32 comphash;
+	u32 key;
+
+	unsane = FALSE;
+	if (!get4l(attr,0) && !get4l(attr,4)) {
+		printf("Entry at 0x%lx was deleted\n",(long)offset);
+	} else {
+		if ((ntfs_attr_size(&attr[20]) + 20) > entrysz) {
+			printf("** Entry is truncated (expected size %ld)\n",
+				(long)ntfs_attr_size(&attr[20] + 20));
+			unsane = TRUE;
+			errors++;
+		}
+		if ((ntfs_attr_size(&attr[20]) + 20) < entrysz) {
+			printf("** Extra data appended to entry (expected size %ld)\n",
+				(long)ntfs_attr_size(&attr[20]) + 20);
+			warnings++;
+		}
+		if (!unsane && !ntfs_valid_descr((const char*)&attr[20],size)) {
+			printf("** General sanity check has failed\n");
+			unsane = TRUE;
+			errors++;
+		}
+		if (!unsane) {
+			comphash = hash((const le32*)&attr[20],entrysz-20);
+			if ((u32)get4l(attr,0) == comphash) {
+				if (opt_v >= 2)
+					printf("Hash	 0x%08lx (correct)\n",
+						(unsigned long)comphash);
+			} else {
+				printf("** hash  0x%08lx (computed : 0x%08lx)\n",
+					(unsigned long)get4l(attr,0),
+					(unsigned long)comphash);
+				unsane = TRUE;
+				errors++;
+			}
+		}
+		if (!unsane) {
+			if ((second ? get8l(attr,8) + 0x40000 : get8l(attr,8)) == offset) {
+				if (opt_v >= 2)
+					printf("Offset	 0x%lx (correct)\n",(long)offset);
+			} else {
+				printf("** offset  0x%llx (expected : 0x%llx)\n",
+					(long long)get8l(attr,8),
+					(long long)(second ? get8l(attr,8) - 0x40000 : get8l(attr,8)));
+//				unsane = TRUE;
+				errors++;
+			}
+		}
+		if (!unsane) {
+			key = get4l(attr,4);
+			if (opt_v >= 2)
+				printf("Key	 0x%x\n",(int)key);
+			if (key) {
+				if (key <= prevkey) {
+					printf("** Unordered key 0x%lx after 0x%lx\n",
+						(long)key,(long)prevkey);
+					unsane = TRUE;
+					errors++;
+				}
+			}
+		}
+	}
+	return (!unsane);
+}
+
+/*
+ *		Check whether a SDS entry is consistent with other known data
+ *	and store current data for subsequent checks
+ */
+
+int consist_sds(const char *attr, unsigned int offset,
+		unsigned int entrysz, BOOL second)
+{
+	int errcnt;
+	u32 key;
+	u32 comphash;
+	struct SECURITY_DATA *psecurdata;
+
+	errcnt = 0;
+	key = get4l(attr,4);
+	if ((key > 0) && (key < MAXSECURID)) {
+		printf("Valid entry at 0x%lx for key 0x%lx\n",
+			(long)offset,(long)key);
+		if (!securdata[key >> SECBLKSZ])
+			newblock(key);
+		if (securdata[key >> SECBLKSZ]) {
+			psecurdata = &securdata[key >> SECBLKSZ][key & ((1 << SECBLKSZ) - 1)];
+			comphash = hash((const le32*)&attr[20],entrysz-20);
+			if (psecurdata->flags & INSDS1) {
+				if (psecurdata->hash != comphash) {
+					printf("** Different hash values : $SDS-1 0x%08lx $SDS-2 0x%08lx\n",
+						(unsigned long)psecurdata->hash,
+						(unsigned long)comphash);
+					errcnt++;
+					errors++;
+				}
+				if (psecurdata->offset != get8l(attr,8)) {
+					printf("** Different offsets : $SDS-1 0x%llx $SDS-2 0x%llx\n",
+						(long long)psecurdata->offset,(long long)get8l(attr,8));
+					errcnt++;
+					errors++;
+				}
+				if (psecurdata->length != get4l(attr,16)) {
+					printf("** Different lengths : $SDS-1 0x%lx $SDS-2 0x%lx\n",
+						(long)psecurdata->length,(long)get4l(attr,16));
+					errcnt++;
+					errors++;
+				}
+			} else {
+				if (second) {
+					printf("** Entry was not present in $SDS-1\n");
+					errcnt++;
+					errors++;
+				}
+				psecurdata->hash = comphash;
+				psecurdata->offset = get8l(attr,8);
+				psecurdata->length = get4l(attr,16);
+			}
+			psecurdata->flags |= (second ? INSDS2 : INSDS1);
+		}
+	} else
+		if (key || get4l(attr,0)) {
+			printf("** Security_id 0x%x out of bounds\n",key);
+			warnings++;
+		}
+	return (errcnt);
+}
+
+
+/*
+ *		       Auditing of $SDS (Linux only)
+ */
+
+int audit_sds(BOOL second)
+{
+	static char attr[MAXATTRSZ + 20];
+	BOOL isdir;
+	BOOL done;
+	BOOL unsane;
+	u32 prevkey;
+	int errcnt;
+	int size;
+	unsigned int entrysz;
+	unsigned int entryalsz;
+	unsigned int offset;
+	int count;
+	int deleted;
+	int mode;
+
+	if (second)
+		printf("\nAuditing $SDS-2\n");
+	else
+		printf("\nAuditing $SDS-1\n");
+	errcnt = 0;
+	offset = (second ? 0x40000 : 0);
+	count = 0;
+	deleted = 0;
+	done = FALSE;
+	prevkey = 0;
+
+	  /* get size of first record */
+
+	size = ntfs_read_sds(ntfs_context,(char*)attr,20,offset);
+	if (size != 20) {
+		if ((size < 0) && (errno == ENOTSUP))
+			printf("** There is no $SDS-%d in this volume\n",
+							(second ? 2 : 1));
+		else {
+			printf("** Could not open $SDS-%d, size %d\n",
+							(second ? 2 : 1),size);
+			errors++;
+			errcnt++;
+		}
+	} else
+		do {
+			entrysz = get4l(attr,16);
+			entryalsz = ((entrysz - 1) | 15) + 1;
+			if (entryalsz <= (MAXATTRSZ + 20)) {
+				/* read next header in anticipation, to get its size */
+				size = ntfs_read_sds(ntfs_context,
+					(char*)&attr[20],entryalsz,offset + 20);
+				if (opt_v)
+					printf("\nAt offset 0x%lx got %lu bytes\n",(long)offset,(long)size);
+			} else {
+				printf("** Security attribute is too long (%ld bytes) - stopping\n",
+					(long)entryalsz);
+				errcnt++;
+			}
+			if ((entryalsz > (MAXATTRSZ + 20)) || (size < (int)(entrysz - 20)))
+				done = TRUE;
+			else {
+				if (opt_v) {
+					printf("Entry size %d bytes\n",entrysz);
+					hexdump(&attr[20],size,8);
+				}
+
+				unsane = !valid_sds(attr,offset,entrysz,
+					size,prevkey,second);
+				if (!unsane) {
+					if (!get4l(attr,0) && !get4l(attr,4))
+						deleted++;
+					else
+						count++;
+					errcnt += consist_sds(attr,offset,
+						entrysz, second);
+					if (opt_v >= 2) {
+						isdir = guess_dir(&attr[20]);
+						printf("Assuming %s descriptor\n",(isdir ? "directory" : "file"));
+						showheader(&attr[20],0);
+						showusid(&attr[20],0);
+						showgsid(&attr[20],0);
+						showdacl(&attr[20],isdir,0);
+						showsacl(&attr[20],isdir,0);
+						showownership(&attr[20]);
+						mode = linux_permissions(
+						    &attr[20],isdir);
+						printf("Interpreted Unix mode 0%03o\n",mode);
+					}
+					prevkey = get4l(attr,4);
+				}
+				if (!unsane) {
+					memcpy(attr,&attr[entryalsz],20);
+					offset += entryalsz;
+					if (!get4l(attr,16)
+					   || ((((offset - 1) | 0x3ffff) - offset + 1) < 20)) {
+						if (second)
+							offset = ((offset - 1) | 0x7ffff) + 0x40001;
+						else
+							offset = ((offset - 1) | 0x7ffff) + 1;
+						if (opt_v)
+							printf("Trying next SDS-%d block at offset 0x%lx\n",
+								(second ? 2 : 1), (long)offset);
+						size = ntfs_read_sds(ntfs_context,
+							(char*)attr,20,offset);
+						if (size != 20) {
+							if (opt_v)
+								printf("Assuming end of $SDS, got %d bytes\n",size);
+							done = TRUE;
+						}
+					}
+				} else {
+					printf("** Sanity check failed - stopping there\n");
+					errcnt++;
+					errors++;
+					done = TRUE;
+				}
+			}
+		} while (!done);
+	if (count || deleted || errcnt) {
+		printf("%d valid and %d deleted entries in $SDS-%d\n",
+				count,deleted,(second ? 2 : 1));
+		printf("%d errors in $SDS-%c\n",errcnt,(second ? '2' : '1'));
+	}
+	return (errcnt);
+}
+
+/*
+ *		Check whether a SII entry is sane
+ */
+
+BOOL valid_sii(const char *entry, u32 prevkey)
+{
+	BOOL valid;
+	u32 key;
+
+	valid = TRUE;
+	key = get4l(entry,16);
+	if (key <= prevkey) {
+		printf("** Unordered key 0x%lx after 0x%lx\n",
+			(long)key,(long)prevkey);
+		valid = FALSE;
+		errors++;
+	}
+	prevkey = key;
+	if (get2l(entry,0) != 20) {
+		printf("** offset %d (instead of 20)\n",(int)get2l(entry,0));
+		valid = FALSE;
+		errors++;
+	}
+	if (get2l(entry,2) != 20) {
+		printf("** size %d (instead of 20)\n",(int)get2l(entry,2));
+		valid = FALSE;
+		errors++;
+	}
+	if (get4l(entry,4) != 0) {
+		printf("** fill1 %d (instead of 0)\n",(int)get4l(entry,4));
+		valid = FALSE;
+		errors++;
+	}
+	if (get2l(entry,12) & 1) {
+		if (get2l(entry,8) != 48) {
+			printf("** index size %d (instead of 48)\n",(int)get2l(entry,8));
+			valid = FALSE;
+			errors++;
+		}
+	} else
+		if (get2l(entry,8) != 40) {
+			printf("** index size %d (instead of 40)\n",(int)get2l(entry,8));
+			valid = FALSE;
+			errors++;
+		}
+	if (get2l(entry,10) != 4) {
+		printf("** index key size %d (instead of 4)\n",(int)get2l(entry,10));
+		valid = FALSE;
+		errors++;
+	}
+	if ((get2l(entry,12) & ~3) != 0) {
+		printf("** flags 0x%x (instead of < 4)\n",(int)get2l(entry,12));
+		valid = FALSE;
+		errors++;
+	}
+	if (get2l(entry,14) != 0) {
+		printf("** fill2 %d (instead of 0)\n",(int)get2l(entry,14));
+		valid = FALSE;
+		errors++;
+	}
+	if (get4l(entry,24) != key) {
+		printf("** key 0x%x (instead of 0x%x)\n",
+						(int)get4l(entry,24),(int)key);
+		valid = FALSE;
+		errors++;
+	}
+	return (valid);
+}
+
+/*
+ *		Check whether a SII entry is consistent with other known data
+ */
+
+int consist_sii(const char *entry)
+{
+	int errcnt;
+	u32 key;
+	struct SECURITY_DATA *psecurdata;
+
+	errcnt = 0;
+	key = get4l(entry,16);
+	if ((key > 0) && (key < MAXSECURID)) {
+		printf("Valid entry for key 0x%lx\n",(long)key);
+		if (!securdata[key >> SECBLKSZ])
+			newblock(key);
+		if (securdata[key >> SECBLKSZ]) {
+			psecurdata = &securdata[key >> SECBLKSZ][key & ((1 << SECBLKSZ) - 1)];
+			psecurdata->flags |= INSII;
+			if (psecurdata->flags & (INSDS1 | INSDS2)) {
+				if ((u32)get4l(entry,20) != psecurdata->hash) {
+					printf("** hash 0x%x (instead of 0x%x)\n",
+						(unsigned int)get4l(entry,20),
+						(unsigned int)psecurdata->hash);
+					errors++;
+				}
+				if (get8l(entry,28) != psecurdata->offset) {
+					printf("** offset 0x%llx (instead of 0x%llx)\n",
+						(long long)get8l(entry,28),
+						(long long)psecurdata->offset);
+					errors++;
+				}
+				if (get4l(entry,36) != psecurdata->length) {
+					printf("** length 0x%lx (instead of %ld)\n",
+						(long)get4l(entry,36),
+						(long)psecurdata->length);
+					errors++;
+				}
+			} else {
+				printf("** Entry was not present in $SDS\n");
+				errors++;
+				psecurdata->hash = get4l(entry,20);
+				psecurdata->offset = get8l(entry,28);
+				psecurdata->length = get4l(entry,36);
+				if (opt_v) {
+					printf("   hash 0x%x\n",(unsigned int)psecurdata->hash);
+					printf("   offset 0x%llx\n",(long long)psecurdata->offset);
+					printf("   length %ld\n",(long)psecurdata->length);
+				}
+				errcnt++;
+			}
+		}
+	} else {
+		printf("** Security_id 0x%x out of bounds\n",key);
+		warnings++;
+	}
+	return (errcnt);
+}
+
+
+/*
+ *		       Auditing of $SII (Linux only)
+ */
+
+int audit_sii()
+{
+	char *entry;
+	int errcnt;
+	u32 prevkey;
+	BOOL valid;
+	BOOL done;
+	int count;
+
+	printf("\nAuditing $SII\n");
+	errcnt = 0;
+	count = 0;
+	entry = (char*)NULL;
+	prevkey = 0;
+	done = FALSE;
+	do {
+		entry = (char*)ntfs_read_sii(ntfs_context,(void*)entry);
+		if (entry) {
+			valid = valid_sii(entry,prevkey);
+			if (valid) {
+				count++;
+				errcnt += consist_sii(entry);
+				prevkey = get4l(entry,16);
+			} else
+				errcnt++;
+		} else
+			if ((errno == ENOTSUP) && !prevkey)
+				printf("** There is no $SII in this volume\n");
+	} while (entry && !done);
+	if (count || errcnt) {
+		printf("%d valid entries in $SII\n",count);
+		printf("%d errors in $SII\n",errcnt);
+	}
+	return (errcnt);
+}
+
+/*
+ *		Check whether a SII entry is sane
+ */
+
+BOOL valid_sdh(const char *entry, u32 prevkey, u32 prevhash)
+{
+	BOOL valid;
+	u32 key;
+	u32 currhash;
+
+	valid = TRUE;
+	currhash = get4l(entry,16);
+	key = get4l(entry,20);
+	if ((currhash < prevhash)
+		|| ((currhash == prevhash) && (key <= prevkey))) {
+		printf("** Unordered hash and key 0x%x 0x%x after 0x%x 0x%x\n",
+			(unsigned int)currhash,(unsigned int)key,
+			(unsigned int)prevhash,(unsigned int)prevkey);
+		valid = FALSE;
+		errors++;
+	}
+	if ((opt_v >= 2) && (currhash == prevhash))
+		printf("Hash collision (not an error)\n");
+
+	if (get2l(entry,0) != 24) {
+		printf("** offset %d (instead of 24)\n",(int)get2l(entry,0));
+		valid = FALSE;
+		errors++;
+	}
+	if (get2l(entry,2) != 20) {
+		printf("** size %d (instead of 20)\n",(int)get2l(entry,2));
+		valid = FALSE;
+		errors++;
+	}
+	if (get4l(entry,4) != 0) {
+		printf("** fill1 %d (instead of 0)\n",(int)get4l(entry,4));
+		valid = FALSE;
+		errors++;
+	}
+	if (get2l(entry,12) & 1) {
+		if (get2l(entry,8) != 56) {
+			printf("** index size %d (instead of 56)\n",(int)get2l(entry,8));
+			valid = FALSE;
+			errors++;
+		}
+	} else
+		if (get2l(entry,8) != 48) {
+			printf("** index size %d (instead of 48)\n",(int)get2l(entry,8));
+			valid = FALSE;
+			errors++;
+		}
+	if (get2l(entry,10) != 8) {
+		printf("** index key size %d (instead of 8)\n",(int)get2l(entry,10));
+		valid = FALSE;
+		errors++;
+	}
+	if ((get2l(entry,12) & ~3) != 0) {
+		printf("** flags 0x%x (instead of < 4)\n",(int)get2l(entry,12));
+		valid = FALSE;
+		errors++;
+	}
+	if (get2l(entry,14) != 0) {
+		printf("** fill2 %d (instead of 0)\n",(int)get2l(entry,14));
+		valid = FALSE;
+		errors++;
+	}
+	if ((u32)get4l(entry,24) != currhash) {
+		printf("** hash 0x%x (instead of 0x%x)\n",
+			(unsigned int)get4l(entry,24),(unsigned int)currhash);
+		valid = FALSE;
+		errors++;
+	}
+	if (get4l(entry,28) != key) {
+		printf("** key 0x%x (instead of 0x%x)\n",
+			(int)get4l(entry,28),(int)key);
+		valid = FALSE;
+		errors++;
+	}
+	if (get4l(entry,44)
+		&& (get4l(entry,44) != 0x490049)) {
+		printf("** fill3 0x%lx (instead of 0 or 0x490049)\n",
+			(long)get4l(entry,44));
+		valid = FALSE;
+		errors++;
+	}
+	return (valid);
+}
+
+/*
+ *		Check whether a SDH entry is consistent with other known data
+ */
+
+int consist_sdh(const char *entry)
+{
+	int errcnt;
+	u32 key;
+	struct SECURITY_DATA *psecurdata;
+
+	errcnt = 0;
+	key = get4l(entry,20);
+	if ((key > 0) && (key < MAXSECURID)) {
+		printf("Valid entry for key 0x%lx\n",(long)key);
+		if (!securdata[key >> SECBLKSZ])
+			newblock(key);
+		if (securdata[key >> SECBLKSZ]) {
+			psecurdata = &securdata[key >> SECBLKSZ][key & ((1 << SECBLKSZ) - 1)];
+			psecurdata->flags |= INSDH;
+			if (psecurdata->flags & (INSDS1 | INSDS2 | INSII)) {
+				if ((u32)get4l(entry,24) != psecurdata->hash) {
+					printf("** hash 0x%x (instead of 0x%x)\n",
+						(unsigned int)get4l(entry,24),
+						(unsigned int)psecurdata->hash);
+					errors++;
+				}
+				if (get8l(entry,32) != psecurdata->offset) {
+					printf("** offset 0x%llx (instead of 0x%llx)\n",
+						(long long)get8l(entry,32),
+						(long long)psecurdata->offset);
+					errors++;
+				}
+				if (get4l(entry,40) != psecurdata->length) {
+					printf("** length %ld (instead of %ld)\n",
+						(long)get4l(entry,40),
+						(long)psecurdata->length);
+					errors++;
+				}
+			} else {
+				printf("** Entry was not present in $SDS nor in $SII\n");
+				errors++;
+				psecurdata->hash = get4l(entry,24);
+				psecurdata->offset = get8l(entry,32);
+				psecurdata->length = get4l(entry,40);
+				if (opt_v) {
+					printf("   offset 0x%llx\n",(long long)psecurdata->offset);
+					printf("   length %ld\n",(long)psecurdata->length);
+				}
+				errcnt++;
+			}
+		}
+	} else {
+		printf("** Security_id 0x%x out of bounds\n",key);
+		warnings++;
+	}
+	return (errcnt);
+}
+
+/*
+ *		       Auditing of $SDH (Linux only)
+ */
+
+int audit_sdh()
+{
+	char *entry;
+	int errcnt;
+	int count;
+	u32 prevkey;
+	u32 prevhash;
+	BOOL valid;
+	BOOL done;
+
+	printf("\nAuditing $SDH\n");
+	count = 0;
+	errcnt = 0;
+	prevkey = 0;
+	prevhash = 0;
+	entry = (char*)NULL;
+	done = FALSE;
+	do {
+		entry = (char*)ntfs_read_sdh(ntfs_context,(void*)entry);
+		if (entry) {
+			valid = valid_sdh(entry,prevkey,prevhash);
+			if (valid) {
+				count++;
+				errcnt += consist_sdh(entry);
+				prevhash = get4l(entry,16);
+				prevkey = get4l(entry,20);
+			} else
+				errcnt++;
+		} else
+			if ((errno == ENOTSUP) && !prevkey)
+				printf("** There is no $SDH in this volume\n");
+	} while (entry && !done);
+	if (count || errcnt) {
+		printf("%d valid entries in $SDH\n",count);
+		printf("%d errors in $SDH\n",errcnt);
+	}
+	return (errcnt);
+}
+
+/*
+ *		Audit summary
+ */
+
+void audit_summary()
+{
+	int count;
+	int flags;
+	int cnt;
+	int found;
+	int i,j;
+
+	count = 0;
+	found = 0;
+	if (opt_r) printf("Summary of security key use :\n");
+	for (i=0; i<(MAXSECURID + (1 << SECBLKSZ) - 1)/(1 << SECBLKSZ); i++)
+		if (securdata[i])
+			for (j=0; j<(1 << SECBLKSZ); j++) {
+				flags = securdata[i][j].flags & (INSDS1 + INSDS2 + INSII + INSDH);
+				if (flags) found++;
+				if (flags
+					&& (flags != (INSDS1 + INSDS2 + INSII + INSDH)))
+					{
+					if (!count && !opt_r)
+						printf("\n** Keys not present in all files :\n");
+					cnt = securdata[i][j].filecount;
+					if (opt_r)
+						printf("Key 0x%x used by %d %s, not in",
+							i*(1 << SECBLKSZ)+j,cnt,
+							(cnt > 1 ? "files" : "file"));
+					else
+						printf("Key 0x%x not in", i*(1 << SECBLKSZ)+j);
+					if (!(flags & INSDS1))
+						printf(" SDS-1");
+					if (!(flags & INSDS2))
+						printf(" SDS-2");
+					if (!(flags & INSII))
+						printf(" SII");
+					if (!(flags & INSDH))
+						printf(" SDH");
+					printf("\n");
+					count++;
+				} else {
+					cnt = securdata[i][j].filecount;
+					if (opt_r && cnt)
+						printf("Key 0x%x used by %d %s\n",
+							i*(1 << SECBLKSZ)+j,cnt,
+							(cnt > 1 ? "files" : "file"));
+				}
+			}
+	if (found) {
+		if (count)
+			printf("%d keys not present in all lists\n",count);
+		else
+			printf("All keys are present in all lists\n");
+	}
+}
+
+/*
+ *		       Auditing (Linux only)
+ */
+
+BOOL audit(const char *volume)
+{
+	BOOL err;
+
+	err = FALSE;
+	if (!getuid() && open_security_api()) {
+		if (open_volume(volume,NTFS_MNT_RDONLY)) {
+			if (audit_sds(FALSE)) err = TRUE;
+			if (audit_sds(TRUE)) err = TRUE;
+			if (audit_sii()) err = TRUE;
+			if (audit_sdh()) err = TRUE;
+			if (opt_r) recurseshow("/");
+
+			audit_summary();
+			close_volume(volume);
+		}
+		else {
+			fprintf(stderr,"Could not open volume %s\n",volume);
+			printerror(stdout);
+			err = TRUE;
+		}
+		close_security_api();
+	}
+	else {
+		if (getuid())
+			fprintf(stderr,"This is only possible as root\n");
+		else fprintf(stderr,"Could not open security API\n");
+		err = TRUE;
+	}
+	return (err);
+}
+
+#endif
+
+#if POSIXACLS
+
+/*
+ *		Encode a Posix ACL string
+ *	[d:]{ugmo}:uid[:perms],...
+ */
+
+struct POSIX_SECURITY *encode_posix_acl(const char *str)
+{
+	int acccnt;
+	int defcnt;
+	int i,k,l;
+	int c;
+	s32 id;
+	u16 perms;
+	u16 apermsset;
+	u16 dpermsset;
+	u16 tag;
+	u16 tagsset;
+	mode_t mode;
+	BOOL defacl;
+	BOOL dmask;
+	BOOL amask;
+	const char *p;
+	struct POSIX_ACL *acl;
+	struct POSIX_SECURITY *pxdesc;
+	enum { PXBEGIN, PXTAG, PXTAG1, PXID, PXID1, PXID2,
+		PXPERM, PXPERM1, PXPERM2, PXOCT, PXNEXT, PXEND, PXERR
+	} state;
+
+				/* raw evaluation of ACE count */
+	p = str;
+	amask = FALSE;
+	dmask = FALSE;
+	if (*p == 'd') {
+		acccnt = 0;
+		defcnt = 1;
+	} else {
+		if ((*p >= '0') && (*p <= '7'))
+			acccnt = 0;
+		else
+			acccnt = 1;
+		defcnt = 0;
+	}
+	while (*p)
+		if (*p++ == ',') {
+			if (*p == 'd') {
+				defcnt++;
+				if (p[1] && (p[2] == 'm'))
+					dmask = TRUE;
+			} else {
+				acccnt++;
+				if (*p == 'm')
+					amask = TRUE;
+			}
+		}
+		/* account for an implicit mask if none defined */
+	if (acccnt && !amask)
+		acccnt++;
+	if (defcnt && !dmask)
+		defcnt++;
+	pxdesc = (struct POSIX_SECURITY*)malloc(sizeof(struct POSIX_SECURITY)
+				+ (acccnt + defcnt)*sizeof(struct POSIX_ACE));
+	if (pxdesc) {
+		pxdesc->acccnt = acccnt;
+		pxdesc->firstdef = acccnt;
+		pxdesc->defcnt = defcnt;
+		acl = &pxdesc->acl;
+		p = str;
+		state = PXBEGIN;
+		id = 0;
+		defacl = FALSE;
+		mode = 0;
+		apermsset = 0;
+		dpermsset = 0;
+		tag = 0;
+		perms = 0;
+		k = l = 0;
+		c = *p++;
+		while ((state != PXEND) && (state != PXERR)) {
+			switch (state) {
+			case PXBEGIN :
+				if (c == 'd') {
+					defacl = TRUE;
+					state = PXTAG1;
+					break;
+				} else
+					if ((c >= '0') && (c <= '7')) {
+						mode = c - '0';
+						state = PXOCT;
+						break;
+					}
+				defacl = FALSE;
+				/* fall through */
+			case PXTAG :
+				switch (c) {
+				case 'u' :
+					tag = POSIX_ACL_USER;
+					state = PXID;
+					break;
+				case 'g' :
+					tag = POSIX_ACL_GROUP;
+					state = PXID;
+					break;
+				case 'o' :
+					tag = POSIX_ACL_OTHER;
+					state = PXID;
+					break;
+				case 'm' :
+					tag = POSIX_ACL_MASK;
+					state = PXID;
+					break;
+				default :
+					state = PXERR;
+					break;
+				}
+				break;
+			case PXTAG1 :
+				if (c == ':')
+					state = PXTAG;
+				else
+					state = PXERR;
+				break;
+			case PXID :
+				if (c == ':') {
+					if ((tag == POSIX_ACL_OTHER)
+					   || (tag == POSIX_ACL_MASK))
+						state = PXPERM;
+					else
+						state = PXID1;
+				} else
+					state = PXERR;
+				break;
+			case PXID1 :
+				if ((c >= '0') && (c <= '9')) {
+					id = c - '0';
+					state = PXID2;
+				} else
+					if (c == ':') {
+						id = -1;
+						if (tag == POSIX_ACL_USER)
+							tag = POSIX_ACL_USER_OBJ;
+						if (tag == POSIX_ACL_GROUP)
+							tag = POSIX_ACL_GROUP_OBJ;
+						state = PXPERM1;
+					} else
+						state = PXERR;
+				break;
+			case PXID2 :
+				if ((c >= '0') && (c <= '9'))
+					id = 10*id + c - '0';
+				else
+					if (c == ':')
+						state = PXPERM1;
+					else
+						state = PXERR;
+				break;
+			case PXPERM :
+				if (c == ':') {
+					id = -1;
+					state = PXPERM1;
+				} else
+					state = PXERR;
+				break;
+			case PXPERM1 :
+				if ((c >= '0') && (c <= '7')) {
+					perms = c - '0';
+					state = PXNEXT;
+					break;
+				}
+				state = PXPERM2;
+				perms = 0;
+				/* fall through */
+			case PXPERM2 :
+				switch (c) {
+				case 'r' :
+					perms |= POSIX_PERM_R;
+					break;
+				case 'w' :
+					perms |= POSIX_PERM_W;
+					break;
+				case 'x' :
+					perms |= POSIX_PERM_X;
+					break;
+				case ',' :
+				case '\0' :
+					if (defacl) {
+						i = acccnt + l++;
+						dpermsset |= perms;
+					} else {
+						i = k++;
+						apermsset |= perms;
+					}
+					acl->ace[i].tag = tag;
+					acl->ace[i].perms = perms;
+					acl->ace[i].id = id;
+					if (c == '\0')
+						state = PXEND;
+					else
+						state = PXBEGIN;
+					break;
+				}
+				break;
+			case PXNEXT :
+				if (!c || (c == ',')) {
+					if (defacl) {
+						i = acccnt + l++;
+						dpermsset |= perms;
+					} else {
+						i = k++;
+						apermsset |= perms;
+					}
+					acl->ace[i].tag = tag;
+					acl->ace[i].perms = perms;
+					acl->ace[i].id = id;
+					if (c == '\0')
+						state = PXEND;
+					else
+						state = PXBEGIN;
+				} else
+					state = PXERR;
+				break;
+			case PXOCT :
+				if ((c >= '0') && (c <= '7'))
+					mode = (mode << 3) + c - '0';
+				else
+					if (c == '\0')
+						state = PXEND;
+					else
+						state = PXBEGIN;
+				break;
+			default :
+				break;
+			}
+			c = *p++;
+		}
+			/* insert default mask if none defined */
+		if (acccnt && !amask) {
+			i = k++;
+			acl->ace[i].tag = POSIX_ACL_MASK;
+			acl->ace[i].perms = apermsset;
+			acl->ace[i].id = -1;
+		}
+		if (defcnt && !dmask) {
+			i = acccnt + l++;
+			acl->ace[i].tag = POSIX_ACL_MASK;
+			acl->ace[i].perms = dpermsset;
+			acl->ace[i].id = -1;
+		}
+			/* compute the mode and tagsset */
+		tagsset = 0;
+		for (i=0; i<acccnt; i++)
+			tagsset |= acl->ace[i].tag;
+			switch (acl->ace[i].tag) {
+			case POSIX_ACL_USER_OBJ :
+				mode |= acl->ace[i].perms << 6;
+				break;
+			case POSIX_ACL_GROUP_OBJ :
+				mode |= acl->ace[i].perms << 3;
+				break;
+			case POSIX_ACL_OTHER :
+				mode |= acl->ace[i].perms;
+				break;
+			default :
+				break;
+			}
+		pxdesc->mode = mode;
+		pxdesc->tagsset = tagsset;
+		pxdesc->acl.version = POSIX_VERSION;
+		pxdesc->acl.flags = 0;
+		pxdesc->acl.filler = 0;
+		if (state != PXERR)
+			ntfs_sort_posix(pxdesc);
+showposix(pxdesc);
+		if ((state == PXERR)
+		   || (k != acccnt)
+		   || (l != defcnt)
+                   || !ntfs_valid_posix(pxdesc)) {
+			if (~pxdesc->tagsset
+			    & (POSIX_ACL_USER_OBJ | POSIX_ACL_GROUP_OBJ | POSIX_ACL_OTHER))
+				fprintf(stderr,"User, group or other permissions missing\n");
+			else
+				fprintf(stderr,"Bad ACL description\n");
+			free(pxdesc);
+			pxdesc = (struct POSIX_SECURITY*)NULL;
+		} else
+			if (opt_v >= 2) {
+				printf("Interpreted input description :\n");
+				showposix(pxdesc);
+			}
+	} else
+		errno = ENOMEM;
+	return (pxdesc);
+}
+
+#endif /* POSIXACLS */
+
+
+int getoptions(int argc, char *argv[])
+{
+	int xarg;
+	int narg;
+	const char *parg;
+	BOOL err;
+
+	opt_a = FALSE;
+	opt_b = FALSE;
+	opt_e = FALSE;
+	opt_h = FALSE;
+#if FORCEMASK
+	opt_m = FALSE;
+#endif
+	opt_r = FALSE;
+	opt_s = FALSE;
+#if SELFTESTS & !USESTUBS
+	opt_t = FALSE;
+#endif
+	opt_u = FALSE;
+	opt_v = 0;
+	xarg = 1;
+	err = FALSE;
+	while ((xarg < argc) && (argv[xarg][0] == '-')) {
+		parg = argv[xarg++];
+		while (*++parg)
+			switch (*parg)
+				{
+#ifndef WIN32
+				case 'a' :
+					opt_a = TRUE;
+					break;
+#endif
+				case 'b' :
+					opt_b = TRUE;
+					break;
+				case 'e' :
+					opt_e = TRUE;
+					break;
+				case 'h' :
+					opt_h = TRUE;
+					break;
+#if FORCEMASK
+				case 'm' :
+					opt_m = TRUE;
+					break;
+#endif
+				case 'r' :
+				case 'R' :
+					opt_r = TRUE;
+					break;
+				case 's' :
+					opt_s = TRUE;
+					break;
+#if SELFTESTS & !USESTUBS
+				case 't' :
+					opt_t = TRUE;
+					break;
+#endif
+				case 'u' :
+					opt_u = TRUE;
+					break;
+				case 'v' :
+					opt_v++;
+					break;
+				default :
+					fprintf(stderr,"Invalid option -%c\n",*parg);
+					err = TRUE;
+			}
+	}
+	narg = argc - xarg;
+#ifdef WIN32
+	if (   ((opt_h || opt_s) && (narg > 1))
+	    || ((opt_r || opt_b || opt_u) && ((narg < 1) || (narg > 2)))
+#if SELFTESTS & !USESTUBS
+	    || (opt_t && (narg > 0))
+#endif
+	    || (opt_e && !opt_s)
+	    || (!opt_h && !opt_r && !opt_b && !opt_s
+#if SELFTESTS & !USESTUBS
+			&& !opt_t
+#endif
+			&& ((narg < 1) || (narg > 2))))
+
+		err = TRUE;
+	if (err) {
+		xarg = 0;
+		fprintf(stderr,"Usage:\n");
+#if SELFTESTS & !USESTUBS
+		fprintf(stderr,"   secaudit -t\n");
+		fprintf(stderr,"	run self-tests\n");
+#endif
+		fprintf(stderr,"   secaudit -h [file]\n");
+		fprintf(stderr,"	display security descriptors within file\n");
+		fprintf(stderr,"   secaudit [-v] file\n");
+		fprintf(stderr,"	display the security parameters of file\n");
+		fprintf(stderr,"   secaudit -r[v] directory\n");
+		fprintf(stderr,"	display the security parameters of files in directory\n");
+		fprintf(stderr,"   secaudit -b[v] directory\n");
+		fprintf(stderr,"        backup the security parameters of files in directory\n");
+		fprintf(stderr,"   secaudit -s[ev] [backupfile]\n");
+		fprintf(stderr,"        set the security parameters as indicated in backup file\n");
+		fprintf(stderr,"        with -e also set extra parameters (Windows attrib)\n");
+		fprintf(stderr,"   secaudit perms file\n");
+		fprintf(stderr,"	set the security parameters of file to perms\n");
+		fprintf(stderr,"   secaudit -r[v] perms directory\n");
+		fprintf(stderr,"	set the security parameters of files in directory to perms\n");
+		fprintf(stderr,"   secaudit -u file\n");
+		fprintf(stderr,"	get a user mapping proposal applicable to file\n");
+#if POSIXACLS
+		fprintf(stderr,"   Note: perms can be an octal mode or a Posix ACL description\n");
+#else
+		fprintf(stderr,"   Note: perms is an octal mode\n");
+#endif
+		fprintf(stderr,"          -v is for verbose, -vv for very verbose\n");
+	}
+#else
+	if (   (opt_h && (narg > 1))
+	    || (opt_a && (narg != 1))
+	    || ((opt_r || opt_b || opt_s || opt_u)
+			&& ((narg < 1) || (narg > 3)))
+#if SELFTESTS & !USESTUBS
+	    || (opt_t && (narg > 0))
+#endif
+	    || (opt_e && !opt_s)
+	    || (!opt_h && !opt_a && !opt_r && !opt_b && !opt_s && !opt_u
+#if SELFTESTS & !USESTUBS
+		&& !opt_t
+#endif
+#ifdef HAVE_SETXATTR
+		&& ((narg < 1) || (narg > 3))))
+#else
+		&& ((narg < 2) || (narg > 3))))
+#endif
+		err = TRUE;
+	if (err) {
+		xarg = 0;
+		fprintf(stderr,"Usage:\n");
+#if SELFTESTS & !USESTUBS
+		fprintf(stderr,"   secaudit -t\n");
+		fprintf(stderr,"	run self-tests\n");
+#endif
+		fprintf(stderr,"   secaudit -h [file]\n");
+		fprintf(stderr,"	display security descriptors within file\n");
+		fprintf(stderr,"   secaudit -a[rv] volume\n");
+		fprintf(stderr,"	audit the volume\n");
+		fprintf(stderr,"   secaudit [-v] volume file\n");
+		fprintf(stderr,"	display the security parameters of file\n");
+		fprintf(stderr,"   secaudit -r[v] volume directory\n");
+		fprintf(stderr,"	display the security parameters of files in directory\n");
+		fprintf(stderr,"   secaudit -b[v] volume directory\n");
+		fprintf(stderr,"        backup the security parameters of files in directory\n");
+		fprintf(stderr,"   secaudit -s[ev] volume [backupfile]\n");
+		fprintf(stderr,"        set the security parameters as indicated in backup file\n");
+		fprintf(stderr,"        with -e also set extra parameters (Windows attrib)\n");
+		fprintf(stderr,"   secaudit volume perms file\n");
+		fprintf(stderr,"	set the security parameters of file to perms\n");
+		fprintf(stderr,"   secaudit -r[v] volume perms directory\n");
+		fprintf(stderr,"	set the security parameters of files in directory to perms\n");
+		fprintf(stderr,"   secaudit -u volume file\n");
+		fprintf(stderr,"	get a user mapping proposal applicable to file\n");
+#ifdef HAVE_SETXATTR
+		fprintf(stderr," special cases, do not require being root :\n");
+		fprintf(stderr,"   secaudit -u mounted-file\n");
+		fprintf(stderr,"	get a user mapping proposal applicable to mounted file\n");
+		fprintf(stderr,"   secaudit [-v] mounted-file\n");
+		fprintf(stderr,"	display the security parameters of a mounted file\n");
+#endif
+#if POSIXACLS
+		fprintf(stderr,"   Note: perms can be an octal mode or a Posix ACL description\n");
+#else
+		fprintf(stderr,"   Note: perms is an octal mode\n");
+#endif
+		fprintf(stderr,"          -v is for verbose, -vv for very verbose\n");
+	}
+#endif
+	if ((sizeof(SID) != 12) && !err) {
+		fprintf(stderr,"Possible alignment problem, check your compiler options\n");
+		err = TRUE;
+		xarg = 0;
+	}
+	return (xarg);
+}
+
+/*
+ *		Memory allocation with checks
+ */
+
+#undef malloc
+#undef calloc
+#undef free
+#undef isalloc
+
+void dumpalloc(const char *txt)
+{
+	struct CHKALLOC *q;
+
+	if (firstalloc) {
+		printf("alloc table at %s\n",txt);
+		for (q=firstalloc; q; q=q->next)
+			printf("%08lx : %u bytes at %08lx allocated at %s line %d\n",
+				(long)q,(unsigned int)q->size,
+				(long)q->alloc,q->file,q->line);
+	}
+}
+
+void *chkmalloc(size_t size, const char *file, int line)
+{
+	void *p;
+	struct CHKALLOC *q;
+
+	p = (void*)malloc(size+1);
+	if (p) {
+		((unsigned char*)p)[size] = 0xaa;
+		q = (struct CHKALLOC*)malloc(sizeof(struct CHKALLOC));
+		if (q) {
+			q->next = firstalloc;
+			q->alloc = p;
+			q->size = size;
+			q->file = file;
+			q->line = line;
+			firstalloc = q;
+		}
+	}
+	return (p);
+}
+
+void *chkcalloc(size_t cnt, size_t size, const char *file, int line)
+{
+	return (chkmalloc(cnt*size,file,line));
+}
+
+void chkfree(void *p, const char *file, int line)
+{
+	struct CHKALLOC *q;
+	struct CHKALLOC *r;
+
+	if (p) {
+		if (firstalloc && (firstalloc->alloc == p)) {
+			r = firstalloc;
+			firstalloc = firstalloc->next;
+		} else {
+			q = firstalloc;
+			if (q)
+				while (q->next && (q->next->alloc != p))
+					q = q->next;
+			if (q && q->next) {
+				r = q->next;
+				q->next = r->next;
+			} else {
+				r = (struct CHKALLOC*)NULL;
+				printf("** freeing unallocated memory in %s line %d\n",file,line);
+				if (!isatty(1))
+					fprintf(stderr,"** freeing unallocated memory in %s line %d\n",file,line);
+			}
+		}
+		if (r) {
+			if (((unsigned char*)p)[r->size] != 0xaa) {
+				printf("** memory corruption, alloc in %s line %d release in %s %d\n",
+					r->file,r->line,file,line);
+				if (!isatty(1))
+					fprintf(stderr,"** memory corruption, alloc in %s line %d release in %s %d\n",
+						r->file,r->line,file,line);
+			}
+			memset(p,0xaa,r->size);
+			free(r);
+			free(p);
+		}
+	}
+}
+
+void *stdmalloc(size_t size)
+{
+	return (malloc(size));
+}
+
+void stdfree(void *p)
+{
+	free(p);
+}
+
+BOOL chkisalloc(void *p, const char *file, int line)
+{
+	struct CHKALLOC *q;
+
+	if (p) {
+		q = firstalloc;
+		while (q && (q->alloc != p))
+			q = q->next;
+	} else
+		q = (struct CHKALLOC*)NULL;
+	if (!p || !q) {
+		printf("error in %s %d : 0x%lx not allocated\n",file,line,(long)p);
+	}
+	return (p && q);
+}
+
+
+
+
+#ifdef WIN32
+
+/*
+ *		 Windows version
+ */
+
+main(argc,argv)
+int argc;
+char *argv[];
+{
+	FILE *fd;
+	int xarg;
+	int mode;
+	unsigned int size;
+	BOOL cmderr;
+	char *filename;
+	const char *p;
+	int i;
+#if POSIXACLS
+	struct POSIX_SECURITY *pxdesc;
+#endif
+
+	printf("%s\n",BANNER);
+	cmderr = FALSE;
+	errors = 0;
+	warnings = 0;
+	xarg = getoptions(argc,argv);
+	if (xarg) {
+		for (i=0; i<(MAXSECURID + (1 << SECBLKSZ) - 1)/(1 << SECBLKSZ); i++)
+			securdata[i] = (struct SECURITY_DATA*)NULL;
+#if POSIXACLS
+		context.mapping[MAPUSERS] = (struct MAPPING*)NULL;
+		context.mapping[MAPGROUPS] = (struct MAPPING*)NULL;
+#endif
+		firstalloc = (struct CHKALLOC*)NULL;
+		mappingtype = MAPNONE;
+		switch (argc - xarg) {
+		case 0 :
+			if (opt_h)
+				showhex(stdin);
+			else
+				if (opt_s)
+					restore(stdin);
+#if SELFTESTS & !USESTUBS
+			if (opt_t)
+				selftests();
+#endif
+			break;
+		case 1 :
+			if (opt_h || opt_s) {
+				fd = fopen(argv[xarg],"r");
+				if (fd) {
+					if (opt_h)
+						showhex(fd);
+					else
+						restore(fd);
+					fclose(fd);
+				} else { 
+					fprintf(stderr,"Could not open %s\n",argv[xarg]);
+					cmderr = TRUE;
+				}
+			} else {
+				size = utf16size(argv[xarg]);
+				if (size) {
+					filename = (char*)malloc(2*size + 2);
+					if (filename) {
+						makeutf16(filename,argv[xarg]);
+						if (opt_u) {
+							cmderr = mapproposal(filename);
+						} else {
+#if POSIXACLS
+							if (local_build_mapping(context.mapping,filename)) {
+								printf("*** Could not get user mapping data\n");
+								warnings++;
+							}
+#endif
+							if (opt_b)
+								cmderr = backup(filename);
+							else {
+								if (opt_r)
+									cmderr = listfiles(filename);
+								else
+									cmderr = singleshow(filename);
+							}
+#if POSIXACLS
+							ntfs_free_mapping(context.mapping);
+#endif
+						}
+						free(filename);
+					} else {
+						fprintf(stderr,"No more memory\n");
+						cmderr = TRUE;
+					}
+				} else {
+					fprintf(stderr,"Bad UTF-8 name \"%s\"\n",argv[xarg]);
+					cmderr = TRUE;
+				}
+			}
+			break;
+		case 2 :
+			mode = 0;
+			p = argv[xarg];
+#if POSIXACLS
+			pxdesc = encode_posix_acl(p);
+			if (pxdesc) {
+				size = utf16size(argv[xarg + 1]);
+				if (size) {
+					filename = (char*)malloc(2*size + 2);
+					if (filename) {
+						makeutf16(filename,argv[xarg + 1]);
+						if (local_build_mapping(context.mapping,filename)) {
+							printf("*** Could not get user mapping data\n");
+							warnings++;
+						}
+						if (opt_r) {
+							for (i=0; i<(MAXSECURID + (1 << SECBLKSZ) - 1)/(1 << SECBLKSZ); i++)
+								securdata[i] = (struct SECURITY_DATA*)NULL;
+							recurseset_posix(filename,pxdesc);
+						} else
+							singleset_posix(filename,pxdesc);
+						ntfs_free_mapping(context.mapping);
+						free(filename);
+					} else {
+						fprintf(stderr,"No more memory\n");
+						cmderr = TRUE;
+					}
+					chkfree(pxdesc,__FILE__,__LINE__);
+				} else {
+					fprintf(stderr,"Bad UTF-8 name \"%s\"\n",argv[xarg + 1]);
+					cmderr = TRUE;
+				}
+			}
+#else
+			while ((*p >= '0') && (*p <= '7'))
+				mode = (mode << 3) + (*p++) - '0';
+			if (*p) {
+				fprintf(stderr,"New mode should be given in octal\n");
+				cmderr = TRUE;
+			} else {
+				size = utf16size(argv[xarg + 1]);
+				if (size) {
+					filename = (char*)malloc(2*size + 2);
+					if (filename) {
+						makeutf16(filename,argv[xarg + 1]);
+#if POSIXACLS
+						if (local_build_mapping(&context,filename)) {
+							printf("*** Could not get user mapping data\n");
+							warnings++;
+						}
+#endif
+						if (opt_r) {
+							for (i=0; i<(MAXSECURID + (1 << SECBLKSZ) - 1)/(1 << SECBLKSZ); i++)
+								securdata[i] = (struct SECURITY_DATA*)NULL;
+							recurseset(filename,mode);
+						} else
+							singleset(filename,mode);
+						free(filename);
+					} else {
+						fprintf(stderr,"No more memory\n");
+						cmderr = TRUE;
+					}
+				} else {
+					fprintf(stderr,"Bad UTF-8 name \"%s\"\n",argv[xarg + 1]);
+					cmderr = TRUE;
+				}
+			}
+#endif
+			break;
+#if FORCEMASK
+		case 3 :
+			mode = 0;
+			forcemsk = 0;
+			p = argv[xarg];
+			while (*p) {
+				if ((*p >= '0') && (*p <= '9'))
+					forcemsk = (forcemsk << 4) + *p - '0';
+				else forcemsk = (forcemsk << 4) + (*p & 7) + 9;
+			p++;
+			}
+			p = argv[xarg + 1];
+			while ((*p >= '0') && (*p <= '7'))
+				mode = (mode << 3) + (*p++) - '0';
+			if (*p) {
+				fprintf(stderr,"New mode should be given in octal\n");
+				cmderr = TRUE;
+			} else {
+				if (opt_r) {
+					recurseset(argv[xarg + 2],mode);
+				}
+				else singleset(argv[xarg + 2],mode);
+			}
+			break;
+#endif
+		}
+		if (warnings)
+			printf("** %u %s signalled\n",warnings,
+				(warnings > 1 ? "warnings were" : "warning was"));
+		if (errors)
+			printf("** %u %s found\n",errors,
+				(errors > 1 ? "errors were" : "error was"));
+		else
+			if (!cmderr)
+				printf("No errors were found\n");
+		if (!isatty(1)) {
+			fflush(stdout);
+			if (warnings)
+				fprintf(stderr,"** %u %s signalled\n",warnings,
+					(warnings > 1 ? "warnings were" : "warning was"));
+			if (errors)
+				fprintf(stderr,"** %u %s found\n",errors,
+					(errors > 1 ? "errors were" : "error was"));
+			else
+				fprintf(stderr,"No errors were found\n");
+		freeblocks();
+		}
+	}
+	dumpalloc("termination");
+	if (cmderr || errors)
+		exit(1);
+	return (0);
+}
+
+#else
+
+/*
+ *		 Linux version
+ */
+
+int main(int argc, char *argv[])
+{
+	FILE *fd;
+	const char *p;
+	int xarg;
+	BOOL cmderr;
+	int i;
+#if POSIXACLS
+	struct POSIX_SECURITY *pxdesc;
+#else
+	unsigned int mode;
+#endif
+
+	printf("%s\n",BANNER);
+	cmderr = FALSE;
+	errors = 0;
+	warnings = 0;
+	xarg = getoptions(argc,argv);
+	if (xarg) {
+		for (i=0; i<(MAXSECURID + (1 << SECBLKSZ) - 1)/(1 << SECBLKSZ); i++)
+			securdata[i] = (struct SECURITY_DATA*)NULL;
+#if POSIXACLS
+		context.mapping[MAPUSERS] = (struct MAPPING*)NULL;
+		context.mapping[MAPGROUPS] = (struct MAPPING*)NULL;
+#endif
+		firstalloc = (struct CHKALLOC*)NULL;
+		mappingtype = MAPNONE;
+		switch (argc - xarg) {
+		case 0 :
+			if (opt_h)
+				showhex(stdin);
+#if SELFTESTS & !USESTUBS
+			if (opt_t)
+				selftests();
+#endif
+			break;
+		case 1 :
+			if (opt_a)
+				cmderr = audit(argv[xarg]);
+			else
+				if (opt_h) {
+					fd = fopen(argv[xarg],"rb");
+					if (fd) {
+						showhex(fd);
+						fclose(fd);
+					} else { 
+						fprintf(stderr,"Could not open %s\n",argv[xarg]);
+						cmderr = TRUE;
+					}
+				} else
+					if (opt_b)
+						cmderr = backup(argv[xarg],"/");
+					else
+						if (opt_r)
+							cmderr = listfiles(argv[xarg],"/");
+						else
+							if (opt_s)
+								cmderr = dorestore(argv[xarg],stdin);
+							else
+								cmderr = processmounted(argv[xarg]);
+			break;
+		case 2 :
+			if (opt_b)
+				cmderr = backup(argv[xarg],argv[xarg+1]);
+			else
+				if (opt_s) {
+					fd = fopen(argv[xarg+1],"rb");
+					if (fd) {
+						if (dorestore(argv[xarg],fd))
+							cmderr = TRUE;
+						fclose(fd);
+					} else { 
+						fprintf(stderr,"Could not open %s\n",argv[xarg]);
+						cmderr = TRUE;
+					}
+				} else
+					if (opt_u)
+						cmderr = mapproposal(argv[xarg],argv[xarg+1]);
+					else
+						cmderr = listfiles(argv[xarg],argv[xarg+1]);
+			break;
+		case 3 :
+			p = argv[xarg+1];
+#if POSIXACLS
+			pxdesc = encode_posix_acl(p);
+			if (pxdesc) {
+				if (!getuid() && open_security_api()) {
+					if (open_volume(argv[xarg],NTFS_MNT_NONE)) {
+						if (opt_r) {
+							for (i=0; i<(MAXSECURID + (1 << SECBLKSZ) - 1)/(1 << SECBLKSZ); i++)
+								securdata[i] = (struct SECURITY_DATA*)NULL;
+							recurseset_posix(argv[xarg + 2],pxdesc);
+						} else
+							singleset_posix(argv[xarg + 2],pxdesc);
+						close_volume(argv[xarg]);
+					} else {
+						fprintf(stderr,"Could not open volume %s\n",argv[xarg]);
+						printerror(stderr);
+						cmderr = TRUE;
+					}
+					close_security_api();
+				} else {
+					if (getuid())
+						fprintf(stderr,"This is only possible as root\n");
+					else
+						fprintf(stderr,"Could not open security API\n");
+					cmderr = TRUE;
+				}
+			chkfree(pxdesc,__FILE__,__LINE__);
+			} else
+				cmderr = TRUE;
+#else
+			mode = 0;
+			while ((*p >= '0') && (*p <= '7'))
+				mode = (mode << 3) + (*p++) - '0';
+			if (*p) {
+				fprintf(stderr,"New mode should be given in octal\n");
+				cmderr = TRUE;
+			} else
+				if (!getuid() && open_security_api()) {
+					if (open_volume(argv[xarg],NTFS_MNT_NONE)) {
+						if (opt_r) {
+							for (i=0; i<(MAXSECURID + (1 << SECBLKSZ) - 1)/(1 << SECBLKSZ); i++)
+								securdata[i] = (struct SECURITY_DATA*)NULL;
+							recurseset(argv[xarg + 2],mode);
+						} else
+							singleset(argv[xarg + 2],mode);
+						close_volume(argv[xarg]);
+					} else {
+						fprintf(stderr,"Could not open volume %s\n",argv[xarg]);
+						printerror(stderr);
+						cmderr = TRUE;
+					}
+					close_security_api();
+				} else {
+					if (getuid())
+						fprintf(stderr,"This is only possible as root\n");
+					else
+						fprintf(stderr,"Could not open security API\n");
+					cmderr = TRUE;
+				}
+#endif
+			break;
+		}
+		if (warnings)
+			printf("** %u %s signalled\n",warnings,
+				(warnings > 1 ? "warnings were" : "warning was"));
+		if (errors)
+			printf("** %u %s found\n",errors,
+				(errors > 1 ? "errors were" : "error was"));
+		else
+			if (!cmderr)
+				printf("No errors were found\n");
+		if (!isatty(1)) {
+			fflush(stdout);
+			if (warnings)
+				fprintf(stderr,"** %u %s signalled\n",warnings,
+					(warnings > 1 ? "warnings were" : "warning was"));
+			if (errors)
+				fprintf(stderr,"** %u %s found\n",errors,
+					(errors > 1 ? "errors were" : "error was"));
+			else
+				if (!cmderr)
+					fprintf(stderr,"No errors were found\n");
+		}
+		freeblocks();
+	} else
+		cmderr = TRUE;
+	dumpalloc("termination");
+	if (cmderr || errors)
+		exit(1);
+	return (0);
+}
+
+#endif
diff --git a/src/secaudit.h b/src/secaudit.h
new file mode 100755
index 0000000000000000000000000000000000000000..a8ad163f92a19c9bb0097cf8a4594cb6af3bd2e9
--- /dev/null
+++ b/src/secaudit.h
@@ -0,0 +1,737 @@
+/*
+ *		General declarations for secaudit
+ *
+ *	These declarations are organized to enable code sharing with ntfs-3g
+ *	library, but should only be used to build tools runnable both
+ *	on Linux (dynamic linking) and Windows (static linking)
+ *
+ * Copyright (c) 2007-2009 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
+ */
+
+/*
+ *		General parameters which may have to be adapted to needs
+ */
+
+#define SELFTESTS 1 /* include code for self-testing */
+#define POSIXACLS 0 /* include code for processing Posix ACLs */
+#define NOREVBOM 0 /* temporary */
+
+#define OWNERFROMACL 1 /* must match option in security.c */
+
+#define MAXATTRSZ 65536 /* Max sec attr size (16448 met for WinXP) */
+#define MAXSECURID 262144
+#define SECBLKSZ 8
+#define MAXFILENAME 4096
+#define FORCEMASK 0 /* Special (dangerous) option -m to force a mask */
+#define MAXLINE 80 /* maximum processed size of a line */
+#define BUFSZ 1024		/* buffer size to read mapping file */
+#define LINESZ 120              /* maximum useful size of a mapping line */
+
+/*
+ *		     Definitions for Linux
+ *	Use explicit or implicit dynamic linking
+ */
+
+#ifdef HAVE_CONFIG_H
+#undef POSIXACLS   /* override default by configure option */
+#define USESTUBS 1 /* API stubs generated at link time */
+#else
+#define USESTUBS 0 /* direct calls to API, based on following definitions */
+#define ENVNTFS3G "NTFS3G"
+#define LIBFILE64 "/lib64/libntfs-3g.so.4921"
+#define LIBFILE "/lib/libntfs-3g.so.4921"
+#endif
+
+#define MAPDIR ".NTFS-3G"
+#define MAPFILE "UserMapping"
+#define MAGIC_API 0x09042009
+
+#ifndef _NTFS_ENDIANS_H
+
+typedef char s8;
+typedef short s16;
+typedef long long s64;
+typedef unsigned char u8;
+typedef unsigned short le16, be16, u16;
+typedef unsigned long long u64;
+#ifdef STSC
+typedef long s32;
+typedef unsigned long le32, be32, u32;
+#else
+typedef int s32;
+typedef unsigned int le32, be32, u32;
+#endif
+
+#ifdef STSC
+#define endian_rev16(x) ((((x) & 255L) << 8) + (((x) >> 8) & 255L))
+#define endian_rev32(x) ((((x) & 255L) << 24) + (((x) & 0xff00L) << 8) \
+		       + (((x) >> 8) & 0xff00L) + (((x) >> 24) & 255L))
+#else
+#define endian_rev16(x) ((((x) & 255) << 8) + (((x) >> 8) & 255))
+#define endian_rev32(x) ((((x) & 255) << 24) + (((x) & 0xff00) << 8) \
+		       + (((x) >> 8) & 0xff00) + (((x) >> 24) & 255))
+#endif
+#define endian_rev64(x) ((((x) & 255LL) << 56) + (((x) & 0xff00LL) << 40) \
+		       + (((x) & 0xff0000LL) << 24) + (((x) & 0xff000000LL) << 8) \
+		       + (((x) >> 8) & 0xff000000LL) + (((x) >> 24) & 0xff0000LL) \
+		       + (((x) >> 40) & 0xff00LL) + (((x) >> 56) & 255LL))
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+#define cpu_to_be16(x) endian_rev16(x)
+#define cpu_to_be32(x) endian_rev32(x)
+#define cpu_to_le16(x) (x)
+#define cpu_to_le32(x) (x)
+#define cpu_to_le64(x) (x)
+#define le16_to_cpu(x) (x)
+#define le32_to_cpu(x) (x)
+#define le64_to_cpu(x) (x)
+
+#else
+
+#define cpu_to_be16(x) (x)
+#define cpu_to_be32(x) (x)
+#define cpu_to_le16(x) endian_rev16(x)
+#define cpu_to_le32(x) endian_rev32(x)
+#define cpu_to_le64(x) endian_rev64(x)
+#define le16_to_cpu(x) endian_rev16(x)
+#define le32_to_cpu(x) endian_rev32(x)
+#define le64_to_cpu(x) endian_rev64(x)
+
+#endif
+
+#define const_le16_to_cpu(x) le16_to_cpu(x)
+#define const_cpu_to_le16(x) cpu_to_le16(x)
+#define const_cpu_to_le32(x) cpu_to_le32(x)
+#define const_cpu_to_be16(x) cpu_to_be16(x)
+#define const_cpu_to_be32(x) cpu_to_be32(x)
+
+#endif /* _NTFS_ENDIANS_H */
+
+#ifndef FALSE
+enum { FALSE, TRUE } ;
+#endif /* FALSE */
+
+#ifdef WIN32
+
+typedef unsigned short uid_t;
+typedef unsigned short gid_t;
+
+#define UNICODE(c) ((unsigned short)(c))
+
+#define __attribute__(x)
+
+#else
+
+#ifndef BOOL
+typedef int BOOL;   /* Already defined in windows.h */
+#endif /* BOOL */
+
+#ifdef STSC
+
+#define ENOTSUP 95
+
+#endif /* STSC */
+
+typedef u32 DWORD; /* must be 32 bits whatever the platform */
+typedef DWORD *LPDWORD;
+
+#define NTFS_MNT_NONE 0    /* no flag for mounting the device */
+#define NTFS_MNT_RDONLY 1  /* flag for mounting the device read-only */
+
+#endif /* WIN32 */
+
+#if defined(WIN32) | defined(STSC)
+
+/*
+ *	On non-Linux computers, there is no mount and the user mapping
+ *	if fetched from a real file (or a dummy one for self tests)
+ */
+
+#define NTFS_FIND_USID(map,uid,buf) ntfs_find_usid(map,uid,buf)
+#define NTFS_FIND_GSID(map,gid,buf) ntfs_find_gsid(map,gid,buf)
+#define NTFS_FIND_USER(map,usid) ntfs_find_user(map,usid)
+#define NTFS_FIND_GROUP(map,gsid) ntfs_find_group(map,gsid)
+
+#else
+
+/*
+ *	On Linux computers, there is a mount and the user mapping
+ *	if either obtained through the mount process or fetched
+ *	from a dummy file for self-tests
+ */
+
+#define NTFS_FIND_USID(map,uid,buf) (mappingtype != MAPEXTERN ? \
+		ntfs_find_usid(map,uid,buf) : relay_find_usid(map,uid,buf))
+#define NTFS_FIND_GSID(map,gid,buf) (mappingtype != MAPEXTERN ? \
+		ntfs_find_gsid(map,gid,buf) : relay_find_gsid(map,gid,buf))
+#define NTFS_FIND_USER(map,usid) (mappingtype != MAPEXTERN ? \
+		ntfs_find_user(map,usid) : relay_find_user(map,usid))
+#define NTFS_FIND_GROUP(map,gsid) (mappingtype != MAPEXTERN ? \
+		ntfs_find_group(map,gsid) : relay_find_group(map,gsid))
+
+#endif
+
+/*
+ *		A few name hijackings or definitions
+ *	needed for using code from ntfs-3g
+ */
+
+#ifdef WIN32
+#define ACL MY_ACL
+#define SID MY_SID
+#define ACCESS_ALLOWED_ACE MY_ACCESS_ALLOWED_ACE
+#define ACCESS_DENIED_ACE MY_ACCESS_DENIED_ACE
+#define FILE_ATTRIBUTE_REPARSE_POINT 0x400
+#define IO_REPARSE_TAG_MOUNT_POINT 0xa0000003
+#define IO_REPARSE_TAG_SYMLINK     0xa000000c
+#else
+#define SE_OWNER_DEFAULTED  const_cpu_to_le16(1)
+#define SE_GROUP_DEFAULTED  const_cpu_to_le16(2)
+#define SE_DACL_PRESENT     const_cpu_to_le16(4)
+#define SE_SACL_PRESENT     const_cpu_to_le16(0x10)
+#define SE_DACL_DEFAULTED   const_cpu_to_le16(8)
+#define SE_SELF_RELATIVE    const_cpu_to_le16(0x8000)
+#define SID_REVISION 1
+#endif /* WIN32 */
+#define SE_DACL_PROTECTED   const_cpu_to_le16(0x1000)
+#define SE_SACL_PROTECTED   const_cpu_to_le16(0x2000)
+#define SE_DACL_AUTO_INHERITED   const_cpu_to_le16(0x400)
+#define SE_SACL_AUTO_INHERITED   const_cpu_to_le16(0x800)
+#define SE_DACL_AUTO_INHERIT_REQ   cpu_to_le16(0x100)
+#define SE_SACL_AUTO_INHERIT_REQ   cpu_to_le16(0x200)
+
+typedef le16 ntfschar;
+
+#define ntfs_log_error(args...) do { printf("** " args); if (!isatty(1)) fprintf(stderr,args); } while(0)
+
+/*
+ *		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];
+};
+
+/*
+ *		A few dummy declarations needed for using code from security.c
+ */
+
+#define MFT_RECORD_IS_DIRECTORY const_cpu_to_le16(1)
+
+struct SECURITY_DATA {
+	u64 offset;
+	char *attr;
+	u32 hash;
+	u32 length;
+	unsigned int filecount:16;
+	unsigned int mode:12;
+	unsigned int flags:4;
+} ;
+
+		/* default security sub-authorities */
+enum {
+	DEFSECAUTH1 = -1153374643, /* 3141592653 */
+	DEFSECAUTH2 = 589793238,
+	DEFSECAUTH3 = 462843383,
+	DEFSECBASE = 10000
+};
+
+#define OWNERID 1016
+#define GROUPID 513
+
+
+#define INSDS1 1
+#define INSDS2 2
+#define INSII 4
+#define INSDH 8
+
+#ifdef WIN32
+
+typedef enum { RECSHOW, RECSET, RECSETPOSIX } RECURSE; 
+
+#endif
+
+/*
+ *		A type large enough to hold any SID
+ */
+
+typedef char BIGSID[40];
+
+/*
+ *		Declarations for memory allocation checks
+ */
+
+struct CHKALLOC
+   {
+   struct CHKALLOC *next;
+   void *alloc;
+   const char *file;
+   int line;
+   size_t size;
+   } ;
+
+#if defined(WIN32) | defined(STSC)
+
+#define S_ISVTX 01000
+#define S_ISGID 02000
+#define S_ISUID 04000
+#define S_IXUSR 0100
+#define S_IWUSR 0200
+#define S_IRUSR 0400
+#define S_IXGRP 010
+#define S_IWGRP 020
+#define S_IRGRP 040
+#define S_IXOTH 001
+#define S_IWOTH 002
+#define S_IROTH 004
+
+#endif
+
+#ifdef WIN32
+#else
+/*
+ *
+ *   See http://msdn2.microsoft.com/en-us/library/aa379649.aspx
+ */
+
+typedef enum {
+	DACL_SECURITY_INFORMATION = 4, // The DACL of the object is being referenced.
+	SACL_SECURITY_INFORMATION = 8, // The SACL of the object is being referenced.
+	LABEL_SECURITY_INFORMATION = 8, // The mandatory integrity label is being referenced.
+	GROUP_SECURITY_INFORMATION = 2, // The primary group identifier of the object is being referenced.
+	OWNER_SECURITY_INFORMATION = 1, // The owner identifier of the object is being referenced.
+} SECURITY_INFORMATION;
+
+#define STANDARD_RIGHTS_READ	  cpu_to_le32(0x20000)
+#define STANDARD_RIGHTS_WRITE	  cpu_to_le32(0x20000)
+#define STANDARD_RIGHTS_EXECUTE   cpu_to_le32(0x20000)
+#define STANDARD_RIGHTS_REQUIRED  cpu_to_le32(0xf0000)
+
+#endif
+
+typedef struct SECHEAD {
+	s8 revision;
+	s8 alignment;
+	le16 control;
+	le32 owner;
+	le32 group;
+	le32 sacl;
+	le32 dacl;
+} SECURITY_DESCRIPTOR_RELATIVE;
+
+typedef struct ACL {
+	s8 revision;
+	s8 alignment1;
+	le16 size;
+	le16 ace_count;
+	le16 alignment2;
+} ACL;
+
+typedef struct {
+	union {
+		struct {
+			unsigned char revision;
+			unsigned char sub_authority_count;
+		} ;
+		struct {
+			/* evade an alignment problem when a 4 byte field  */
+			/* in a struct implies alignment of the struct */
+			le16 dummy;
+			be16 high_part;
+			be32 low_part;
+		} identifier_authority;
+	} ;
+	le32 sub_authority[1];
+} SID;
+
+typedef u8 ACE_FLAGS;
+
+typedef struct ACE {
+	u8 type;
+	u8 flags;
+	le16 size;
+	le32 mask;
+	SID sid;
+} ACCESS_ALLOWED_ACE, ACCESS_DENIED_ACE;
+
+
+/*
+ *          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 */
+};
+
+/*
+ *		       Posix ACL structures
+ */
+
+struct POSIX_ACE {
+	u16 tag;
+	u16 perms;
+	s32 id;
+} ;
+
+struct POSIX_ACL {
+	u8 version;
+	u8 flags;
+	u16 filler;
+	struct POSIX_ACE ace[0];
+} ;
+
+struct POSIX_SECURITY {
+	mode_t mode;
+	int acccnt;
+	int defcnt;
+	int firstdef;
+	u16 tagsset;
+	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 */
+} ;
+
+/*
+ *		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
+
+/*
+ *		 A few definitions adapted from winnt.h
+ *	    (Windows version uses actual definitions from winnt.h, which are
+ *	     not compatible with code from security.c on a big-endian computer)
+ */
+
+#ifndef WIN32
+
+#define DELETE				 cpu_to_le32(0x00010000L)
+#define READ_CONTROL			 cpu_to_le32(0x00020000L)
+#define WRITE_DAC			 cpu_to_le32(0x00040000L)
+#define WRITE_OWNER			 cpu_to_le32(0x00080000L)
+#define SYNCHRONIZE			 cpu_to_le32(0x00100000L)
+
+
+#define FILE_READ_DATA		  cpu_to_le32( 0x0001 )    // file & pipe
+#define FILE_LIST_DIRECTORY	  cpu_to_le32( 0x0001 )    // directory
+
+#define FILE_WRITE_DATA 	  cpu_to_le32( 0x0002 )    // file & pipe
+#define FILE_ADD_FILE		  cpu_to_le32( 0x0002 )    // directory
+
+#define FILE_APPEND_DATA	  cpu_to_le32( 0x0004 )    // file
+#define FILE_ADD_SUBDIRECTORY	  cpu_to_le32( 0x0004 )    // directory
+#define FILE_CREATE_PIPE_INSTANCE cpu_to_le32( 0x0004 )    // named pipe
+
+
+#define FILE_READ_EA		  cpu_to_le32( 0x0008 )    // file & directory
+
+#define FILE_WRITE_EA		  cpu_to_le32( 0x0010 )    // file & directory
+
+#define FILE_EXECUTE		  cpu_to_le32( 0x0020 )    // file
+#define FILE_TRAVERSE		  cpu_to_le32( 0x0020 )    // directory
+
+#define FILE_DELETE_CHILD	  cpu_to_le32( 0x0040 )    // directory
+
+#define FILE_READ_ATTRIBUTES	  cpu_to_le32( 0x0080 )    // all
+
+#define FILE_WRITE_ATTRIBUTES	  cpu_to_le32( 0x0100 )    // all
+
+#define FILE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | \
+				 cpu_to_le32(0x1FF))
+
+#define FILE_GENERIC_READ	  (STANDARD_RIGHTS_READ     |\
+				   FILE_READ_DATA	    |\
+				   FILE_READ_ATTRIBUTES     |\
+				   FILE_READ_EA 	    |\
+				   SYNCHRONIZE)
+
+
+#define FILE_GENERIC_WRITE	  (STANDARD_RIGHTS_WRITE    |\
+				   FILE_WRITE_DATA	    |\
+				   FILE_WRITE_ATTRIBUTES    |\
+				   FILE_WRITE_EA	    |\
+				   FILE_APPEND_DATA	    |\
+				   SYNCHRONIZE)
+
+
+#define FILE_GENERIC_EXECUTE	  (STANDARD_RIGHTS_EXECUTE  |\
+				   FILE_READ_ATTRIBUTES     |\
+				   FILE_EXECUTE 	    |\
+				   SYNCHRONIZE)
+
+#define GENERIC_READ			 cpu_to_le32(0x80000000L)
+#define GENERIC_WRITE			 cpu_to_le32(0x40000000L)
+#define GENERIC_EXECUTE 		 cpu_to_le32(0x20000000L)
+#define GENERIC_ALL	 		 cpu_to_le32(0x10000000L)
+
+
+#define OBJECT_INHERIT_ACE		  (0x1)
+#define CONTAINER_INHERIT_ACE		  (0x2)
+#define NO_PROPAGATE_INHERIT_ACE	  (0x4)
+#define INHERIT_ONLY_ACE		  (0x8)
+#define INHERITED_ACE			  (0x10)
+#define VALID_INHERIT_FLAGS		  (0x1F)
+
+/*
+ *	     Other useful definitions
+ */
+
+#define ACL_REVISION 2
+#define ACCESS_ALLOWED_ACE_TYPE 0
+#define ACCESS_DENIED_ACE_TYPE 1
+#define SECURITY_DESCRIPTOR_REVISION 1
+
+#endif /* !WIN32 */
+
+#ifndef ACL_REVISION_DS	/* not always defined in <windows.h> */
+#define ACL_REVISION_DS 4
+#endif
+
+#ifndef INHERITED_ACE /* not always defined in <windows.h> */
+#define INHERITED_ACE			  (0x10)
+#undef VALID_INHERIT_FLAGS
+#define VALID_INHERIT_FLAGS		  (0x1F)
+#endif
+
+/*
+ *		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 | GENERIC_ALL)
+#define FILE_GWRITE (FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE \
+			| GENERIC_ALL)
+#define FILE_GEXEC (FILE_EXECUTE | GENERIC_EXECUTE | GENERIC_ALL)
+#define DIR_GREAD (FILE_LIST_DIRECTORY | GENERIC_READ | GENERIC_ALL)
+#define DIR_GWRITE (FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY | GENERIC_WRITE \
+			| GENERIC_ALL)
+#define DIR_GEXEC (FILE_TRAVERSE | GENERIC_EXECUTE | GENERIC_ALL)
+
+	/* 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 */
+
+
+struct SII {		/* this is an image of an $SII index entry */
+	le16 offs;
+	le16 size;
+	le32 fill1;
+	le16 indexsz;
+	le16 indexksz;
+	le16 flags;
+	le16 fill2;
+	le32 keysecurid;
+
+	/* did not find official description for the following */
+	le32 hash;
+	le32 securid;
+	le32 dataoffsl;	/* documented as badly aligned */
+	le32 dataoffsh;
+	le32 datasize;
+} ;
+
+struct SDH {		/* this is an image of an $SDH index entry */
+	le16 offs;
+	le16 size;
+	le32 fill1;
+	le16 indexsz;
+	le16 indexksz;
+	le16 flags;
+	le16 fill2;
+	le32 keyhash;
+	le32 keysecurid;
+
+	/* did not find official description for the following */
+	le32 hash;
+	le32 securid;
+	le32 dataoffsl;
+	le32 dataoffsh;
+	le32 datasize;
+	le32 fill3;
+	} ;
+
+#ifndef INVALID_FILE_ATTRIBUTES     /* not defined in old windows.h */
+#define INVALID_FILE_ATTRIBUTES (-1)
+#endif
+
+enum { MAPUSERS, MAPGROUPS, MAPCOUNT } ;
+
+struct SECURITY_CONTEXT {
+	struct MAPPING *mapping[MAPCOUNT];
+} ;
+
+typedef enum { MAPNONE, MAPEXTERN, MAPLOCAL, MAPDUMMY } MAPTYPE;
+
+
+
+struct passwd {
+	uid_t pw_uid;
+} ;
+
+struct group {
+	gid_t gr_gid;
+} ;
+
+typedef int (*FILEREADER)(void *fileid, char *buf, size_t size, off_t pos);
+
+/*
+ *		Data defined in secaudit.c
+ */
+
+extern MAPTYPE mappingtype;
+
+/*
+ *		Functions defined in acls.c
+ */
+
+BOOL ntfs_valid_descr(const char *securattr, unsigned int attrsz);
+BOOL ntfs_valid_posix(const struct POSIX_SECURITY *pxdesc);
+BOOL ntfs_valid_pattern(const SID *sid);
+BOOL ntfs_same_sid(const SID *first, const SID *second);
+
+
+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);
+
+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_permissions_posix(
+			struct MAPPING* const mapping[],
+			const char *securattr,
+			const SID *usid, const SID *gsid, BOOL isdir);
+int ntfs_build_permissions(const char *securattr,
+			const SID *usid, const SID *gsid, BOOL isdir);
+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[]);
+
+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);
+char *ntfs_build_descr(mode_t mode,
+			int isdir, const SID * usid, const SID * gsid);
+
+/*
+ *		Functions defined in secaudit.c
+ */
+
+void *chkmalloc(size_t, const char*, int);
+void *chkcalloc(size_t, size_t, const char *, int);
+void chkfree(void*, const char*, int);
+BOOL chkisalloc(void*, const char*, int);
+void dumpalloc(const char*);
+
+#define malloc(sz) chkmalloc(sz, __FILE__, __LINE__)
+#define calloc(cnt,sz) chkcalloc(cnt, sz, __FILE__, __LINE__)
+#define free(ptr) chkfree(ptr, __FILE__, __LINE__)
+#define isalloc(ptr) chkisalloc(ptr, __FILE__, __LINE__)
+#define ntfs_malloc(sz) chkmalloc(sz, __FILE__, __LINE__)
+
+struct passwd *getpwnam(const char *user);
+struct group *getgrnam(const char *group);
+
+const SID *relay_find_usid(const struct MAPPING *usermapping,
+			uid_t uid, SID *pdefsid);
+const SID *relay_find_gsid(const struct MAPPING *groupmapping,
+			gid_t gid, SID *pdefsid);
+uid_t relay_find_user(const struct MAPPING *usermapping, const SID *usid);
+gid_t relay_find_group(const struct MAPPING *groupmapping, const SID * gsid);
+
diff --git a/src/usermap.c b/src/usermap.c
new file mode 100755
index 0000000000000000000000000000000000000000..19c5c9065159bbb64311e0802103d8ae91036ea6
--- /dev/null
+++ b/src/usermap.c
@@ -0,0 +1,1365 @@
+/*
+ *               Windows to Linux user mapping for ntfs-3g
+ *
+ * 
+ * Copyright (c) 2007-2014 Jean-Pierre Andre
+ *
+ *    A quick'n dirty program scanning owners of files in
+ *      "c:\Documents and Settings" (and "c:\Users")
+ *     and asking user to map them to Linux accounts
+ *
+ *          History
+ *
+ *  Sep 2007
+ *     - first version, limited to Win32
+ *
+ *  Oct 2007
+ *     - ported to Linux (rewritten would be more correct)
+ *
+ *  Nov 2007 Version 1.0.0
+ *     - added more defaults
+ *
+ *  Nov 2007 Version 1.0.1
+ *     - avoided examining files whose name begin with a '$'
+ *
+ *  Jan 2008 Version 1.0.2
+ *     - moved user mapping file to directory .NTFS-3G (hidden for Linux)
+ *     - fixed an error case in Windows version
+ *
+ *  Nov 2008 Version 1.1.0
+ *     - fixed recursions for account in Linux version
+ *     - searched owner in c:\Users (standard location for Vista)
+ *
+ *  May 2009 Version 1.1.1
+ *     - reordered mapping records to limit usage of same SID for user and group
+ *     - fixed decoding SIDs on 64-bit systems
+ *     - fixed a pointer to dynamic data in mapping tables
+ *     - fixed default mapping on Windows
+ *     - fixed bug for renaming UserMapping on Windows
+ *
+ *  May 2009 Version 1.1.2
+ *     - avoided selecting DOS names on Linux
+ *
+ *  Nov 2009 Version 1.1.3
+ *     - silenced compiler warnings for unused parameters
+ *
+ *  Jan 2010 Version 1.1.4
+ *     - fixed compilation problems for Mac OSX (Erik Larsson)
+ *
+ *  Apr 2014 Version 1.1.5
+ *     - displayed the parent directory of selected files
+ *
+ *  May 2014 Version 1.1.6
+ *     - fixed a wrong function header
+ */
+
+/*
+ * 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
+ */
+
+/*
+ *		General parameters which may have to be adapted to needs
+ */
+
+#ifdef HAVE_CONFIG_H
+#define USESTUBS 1 /* API stubs generated at link time */
+#else
+#define USESTUBS 0 /* direct calls to API, based on following definitions */
+#define ENVNTFS3G "NTFS3G"
+#define LIBFILE64 "/lib64/libntfs-3g.so.491"
+#define LIBFILE "/lib/libntfs-3g.so.491"
+#endif
+
+#define GET_FILE_SECURITY "ntfs_get_file_security"
+#define SET_FILE_SECURITY "ntfs_set_file_security"
+#define READ_DIRECTORY "ntfs_read_directory"
+#define INIT_FILE_SECURITY "ntfs_initialize_file_security"
+#define LEAVE_FILE_SECURITY "ntfs_leave_file_security"
+
+#define VERSION "1.1.6"
+#define MAPDIR ".NTFS-3G"
+#define MAPFILE "UserMapping"
+#define MAXATTRSZ 2048
+#define MAXSIDSZ 80
+#define MAXNAMESZ 256
+#define OWNERS1 "Documents and Settings"
+#define OWNERS2 "Users"
+
+/*
+ *		Define WIN32 for a Windows execution
+ *	may have to be adapted to compiler or something else
+ */
+
+#ifndef WIN32
+#if defined(__WIN32) | defined(__WIN32__) | defined(WNSC)
+#define WIN32 1
+#endif
+#endif
+
+#ifdef WIN32
+#define BANNER "Generated by usermap for Windows, v " VERSION
+#else
+#define BANNER "Generated by usermap for Linux, v " VERSION
+#endif
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+/*
+ *	Define the security API according to platform
+ */
+
+#ifdef WIN32
+
+#include <fcntl.h>
+#include <windows.h>
+
+#define STATIC
+
+typedef enum { DENIED, AGREED } boolean;
+
+#else
+
+#include <unistd.h>
+#include <dlfcn.h>
+
+typedef enum { DENIED, AGREED } boolean, BOOL;
+typedef unsigned int DWORD; /* must be 32 bits whatever the platform */
+typedef DWORD *LPDWORD;
+
+enum {  OWNER_SECURITY_INFORMATION = 1,
+        GROUP_SECURITY_INFORMATION = 2,
+        DACL_SECURITY_INFORMATION = 4,
+        SACL_SECURITY_INFORMATION = 8
+} ;
+
+struct CALLBACK {
+	const char *accname;
+	const char *dir;
+	int levels;
+	int docset;
+} ;
+
+typedef int (*dircallback)(struct CALLBACK *context, char *ntfsname,
+	int length, int type, long long pos, unsigned long long mft_ref,
+	unsigned int dt_type);
+
+#if USESTUBS
+
+#define STATIC static
+
+BOOL ntfs_get_file_security(void *scapi,
+                const char *path, DWORD selection,
+                char *buf, DWORD buflen, LPDWORD psize);
+BOOL ntfs_set_file_security(void *scapi,
+                const char *path, DWORD selection, const char *attr);
+BOOL ntfs_read_directory(void *scapi,
+		const char *path, dircallback callback, void *context);
+void *ntfs_initialize_file_security(const char *device,
+                                unsigned long flags);
+BOOL ntfs_leave_file_security(void *scapi);
+
+#else
+
+#define STATIC
+
+BOOL (*ntfs_get_file_security)(void *scapi,
+                const char *path, DWORD selection,
+                char *buf, DWORD buflen, LPDWORD psize);
+BOOL (*ntfs_set_file_security)(void *scapi,
+                const char *path, DWORD selection, const char *attr);
+BOOL (*ntfs_read_directory)(void *scapi,
+		const char *path, dircallback callback, void *context);
+void *(*ntfs_initialize_file_security)(const char *device,
+                                unsigned long flags);
+BOOL (*ntfs_leave_file_security)(void *scapi);
+
+#endif
+
+STATIC boolean open_security_api(void);
+STATIC boolean close_security_api(void);
+STATIC boolean open_volume(const char *volume);
+STATIC boolean close_volume(const char *volume);
+
+#endif
+
+struct MAPPING {
+	struct MAPPING *next;
+	const char *uidstr;
+	const char *gidstr;
+	const char *sidstr;
+	const unsigned char *sid;
+	const char *login;
+	boolean defined;
+};
+
+struct MAPPING *firstmapping;
+struct MAPPING *lastmapping;
+
+#ifdef WIN32
+char *currentwinname;
+char *currentdomain;
+unsigned char *currentsid;
+#endif
+
+#ifndef WIN32
+
+void *ntfs_handle;
+void *ntfs_context = (void*)NULL;
+
+/*
+ *		Shut down compiler warnings for unused parameters
+ */
+
+static long unused(const void *p)
+{
+return ((long)p);
+}
+
+/*
+ *		Open and close the security API (platform dependent)
+ */
+
+STATIC boolean open_security_api(void)
+{
+#if USESTUBS
+	return (AGREED);
+#else
+	char *error;
+	boolean err;
+	const char *libfile;
+
+	err = AGREED;
+	libfile = getenv(ENVNTFS3G);
+	if (!libfile)
+		libfile = (sizeof(char*) == 8 ? LIBFILE64 : LIBFILE);
+	ntfs_handle = dlopen(libfile,RTLD_LAZY);
+	if (ntfs_handle) {
+		ntfs_initialize_file_security =
+				dlsym(ntfs_handle,INIT_FILE_SECURITY);
+		error = dlerror();
+		if (error)
+			fprintf(stderr," %s\n",error);
+		else {
+			ntfs_leave_file_security =
+					dlsym(ntfs_handle,LEAVE_FILE_SECURITY);
+			ntfs_get_file_security =
+					dlsym(ntfs_handle,GET_FILE_SECURITY);
+			ntfs_set_file_security =
+					dlsym(ntfs_handle,SET_FILE_SECURITY);
+			ntfs_read_directory =
+					dlsym(ntfs_handle,READ_DIRECTORY);
+			err = !ntfs_initialize_file_security
+				|| !ntfs_leave_file_security
+				|| !ntfs_get_file_security
+				|| !ntfs_set_file_security
+				|| !ntfs_read_directory;
+			if (error)
+				fprintf(stderr,"ntfs-3g API not available\n");
+		}
+	} else {
+		fprintf(stderr,"Could not open ntfs-3g library\n");
+		fprintf(stderr,"\nPlease set environment variable \"" ENVNTFS3G "\"\n");
+		fprintf(stderr,"to appropriate path and retry\n");
+	}
+	return (!err);
+#endif
+}
+
+STATIC boolean close_security_api(void)
+{
+#if USESTUBS
+	return (0);
+#else
+	return (!dlclose(ntfs_handle));
+#endif
+}
+
+/*
+ *		Open and close a volume (platform dependent)
+ *	assuming a single volume needs to be opened at any time
+ */
+
+STATIC boolean open_volume(const char *volume)
+{
+	boolean ok;
+
+	ok = DENIED;
+	if (!ntfs_context) {
+		ntfs_context = ntfs_initialize_file_security(volume,0);
+		if (ntfs_context) {
+			fprintf(stderr,"\"%s\" opened\n",volume);
+			ok = AGREED;
+		} else {
+			fprintf(stderr,"Could not open \"%s\"\n",volume);
+			fprintf(stderr,"Make sure \"%s\" is not mounted\n",volume);
+		}
+	} else
+		fprintf(stderr,"A volume is already open\n");
+	return (ok);
+}
+
+STATIC boolean close_volume(const char *volume)
+{
+	boolean r;
+
+	r = ntfs_leave_file_security(ntfs_context);
+	if (r)
+		fprintf(stderr,"\"%s\" closed\n",volume);
+	else
+		fprintf(stderr,"Could not close \"%s\"\n",volume);
+	ntfs_context = (void*)NULL;
+	return (r);
+}
+
+/*
+ *		A poor man's conversion of Unicode to UTF8
+ *	We are assuming outputs to terminal expect UTF8
+ */
+
+STATIC void to_utf8(char *dst, const char *src, unsigned int cnt)
+{
+	unsigned int ch;
+	unsigned int i;
+
+	for (i=0; i<cnt; i++) {
+		ch = *src++ & 255;
+		ch += (*src++ & 255) << 8;
+		if (ch < 0x80)
+			*dst++ = ch;
+		else
+			if (ch < 0x1000) {
+				*dst++ = 0xc0 + (ch >> 6);
+				*dst++ = 0x80 + (ch & 63);
+			} else {
+				*dst++ = 0xe0 + (ch >> 12);
+				*dst++ = 0x80 + ((ch >> 6) & 63);
+				*dst++ = 0x80 + (ch & 63);
+			}
+	}
+	*dst = 0;
+}
+
+STATIC int utf8_size(const char *src, unsigned int cnt)
+{
+	unsigned int ch;
+	unsigned int i;
+	int size;
+
+	size = 0;
+	for (i=0; i<cnt; i++) {
+		ch = *src++ & 255;
+		ch += (*src++ & 255) << 8;
+		if (ch < 0x80)
+			size++;
+		else
+			if (ch < 0x1000)
+				size += 2;
+			else
+				size += 3;
+	}
+	return (size);
+}
+
+#endif
+
+
+STATIC void welcome(void)
+{
+	printf("\nThis tool will help you to build a mapping of Windows users\n");
+	printf("to Linux users.\n");
+	printf("Be prepared to give Linux user id (uid) and group id (gid)\n");
+	printf("for owners of files which will be selected.\n");
+}
+
+STATIC unsigned int get2l(const unsigned char *attr, int p)
+{
+	int i;
+	unsigned int v;
+
+	v = 0;
+	for (i = 0; i < 2; i++)
+		v += (attr[p + i] & 255) << (8 * i);
+	return (v);
+}
+
+STATIC unsigned long get4l(const unsigned char *attr, int p)
+{
+	int i;
+	unsigned long v;
+
+	v = 0;
+	for (i = 0; i < 4; i++)
+		v += (attr[p + i] & 255L) << (8 * i);
+	return (v);
+}
+
+STATIC unsigned long long get6h(const unsigned char *attr, int p)
+{
+	int i;
+	unsigned long long v;
+
+	v = 0;
+	for (i = 0; i < 6; i++)
+		v = (v << 8) + (attr[p + i] & 255L);
+	return (v);
+}
+
+STATIC char *decodesid(const unsigned char *sid)
+{
+	char *str;
+	int i;
+	unsigned long long auth;
+	unsigned long subauth;
+
+	str = (char *)malloc(MAXSIDSZ);
+	if (str) {
+		strcpy(str, "S");
+		sprintf(&str[strlen(str)], "-%d", sid[0]);	/* revision */
+		auth = get6h(sid, 2);
+#ifdef WIN32
+		sprintf(&str[strlen(str)], "-%I64u", auth);	/* main authority */
+#else
+		sprintf(&str[strlen(str)], "-%llu", auth);	/* main authority */
+#endif
+		for (i = 0; (i < 8) && (i < sid[1]); i++) {
+			subauth = get4l(sid, 8 + 4 * i);
+			sprintf(&str[strlen(str)], "-%lu", subauth);	/* sub-authority */
+		}
+	}
+	return (str);
+}
+
+/*
+ *        Test whether a generic group (S-1-5-21- ... -513)
+ */
+
+STATIC boolean isgenericgroup(const char *sid)
+{
+	boolean yes;
+
+	yes = !strncmp(sid,"S-1-5-21-",9)
+		&& !strcmp(strrchr(sid,'-'),"-513");
+	return (yes);
+}
+
+STATIC unsigned char *makegroupsid(const unsigned char *sid)
+{
+	static unsigned char groupsid[MAXSIDSZ];
+	int size;
+
+	size = 8 + 4*sid[1];
+	memcpy(groupsid, sid, size);
+		/* replace last level by 513 */
+	groupsid[size - 4] = 1;
+	groupsid[size - 3] = 2;
+	groupsid[size - 2] = 0;
+	groupsid[size - 1] = 0;
+	return (groupsid);
+}
+
+STATIC void domapping(const char *accname, const char *filename,
+		const char *dir, const unsigned char *sid, int type)
+{
+	char buf[81];
+	char *sidstr;
+	char *idstr;
+	int sidsz;
+	boolean reject;
+	struct MAPPING *mapping;
+	char *login;
+	char *p;
+
+	if ((get6h(sid, 2) == 5) && (get4l(sid, 8) == 21)) {
+		sidstr = decodesid(sid);
+		mapping = firstmapping;
+		while (mapping && strcmp(mapping->sidstr, sidstr))
+			mapping = mapping->next;
+		if (mapping
+		    && (mapping->defined
+			 || !accname
+			 || !strcmp(mapping->login, accname)))
+			free(sidstr);	/* decision already known */
+		else {
+			do {
+				reject = DENIED;
+				printf("\n");
+				if (accname)
+					printf("Under Windows login \"%s\"\n", accname);
+				if (dir)
+					printf("   in directory \"%s\"\n",dir);
+				printf("   file \"%s\" has no mapped %s\n",
+					       filename,(type ? "group" : "owner"));
+				printf("By which Linux login should this file be owned ?\n");
+				printf("Enter %s of login, or just press \"enter\" if this file\n",
+					(type ? "gid" : "uid"));
+				printf("does not belong to a user, or you do not known to whom\n");
+				printf("\n");
+				if (type)
+					printf("Group : ");
+				else
+					printf("User : ");
+				p = fgets(buf, 80, stdin);
+				if (p && p[0] && (p[strlen(p) - 1] == '\n'))
+					p[strlen(p) - 1] = '\0';
+
+				if (p && p[0]
+					 && ((p[0] == '0') || !strcmp(p, "root"))) {
+					printf("Please do not map users to root\n");
+					printf("Administrators will be mapped automatically\n");
+					reject = AGREED;
+				}
+				if (reject)
+					printf("Please retry\n");
+			} while (reject);
+			if (!mapping) {
+				mapping =
+				    (struct MAPPING *)
+				    malloc(sizeof(struct MAPPING));
+				mapping->next = (struct MAPPING *)NULL;
+				mapping->defined = DENIED;
+				if (lastmapping)
+					lastmapping->next = mapping;
+				else
+					firstmapping = mapping;
+				lastmapping = mapping;
+			}
+			if (mapping) {
+				if (p && p[0]) {
+					idstr = (char *)malloc(strlen(p) + 1);
+					if (idstr) {
+						strcpy(idstr, p);
+						if (type) {
+							mapping->uidstr = "";
+							mapping->gidstr = idstr;
+						} else {
+							mapping->uidstr = idstr;
+							mapping->gidstr = idstr;
+						}
+						mapping->defined = AGREED;
+					}
+				}
+				mapping->sidstr = sidstr;
+				if (accname) {
+					login = (char*)malloc(strlen(accname) + 1);
+					if (login)
+						strcpy(login,accname);
+					mapping->login = login;
+				} else
+					mapping->login = (char*)NULL;
+				sidsz = 8 + sid[1]*4;
+				p = (char*)malloc(sidsz);
+				if (p) {
+					memcpy(p, sid, sidsz);
+				}
+				mapping->sid = (unsigned char*)p;
+			}
+		}
+	}
+}
+
+STATIC void listaclusers(const char *accname, const unsigned char *attr, int off)
+{
+	int i;
+	int cnt;
+	int x;
+
+	cnt = get2l(attr, off + 4);
+	x = 8;
+	for (i = 0; i < cnt; i++) {
+		domapping(accname, (char *)NULL, (char*)NULL, 
+                                       &attr[off + x + 8], 2);
+		x += get2l(attr, off + x + 2);
+	}
+}
+
+#ifdef WIN32
+
+STATIC void account(const char *accname, const char *dir, const char *name, int type)
+{
+	unsigned char attr[MAXATTRSZ];
+	unsigned long attrsz;
+	char *fullname;
+	int attrib;
+
+	fullname = (char *)malloc(strlen(dir) + strlen(name) + 2);
+	if (fullname) {
+		strcpy(fullname, dir);
+		strcat(fullname, "\\");
+		strcat(fullname, name);
+		attrib = GetFileAttributes(fullname);
+		if (attrib & 0x10) {	/* only directories processed */
+			if (GetFileSecurity
+			    (fullname, OWNER_SECURITY_INFORMATION, attr, MAXATTRSZ,
+			     &attrsz)) {
+				domapping(accname, name, dir, &attr[20], 0);
+				attrsz = 0;
+				if (GetFileSecurity
+				    (fullname, GROUP_SECURITY_INFORMATION, attr,
+				     MAXATTRSZ, &attrsz))
+					domapping(accname, name, dir, &attr[20], 1);
+				else
+					printf("   No group SID\n");
+				attrsz = 0;
+				if (GetFileSecurityA
+				    (fullname, DACL_SECURITY_INFORMATION, attr,
+				     MAXATTRSZ, &attrsz)) {
+					if (type == 0)
+						listaclusers(accname, attr, 20);
+				} else
+					printf
+					    ("   No discretionary access control list\n");
+			}
+		}
+	free(fullname);
+	}
+}
+
+#else
+
+STATIC void account(const char *accname, const char *dir, const char *name, int type)
+{
+	unsigned char attr[MAXATTRSZ];
+	DWORD attrsz;
+	char *fullname;
+
+	fullname = (char *)malloc(strlen(dir) + strlen(name) + 2);
+	if (fullname) {
+		strcpy(fullname, dir);
+		strcat(fullname, "/");
+		strcat(fullname, name);
+		if (ntfs_get_file_security(ntfs_context,
+			fullname, OWNER_SECURITY_INFORMATION,
+			(char*)attr, MAXATTRSZ, &attrsz)) {
+			domapping(accname, name, dir, &attr[20], 0);
+			attrsz = 0;
+			if (ntfs_get_file_security(ntfs_context,
+			     fullname, GROUP_SECURITY_INFORMATION,
+			     (char*)attr, MAXATTRSZ, &attrsz))
+				domapping(accname, name, dir, &attr[20], 1);
+			else
+				printf("   No group SID\n");
+			attrsz = 0;
+			if (ntfs_get_file_security(ntfs_context,
+			     fullname, DACL_SECURITY_INFORMATION,
+			     (char*)attr, MAXATTRSZ, &attrsz)) {
+				if (type == 0)
+					listaclusers(accname, attr, 20);
+			} else
+				printf("   No discretionary access control list for %s !\n",
+					dir);
+		}
+	free(fullname);
+	}
+}
+
+#endif
+
+
+/*
+ *		recursive search of file owners and groups in a directory
+ */
+
+#ifdef WIN32
+
+STATIC boolean recurse(const char *accname, const char *dir, int levels)
+{
+	WIN32_FIND_DATA found;
+	HANDLE search;
+	char *filter;
+	char *fullname;
+	boolean err;
+
+	err = DENIED;
+	filter = (char *)malloc(strlen(dir) + 5);
+	if (filter) {
+		strcpy(filter, dir);
+		strcat(filter, "\\*.*");
+		search = FindFirstFile(filter, &found);
+		if (search != INVALID_HANDLE_VALUE) {
+			do {
+				if (found.cFileName[0] != '.') {
+					account(accname, dir, found.cFileName,1);
+					if (levels > 0) {
+						fullname =
+						    (char *)malloc(strlen(dir) +
+								   strlen(found.cFileName)
+								   + 2);
+						if (fullname) {
+							strcpy(fullname, dir);
+							strcat(fullname, "\\");
+							strcat(fullname,
+							       found.cFileName);
+							recurse(accname,
+								fullname,
+								levels - 1);
+							free(fullname);
+						}
+					}
+				}
+			} while (FindNextFile(search, &found));
+			FindClose(search);
+		}
+		free(filter);
+	} else {
+		printf("Directory %s not found\n",dir);
+		err = AGREED;
+	}
+	return (!err);
+}
+
+#else
+
+STATIC boolean recurse(const char *accname, const char *dir, int levels, int docset);
+
+STATIC int callback(struct CALLBACK *context, char *ntfsname,
+	int length, int type, long long pos, unsigned long long mft_ref,
+	unsigned int dt_type)
+{
+	char *fullname;
+	char *accname;
+	char *name;
+
+	unused((void*)&pos);
+	unused((void*)&mft_ref);
+	unused((void*)&dt_type);
+	fullname = (char *)malloc(strlen(context->dir)
+			 + utf8_size(ntfsname, length) + 2);
+	if (fullname) {
+		if (strcmp(context->dir,"/")) {
+			strcpy(fullname, context->dir);
+			strcat(fullname, "/");
+		} else
+			strcpy(fullname,"/");
+			/* Unicode to ascii conversion by a lazy man */
+		name = &fullname[strlen(fullname)];
+		to_utf8(name, ntfsname, length);
+			/* ignore special files and DOS names */
+		if ((type != 2)
+		   && strcmp(name,".")
+		   && strcmp(name,"..")
+		   && (name[0] != '$')) {
+			switch (context->docset) {
+			case 2 :
+					/*
+					 * only "Documents and Settings"
+					 * or "Users"
+					 */
+				if (!strcmp(name,OWNERS1)
+				   || !strcmp(name,OWNERS2)) {
+					recurse((char*)NULL, fullname, 2, 1);
+				}
+				break;
+					/*
+					 * within "Documents and Settings"
+					 * or "Users"
+					 */
+			case 1 :
+				accname = (char*)malloc(strlen(name) + 1);
+				if (accname) {
+					strcpy(accname, name);
+					if (context->levels > 0)
+						recurse(name, fullname,
+							context->levels - 1, 0);
+				}
+				break;
+					/*
+					 * not related to "Documents and Settings"
+					 * or "Users"
+					 */
+			case 0 :
+				account(context->accname, context->dir,
+					name, 1);
+				if (context->levels > 0)
+					recurse(context->accname, fullname,
+						context->levels - 1, 0);
+				break;
+			}
+		}
+		free(fullname);
+	}
+/* check expected return value */
+	return (0);
+}
+
+STATIC boolean recurse(const char *accname, const char *dir, int levels, int docset)
+{
+	struct CALLBACK context;
+	boolean err;
+
+	err = DENIED;
+	context.dir = dir;
+	context.accname = accname;
+	context.levels = levels;
+	context.docset = docset;
+	ntfs_read_directory(ntfs_context,dir,callback,&context);
+	return (!err);
+}
+#endif
+
+/*
+ *          Search directory "Documents and Settings" for user accounts
+ */
+
+#ifdef WIN32
+
+STATIC boolean getusers(const char *dir, int levels)
+{
+	WIN32_FIND_DATA found;
+	HANDLE search;
+	char *filter;
+	char *fullname;
+	char *accname;
+	boolean err;
+	const char *docset;
+
+	/* first get files from "Documents and Settings" */
+	err = DENIED;
+	if (sizeof(OWNERS1) > sizeof(OWNERS2))
+		filter = (char *)malloc(strlen(dir) + strlen(OWNERS1) + 6);
+	else
+		filter = (char *)malloc(strlen(dir) + strlen(OWNERS2) + 6);
+	if (filter) {
+		docset = OWNERS1;
+		strcpy(filter, dir);
+		strcat(filter, "\\");
+		strcat(filter, docset);
+		strcat(filter, "\\*.*");
+		search = FindFirstFile(filter, &found);
+			/* if failed, retry with "Users" */
+		if (search == INVALID_HANDLE_VALUE) {
+			docset = OWNERS2;
+			strcpy(filter, dir);
+			strcat(filter, "\\");
+			strcat(filter, docset);
+			strcat(filter, "\\*.*");
+			search = FindFirstFile(filter, &found);
+		}
+		if (search != INVALID_HANDLE_VALUE) {
+			do {
+				if (found.cFileName[0] != '.') {
+					fullname =
+					    (char *)malloc(strlen(dir)
+							 + strlen(docset)
+							 + strlen(found.cFileName) + 3);
+					accname = (char *)
+					       malloc(strlen(found.cFileName) + 1);
+					if (fullname && accname) {
+						strcpy(accname,
+						       found.cFileName);
+						
+						strcpy(fullname, dir);
+						strcat(fullname, "\\");
+						strcat(fullname, docset);
+						strcat(fullname, "\\");
+						strcat(fullname,
+						       found.cFileName);
+						recurse(accname, fullname, 2);
+
+						free(fullname);
+					}
+				}
+			} while (FindNextFile(search, &found));
+			FindClose(search);
+		} else {
+			printf("No subdirectory found in %s\\%s\n",dir,docset);
+		}
+			/* now search in other directories */
+		strcpy(filter, dir);
+		strcat(filter, "\\*.*");
+		search = FindFirstFile(filter, &found);
+		if (search != INVALID_HANDLE_VALUE) {
+			do {
+				if ((found.cFileName[0] != '.')
+					&& strcmp(found.cFileName,OWNERS1)
+					&& strcmp(found.cFileName,OWNERS2)) {
+					fullname =
+					    (char *)malloc(strlen(dir)
+							 + strlen(found.cFileName) + 2);
+					if (fullname) {
+						strcpy(fullname, dir);
+						strcat(fullname, "\\");
+						strcat(fullname,
+						       found.cFileName);
+						recurse((char*)NULL, fullname, 2);
+						free(fullname);
+					}
+				}
+			} while (FindNextFile(search, &found));
+			FindClose(search);
+		} else {
+			printf("No directory found in %s\n",dir);
+			err = AGREED;
+		}
+	}
+	return (!err);
+}
+
+#else
+
+STATIC boolean getusers(const char *dir, int levels)
+{
+	boolean err;
+	struct CALLBACK context;
+
+	printf("* Search for \"" OWNERS1 "\" and \"" OWNERS2 "\"\n");
+	err = DENIED;
+	context.dir = dir;
+	context.accname = (const char*)NULL;
+	context.levels = levels;
+	context.docset = 2;
+	ntfs_read_directory(ntfs_context,dir,callback,&context);
+	printf("* Search for other directories %s\n",dir);
+	context.docset = 0;
+	ntfs_read_directory(ntfs_context,dir,callback,&context);
+
+	return (!err);
+}
+
+#endif
+
+#ifdef WIN32
+/*
+ *		Get the current login name (Win32 only)
+ */
+
+STATIC void loginname(boolean silent)
+{
+	char *winname;
+	char *domain;
+	unsigned char *sid;
+	unsigned long namesz;
+	unsigned long sidsz;
+	unsigned long domainsz;
+	int nametype;
+	boolean ok;
+	int r;
+
+	ok = FALSE;
+	winname = (char*)malloc(MAXNAMESZ);
+	domain = (char*)malloc(MAXNAMESZ);
+	sid = (char*)malloc(MAXSIDSZ);
+
+	namesz = MAXNAMESZ;
+	domainsz = MAXNAMESZ;
+	sidsz = MAXSIDSZ;
+	if (winname
+	    && domain
+	    && sid
+	    && GetUserName(winname,&namesz)) {
+		winname[namesz] = '\0';
+		if (!silent)
+			printf("Your current user name is %s\n",winname);
+		nametype = 1;
+		r = LookupAccountName((char*)NULL,winname,sid,&sidsz,
+			domain,&domainsz,&nametype);
+		if (r) {
+			domain[domainsz] = '\0';
+			if (!silent)
+				printf("Your account domain is %s\n",domain);
+			ok = AGREED;
+		}
+	   }
+	if (ok) {
+		currentwinname = winname;
+		currentdomain = domain;
+		currentsid = sid;
+	} else {
+		currentwinname = (char*)NULL;
+		currentdomain = (char*)NULL;
+		currentsid = (unsigned char*)NULL;
+	}
+}
+
+/*
+ *		Minimal output on stdout
+ */
+
+boolean minimal(unsigned char *sid)
+{
+	const unsigned char *groupsid;
+	boolean ok;
+
+	ok = DENIED;
+	if (sid) {
+		groupsid = makegroupsid(sid);
+		printf("# %s\n",BANNER);
+		printf("# For Windows account \"%s\" in domain \"%s\"\n",
+			currentwinname, currentdomain);
+		printf("# Replace \"user\" and \"group\" hereafter by matching Linux login\n");
+		printf("user::%s\n",decodesid(sid));
+		printf(":group:%s\n",decodesid(groupsid));
+		ok = AGREED;
+	}
+	return (ok);
+}
+
+#endif
+
+STATIC boolean outputmap(const char *volume, const char *dir)
+{
+	char buf[256];
+	int fn;
+	char *fullname;
+	char *backup;
+	struct MAPPING *mapping;
+	boolean done;
+	boolean err;
+	boolean undecided;
+#ifdef WIN32
+#else
+	struct stat st;
+	int s;
+#endif
+
+	done = DENIED;
+	fullname = (char *)malloc(strlen(MAPFILE) + 1
+				+ strlen(volume) + 1
+				+ (dir ? strlen(dir) + 1 : 0));
+	if (fullname) {
+#ifdef WIN32
+		strcpy(fullname, volume);
+		if (dir && dir[0]) {
+			strcat(fullname, "\\");
+			strcat(fullname,dir);
+		}
+
+			/* build directory, if not present */
+		if (GetFileAttributes(fullname) & 0x80000000) {
+			printf("* Creating directory %s\n", fullname);
+			mkdir(fullname);
+		}
+
+		strcat(fullname, "\\");
+		strcat(fullname, MAPFILE);
+		printf("\n");
+
+		if (!(GetFileAttributes(fullname) & 0x80000000)) {
+			backup = (char*)malloc(strlen(fullname) + 5);
+			strcpy(backup,fullname);
+			strcat(backup,".bak");
+			unlink(backup);
+			if (!rename(fullname,backup))
+				printf("* Old mapping file moved to %s\n",backup);
+		}
+#else
+		strcpy(fullname, MAPFILE);
+		printf("\n");
+
+		s = stat(fullname,&st);
+		if (!s) {
+			backup = (char*)malloc(strlen(fullname + 5));
+			strcpy(backup,fullname);
+			strcat(backup,".bak");
+			if (rename(fullname,backup))
+				printf("* Old mapping file moved to %s\n",backup);
+		}
+#endif
+
+		printf("* Creating file %s\n", fullname);
+		err = DENIED;
+#ifdef WIN32
+		fn = open(fullname,O_CREAT + O_TRUNC + O_WRONLY + O_BINARY, 
+			S_IREAD + S_IWRITE);
+#else
+		fn = open(fullname,O_CREAT + O_TRUNC + O_WRONLY,
+			S_IREAD + S_IWRITE);
+#endif
+		if (fn > 0) {
+			sprintf(buf,"# %s\n",BANNER);
+			if (!write(fn,buf,strlen(buf)))
+				err = AGREED;
+			printf("%s",buf);
+			undecided = DENIED;
+				/* records for owner only or group only */
+			for (mapping = firstmapping; mapping && !err;
+			     mapping = mapping->next)
+				if (mapping->defined
+				    && (!mapping->uidstr[0] || !mapping->gidstr[0])) {
+					sprintf(buf,"%s:%s:%s\n",
+						mapping->uidstr,
+						mapping->gidstr,
+						mapping->sidstr);
+					if (!write(fn,buf,strlen(buf)))
+						err = AGREED;
+					printf("%s",buf);
+				} else
+					undecided = AGREED;
+				/* records for both owner and group */
+			for (mapping = firstmapping; mapping && !err;
+			     mapping = mapping->next)
+				if (mapping->defined
+				    && mapping->uidstr[0] && mapping->gidstr[0]) {
+					sprintf(buf,"%s:%s:%s\n",
+						mapping->uidstr,
+						mapping->gidstr,
+						mapping->sidstr);
+					if (!write(fn,buf,strlen(buf)))
+						err = AGREED;
+					printf("%s",buf);
+				} else
+					undecided = AGREED;
+			done = !err;
+			close(fn);
+			if (undecided) {
+				printf("Undecided :\n");
+				for (mapping = firstmapping; mapping;
+				     mapping = mapping->next)
+					if (!mapping->defined) {
+						printf("   %s\n", mapping->sidstr);
+					}
+			}
+#ifndef WIN32
+			printf("\n* You will have to move the file \"" MAPFILE "\"\n");
+			printf("  to directory \"" MAPDIR "\" after mounting\n");
+#endif
+		}
+	}
+	if (!done)
+		fprintf(stderr, "* Could not create mapping file \"%s\"\n", fullname);
+	return (done);
+}
+
+STATIC boolean sanitize(void)
+{
+	char buf[81];
+	boolean ok;
+	int ownercnt;
+	int groupcnt;
+	struct MAPPING *mapping;
+	struct MAPPING *firstowner;
+	struct MAPPING *genericgroup;
+	struct MAPPING *group;
+	char *sidstr;
+
+		/* count owners and groups */
+		/* and find first user, and a generic group */
+	ownercnt = 0;
+	groupcnt = 0;
+	firstowner = (struct MAPPING*)NULL;
+	genericgroup = (struct MAPPING*)NULL;
+	for (mapping=firstmapping; mapping; mapping=mapping->next) {
+		if (mapping->defined && mapping->uidstr[0]) {
+			if (!ownercnt)
+				firstowner = mapping;
+			ownercnt++;
+		}
+		if (mapping->defined && mapping->gidstr[0] && !mapping->uidstr[0]) {
+			groupcnt++;
+		}
+		if (!mapping->defined && isgenericgroup(mapping->sidstr)) {
+			genericgroup = mapping;
+		}
+	}
+#ifdef WIN32
+		/* no user defined, on Windows, suggest a mapping */
+		/* based on account currently used */
+	if (!ownercnt && currentwinname && currentsid) {
+		char *owner;
+		char *p;
+
+		printf("\nYou have defined no file owner,\n");
+		printf("   please enter the Linux login which should be mapped\n");
+		printf("   to account you are currently using\n");
+		printf("   Linux user ? ");
+		p = fgets(buf, 80, stdin);
+		if (p && p[0] && (p[strlen(p) - 1] == '\n'))
+			p[strlen(p) - 1] = '\0';
+		if (p && p[0]) {
+			firstowner = (struct MAPPING*)malloc(sizeof(struct MAPPING));
+			owner = (char*)malloc(strlen(p) + 1);
+			if (firstowner && owner) {
+				strcpy(owner, p);
+				firstowner->next = firstmapping;
+				firstowner->uidstr = owner;
+				firstowner->gidstr = "";
+				firstowner->sidstr = decodesid(currentsid);
+				firstowner->sid = currentsid;
+				firstmapping = firstowner;
+				ownercnt++;
+				/* prefer a generic group with the same authorities */
+				for (mapping=firstmapping; mapping;
+						mapping=mapping->next)
+					if (!mapping->defined
+					    && isgenericgroup(mapping->sidstr)
+					    && !memcmp(firstowner->sidstr,
+							mapping->sidstr,
+							strlen(mapping->sidstr)-3))
+						genericgroup = mapping;
+			}
+		}
+	}
+#endif
+	if (ownercnt) {
+			/*
+			 *   No group was selected, but there were a generic group
+			 *   insist in using it, associated to the first user
+			 */
+		if (!groupcnt) {
+			printf("\nYou have defined no group, this can cause problems\n");
+			printf("Do you accept defining a standard group ?\n");
+			if (!fgets(buf,80,stdin)
+			   || ((buf[0] != 'n')
+			      && (buf[0] != 'N'))) {
+				if (genericgroup) {
+					genericgroup->uidstr = "";
+					genericgroup->gidstr = firstowner->uidstr;
+					genericgroup->defined = AGREED;
+				} else {
+					group = (struct MAPPING*)
+						malloc(sizeof(struct MAPPING));
+					sidstr = decodesid(
+						makegroupsid(firstowner->sid));
+					if (group && sidstr) {
+						group->uidstr = "";
+						group->gidstr = firstowner->
+								uidstr;
+						group->sidstr = sidstr;
+						group->defined = AGREED;
+						group->next = firstmapping;
+						firstmapping = group;
+					}
+				}
+			}
+		}
+		ok = AGREED;
+	} else {
+		printf("\nYou have defined no user, no mapping can be built\n");
+		ok = DENIED;
+	}
+
+	return (ok);
+}
+
+STATIC boolean checkoptions(int argc, char *argv[], boolean silent)
+{
+	boolean err;
+#ifdef WIN32
+	int xarg;
+	const char *pvol;
+
+	if (silent)
+		err = (argc != 1);
+	else {
+		err = (argc < 2);
+		for (xarg=1; (xarg<argc) && !err; xarg++) {
+			pvol = argv[xarg];
+			if (pvol[0] && (pvol[1] == ':') && !pvol[2]) {
+				err = !(((pvol[0] >= 'A') && (pvol[0] <= 'Z'))
+					|| ((pvol[0] >= 'a') && (pvol[0] <= 'z')));
+			}
+		}
+	}
+	if (err) {
+		fprintf(stderr, "Usage : usermap [vol1: [vol2: ...]]\n");
+		fprintf(stderr, "    \"voln\" are the letters of the partition to share with Linux\n");
+		fprintf(stderr, "        eg C:\n");
+		fprintf(stderr, "    the Windows system partition should be named first\n");
+	}
+#else
+	unused((void*)argv);
+	unused((void*)&silent);
+	err = (argc < 2);
+	if (err) {
+		fprintf(stderr, "Usage : usermap dev1 [dev2 ...]\n");
+		fprintf(stderr, "    \"dev.\" are the devices to share with Windows\n");
+		fprintf(stderr, "        eg /dev/sdb1\n");
+		fprintf(stderr, "    the devices should not be mounted\n");
+		fprintf(stderr, "    the Windows system partition should be named first\n");
+	} else
+		if (getuid()) {
+			fprintf(stderr, "\nSorry, only root can start usermap\n");
+			err = AGREED;
+		}
+#endif
+	return (!err);
+}
+
+STATIC boolean process(int argc, char *argv[])
+{
+	boolean ok;
+	int xarg;
+	int targ;
+
+	firstmapping = (struct MAPPING *)NULL;
+	lastmapping = (struct MAPPING *)NULL;
+	ok = AGREED;
+#ifdef WIN32
+	for (xarg=1; (xarg<argc) && ok; xarg++) {
+		printf("\n* Scanning \"%s\" (two levels)\n",argv[xarg]);
+		ok = getusers(argv[xarg],2);
+	}
+#else
+	for (xarg=1; (xarg<argc) && ok; xarg++)
+		if (open_volume(argv[xarg])) {
+			printf("\n* Scanning \"%s\" (two levels)\n",argv[xarg]);
+			ok = getusers("/",2);
+			close_volume(argv[xarg]);
+		} else
+			ok = DENIED;
+#endif
+	if (ok && sanitize()) {
+		targ = (argc > 2 ? 2 : 1);
+		if (!outputmap(argv[targ],MAPDIR)) {
+			printf("Trying to write file on root directory\n");
+			if (outputmap(argv[targ],(const char*)NULL)) {
+				printf("\nNote : you will have to move the file to directory \"%s\" on Linux\n",
+					MAPDIR);
+			} else
+				ok = DENIED;
+		} else
+			ok = DENIED;
+	} else
+		ok = DENIED;
+	return (ok);
+}
+
+int main(int argc, char *argv[])
+{
+	boolean ok;
+	boolean silent;
+
+	silent = !isatty(1);
+	if (!silent)
+		welcome();
+	if (checkoptions(argc, argv, silent)) {
+#ifdef WIN32
+		loginname(silent);
+		if (silent)
+			ok = minimal(currentsid);
+		else
+			ok = process(argc, argv);
+#else
+		if (open_security_api()) {
+			ok = process(argc,argv);
+			if (!close_security_api()) ok = DENIED;
+		}
+		else {
+			ok = DENIED;
+		}
+#endif
+	} else
+		ok = DENIED;
+	if (!ok)
+		exit(1);
+	return (0);
+}
diff --git a/stamp-h1 b/stamp-h1
new file mode 100755
index 0000000000000000000000000000000000000000..4547fe1b5efa99ebbf20e1fa55fdbd528abd3a97
--- /dev/null
+++ b/stamp-h1
@@ -0,0 +1 @@
+timestamp for config.h