summaryrefslogtreecommitdiffstats
path: root/dosfstools
diff options
context:
space:
mode:
Diffstat (limited to 'dosfstools')
-rw-r--r--dosfstools/Android.mk58
-rw-r--r--dosfstools/COPYING674
-rw-r--r--dosfstools/ChangeLog2096
-rw-r--r--dosfstools/Makefile170
-rw-r--r--dosfstools/VERSION1
-rwxr-xr-xdosfstools/bin/Nindent18
-rw-r--r--dosfstools/doc/ANNOUNCE.mkdosfs41
-rw-r--r--dosfstools/doc/ChangeLog.dosfsck10
-rw-r--r--dosfstools/doc/ChangeLog.dosfstools-2.x161
-rw-r--r--dosfstools/doc/ChangeLog.mkdosfs18
-rw-r--r--dosfstools/doc/README.dosfsck60
-rw-r--r--dosfstools/doc/README.dosfstools-2.x60
-rw-r--r--dosfstools/doc/README.mkdosfs50
-rw-r--r--dosfstools/doc/TODO.dosfstools-2.x14
-rw-r--r--dosfstools/manpages/Makefile50
-rwxr-xr-xdosfstools/manpages/bin/update-version.sh55
-rw-r--r--dosfstools/manpages/de/fatlabel.de.868
-rw-r--r--dosfstools/manpages/de/fsck.fat.de.8189
-rw-r--r--dosfstools/manpages/de/mkfs.fat.de.8172
-rw-r--r--dosfstools/manpages/en/fatlabel.865
-rw-r--r--dosfstools/manpages/en/fsck.fat.8206
-rw-r--r--dosfstools/manpages/en/mkfs.fat.8178
-rw-r--r--dosfstools/manpages/po/de/fatlabel.8.po173
-rw-r--r--dosfstools/manpages/po/de/fsck.fat.8.po559
-rw-r--r--dosfstools/manpages/po/de/mkfs.fat.8.po481
-rw-r--r--dosfstools/manpages/po4a.cfg5
-rw-r--r--dosfstools/manpages/pot/fatlabel.8.pot176
-rw-r--r--dosfstools/manpages/pot/fsck.fat.8.pot562
-rw-r--r--dosfstools/manpages/pot/mkfs.fat.8.pot484
-rw-r--r--dosfstools/src/boot.c568
-rw-r--r--dosfstools/src/boot.h32
-rw-r--r--dosfstools/src/check.c1089
-rw-r--r--dosfstools/src/check.h40
-rw-r--r--dosfstools/src/common.c119
-rw-r--r--dosfstools/src/common.h56
-rw-r--r--dosfstools/src/fat.c558
-rw-r--r--dosfstools/src/fat.h85
-rw-r--r--dosfstools/src/fatlabel.c144
-rw-r--r--dosfstools/src/file.c276
-rw-r--r--dosfstools/src/file.h72
-rw-r--r--dosfstools/src/fsck.fat.c215
-rw-r--r--dosfstools/src/fsck.fat.h191
-rw-r--r--dosfstools/src/io.c232
-rw-r--r--dosfstools/src/io.h71
-rw-r--r--dosfstools/src/lfn.c528
-rw-r--r--dosfstools/src/lfn.h39
-rw-r--r--dosfstools/src/mkfs.fat.c1757
-rw-r--r--dosfstools/src/msdos_fs.h61
-rw-r--r--dosfstools/src/version.h29
49 files changed, 13016 insertions, 0 deletions
diff --git a/dosfstools/Android.mk b/dosfstools/Android.mk
new file mode 100644
index 000000000..7b6d62349
--- /dev/null
+++ b/dosfstools/Android.mk
@@ -0,0 +1,58 @@
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := \
+ src/boot.c \
+ src/check.c \
+ src/common.c \
+ src/fat.c \
+ src/file.c \
+ src/io.c \
+ src/lfn.c \
+ src/fsck.fat.c
+
+LOCAL_SHARED_LIBRARIES := libc
+LOCAL_CFLAGS += -D_USING_BIONIC_
+LOCAL_CFLAGS += -DUSE_ANDROID_RETVALS
+LOCAL_CFLAGS += -Wno-sign-compare
+LOCAL_MODULE = fsck.fat
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := \
+ src/boot.c \
+ src/check.c \
+ src/common.c \
+ src/fat.c \
+ src/file.c \
+ src/io.c \
+ src/lfn.c \
+ src/fatlabel.c
+
+LOCAL_C_INCLUDES += bionic/libc/kernel/common
+LOCAL_SHARED_LIBRARIES := libc
+LOCAL_CFLAGS += -D_USING_BIONIC_
+LOCAL_CFLAGS += -Wno-sign-compare
+LOCAL_MODULE = fatlabel
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := src/mkfs.fat.c
+
+LOCAL_SHARED_LIBRARIES := libc
+LOCAL_CFLAGS += -D_USING_BIONIC_
+LOCAL_CFLAGS += -Wno-sign-compare
+LOCAL_MODULE = mkfs.fat
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
+include $(BUILD_EXECUTABLE)
+
+endif
diff --git a/dosfstools/COPYING b/dosfstools/COPYING
new file mode 100644
index 000000000..94a9ed024
--- /dev/null
+++ b/dosfstools/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/dosfstools/ChangeLog b/dosfstools/ChangeLog
new file mode 100644
index 000000000..f6a1e3da9
--- /dev/null
+++ b/dosfstools/ChangeLog
@@ -0,0 +1,2096 @@
+commit ad1342e
+Author: Andreas Bombe <aeb@debian.org>
+Date: Sat May 16 02:10:18 2015 +0200
+
+ manpages: Mark MT and ME tags as untranslated for po4a
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit 3ed9ec2
+Author: Andreas Bombe <aeb@debian.org>
+Date: Sun May 10 19:59:02 2015 +0200
+
+ mkfs: Small changes to FAT32 cluster size selection
+
+ Put the cluster size selection back in line with the table used in
+ Microsoft's fatgen103.pdf and fix the comment. This only involved
+ changing some comparison operators, all values stayed the same.
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit 9984552
+Author: Andreas Bombe <aeb@debian.org>
+Date: Mon Apr 20 23:41:34 2015 +0200
+
+ fsck: Mention -r is default in usage message
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit 3eaca68
+Author: Andreas Bombe <aeb@debian.org>
+Date: Mon Apr 20 23:30:56 2015 +0200
+
+ manpages: Remove obsolete information about Linux FAT support
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit a5e34de
+Author: Andreas Bombe <aeb@debian.org>
+Date: Thu Apr 16 23:16:08 2015 +0200
+
+ manpages: Convert the rest of argument placeholders to upper case
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit 2303765
+Author: Andreas Bombe <aeb@debian.org>
+Date: Thu Apr 16 22:51:20 2015 +0200
+
+ manpages: Fix formatting
+
+ Make the manpages conform to the rules for groff sources. First,
+ eliminate empty lines because these create vertical spaces where it
+ isn't desired. Man page sources should not contain empty lines. Second,
+ put a line break between sentences in a paragraph. A period is
+ recognized and formatted as a full stop period only when a line break
+ comes right after it.
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit d3969b8
+Author: Andreas Bombe <aeb@debian.org>
+Date: Fri Apr 10 20:32:50 2015 +0200
+
+ fsck: Verify first cluster of a file is not 1
+
+ Previously the FAT was checked for any out of bounds entries which were
+ cleared. However the first cluster of a file, as specified in its
+ directory entry, was not verified to not be 1.
+
+ In addition to missing this filesystem error, code that correctly
+ assumes the FAT contained no bad entries anymore could still look up
+ invalid table indices depending on the value stored in entry 1. With
+ the right values and FAT size this can lead to a segfault by accessing
+ unallocated memory.
+
+ Now test_file() will ignore files where the first cluster equals 1 and
+ an additional check in check_file() will truncate them.
+
+ This bug was reported in http://bugs.debian.org/773885 by Jakub Wilk.
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit 2a56575
+Author: Andreas Bombe <aeb@debian.org>
+Date: Thu Apr 2 23:35:00 2015 +0200
+
+ Simplify synopses of man pages
+
+ Since there is only one mode of invocation for the tools, it is
+ somewhat pointless to list every possible option in the synopsis.
+
+ Fix a few style inconsistencies in addition, specifically that
+ placeholders for option arguments are in capital letters and should be
+ shown where the option is described.
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit 40f1436
+Author: Andreas Bombe <aeb@debian.org>
+Date: Wed Apr 1 20:55:58 2015 +0200
+
+ Update homepage and maintainer sections of man pages
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit 0169db8
+Author: Andreas Bombe <aeb@debian.org>
+Date: Wed Apr 1 20:05:01 2015 +0200
+
+ mkfs: Show a clearer message that file already exists with -C
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit 2967e27
+Author: Andreas Bombe <aeb@debian.org>
+Date: Mon Mar 30 21:12:51 2015 +0200
+
+ mkfs: Remove O_TRUNC from file creation call
+
+ open() is called with O_EXCL | O_CREAT, so it will definitely create a
+ new, empty file or error out. O_TRUNC is superfluous and may be harmless
+ in practice but its effect under these circumstances is unspecified.
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit 90612df
+Author: Andreas Bombe <aeb@debian.org>
+Date: Mon Mar 30 21:09:51 2015 +0200
+
+ mkfs: Use ftruncate() for expanding created file
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit 58e8e09
+Author: Andreas Bombe <aeb@debian.org>
+Date: Tue Mar 24 21:32:40 2015 +0100
+
+ mkfs: Add --invariant option
+
+ The --invariant option is designed to prevent random or time based
+ differences to end up in generated filesystems so that multiple runs
+ generate on the same file or device create completely identical results.
+
+ This is intended for debugging or regression testing of mkfs.fat.
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit 354feaf
+Author: Andreas Bombe <aeb@debian.org>
+Date: Thu Mar 19 21:35:21 2015 +0100
+
+ mkfs: Add long option parsing
+
+ Add long option parsing with getopt_long() to mkfs and define --help as
+ the first long option. The usage() function now takes an exit code
+ parameter so that the --help option handling can exit the program with
+ a success exit code.
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit b611549
+Author: Andreas Bombe <aeb@debian.org>
+Date: Mon Mar 16 21:08:35 2015 +0100
+
+ Do not expect EOF as return value of getopt()
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit a41fc32
+Author: Andreas Bombe <aeb@debian.org>
+Date: Wed Mar 11 21:45:04 2015 +0100
+
+ fsck.fat: Fix read beyond end of array on FAT12
+
+ When a FAT12 filesystem contains an odd number of clusters, setting the
+ last cluster with set_fat() will trigger a read of the next entry,
+ which does not exist in the fat array allocated for this.
+
+ Round up the allocation to an even number of FAT entries for FAT12 so
+ that this is fixed without introducing special casing in get_fat().
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit e18d72f
+Author: Álvaro Fernández Rojas <noltari@gmail.com>
+Date: Sat Mar 7 13:23:23 2015 +0100
+
+ Remove linux/msdos_fs.h includes
+
+ Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit 245d0cc
+Author: Álvaro Fernández Rojas <noltari@gmail.com>
+Date: Thu Feb 26 19:22:54 2015 +0100
+
+ Remove non standard int types
+
+ Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit 628b3ec
+Author: Álvaro Fernández Rojas <noltari@gmail.com>
+Date: Thu Feb 26 19:41:19 2015 +0100
+
+ Improve .gitignore
+
+ Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit 02b5a6d
+Author: Álvaro Fernández Rojas <noltari@gmail.com>
+Date: Thu Feb 26 12:51:23 2015 +0100
+
+ Makefile: avoid using install -D
+
+ OS X and FreeBSD are not compatible with this option
+
+ Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit fb6aea6
+Author: Álvaro Fernández Rojas <noltari@gmail.com>
+Date: Thu Feb 26 12:50:57 2015 +0100
+
+ Makefile: fix typo in uninstall-man
+
+ Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit 357ab07
+Author: Andreas Bombe <aeb@debian.org>
+Date: Thu Feb 19 21:22:54 2015 +0100
+
+ fsck.fat: Make -r option default
+
+ Default mode is now to interactively repair with the option to write
+ the changes back at the end (like the -r option) instead of the previous
+ default mode of interactively correcting but never writing back the
+ changes.
+
+ The -r option continues to be recognized by fsck.fat.
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit 266a5fc
+Author: Andreas Bombe <aeb@debian.org>
+Date: Fri Feb 20 03:19:28 2015 +0100
+
+ mkfs.fat: Allow 0xF0 to be specified as media byte
+
+ Let the -M option accept 0xF0, which should be the proper descriptor
+ byte for 3.5" 1.44 MB and 2.88 MB floppies.
+
+ Also split the error reporting for -M between badly formatted and
+ invalid numbers.
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit 16e97e9
+Author: Andreas Bombe <aeb@debian.org>
+Date: Wed Jan 28 15:07:18 2015 +0100
+
+ Make all char* that may take literals const
+
+ Every char* variable or function argument that may be given a literal
+ string is now made const. Additionally add -Wwrite-strings to CFLAGS to
+ enable a warning where const would be missing.
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit 8b8948c
+Author: Andreas Bombe <aeb@debian.org>
+Date: Mon Dec 29 18:24:54 2014 +0100
+
+ mkfs.fat.c: Use unsigned char for binary data
+
+ Simple char technically works for the dummy_boot_jump variables, but
+ some compiler warning settings would give a warning over a signed char
+ overflowing with the values given as initializers.
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit 45aeed0
+Author: Andreas Bombe <aeb@debian.org>
+Date: Sun Nov 16 19:49:22 2014 +0100
+
+ Fix indentation of "fix power loss damage" commit
+
+ I fixed the (sometimes misleading) indentation of the code introduced in
+ commit 6893c45 to be in line with the reset of the code and also removed
+ the /* PATCH ED+DL */ comments which are quite meaningless to the wider
+ world.
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit 75c5446
+Author: Andreas Bombe <aeb@debian.org>
+Date: Sat Nov 15 16:48:48 2014 +0100
+
+ Add tags and editor backup files to .gitignore
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit cb98ae2 (tag: v3.0.27)
+Author: Andreas Bombe <aeb@debian.org>
+Date: Wed Nov 12 01:10:23 2014 +0100
+
+ Releasing version 3.0.27.
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit e2c8f06
+Author: Andreas Bombe <aeb@debian.org>
+Date: Wed Nov 12 00:22:17 2014 +0100
+
+ fsck.fat: Don't print version string every time -v is encountered
+
+ Remove the printing of the version string every time -v is seen during
+ command line parsing in fsck.fat. The version string is printed anyway
+ before opening the filesystem device/image.
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit 82076b6
+Author: Andreas Bombe <aeb@debian.org>
+Date: Tue Nov 11 23:25:30 2014 +0100
+
+ Fix attempt to rename root dir in fsck due to uninitialized fields
+
+ When add_file() is called with offset 0, it will construct a DIR_ENT for
+ the root directory instead of reading the contents from the filesystem.
+ It did not initialize the whole DIR_ENT on the stack, just select
+ values.
+
+ In particular, the lcase field was left with an undefined value. If
+ that value happened to include the FAT_NO_83NAME bit, the "neither long
+ nor short file name" check in bad_name() added in 3.0.26 would trigger
+ and cause an attempt to rename the entry (which is not possible).
+ Example run:
+
+ $ /sbin/fsck.fat -y bad.img
+ fsck.fat 3.0.26 (2014-03-07)
+ /
+ Bad short file name ().
+ Auto-renaming it.
+ Renamed to
+ bad.img: 14 files, 19388/403266 clusters
+
+ This commit changes the initialization zeroize the whole struct before
+ setting individual fields. Thanks to AlexisM, who found the cause and
+ posted a patch on the Debian bug http://bugs.debian.org/764992 .
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit c24ecb6
+Author: Andreas Bombe <aeb@debian.org>
+Date: Tue Nov 11 22:49:50 2014 +0100
+
+ Support long file names in volume labeling code
+
+ The code to find the volume label directory entry in find_volume_de()
+ did not consider long file names so far. Directory entries that make up
+ long file names have four attribute bits set, including the "volume"
+ bit.
+
+ This caused the code to mistake a directory entry that is part of a
+ long file name as the volume name entry. If such an entry is found
+ first, fatlabel would print garbage when asked to display the label and
+ mangle the long file name when asked to set it. The latter would lead
+ to the loss of the long file name and require a fsck to clean up.
+
+ Change so that the set of attributes equal that of LFN entries will no
+ langer match as a volume label.
+
+ Signed-off-by: Andreas Bombe <aeb@debian.org>
+
+commit 1646f6e (tag: v3.0.26)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Mar 7 18:40:13 2014 +0100
+
+ Releasing version 3.0.26.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 6893c45
+Author: Dir Lotter <dirk.lotter@siemens.com>
+Date: Fri Mar 7 18:25:39 2014 +0100
+
+ Fix "odd" files created by frequent power-loss.
+
+ After running many power losses the filesystem can degrate, containing "odd"
+ files making the filesystem corrupt that could not be solved by fsck:
+
+ * file was not visible in a ls -l
+ * ls -i reported a "invalid file name" on the console
+ * a test program with diropen/dirread showed the file, a stat on this file
+ failed
+ * file was not accessible and could not be deleted
+
+ After digging into the code we found why fsck didn't repair the file system:
+ One thing was we don't have short filenames. Another issue was that the LFN
+ pointer was set to NULL and so it looked like we didn't have short and long
+ filenames.
+
+ Our patch of check.c includes:
+
+ * returns 1 from function bad_name() in case no short and no long filename
+ exist
+ * auto_rename() and rename_file() got a special handling for the case no short
+ file name exist:
+ - it enables the short file name (we think here was a weakness of the old
+ code: it changed the short filename but didn't enabled it in the
+ file->dir_ent.lcase entry)
+ - it reset all attributes except ATTR_DIR and ATTR_VOLUME
+
+ This solved our problem pretty well.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 621e11f
+Author: Natanael Copa <ncopa@alpinelinux.org>
+Date: Sat Feb 8 18:53:30 2014 +0100
+
+ Build fixes for musl libc.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 52588b7 (tag: v3.0.25)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Jan 17 07:11:11 2014 +0100
+
+ Releasing version 3.0.25.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit acf64ae
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Jan 17 07:09:54 2014 +0100
+
+ Updating copyright headers for 2014.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 21fe921
+Author: Andrew Tridgell <tridge@samba.org>
+Date: Tue Jan 14 09:37:51 2014 +1100
+
+ Fixed remaining 64 bit build warnings.
+
+ Some of these may be real bugs.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 9e3a2b1
+Author: Andrew Tridgell <tridge@samba.org>
+Date: Tue Jan 14 09:25:28 2014 +1100
+
+ Prevent corruption of FAT during fsck on 64 bit platforms.
+
+ unsigned long is 64 bit on x86-64, which means set_fat was writing two
+ entries, which corrupts the next entry. This can cause loss of data in
+ another file.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 0d2c9bc (tag: v3.0.24)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Sat Nov 23 10:36:55 2013 +0100
+
+ Releasing version 3.0.24.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 55bd7b7
+Author: Jaroslav Skarvada <jskarvad@redhat.com>
+Date: Sat Nov 23 10:34:48 2013 +0100
+
+ Fixed dosfsck on big endian platforms (Resolves: rhbz#1029695).
+
+ It seems there is problem in the double conversion on big endians.
+ The first conversion is done by the explicit conversion to __u16
+ in the GET_UNALIGNED_W macro, so the secondary conversion by le16toh
+ seems to be redundant (and wrong).
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 6debb4a (tag: v3.0.23)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Tue Oct 15 08:05:46 2013 +0200
+
+ Releasing version 3.0.23.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 07d85ff
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Tue Oct 15 08:04:11 2013 +0200
+
+ Reformating mkfs.fat manpage.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 137552f
+Author: Michael Shigorin <mike@altlinux.org>
+Date: Tue Oct 15 01:29:33 2013 +0400
+
+ Fixing "Fixing default sectors per cluster for FAT32" for UEFI.
+
+ FAT32 "EFI System Partition" is basically required for UEFI boot;
+ commit ge048a8d broke that for me with both virtualbox-4.2 and
+ real hardware (ASUS C60M1-I to be exact) given ~250Mb filesystem.
+
+ This commit amends that one by reverting its effects for these
+ small sizes by restoring 512b cluster size for <= 260Mb FAT32.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 2000696
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Aug 9 09:38:13 2013 +0200
+
+ Also allowing lowercase labels in mkfs (with warning message) consistent with the recent fsck change, thanks to Michael Baum <mbaum@devonit.com>.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 9b04807
+Author: Tim Harder <radhermit@gentoo.org>
+Date: Fri Jul 19 18:15:21 2013 +0200
+
+ Add install-man dependency to install-symlinks Makefile target.
+
+ This fixes a race condition during parallel installs where man page
+ symlinks won't be installed because install-man hasn't been run yet.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 651f91c (tag: v3.0.22)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Jul 19 07:01:19 2013 +0200
+
+ Releasing version 3.0.22.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 3dc5560
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Jul 19 06:55:24 2013 +0200
+
+ Addding install-symlinks target to phony targets in Makefile.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit c6c0581
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Jul 19 06:55:00 2013 +0200
+
+ Adding uninstall-symlinks target in Makefile.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 465dd8c
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Jul 19 06:45:40 2013 +0200
+
+ Allowing fatlabel to write labels in all lowercase but give a warning about DOS/Windows (Closes: #714971).
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 3621b30
+Author: John S Gruber <JohnSGruber@gmail.com>
+Date: Fri Jul 19 06:40:21 2013 +0200
+
+ Add options and make dos boot sector more compatible with reference system (Closes: #552673).
+
+ Unless overridden by the user sets the DOS boot sector's
+ hidden-sectors field to match the start of a hard disk's
+ partition.
+
+ Initialize DOS boot sector drive_number according to FAT media type
+ Addresses LP: #398241 and Debian #552673
+
+ Adds options to override the DOS boot sector device_number and
+ the FAT media type.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit be1eed5
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Wed Jul 17 12:52:20 2013 +0200
+
+ Correcting wrong check preventing installation of fatlabel legacy manpage symlink.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit d0065d3 (tag: v3.0.21)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Tue Jul 16 08:34:28 2013 +0200
+
+ Releasing version 3.0.21.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit a74c12c
+Author: Jaroslav Skarvada <jskarvad@redhat.com>
+Date: Tue Jun 25 14:53:14 2013 +0200
+
+ Adding the missing -p option to the fsck manpage (to be consistent with the output of the tool).
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 25e03c9
+Author: Patrick J. Volkerding <volkerdi@slackware.com>
+Date: Mon Jun 24 14:23:00 2013 +0200
+
+ Using $MANDIR instead of hardcoded ${PREFIX}/share/man in the Makefile.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 7fd9cf7
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Jun 14 18:50:31 2013 +0200
+
+ Making install-symlinks Makefile target depend on install-bin to not break when using make in parallel, thanks to David Walser <luigiwalser@yahoo.com>.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit a76bbcd
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Wed Jun 12 13:00:10 2013 +0200
+
+ Using US digit date format in version date, rather than name abbrev.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit a64195f (tag: v3.0.20)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Wed Jun 12 12:25:32 2013 +0200
+
+ Releasing version 3.0.20.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 1a5d99f
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Wed Jun 12 12:07:58 2013 +0200
+
+ Softening message about different boot sectors a bit (Closes: #704198).
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 4727286
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Wed Jun 12 11:42:52 2013 +0200
+
+ Harmonizing program name output.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 17c956c
+Author: Martin Wilck <mwilck@arcor.de>
+Date: Wed Jun 12 11:38:00 2013 +0200
+
+ Don't align FAT to cluster size.
+
+ See previous patch for explanation.
+
+ With this patch and the previous two, the
+ mkdosfs generated FAT32 file systems work well in my extremely
+ picky TechniSat device. Of course, they're also detected cleanly
+ by Linux and Windows.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit d63e0d6
+Author: Martin Wilck <mwilck@arcor.de>
+Date: Wed Jun 12 11:36:08 2013 +0200
+
+ Don't align FAT32 reserved sectors to cluster size.
+
+ For certain file system sizes (in particular, exact GB sizes -
+ don't ask me why) a Technisat HD S2 Plus DVB receiver will still
+ choke on mkdosfs generated file systems, even if the sectors per
+ cluster problem is fixed.
+
+ By comparing the properties of generated FAT32 FS with results
+ of the Windows tool "h2format" (www.heise.de/download/h2format.html),
+ I found that the remaining problems were caused by rounding of the
+ reserved sectors and FAT space to cluster size (the h2format tool
+ doesn't do this).
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit e048a8d
+Author: Martin Wilck <mwilck@arcor.de>
+Date: Wed Jun 12 11:33:33 2013 +0200
+
+ Fixing default sectors per cluster for FAT32 (Closes: #690062).
+
+ The default sectors per cluster calculated by mkdosfs are outdated,
+ see http://technet.microsoft.com/en-us/library/cc938438.aspx.
+
+ The deviations may cause some 3rd party devices (e.g. TechniSat DVB
+ receivers) to hang when reading mkdosfs generated file systems.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 86509aa
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Tue Jun 11 20:19:09 2013 +0200
+
+ Splitting out legacy symlink creation in toplevel Makefile to own target.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit da37dd1
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Wed Jun 12 11:29:12 2013 +0200
+
+ Correcting wrong toolname in fsck.fat.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit b29a722
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Tue Jun 11 19:51:47 2013 +0200
+
+ Consistently spelling filesystem as filesystem, and not file system.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 977d7aa
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Tue Jun 11 19:30:19 2013 +0200
+
+ Removing Debian reference in GPL license headers.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 5505cc2 (tag: v3.0.19)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Tue Jun 11 18:46:03 2013 +0200
+
+ Releasing version 3.0.19.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 2c88f35
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Tue Jun 11 18:44:50 2013 +0200
+
+ Running indent on source files.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit d495d43
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Tue Jun 11 18:41:41 2013 +0200
+
+ Using memcpy instead of strcpy to fix segfault with fortify, thanks to Dave Reisner <falconindy@jabber.org>.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 9fb4ffc
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Sun Jun 9 13:17:16 2013 +0200
+
+ Correcting fsck.fat spelling error in manpages, thanks to E.J.M. Hartman <E.J.M.Hartman@tudelft.nl>.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 2d8ef9b (tag: v3.0.18)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Thu Jun 6 09:49:00 2013 +0200
+
+ Releasing version 3.0.18.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit d4e1180
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Thu Jun 6 09:38:45 2013 +0200
+
+ Adding initial i18n support for manpages with po4a.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit ea8f712
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Thu Jun 6 09:17:13 2013 +0200
+
+ Renaming tools to sane namespace and keeping legacy symlinks in place.
+
+ dosfslabel becomes fatlabel,
+ dosfsck becomes fsck.fat,
+ and mkdosfs becomes mkfs.fat.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit a42b127
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Wed Jun 5 07:12:03 2013 +0200
+
+ Correcting wrong spelling of Debian in mkdosfs manpage.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 2749084
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Wed Jun 5 07:10:50 2013 +0200
+
+ Correcting spelling typo in boot.c.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 6461c83
+Author: Martin Pitt <martinpitt@gnome.org>
+Date: Fri May 24 09:35:44 2013 +0200
+
+ dosfslabel: Do not read beyond string length (Closes: #709587).
+
+ When checking whether the label contains any lower-case characters, do not read
+ beyond the end of the string.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 4203a90 (tag: v3.0.17)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Wed May 29 10:14:09 2013 +0200
+
+ Releasing version 3.0.17.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 3aa88ed
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Wed May 29 09:48:24 2013 +0200
+
+ Updating maximal lenght of a label in manpage to talk about bytes instead of characters, thanks to Francois Wendling <frwendling@gmail.com> (Closes: #655953).
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 0916f8a
+Author: Jaroslav Skarvada <jskarvad@redhat.com>
+Date: Wed May 29 09:56:08 2013 +0200
+
+ Fixing segfault in dosfslabel.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 4a265c6
+Author: James Byrne <jbyrne@aminocom.com>
+Date: Mon Apr 22 12:29:51 2013 +0100
+
+ Allow operation on SH4 CPUs and remove compiler warnings.
+
+ Simplify the GET_UNALIGNED_W macro and use it in all cases instead of making it
+ conditional on CPU types. This missed some CPUs that needed it (e.g. SH4), and
+ in any case the implementation caused "dereferencing type-punned pointer will
+ break strict-aliasing rules" warnings.
+
+ Enable extra warnings, but disable signed comparison and missing field
+ initializer warnings as these are not helpful.
+
+ Update write_boot_label() so that the boot_sector_16 and boot_sector cases are
+ handled separately instead of using an aliased pointer, as that causes
+ "dereferencing type-punned pointer will break strict-aliasing rules" warnings.
+
+ Make date_dos2unix(), usage() and cdiv() static functions as they are only used
+ in the files in which they are declared.
+
+ Update bad_name() and lfn_get() so that the extension is processed separately
+ instead of by indexing past the end of the name field as that causes "array
+ subscript is above array bounds" warnings.
+
+ Update the dosfsck() main function to avoid a warning that free_clusters may
+ be used uninitialized. Do not print the final count of files and clusters when
+ dosfsck is run with the "-b" option because the used files and clusters have
+ not been counted in this case.
+
+ Alter the setup_tables() function so that it does not cause an "array subscript
+ is below array bounds" warning.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit eb68a14
+Author: James Byrne <jbyrne@aminocom.com>
+Date: Mon Apr 22 13:32:01 2013 +0100
+
+ Add a .gitignore file.
+
+ Add a .gitignore file so that the results of compilation do not appear as
+ changes.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 336e8f1
+Author: James Byrne <jbyrne@aminocom.com>
+Date: Mon Apr 22 12:38:52 2013 +0100
+
+ Finish cleanup of byteswap code.
+
+ Commit 9ba8992 left three references to the old CT_LE_W macro.
+ Remove these since no conversion was needed as the value being
+ converted was zero.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 64b6227
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Thu Apr 4 08:08:00 2013 +0200
+
+ Shortening links to upstream homepage.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 76304be
+Author: Cristian Rodríguez <crrodriguez@opensuse.org>
+Date: Fri Mar 1 08:23:34 2013 +0100
+
+ Fix offsetof definition.
+
+ * include stddef.h to get the correct offsetof definition.
+ * remove local offsetof definition, systems not having it on stddef.h
+ are in violation of C89, C99, POSIX.1-2001.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 9ba8992
+Author: Cristian Rodríguez <crrodriguez@opensuse.org>
+Date: Fri Mar 1 08:58:36 2013 +0100
+
+ Cleanup byteswap code.
+
+ Remove all duplicate macro definitions for byteswapping routines
+ and replace them for proper usage of userspace endian(3).
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 8733e12 (tag: v3.0.16)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Wed May 29 10:06:01 2013 +0200
+
+ Releasing version 3.0.16.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit a9fa87e
+Author: Petr Gajdos <pgajdos@suse.cz>
+Date: Fri Mar 1 08:34:12 2013 +0100
+
+ Create rootdir entry volume label with mkdosfs, create it when
+ it doesn't exist with dosfslabel.
+
+ See https://bugzilla.novell.com/show_bug.cgi?id=657011#c4
+ for more information.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 92057f1
+Author: Petr Gajdos <pgajdos@suse.cz>
+Date: Fri Mar 1 08:33:18 2013 +0100
+
+ Forbid lowercase letters in label.
+
+ See https://bugzilla.novell.com/show_bug.cgi?id=657011#c4 and
+ http://support.microsoft.com/kb/71715/en-us for more information.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 5e265c4
+Author: Petr Gajdos <pgajdos@suse.cz>
+Date: Fri Mar 1 08:32:02 2013 +0100
+
+ Read label also from rootdir entry.
+
+ See https://bugzilla.novell.com/show_bug.cgi?id=657011#c4
+ for more information.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 5cec53c
+Author: Petr Gajdos <pgajdos@suse.cz>
+Date: Fri Mar 1 08:30:21 2013 +0100
+
+ alloc_rootdir_entry() is intended to be called with pattern == "FSCK%04dREC",
+ the old code (probably c&p from auto_rename()) doesn't reflect this.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 63938f0
+Author: Petr Gajdos <pgajdos@suse.cz>
+Date: Fri Mar 1 08:29:00 2013 +0100
+
+ Instead of eleven blanks, fill in "NO NAME " as specification tells.
+
+ See https://bugzilla.novell.com/show_bug.cgi?id=657011#c4 and
+ http://www.win.tue.nl/~aeb/linux/fs/fat/fat-1.html for more information.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 10c1c41
+Author: Petr Gajdos <pgajdos@suse.cz>
+Date: Fri Mar 1 08:58:15 2013 +0100
+
+ Write uppercase letters in label.
+
+ See https://bugzilla.novell.com/show_bug.cgi?id=657011#c4 and
+ http://support.microsoft.com/kb/71715/en-us for more information.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit a75fb1c (tag: v3.0.15)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Thu Feb 21 15:06:52 2013 +0100
+
+ Releasing version 3.0.15.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit c8f84fd
+Author: Alexander Korolkov <alexander.korolkov@gmail.com>
+Date: Mon Feb 4 00:22:34 2013 +0400
+
+ Using wcstombs() to convert LFN unicode characters to printable text.
+
+ This closes Debian bug #596336.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 1546545
+Author: Alexander Korolkov <alexander.korolkov@gmail.com>
+Date: Sun Sep 5 18:59:47 2010 +0400
+
+ Recode short filenames from DOS codepage (default 437).
+
+ Recode short filenames from DOS codepage (default 437) to the current
+ character encoding. This makes messages of dosfsck more readable.
+ Partially closes Debian bug #596336.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit ad76cae
+Author: Jaroslav Skarvada <jskarvad@redhat.com>
+Date: Thu Feb 21 14:40:52 2013 +0100
+
+ Fixing root directory allocation.
+
+ See https://bugzilla.redhat.com/show_bug.cgi?id=674095 for more information.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit b8201b3
+Author: Jaroslav Skarvada <jskarvad@redhat.com>
+Date: Thu Feb 21 14:40:25 2013 +0100
+
+ Fixing device detection.
+
+ See https://bugzilla.redhat.com/show_bug.cgi?id=710480 for more information.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 7a75638 (tag: v3.0.14)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Wed Jan 23 13:22:01 2013 +0100
+
+ Releasing version 3.0.14.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 5bdd7ef
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Wed Jan 23 13:16:20 2013 +0100
+
+ Documenting dosfsck -b in its manpage.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit a307be2
+Author: Oleksij Rempel <bug-track@fisher-privat.net>
+Date: Wed Jan 23 12:36:56 2013 +0100
+
+ Adding option for bootsector read-only check.
+
+ Most boot sectors may contains marker for filesystem state. We can this
+ bit on every mount and warn user if some thing wrong, without checking
+ complete filesystem.
+
+ Signed-off-by: Oleksij Rempel <bug-track@fisher-privat.net>
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit ce2f8dc
+Author: Oleksij Rempel <bug-track@fisher-privat.net>
+Date: Wed Jan 23 12:35:13 2013 +0100
+
+ Checking boot sector for dirty bit.
+
+ Some OSos use reseved byte of boot sector to set state of the file
+ system. If first bit set, then filesystem is proably damaged - write
+ operation was not finished/cache not snycted/...
+
+ Signed-off-by: Oleksij Rempel <bug-track@fisher-privat.net>
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit f33ee8c
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Wed Jan 23 12:25:59 2013 +0100
+
+ Completing and updating all copyright headers for 2013.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit bfe6d25
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Wed Jan 23 12:17:20 2013 +0100
+
+ Updating my email address.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 13cdb4d (tag: v3.0.13)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Sat Jun 30 19:10:44 2012 +0200
+
+ Releasing version 3.0.13.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit d039482
+Author: Jaroslav Škarvada <jskarvad@redhat.com>
+Date: Sat Jun 30 19:09:11 2012 +0200
+
+ Fix 'dosfslabel throws "Seek to 114116076544:Invalid argument" error when labeling'.
+
+ See https://bugzilla.redhat.com/show_bug.cgi?id=693662 for more information.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit e243612 (tag: v3.0.12)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Sat Oct 29 08:40:53 2011 +0200
+
+ Releasing version 3.0.12.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 025b4f0
+Author: Michael Casadevall <mcasadevall@ubuntu.com>
+Date: Tue Jun 7 19:19:30 2011 +0200
+
+ Correcting miscalculation of sector number in some cases.
+
+ mkdosfs will incorrectly calculate the number of sectors of a
+ given FAT partition if the number sectors are odd due to
+ count_blocks incorrectly handling the remainder of a division
+ operation. This miscalculation causes the OMAP4 bootloader to
+ fail to boot.
+
+ This bug can be observed by comparing the total sector size in
+ fdisk expert more to fsck.msdos; this discrepancy only shows up
+ when the number of sectors are odd.
+
+ See https://bugs.launchpad.net/ubuntu/+source/dosfstools/+bug/794043
+ for more information.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 91a1fb9
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Sat Jan 8 23:38:59 2011 +0100
+
+ Re-running Nindent.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 0390c4c
+Author: Sergey Gusarov <laborer2008@gmail.com>
+Date: Sat Jan 8 23:36:11 2011 +0100
+
+ Fixing compiler warnings related to the mismatch of types "char *" / "unsigned
+ char *".
+
+ These warnings appear when you compile the project with the option "-Wall", what
+ is done with the current default Makefile.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 4a8f8a6
+Author: Jaroslav Skarvada <jskarvad@redhat.com>
+Date: Thu Jan 6 22:35:00 2011 +0100
+
+ Fixing overflow bug in reclaim_file function, see
+ https://bugzilla.redhat.com/show_bug.cgi?id=660154 for more information.
+
+ The problem is that alloc_rootdir_entry counts with 10000 files at max, but the
+ filename buffer is only 8 chars long. Due to pattern mask used it results to
+ only 10 files at max (FSCK0-9REC). If there is more than 10 files, it overflows
+ and hangs.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit e0366da
+Author: Sergey Gusarov <laborer2008@gmail.com>
+Date: Thu Jan 6 22:31:39 2011 +0100
+
+ Fixing conversion specifiers in accordance with the type of expressions.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 2d8be9c
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Sun Jan 2 15:41:44 2011 +0100
+
+ Indenting source files.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 697af85
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Sun Jan 2 15:39:03 2011 +0100
+
+ Adding Nindent script from syslinux.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 66d55cd (tag: v3.0.11)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Dec 24 17:58:29 2010 +0100
+
+ Releasing version 3.0.11.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit d579802
+Author: Michael Stapelberg <michael@stapelberg.de>
+Date: Fri Nov 19 14:09:36 2010 +0100
+
+ Add better error message when the device cannot be opened.
+
+ This is helpful for SD cards or other removable media which have an enabled
+ write lock -- without the "Permission denied" message, the user has to strace
+ mkdosfs to find out what's going on.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit bb6000f
+Author: Jaroslav Skarvada <jskarvad@redhat.com>
+Date: Fri Oct 8 13:38:16 2010 +0200
+
+ Unalign on s390x, see http://bugzilla.redhat.com/show_bug.cgi?id=624596 for
+ more information.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 5ef7f1f (tag: v3.0.10)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Sun Sep 12 09:35:47 2010 +0200
+
+ Releasing version 3.0.10.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit ea41797
+Author: Alexander Korolkov <alexander.korolkov@gmail.com>
+Date: Sun Sep 12 09:29:12 2010 +0200
+
+ Modify LFN direntries when file is renamed or deleted, see
+ Debian bug #596329.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit e56ff72
+Author: Alexander Korolkov <alexander.korolkov@gmail.com>
+Date: Sun Sep 12 09:27:07 2010 +0200
+
+ If the test of short filename fails, dosfsck could complain about
+ bad long filename, see Debian bug #596327.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit f0a42d0
+Author: Alexander Korolkov <alexander.korolkov@gmail.com>
+Date: Sun Sep 12 09:24:47 2010 +0200
+
+ dosfsck: don't complain about bad filenames when short filename
+ contains 7 or more characters with codes 128-255, see Debian
+ bug #596327.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 0113c5b
+Author: Mitch Rybczynski <mrybczynski@miovision.com>
+Date: Mon Jul 5 14:45:54 2010 +0200
+
+ Adding __arm__ define check for some crosscompile toolchains.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 88cb84f
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Sun Mar 14 16:42:32 2010 +0100
+
+ Modernizing dosfslabel manpage.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 5aa7ec4
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Sun Mar 14 16:33:47 2010 +0100
+
+ Modernizing dosfsck manpage.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 807ed80
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Sun Mar 14 16:05:32 2010 +0100
+
+ Fixing spelling error in boot.c.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 5b6849d (tag: v3.0.9)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Sun Jan 31 08:31:32 2010 +0100
+
+ Releasing version 3.0.9.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 33bca7d
+Author: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Date: Sun Jan 31 00:11:41 2010 -0500
+
+ Be sure to store the updated reserved_sector count in the boot sector,
+ see Debian bug #567337.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 2a3bef8 (tag: v3.0.8)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Sat Jan 23 10:16:18 2010 +0100
+
+ Releasing version 3.0.8.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 726c02d
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Sat Jan 23 10:15:01 2010 +0100
+
+ Removing some cruft in end-comments.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit a5961d7
+Author: Steven J. Magnani <steve@digidescorp.com>
+Date: Thu Jan 21 16:58:11 2010 +0100
+
+ When compiling a 32-bit version of dosfstools on an x86_64 machine,
+ the resulting applications report strange errors on "large" (> 2 GiB)
+ partitions:
+
+ Seek to -2118967808:Invalid argument
+
+ Warning: Filesystem is FAT32 according to fat_length and fat32_length fields,
+ but has only 8613 clusters, less than the required minimum of 65525.
+ This may lead to problems on some systems.
+
+ This appears to be due to compilation with a 32-bit off_t and lseek() library
+ function.
+
+ Use lseek64 for positioning, and change some suspect uses of off_t to loff_t.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit bbb25bf
+Author: Steven J. Magnani <steve@digidescorp.com>
+Date: Thu Jan 21 16:56:26 2010 +0100
+
+ If dosfsck is run in read-only mode (-n), exit with code 0
+ if the only issue found is an uninitialized free cluster summary.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 1cae726
+Author: Steven J. Magnani <steve@digidescorp.com>
+Date: Thu Jan 21 16:55:30 2010 +0100
+
+ On x86_64, dosfsck incorrectly claims that a free_cluster summary of
+ 0xFFFFFFFF, defined by Microsoft to be "uninitialized," is wrong.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 62f806a
+Author: H. Peter Anvin <hpa@zytor.com>
+Date: Fri Jan 8 09:16:38 2010 +0100
+
+ mkdosfs: correct alignment of the root directory.
+
+ Correct the code to align the root directory; it was broken before
+ since bs.dir_entries had already been set at the point of alignment.
+ This patch removes the dual use of bs.dir_entries and root_dir_entries
+ to carry the same information: the information is carried in
+ root_dir_entires exclusively, and then bs.dir_entries is set inside
+ setup_tables() at a late point.
+
+ The code to align the root directory is also wrapped in
+ if (align_structures); this avoids rounding the number of root
+ directory entries up to a whole sector when used with -a
+ (i.e. preserves the previous behavior.)
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 8825bda
+Author: H. Peter Anvin <hpa@zytor.com>
+Date: Wed Jan 6 20:55:36 2010 +0100
+
+ mkdosfs: improve wording in the man page for the -a option.
+
+ Improve the English language used in the man page for the -a (no
+ align) option to mkdosfs.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 21d3f81
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Wed Jan 6 11:27:25 2010 +0100
+
+ Adding reference to dosfslable in mkdosfs manpage.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 247ba06
+Author: H. Peter Anvin <hpa@zytor.com>
+Date: Wed Jan 6 11:18:55 2010 +0100
+
+ mkdosfs: by default align all structures to cluster boundaries
+
+ Align all data structures (reserved sectors, FATs, root directory for
+ FAT12/16) to an even multiple of the cluster size. This means that if
+ the partition is aligned, so will all clusters be. This adds
+ significant performance for anything where the physical sector size is
+ larger than the logical sector size, e.g. flash media or large-sector
+ hard disks.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 171bc07 (tag: v3.0.7)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Thu Dec 24 10:53:36 2009 +0100
+
+ Releasing version 3.0.7.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 28708fc
+Author: Ben Hutchings <ben@decadent.org.uk>
+Date: Thu Dec 24 09:55:52 2009 +0100
+
+ Fixing dosfslabel to set volume label in the right place,
+ see Debian bug #559985.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 2c405dd
+Author: Lubomir Rintel <lkundrak@v3.sk>
+Date: Thu Dec 24 09:39:39 2009 +0100
+
+ Fixing out-of bound writes.
+
+ Firstly, packed attribute is added to the structure so that extension
+ is guarranteed to immediately follow name for the cross-name-extension
+ reads to succeed.
+
+ Secondly, writes into dir_entry->name that span through the extension as
+ well are split into two, so that FORTIFY_SOURCE's bound checking does
+ not abort dosfsck. There also was an off-by-one error in auto_rename()'s
+ sprintf().
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit b8f3efe
+Author: San Mehat <san@google.com>
+Date: Thu Dec 24 09:31:41 2009 +0100
+
+ Adding custom exit code in dosfsck for the case where the FS is read only.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 0657e01 (tag: v3.0.6)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Sun Oct 4 10:59:33 2009 +0200
+
+ Releasing version 3.0.6.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit bc84254
+Author: Steven J. Magnani <steve@digidescorp.com>
+Date: Sun Oct 4 10:58:43 2009 +0200
+
+ Attempt to improve clarity of the orphan cluster reclaim code.
+ Minor optimization - remove some unnecessary checking.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 8054b4a
+Author: Steven J. Magnani <steve@digidescorp.com>
+Date: Sun Oct 4 08:37:19 2009 +0200
+
+ Close hole that permitted clusters to link to (invalid) cluster 1.
+
+ If an orphan chain that linked to cluster 1 was reclaimed to a file,
+ deletion of the file would result in a filesystem panic.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit e51af88
+Author: Steven J. Magnani <steve@digidescorp.com>
+Date: Sun Oct 4 08:32:30 2009 +0200
+
+ Fix erroneous report of huge number of clusters in use on big-endian
+ systems when the FSINFO free cluster count is reset.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 16ba63f (tag: v3.0.5)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Mon Jul 27 14:26:11 2009 +0200
+
+ Releasing version 3.0.5.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 28ff9d9
+Author: Piotr Kaczuba <pepe@attika.ath.cx>
+Date: Sun Jul 26 22:21:25 2009 +0200
+
+ Signed/unsigned char mismatch in check.c causes false positives
+ in bad_name() and can result in data loss, see Debian bug #538758.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit d42a273
+Author: Andrew Tridgell <tridge@samba.org>
+Date: Sun Jul 26 22:12:06 2009 +0200
+
+ Update to new kernel patches that add FAT_NO_83NAME flag.
+
+ See http://lkml.org/lkml/2009/7/20/425 and
+ http://lkml.org/lkml/2009/7/20/424 for more information.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit dd0f0b5 (tag: v3.0.4)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Tue Jul 21 08:10:52 2009 +0200
+
+ Releasing version 3.0.4.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit b9f37a6
+Author: Andrew Tridgell <tridge@samba.org>
+Date: Tue Jul 21 07:59:22 2009 +0200
+
+ Modify dosfstools to support the dummy 8.3 short filename values
+ used by Linux systems with the VFAT_FS_DUALNAMES option disabled.
+
+ See http://lkml.org/lkml/2009/6/26/313 and
+ http://lkml.org/lkml/2009/6/26/314 for more information.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit ecd15e8
+Author: Paul Rupe <prupe@nc.rr.com>
+Date: Tue May 19 10:37:52 2009 +0200
+
+ Fixing "Too many files need repair" error during fsck.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 7c16098 (tag: v3.0.3)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Mon May 18 15:12:04 2009 +0200
+
+ Releasing version 3.0.3.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit b396dcf
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Mon May 18 15:10:55 2009 +0200
+
+ Also declaring arm as an unaligned architecture, see Debian bug #502961.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit ff1b24e
+Author: Steven J. Magnani <steve@digidescorp.com>
+Date: Mon May 18 15:01:49 2009 +0200
+
+ Adding support for limited-memory embedded systems.
+
+ This patch reorganizes heap memory usage by dosfsck and mkdosfs
+ to support limited-memory embedded systems - in particular, those
+ based on Xilinx's Microblaze processor. It also adds a few comments.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 89f0b72
+Author: Mike Frysinger <vapier@gentoo.org>
+Date: Thu Mar 5 07:03:36 2009 +0100
+
+ Declaring Blackfin as an unaligned architecture.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit b54a8a4 (tag: v3.0.2)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Sat Feb 28 09:48:04 2009 +0100
+
+ Releasing version 3.0.2.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 9500529
+Author: Hiroaki Ishizawa <hiroaki.ishizawa@gmail.com>
+Date: Fri Feb 13 10:00:46 2009 +0100
+
+ dosfsck corrupts root directory when fs->nfats is 1.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 043f8a8
+Author: Stepan Kasal <skasal@redhat.com>
+Date: Fri Jan 30 14:56:33 2009 +0100
+
+ src/dosfslabel.c (main): After writing the label, exit code should be 0.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 017da27
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Jan 30 14:06:01 2009 +0100
+
+ Also installing ChangeLog in install-doc target of Makefile.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 1c76f0f
+Author: Stepan Kasal <skasal@redhat.com>
+Date: Fri Jan 30 14:05:12 2009 +0100
+
+ Makefile: Do not clobber time stamps of doc files.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit df2d2f1 (tag: v3.0.1)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Sun Nov 23 22:45:45 2008 +0100
+
+ Releasing version 3.0.1.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 17b269b
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Sun Nov 23 18:41:01 2008 +0100
+
+ Applying Fedoras dosfstools-vfat-timingfix.diff from Bill Nottingham
+ <notting@redhat.com> to fix vfat timing issue. See
+ https://bugzilla.redhat.com/show_bug.cgi?id=448247 for more information.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit e597caf
+Author: Ulrich Mueller <ulm@gentoo.org>
+Date: Tue Oct 7 07:55:37 2008 +0200
+
+ Patch to check for bad number of clusters in dosfsck:
+
+ * FAT16 filesystems with 65525 clusters or more will be rejected
+ (Before, this was not tested for. Up to 65535 clusters were accepted
+ as good).
+
+ * For FAT32 filesystems with less than 65525 a warning message will be
+ output.
+
+ Macro MSDOS_FAT12 is now replaced by FAT12_THRESHOLD to make it
+ consistent with the definition in mkdosfs and to remove the dependency
+ on the kernel version.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 90102bc
+Author: Dann Frazier <dannf@hp.com>
+Date: Tue Sep 30 07:25:19 2008 +0200
+
+ Changing some wording to make the indended meaning of "full-disk device"
+ more obvious.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 21e9ba0 (tag: v3.0.0)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Sun Sep 28 11:43:19 2008 +0200
+
+ Releasing version 3.0.0.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit eaf145d
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Sun Sep 28 11:29:01 2008 +0200
+
+ Adding GPL headers to all files.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 0826117
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Sun Sep 28 10:51:55 2008 +0200
+
+ Adding new GPL license file.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit f8d6127
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 23:31:12 2008 +0200
+
+ Redoing Makefile from scratch.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit b4feb73
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Sat Sep 27 00:17:38 2008 +0200
+
+ Removing whitespaces in all files at EOL and EOF.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 1410138
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 23:48:56 2008 +0200
+
+ Adding Debians dosfslabel.8 manpage from Francois Wendling
+ <frwendling@free.fr>.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit f62e7f2
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 18:36:04 2008 +0200
+
+ Updating version.h includes to new location of version.h file.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 32e5952
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 18:19:36 2008 +0200
+
+ Removing old lsm file.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 25a433b
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 18:07:47 2008 +0200
+
+ Removing old cvsignore files.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit acac13f
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 18:18:39 2008 +0200
+
+ Removing old build file.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 3ecdd21
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 18:19:16 2008 +0200
+
+ Removing old GPL license files.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit f183d0e
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 18:21:57 2008 +0200
+
+ Unifying dosfsck and mkdosfs Makefiles in common src/Makefile.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 61e7466
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 18:04:02 2008 +0200
+
+ Unifying dosfsck and mkdosfs sources in common src directory.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 7552d57
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 18:05:27 2008 +0200
+
+ Unifying dosfsck and mkdosfs manpages in common man directory.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 124598b
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 18:12:29 2008 +0200
+
+ Unifying dosfsck and mkdosfs documents in common doc directory.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit fb9c46b
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 15:39:51 2008 +0200
+
+ Applying Gentoos dosfstools-2.11-preen.patch from Roy Marples
+ <uberlord@gentoo.org> to alias dosfsck -p to -a:
+
+ * Map -p to -a for baselayout-2, #177514.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit aaa40a9
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 15:49:43 2008 +0200
+
+ Applying Gentoos dosfstools-2.11-build.patch from Mike Frysinger
+ <vapier@gentoo.org> to improve Makefile:
+
+ * Respect user settings #157785/#157786 by Diego Petteno.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 251626d
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 15:37:34 2008 +0200
+
+ Applying Gentoos dosfstools-2.11-verify-double-count-fix.patch from
+ Robin H. Johnson <robbat2@gentoo.org> to fix double count of files
+ during verification:
+
+ * Don't double-count n_files during a verification pass.
+ Bugzilla: http://bugs.gentoo.org/show_bug.cgi?id=99845
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit e670ea8
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 15:33:36 2008 +0200
+
+ Applying Gentoos dosfstools-2.11-fat32size.patch from Mike Frysinger
+ <vapier@gentoo.org> to fix generation of filesystems on 256meg devices:
+
+ * Fix generation of FAT filesystems on devices that are 256meg in size
+ Patch by Ulrich Mueller and accepted upstream
+ http://bugs.gentoo.org/112504
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit a6dc6a4
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 15:22:06 2008 +0200
+
+ Applying Suses dosfstools-2.11-unsupported-sector-size.patch from Petr
+ Gajdos <pgajdos@suse.cz> to add sector size warning:
+
+ * added warning for creation msdos on filesystem with sector size
+ greater than 4096 [fate#303325]
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit f746956
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 15:18:35 2008 +0200
+
+ Applying Suses dosfstools-2.11-mkdosfs-geo0.diff from Ludwig Nussel
+ <lnussel@suse.de> to fix handling of zero heads and sectors:
+
+ * the HDIO_GETGEO ioctl works on device mapper devices but returns
+ zero heads and sectors. Therefore let's a) assume dummy values in
+ that case in mkdosfs and b) don't consider such fat file systems as
+ invalid in dosfsck. The Linux kernel accepts them anyways.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit cf243e4
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 15:15:40 2008 +0200
+
+ Applying Suses dosfstools-2.11-linuxfs.patch from Ruediger Oertel
+ <ro@suse.de> to not include linux/fs.h.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 2d4f184
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 15:11:50 2008 +0200
+
+ Applying Fedoras dosfstools-2.11-assumeKernel26.patch from Peter Vrabec
+ <pvrabec@redhat.com> to remove linux 2.6 conditionals:
+
+ * LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) does not work with
+ glibc-kernheaders-2.4-9.1.94
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 739a6fb
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 15:05:00 2008 +0200
+
+ Applying Debians 99-conglomeration.dpatch (no other information
+ available).
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 3b5ed8a
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 14:26:41 2008 +0200
+
+ Applying Debians 15-manpage-files.dpatch from Daniel Baumann
+ <daniel@debian.org> to improve dosfsck manpage:
+
+ * Lists fsckNNNN.rec files in FILES section (Closes: #444596).
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 3b6a863
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 14:34:42 2008 +0200
+
+ Applying Debians 13-getopt.dpatch from Adonikam Virgo
+ <adonikam@virgonet.org> to fix mkdosfs getopt:
+
+ * Fixes backup sector getopt (Closes: #232387, #479794).
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 1b2c8ca
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 14:34:17 2008 +0200
+
+ Applying Debians 12-zero-slot.dpatch by Karl Tomlinson
+ <karlt@karlt.net> to fix dosfsck zero slot crashes:
+
+ * Fixes crashes due to zero slot numbers causing a negative offset in
+ the call to copy_lfn_part in lfn_add_slot. On amd64 this results in
+ a SIGSEGV in copy_lfn_part. On x86 the result is heap corruption and
+ thus sometimes a SIGSEGV or double free abort later. (Closes:
+ #152550, #353198, #356377, #401798).
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit eec8585
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 14:33:54 2008 +0200
+
+ Applying Debians 11-memory-efficiency.dpatch from Eero Tamminen
+ <eero.tamminen@nokia.com> to improve dosfsck memory efficiency:
+
+ * Improves memory efficiency when checking filesystems.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 06bd669
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 14:33:28 2008 +0200
+
+ Applying Debians 10-manpage-synopsis.dpatch from Daniel Baumann
+ <daniel@debian.org> to fix manpage synopsis:
+
+ * List alternative binary names in manpage synopsis (Closes: #284983).
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 42d340d
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 14:32:46 2008 +0200
+
+ Applying Debians 09-manpage-fat32.dpatch from Daniel Baumann
+ <daniel@debian.org> to improve mkdosfs manpage:
+
+ * Don't claim that FAT32 is not choosed automatically (Closes:
+ #414183).
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 0f5ce0d
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 14:32:23 2008 +0200
+
+ Applying Debians 08-manpage-drop.dpatch from Daniel Baumann
+ <daniel@debian.org> to improve dosfsck manpage:
+
+ * Don't use confusing word 'drop' when 'delete' is meant (Closes:
+ #134100).
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 8ec54dd
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 14:31:50 2008 +0200
+
+ Applying Debians 07-manpage-spelling.dpatch from Justin Pryzby
+ <justinpryzby@users.sourceforge.net> to fix mkdosfs manpage typos.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 4371588
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 14:30:31 2008 +0200
+
+ Applying Suses dosfstools-2.11_determine-sector-size.patch from Petr
+ Gajdos <pgajdos@suse.cz> to determine mkdosfs sector size automatically:
+
+ * determine sector size of device automatically or if -S parameter
+ present, verify, that it's not under physical sector size
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit fc92e19
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 14:30:03 2008 +0200
+
+ Applying Suses dosfstools-2.11-o_excl.patch from Pavol Rusnak
+ <prusnak@suse.cz> to use O_EXCL in mkdosfs:
+
+ * mkdosfs now opens device with O_EXCL [#238687]
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 3084697
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 14:29:36 2008 +0200
+
+ Applying Debians 04-unaligned-memory.dpatch from Khalid Aziz
+ <khalid_aziz@hp.com> to fix dosfsck unaligned memory accesses:
+
+ * Fix unaligned memory accesses which cause warnings to appear
+ everytime the elilo bootloader script runs. This has led a number of
+ users to believe their install has failed (Closes: #258839).
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 6d5c091
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 13:47:40 2008 +0200
+
+ Applying Fedoras dosfstools-2.11-label.patch from Jeremy Katz
+ <katzj@redhat.com> to add dosfslabel (originally by Peter Jones).
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 07ef487
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 13:41:14 2008 +0200
+
+ Applying Fedoras dosfstools-2.11-fortify.patch from Jakub Jelinek
+ <jakub@redhat.com> to make it build with -D_FORTIFY_SOURCE=2:
+
+ * This violates -D_FORTIFY_SOURCE=2 (which is stricter than C
+ standard), but isn't actually any buffer overflow. But using memcpy
+ is more efficient anyway.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit 78f9dca
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Fri Sep 26 13:40:47 2008 +0200
+
+ Applying Fedoras dosfstools-2.7-argfix.patch (no other information
+ available).
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
+
+commit ba6774a (tag: v2.11)
+Author: Daniel Baumann <mail@daniel-baumann.ch>
+Date: Thu Jun 26 12:45:36 2008 +0200
+
+ Adding version 2.11.
+
+ Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
diff --git a/dosfstools/Makefile b/dosfstools/Makefile
new file mode 100644
index 000000000..fa993559c
--- /dev/null
+++ b/dosfstools/Makefile
@@ -0,0 +1,170 @@
+# Makefile
+#
+# Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# The complete text of the GNU General Public License
+# can be found in /usr/share/common-licenses/GPL-3 file.
+
+SHELL := sh -e
+LANGUAGES = $(shell cd manpages/po && ls)
+
+DESTDIR =
+PREFIX = /usr/local
+SBINDIR = $(PREFIX)/sbin
+DOCDIR = $(PREFIX)/share/doc
+MANDIR = $(PREFIX)/share/man
+
+#OPTFLAGS = -O2 -fomit-frame-pointer -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
+OPTFLAGS = -O2 -fomit-frame-pointer -D_GNU_SOURCE $(shell getconf LFS_CFLAGS)
+#WARNFLAGS = -Wall -pedantic -std=c99
+WARNFLAGS = -Wall -Wextra -Wno-sign-compare -Wno-missing-field-initializers -Wmissing-prototypes -Wstrict-prototypes -Wwrite-strings
+DEBUGFLAGS = -g
+CFLAGS += $(OPTFLAGS) $(WARNFLAGS) $(DEBUGFLAGS)
+
+VPATH = src
+
+all: build
+
+build: fatlabel fsck.fat mkfs.fat
+
+fatlabel: boot.o check.o common.o fat.o file.o io.o lfn.o fatlabel.o
+
+fsck.fat: boot.o check.o common.o fat.o file.o io.o lfn.o fsck.fat.o
+
+mkfs.fat: mkfs.fat.o
+
+rebuild: distclean build
+
+install: install-bin install-doc install-man install-symlinks
+
+install-bin: build
+ install -d -m 0755 $(DESTDIR)/$(SBINDIR)
+ install -m 0755 fatlabel fsck.fat mkfs.fat $(DESTDIR)/$(SBINDIR)
+
+install-doc:
+ install -d -m 0755 $(DESTDIR)/$(DOCDIR)/dosfstools
+ install -p -m 0644 ChangeLog doc/* $(DESTDIR)/$(DOCDIR)/dosfstools
+
+install-man:
+ for MANPAGE in manpages/en/*; \
+ do \
+ SECTION="8"; \
+ mkdir -p $(DESTDIR)/$(MANDIR)/man$${SECTION}/; \
+ install -m 0644 $${MANPAGE} $(DESTDIR)/$(MANDIR)/man$${SECTION}/$$(basename $${MANPAGE}); \
+ done
+
+ for LANGUAGE in $(LANGUAGES); \
+ do \
+ for MANPAGE in manpages/$${LANGUAGE}/*; \
+ do \
+ SECTION="8"; \
+ mkdir -p $(DESTDIR)/$(MANDIR)/$${LANGUAGE}/man$${SECTION}/; \
+ install -m 0644 $${MANPAGE} $(DESTDIR)/$(MANDIR)/$${LANGUAGE}/man$${SECTION}/$$(basename $${MANPAGE} .$${LANGUAGE}.$${SECTION}).$${SECTION}; \
+ done; \
+ done
+install-symlinks: install-bin install-man
+ if [ -e $(DESTDIR)/$(SBINDIR)/fatlabel ]; \
+ then \
+ ln -sf fatlabel $(DESTDIR)/$(SBINDIR)/dosfslabel; \
+ if [ -e $(DESTDIR)/$(MANDIR)/man8/fatlabel.8 ]; \
+ then \
+ ln -sf fatlabel.8 $(DESTDIR)/$(MANDIR)/man8/dosfslabel.8; \
+ fi; \
+ fi
+
+ if [ -e $(DESTDIR)/$(SBINDIR)/fsck.fat ]; \
+ then \
+ ln -sf fsck.fat $(DESTDIR)/$(SBINDIR)/dosfsck; \
+ ln -sf fsck.fat $(DESTDIR)/$(SBINDIR)/fsck.msdos; \
+ ln -sf fsck.fat $(DESTDIR)/$(SBINDIR)/fsck.vfat; \
+ if [ -e $(DESTDIR)/$(MANDIR)/man8/fsck.fat.8 ]; \
+ then \
+ ln -sf fsck.fat.8 $(DESTDIR)/$(MANDIR)/man8/dosfsck.8; \
+ ln -sf fsck.fat.8 $(DESTDIR)/$(MANDIR)/man8/fsck.msdos.8; \
+ ln -sf fsck.fat.8 $(DESTDIR)/$(MANDIR)/man8/fsck.vfat.8; \
+ fi; \
+ fi
+
+ if [ -e $(DESTDIR)/$(SBINDIR)/mkfs.fat ]; \
+ then \
+ ln -sf mkfs.fat $(DESTDIR)/$(SBINDIR)/mkdosfs; \
+ ln -sf mkfs.fat $(DESTDIR)/$(SBINDIR)/mkfs.msdos; \
+ ln -sf mkfs.fat $(DESTDIR)/$(SBINDIR)/mkfs.vfat; \
+ if [ -e $(DESTDIR)/$(MANDIR)/man8/mkfs.fat.8 ]; \
+ then \
+ ln -sf mkfs.fat.8 $(DESTDIR)/$(MANDIR)/man8/mkdosfs.8; \
+ ln -sf mkfs.fat.8 $(DESTDIR)/$(MANDIR)/man8/mkfs.msdos.8; \
+ ln -sf mkfs.fat.8 $(DESTDIR)/$(MANDIR)/man8/mkfs.vfat.8; \
+ fi; \
+ fi
+
+uninstall: uninstall-symlinks uninstall-man uninstall-doc uninstall-bin
+
+uninstall-bin:
+ rm -f $(DESTDIR)/$(SBINDIR)/fatlabel
+ rm -f $(DESTDIR)/$(SBINDIR)/fsck.fat
+ rm -f $(DESTDIR)/$(SBINDIR)/mkfs.fat
+
+ rmdir --ignore-fail-on-non-empty $(DESTDIR)/$(SBINDIR)
+
+uninstall-doc:
+ rm -rf $(DESTDIR)/$(DOCDIR)/dosfstools
+
+ rmdir --ignore-fail-on-non-empty $(DESTDIR)/$(DOCDIR)
+
+uninstall-man:
+ for MANPAGE in manpages/en/*; \
+ do \
+ SECTION="8"; \
+ rm -f $(DESTDIR)/$(MANDIR)/man$${SECTION}/$$(basename $${MANPAGE} .en.$${SECTION}).$${SECTION}; \
+ done
+
+ for LANGUAGE in $(LANGUAGES); \
+ do \
+ for MANPAGE in manpages/$${LANGUAGE}/*; \
+ do \
+ SECTION="8"; \
+ rm -f $(DESTDIR)/$(MANDIR)/$${LANGUAGE}/man$${SECTION}/$$(basename $${MANPAGE} .$${LANGUAGE}.$${SECTION}).$${SECTION}; \
+ done; \
+ done
+
+uninstall-symlinks:
+ rm -f $(DESTDIR)/$(SBINDIR)/dosfslabel
+ rm -f $(DESTDIR)/$(MANDIR)/man8/dosfslabel.8
+
+ rm -f $(DESTDIR)/$(SBINDIR)/dosfsck
+ rm -f $(DESTDIR)/$(MANDIR)/man8/dosfsck.8
+ rm -f $(DESTDIR)/$(SBINDIR)/fsck.msdos
+ rm -f $(DESTDIR)/$(MANDIR)/man8/fsck.msdos.8
+ rm -f $(DESTDIR)/$(SBINDIR)/fsck.vfat
+ rm -f $(DESTDIR)/$(MANDIR)/man8/fsck.vfat.8
+
+ rm -f $(DESTDIR)/$(SBINDIR)/mkdosfs
+ rm -f $(DESTDIR)/$(MANDIR)/man8/mkdosfs.8
+ rm -f $(DESTDIR)/$(SBINDIR)/mkfs.msdos
+ rm -f $(DESTDIR)/$(MANDIR)/man8/mkfs.msdos.8
+ rm -f $(DESTDIR)/$(SBINDIR)/mkfs.vfat
+ rm -f $(DESTDIR)/$(MANDIR)/man8/mkfs.vfat.8
+
+reinstall: distclean install
+
+clean:
+ rm -f *.o
+
+distclean: clean
+ rm -f fatlabel fsck.fat mkfs.fat
+
+.PHONY: build rebuild install install-bin install-doc install-man install-symlinks uninstall uninstall-bin uninstall-doc uninstall-man uninstall-symlinks reinstall clean distclean
diff --git a/dosfstools/VERSION b/dosfstools/VERSION
new file mode 100644
index 000000000..0baec4d10
--- /dev/null
+++ b/dosfstools/VERSION
@@ -0,0 +1 @@
+3.0.28
diff --git a/dosfstools/bin/Nindent b/dosfstools/bin/Nindent
new file mode 100755
index 000000000..cf8ecfd50
--- /dev/null
+++ b/dosfstools/bin/Nindent
@@ -0,0 +1,18 @@
+#!/bin/sh
+PARAM="-npro -kr -i4 -ts8 -sob -l80 -ss -ncs -cp1"
+RES=`indent --version`
+V1=`echo $RES | cut -d' ' -f3 | cut -d'.' -f1`
+V2=`echo $RES | cut -d' ' -f3 | cut -d'.' -f2`
+V3=`echo $RES | cut -d' ' -f3 | cut -d'.' -f3`
+if [ $V1 -gt 2 ]; then
+ PARAM="$PARAM -il0"
+elif [ $V1 -eq 2 ]; then
+ if [ $V2 -gt 2 ]; then
+ PARAM="$PARAM -il0";
+ elif [ $V2 -eq 2 ]; then
+ if [ $V3 -ge 10 ]; then
+ PARAM="$PARAM -il0"
+ fi
+ fi
+fi
+exec indent $PARAM "$@"
diff --git a/dosfstools/doc/ANNOUNCE.mkdosfs b/dosfstools/doc/ANNOUNCE.mkdosfs
new file mode 100644
index 000000000..2e01716b4
--- /dev/null
+++ b/dosfstools/doc/ANNOUNCE.mkdosfs
@@ -0,0 +1,41 @@
+Announcing the release of mkdosfs version 0.3b (Yggdrasil)
+
+It seems I didn't get the bug completely fixed in 0.3a. Some
+borderline cases would still allocate too many sectors for the FAT.
+Again, nothing to worry about, just a nitpick -- this one would only
+in certain cases add one sector per FAT.
+
+Announcing the release of mkdosfs version 0.3a (Yggdrasil)
+
+Fixed a bug which would cause too many sectors to be reserved for the
+FAT (filesystem will still work fine, but have slightly less space
+available).
+
+Announcing the release of mkdosfs version 0.3 (Yggdrasil)
+
+This version correctly handles even very large filesystems, and
+properly supports the modern (3.3+) DOS bootsector format, including a
+message printed on boot attempts.
+
+Peter Anvin
+Yggdrasil Computing, Inc.
+hpa@yggdrasil.com
+
+ --------------
+
+Announcing the release of mkdosfs version 0.2
+
+
+I've just uploaded mkdosfs to sunsite.unc.edu. It works in a similar way
+to Remy Card's mke2fs, but creates an MS-DOS filesystem.
+
+The filename is mkdosfs-0.2.tar.gz.
+
+This second release should fix a small bug that could lead to FAT sizes that
+Linux's dosfs would accept but MS-DOS wouldn't.
+
+The archive contains a manual page, binary and source versions.
+
+
+Dave Hudson
+dave@humbug.demon.co.uk
diff --git a/dosfstools/doc/ChangeLog.dosfsck b/dosfstools/doc/ChangeLog.dosfsck
new file mode 100644
index 000000000..f628ac289
--- /dev/null
+++ b/dosfstools/doc/ChangeLog.dosfsck
@@ -0,0 +1,10 @@
+Changes from version 0 to 1
+===========================
+
+ - fixed an off-by-two error in check.c:check_file
+ - fixed marking clusters bad in fat.c:set_fat
+ - fat.c:reclaim_free was also reclaiming bad clusters.
+ - fixed many incorrect byte sex conversions in check.c and fat.c
+ - -t and -w now require -a or -r
+ - added option -d to drop files.
+ - added option -u to try to "undelete" non-directory files.
diff --git a/dosfstools/doc/ChangeLog.dosfstools-2.x b/dosfstools/doc/ChangeLog.dosfstools-2.x
new file mode 100644
index 000000000..7ed9efe94
--- /dev/null
+++ b/dosfstools/doc/ChangeLog.dosfstools-2.x
@@ -0,0 +1,161 @@
+version 2.11
+============
+
+ - all: don't use own llseek() anymore, glibc lseek() does everything we need
+ - dosfsck: lfn.c: avoid segfault
+ - dosfsck: check.c, lfn.c: check for orphaned LFN slots
+ - dosfsck: check.c alloc_rootdir_entry(): set owner of newly alloced clusters
+ - dosfsck: dosfsck.h: better use <byteswap.h> for byte swapping
+ - dosfsck: io.c: added code for real DOS
+ - mkdosfs: raised FAT12_THRESHOLD from 4078 to 4085, introduced MIN_CLUST_32
+ - mkdosfs: fix loop device size
+ - mkdosfs: by default, use FAT32 on devices >= 512MB
+ - mkdosfs: fix a memory leak (blank_sector)
+ - mkdosfs: fix parsing of number of blocks on command line, so that numbers
+ >2G can be used
+ - mkdosfs: add 'b' to getopt() string so this option can be used :)
+ - mkdosfs: fix parsing of -i arg (should be unsigned)
+ - mkdosfs: change default permissions of created images (-C) to 0666 & ~umask
+ - mkdosfs: relax geometry check: if HDIO_GETGEO fails, print a warning and
+ default to H=255,S=63
+ - dosfsck: new option -n (no-op): just check non-interactively, but
+ don't write anything to filesystem
+ - A few #include changes to support compilation with linux 2.6
+ headers (thanks to Jim Gifford <jim@jg555.com>)
+ - dosfsck: remove directory entries pointing to start cluster 0, if they're
+ not "." or ".." entries that should actually point to the root dir
+ (pointed out by Thomas Winkler <twinkler@sysgo.de>)
+ - mkdosfs: new option -h to set number of hidden sectors
+ (thanks to Godwin Stewart <gstewart@spamcop.net>)
+ - all: updated my mail address everywhere...
+
+version 2.10
+============
+
+ - dosfsck: various 64-bit fixes and removed some warnings by Michal
+ Cihar <mcihar@suse.cz>
+ - mkdosfs: better error message if called without parameters (also
+ suggested by Michal)
+
+version 2.9
+===========
+
+ - dosfsck: if EOF from stdin, exit with error code
+ - dosfsck: Fix potential for "Internal error: next_cluster on bad cluster".
+ - dosfsck: When clearing long file names, don't overwrite the dir
+ entries with all zeros, but put 0xe5 into the first byte.
+ Otherwise, some OSes stop reading the directory at that point...
+ - dosfsck: in statistics printed by -v, fix 32bit overflow in number
+ of data bytes.
+ - dosfsck: fix an potential overflow in "too many clusters" check
+ - dosfsck: fix 64bit problem in fat.c (Debian bug #152769)
+ - dosfsck: allow FAT size > 32MB.
+ - dosfsck: allow for only one FAT
+ - dosfsck: with -v, also check that last sector of the filesystem can
+ be read (in case a partition is smaller than the fs thinks)
+ - mkdosfs: add note in manpage that creating bootable filesystems is
+ not supported.
+ - mkdosfs: better error message with pointer to -I if target is a
+ full-disk device.
+
+version 2.8
+===========
+
+ - dosfsck: Fixed endless loop whenever a volume label was present.
+
+version 2.7
+===========
+
+ - dosfsck: Don't check volume label for bad characters, everything
+ seems to be allowed there... Also ignore duplicate names where one of
+ them is a volume label.
+
+version 2.6
+===========
+
+ - mkdosfs: Added correct heads definition for 2.88M floppies if not
+ created via loopback.
+ - dosfsck: If boot sector and its backup are different (FAT32), offer
+ to write the backup to sector 0. (tnx to Pavel Roskin for this)
+ - For 64 bit alpha, struct bootsector in dosfsck.h must be defined
+ with __attribute__((packed)).
+ - mkdosfs now actually accepts -R option. (tnx to David Kerrawn)
+ - Fixed typo in dosfsck boot.c (recognition of boot signature in FSINFO)
+ - Various compilation fixes for 2.4 kernel headers and for ia64.
+
+version 2.5
+===========
+
+ - The llseek() implementation for alpha didn't really work; fixed it.
+
+version 2.4
+===========
+
+ - Fix compiling problem on alpha (made a silly typo...)
+
+version 2.3
+===========
+
+ - mkdosfs: Fixed usage message (printed only "bad address").
+ - both: made man pages and usage statements more consistent.
+ - both: fix llseek function for alpha.
+ - dosfsck: fix reading of unaligned fields in boot sector for alpha.
+ - dosfsck: fixed renaming of files (extension wasn't really written).
+
+version 2.2
+===========
+
+ - Added dosfsck/COPYING, putting dosfsck officially under GPL (Werner
+ and I agree that it should be GPL).
+ - mkdosfs: Allow creation of a 16 bit FAT on filesystems that are too
+ small for it if the user explicitly selected FAT16 (but a warning
+ is printed). Formerly, you got the misleading error message "make
+ the fs a bit smaller".
+ - dosfsck: new option -y as synonym for -y; for compability with
+ other fs checkers, which also accept this option.
+ - dosfsck: Now prints messages similar to e2fsck: at start version
+ and feature list; at end number of files (and directories) and
+ number of used/total clusters. This makes the printouts of *fsck at
+ boot time nicer.
+ - dosfsck: -a (auto repair) now turns on -f (salvage files), too. -a
+ should act as non-destructive as possible, so lost clusters should
+ be assigned to files. Otherwise the data in them might be
+ overwritten later.
+ - dosfsck: Don't drop a directory with lots of bad entries in
+ auto-repair mode for the same reason as above.
+ - dosfsck: avoid deleting the whole FAT32 root dir if something is
+ wrong with it (bad start cluster or the like).
+ - general: also create symlinks {mkfs,fsck}.vfat.8 to the respective
+ real man pages.
+
+version 2.1
+===========
+
+ - Fix some forgotten loff_t's for filesystems > 4GB. (Thanks to
+ <ki@kretz.co.at>).
+ - Fix typo in mkdosfs manpage.
+ - Removed inclusion of <linux/loop.h> from mkdosfs.c; it's unnecessary and
+ caused problems in some environments.
+ - Fix condition when to expect . and .. entries in a directory. (Was
+ wrong for non-FAT32 if first entry in root dir was a directory also.)
+ - Also create mkfs.vfat and fsck.vfat symlinks, so that also
+ filesystems listed with type "vfat" in /etc/fstab can be
+ automatically checked.
+
+version 2.0
+===========
+
+ - merge of mkdosfs and dosfstools in one package
+ - new maintainer: Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
+ - FAT32 support in both mkdosfs and dosfsck
+ - VFAT (long filename) support in dosfsck
+ - Support for Atari variant of MS-DOS filesystem in both tools
+ - Working support for big-endian systems in both tools
+ - Better support for loop devices in mkdosfs: usual floppy sizes are
+ detected and media byte etc. set accordingly; if loop fs has no
+ standard floppy size, use hd params
+ (mainly by Giuliano Procida <gpp10@cus.cam.ac.uk>)
+ - Removed lots of gcc warnings
+ - Fixed some minor calculation bugs in mkdosfs.
+
+For change logs previous to 2.0, see the CHANGES files in the subdirectories.
diff --git a/dosfstools/doc/ChangeLog.mkdosfs b/dosfstools/doc/ChangeLog.mkdosfs
new file mode 100644
index 000000000..e39d9d6a4
--- /dev/null
+++ b/dosfstools/doc/ChangeLog.mkdosfs
@@ -0,0 +1,18 @@
+28th January 1995 H. Peter Anvin (hpa@yggdrasil.com)
+
+ Better algorithm to select cluster sizes on large filesystems.
+ Added bogus boot sector code that on attempts to boot prints a
+ message (which can be chosen at mkdosfs time) and lets the user
+ press any key and try again. Corrected support for 1.2 Mb
+ floppies. mkdosfs now generates the extended bootsector
+ (superblock) format of DOS 3.3+, with support for volume ID's and
+ volume labels (volume labels are also written to the root
+ directory, as they should).
+
+18th February 1994 Dave Hudson (dave@humbug.demon.co.uk)
+
+ Released version 0.2 - clears a bug in the FAT sizing code.
+
+1st September 1993 Dave Hudson (dave@humbug.demon.co.uk)
+
+ Released version 0.1 - ALPHA release of mkdosfs
diff --git a/dosfstools/doc/README.dosfsck b/dosfstools/doc/README.dosfsck
new file mode 100644
index 000000000..3038f363b
--- /dev/null
+++ b/dosfstools/doc/README.dosfsck
@@ -0,0 +1,60 @@
+dosfsck, version 1
+==================
+
+WARNING: This is ALPHA test software. Use at your own risk.
+
+dosfsck is the Linux equivalent of PC/MS-DOS' CHKDSK. It checks the
+consistency of PC/MS-DOS filesystems and optionally tries to repair
+them. The tests dosfsck performs are described in the man page.
+
+dosfsck needs header files from dosfs.9 (or later) to compile.
+
+Before using dosfsck to repair a filesystem that contains data of any
+value, you should verify that dosfsck is able to correct all reported
+errors. (Except fatal errors and those reported as unfixable, of
+course.) In order to do this, run it with the -V option, e.g.
+
+ dosfsck -V /dev/sda1 (automatic check)
+or dosfsck -V -r /dev/sda1 (interactive check and repair)
+
+dosfsck will perform two passes: in the first pass, inconsistencies are
+detected and a list of changes to correct the problems is generated. In
+the second pass, those changes are applied whenever dosfsck reads data
+from disk. Hence no fixable errors should be reported in the second
+pass if the first pass was successful.
+
+Please notify the author if fixable errors are reported in the second
+pass.
+
+After verifying that dosfsck appears to be able to perform the desired
+operations, either confirm that you want the changes to be performed
+(if dosfsck was started with -r) or re-run dosfsck with the -a option
+(if it was started without -r).
+
+Please send bug reports, comments, flames, etc. to
+almesber@nessie.cs.id.ethz.ch or almesber@bernina.ethz.ch
+
+- Werner
+
+FAT32 and LFN support
+=====================
+
+I've finally implemented some of the new features of MS-DOS
+filesystems: FAT32 and long filenames.
+
+FAT32 is automatically detected and of course the different FAT
+structure is handled. (Internally many changes were needed, so 32 bit
+variables for all cluster numbers and 64 bit vars for offsets inside
+the filesystem.) New checks for FAT32 are most notably on the backup
+boot sector and the new info sector. Also the possibility that the
+root directory resides in a cluster chain (instead of in a static
+area) on FAT32 is handled.
+
+dosfscheck also knows about VFAT long filenames now. It parses those
+names and uses them in listings etc. when available. There are also
+some checks on the (cruel) structure of how LFNs are stored and some
+attempts to fix problems.
+
+- Roman <roman@hodek.net>
+
+BTW, version 2 isn't ALPHA anymore :-)
diff --git a/dosfstools/doc/README.dosfstools-2.x b/dosfstools/doc/README.dosfstools-2.x
new file mode 100644
index 000000000..5fb00ed07
--- /dev/null
+++ b/dosfstools/doc/README.dosfstools-2.x
@@ -0,0 +1,60 @@
+
+Atari format support
+====================
+
+Both mkdosfs and dosfsck now can also handle the Atari variation of
+the MS-DOS filesystem format. The Atari format has some minor
+differences, some caused by the different machine architecture (m68k),
+some being "historic" (Atari didn't change some things that M$
+changed).
+
+Both tools automatically select Atari format if they run on an Atari.
+Additionally the -A switch toggles between Atari and MS-DOS format.
+I.e., on an Atari it selects plain DOS format, on any other machine it
+switches to Atari format.
+
+The differences are in detail:
+
+ - Atari TOS doesn't like cluster sizes != 2, so the usual solution
+ for bigger partitions was to increase the logical sector size. So
+ mkdosfs can handle sector sizes != 512 now, you can also manually
+ select it with the -S option. On filesystems larger than approx. 32
+ MB, the sector size is automatically increased (stead of the
+ cluster size) to make the filesystem fit. mkdosfs will always use 2
+ sectors per cluster (also with the floppy standard configurations),
+ except when directed otherwise on the command line.
+
+ - From the docs, all values between 0xfff8 and 0xffff in the FAT mark
+ an end-of-file. However, DOS usually uses 0xfff8 and Atari 0xffff.
+ This seems to be only an consmetic difference. At least TOS doesn't
+ complain about 0xffff EOF marks. Don't know what DOS thinks of
+ 0xfff8 :-) Anyway, both tools use the EOF mark common to the
+ system (DOS/Atari).
+
+ - Something similar of the bad cluster marks: On Atari the FAT values
+ 0xfff0 to 0xfff7 are used for this, under DOS only 0xfff7 (the
+ others can be normal cluster numbers, allowing 7 more clusters :-)
+ However, both systems usually mark with 0xfff7. Just dosfsck has to
+ interpret 0xfff0...0xfff7 differently.
+
+ - Some fields in the boot sector are interpreted differently. For
+ example, Atari has a disk serial number (used to aid disk change
+ detection) where DOS stores the system name; the 'hidden' field is
+ 32 bit for DOS, but 16 bit for Atari, and there's no 'total_sect'
+ field; the 12/16 bit FAT decision is different: it's not based on
+ the number of clusters, but always FAT12 on floppies and FAT16 on
+ hard disks. mkdosfs nows about these differences and constructs the
+ boot sector accordingly.
+
+ - In dosfsck, the boot sector differences also have to known, to not
+ warn about things that are no error on Atari. In addition, most
+ Atari formatting tools fill the 'tracks' and 'heads' fields with 0
+ for hard disks, because they're meaningless on SCSI disks (Atari
+ has/had no IDE). Due to this, the check that they should be
+ non-zero is switched off.
+
+ - Under Atari TOS, some other characters are illegal in filenames:
+ '<', '>', '|', '"', and ':' are allowed, but all non-ASCII chars
+ (codes >= 128) are forbidden.
+
+- Roman <Roman.Hodek@informatik.uni-erlangen.de>
diff --git a/dosfstools/doc/README.mkdosfs b/dosfstools/doc/README.mkdosfs
new file mode 100644
index 000000000..5bd9b21b3
--- /dev/null
+++ b/dosfstools/doc/README.mkdosfs
@@ -0,0 +1,50 @@
+mkdosfs - Make DOS filesystem utilty.
+
+
+I wrote this, partially to complement the dosfsck utility written by Werner
+Almesberger (who graciously gave me some pointers when I asked for some
+advice about writing this code), and also to avoid me having to boot DOS
+just to create data partitions (I use Linux to back up DOS :-) ).
+
+The code is really derived from Remy Card's mke2fs utility - I used this as a
+framework, although all of the filesystem specific stuff was removed and the
+DOS stuff inserted. I believe originally mke2fs was based on Linus' mkfs
+code, hence the acknowledgements in the source code.
+
+Neither Remy nor Linus have had any involvement with mkdosfs, so if there are
+any bugs they're almost certainly "all my own work".
+
+The code has been available for ftp since 1st September 1993, and I have yet
+to receive any bug reports from users. I don't know of any bugs, but if you
+do find a bug or have any constructive comments, please mail me!
+
+The only bug I found with version 0.1 was an obscure fault that could lead
+to an invalid (for MS-DOS, not Linux's dos fs) number of sectors used in the
+file allocation table(s).
+
+
+Dave Hudson
+dave@humbug.demon.co.uk
+
+
+FAT32 support
+=============
+
+mkdosfs now can also create filesystems in the new FAT32 format. To do
+this, give mkdosfs a "-F 32" option. FAT32 isn't selected
+automatically (yet), even if very large clusters are needed with
+FAT16. With FAT32 you have two additional options, -R to select the
+number of reserved sectors (usually 32), and -b to select the location
+of the backup boot sector (default 6). Of course such a backup is
+created, as well as the new info sector. On FAT32, the root directory
+is always created as a cluster chain. Sorry, there's no switch to
+generate an old static root dir.
+
+One bigger bug fix besides FAT32 was to reject filesystems that need a
+16 bit FAT to fit all possible clusters, but the bigger FAT needs some
+more sectors, so the total number of clusters drop below the border
+where MS-DOS expects a 12 bit FAT. So such filesystems would be FAT16,
+but interpreted as FAT32 by DOS. The fix is to reduce filesystem size
+a bit.
+
+- Roman <roman@hodek.net>
diff --git a/dosfstools/doc/TODO.dosfstools-2.x b/dosfstools/doc/TODO.dosfstools-2.x
new file mode 100644
index 000000000..dbc2de074
--- /dev/null
+++ b/dosfstools/doc/TODO.dosfstools-2.x
@@ -0,0 +1,14 @@
+ -*- mode: indented-text -*-
+
+ - dosfsck: Better checking of file times: ctime <= mtime <= atime
+
+ - mkdosfs: If /etc/bootsect.dos (or similar) exists, use it as a
+ template for generating boot sectors. This way, you can, e.g., make
+ bootable DOS disks.
+
+ Addendum: Don't know if that's so wise... There are really many
+ variants of DOS/Windows bootcode out in the wild, and the code is
+ proprietary, too.
+
+ - dosfsck: read-only sector test (-t without -a or -r); just print
+ out errors.
diff --git a/dosfstools/manpages/Makefile b/dosfstools/manpages/Makefile
new file mode 100644
index 000000000..ee8a47829
--- /dev/null
+++ b/dosfstools/manpages/Makefile
@@ -0,0 +1,50 @@
+# Makefile
+
+## dosfstools(7)
+## Copyright (C) 2006-2014 Daniel Baumann <mail@daniel-baumann.ch>
+##
+## This program comes with ABSOLUTELY NO WARRANTY; for details see COPYING.
+## This is free software, and you are welcome to redistribute it
+## under certain conditions; see COPYING for details.
+
+
+SHELL := sh -e
+
+LANGUAGES = $(shell cd po && ls)
+
+all: build
+
+po4a.cfg:
+ echo "[po4a_langs] $(LANGUAGES)" > po4a.cfg
+ echo "[po4a_paths] pot/\$$master.pot \$$lang:po/\$$lang/\$$master.po" >> po4a.cfg
+
+ for MANPAGE in en/*; \
+ do \
+ SECTION="$$(basename $${MANPAGE} | sed -e 's|\.|\n|g' | tail -n1)"; \
+ echo "[type: man] $${MANPAGE} \$$lang:\$$lang/$$(basename $${MANPAGE} .$${SECTION}).\$$lang.$${SECTION}" >> po4a.cfg; \
+ done
+
+update:
+ ./bin/update-version.sh
+
+build: po4a.cfg
+ @if [ ! -x "$$(which po4a 2>/dev/null)" ]; \
+ then \
+ echo "E: po4a - command not found"; \
+ echo "I: po4a can be obtained from:"; \
+ echo "I: http://po4a.alioth.debian.org/"; \
+ echo "I: On Debian based systems, po4a can be installed with:"; \
+ echo "I: apt-get install po4a"; \
+ exit 1; \
+ fi
+
+ po4a --keep 0 --no-backups -o untranslated=MT,ME \
+ --package-name dosfstools po4a.cfg
+
+clean:
+ rm -rf $(LANGUAGES)
+
+distclean: clean
+ rm -f po4a.cfg
+
+rebuild: distclean update build
diff --git a/dosfstools/manpages/bin/update-version.sh b/dosfstools/manpages/bin/update-version.sh
new file mode 100755
index 000000000..48e9c08c0
--- /dev/null
+++ b/dosfstools/manpages/bin/update-version.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+
+## dosfstools(7)
+## Copyright (C) 2006-2014 Daniel Baumann <mail@daniel-baumann.ch>
+##
+## This program comes with ABSOLUTELY NO WARRANTY; for details see COPYING.
+## This is free software, and you are welcome to redistribute it
+## under certain conditions; see COPYING for details.
+
+
+set -e
+
+PROJECT="dosfstools"
+VERSION="$(cat ../VERSION)"
+
+DATE="$(LC_ALL=C date +%Y\\\\-%m\\\\-%d)"
+
+DAY="$(LC_ALL=C date +%d)"
+MONTH="$(LC_ALL=C date +%m)"
+YEAR="$(LC_ALL=C date +%Y)"
+
+echo "Updating version headers..."
+
+for MANPAGE in en/*
+do
+ PROGRAM="$(basename ${MANPAGE} | sed -e 's|\(.*\).[0-9]$|\1|' | tr [a-z] [A-Z])"
+ SECTION="$(basename ${MANPAGE} | sed -e 's|.*.\([0-9]\)$|\1|')"
+
+ sed -i -e "s|^.TH.*$|.TH ${PROGRAM} ${SECTION} ${DATE} ${VERSION} \"${PROJECT}\"|" ${MANPAGE}
+done
+
+# European date format
+for _LANGUAGE in de es fr it
+do
+ if ls po/${_LANGUAGE}/*.po > /dev/null 2>&1
+ then
+ for _FILE in po/${_LANGUAGE}/*.po
+ do
+ sed -i -e "s|^msgstr .*.2014-.*$|msgstr \"${DAY}.${MONTH}.${YEAR}\"|g" \
+ -e "s|^msgstr .*.2014\"$|msgstr \"${DAY}.${MONTH}.${YEAR}\"|g" \
+ "${_FILE}"
+ done
+ fi
+done
+
+# Brazilian date format
+if ls po/pt_BR/*.po > /dev/null 2>&1
+then
+ for _FILE in po/pt_BR/*.po
+ do
+ sed -i -e "s|^msgstr .*.2014-.*$|msgstr \"${DAY}-${MONTH}-${YEAR}\"|g" \
+ -e "s|^msgstr .*-2014\"$|msgstr \"${DAY}-${MONTH}-${YEAR}\"|g" \
+ "${_FILE}"
+ done
+fi
diff --git a/dosfstools/manpages/de/fatlabel.de.8 b/dosfstools/manpages/de/fatlabel.de.8
new file mode 100644
index 000000000..53f5515ed
--- /dev/null
+++ b/dosfstools/manpages/de/fatlabel.de.8
@@ -0,0 +1,68 @@
+.\" fatlabel.8 - manpage for fatlabel
+.\"
+.\" Copyright (C) 2006-2014 Daniel Baumann <daniel@debian.org>
+.\"
+.\" This program is free software: you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation, either version 3 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful,
+.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.\" GNU General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License
+.\" along with this program. If not, see <http://www.gnu.org/licenses/>.
+.\"
+.\" The complete text of the GNU General Public License
+.\" can be found in /usr/share/common-licenses/GPL-3 file.
+.\"
+.\"
+.\"*******************************************************************
+.\"
+.\" This file was generated with po4a. Translate the source file.
+.\"
+.\"*******************************************************************
+.TH FATLABEL 8 2015\-05\-16 3.0.28 dosfstools
+.SH NAME
+.\" ----------------------------------------------------------------------------
+\fBfatlabel\fP \- set or get MS\-DOS filesystem label
+.SH SYNOPSIS
+.\" ----------------------------------------------------------------------------
+\fBfatlabel\fP \fIDEVICE\fP [\fILABEL\fP]
+.SH DESCRIPTION
+\fBfatlabel\fP set or gets a MS\-DOS filesystem label from a given device.
+.PP
+.\" ----------------------------------------------------------------------------
+If \fILABEL\fP is omitted, then the label name of the specified device is
+written on the standard output. A label can't be longer than 11 bytes.
+.SH OPTIONS
+.IP "\fB\-h\fP, \fB\-\-help\fP" 4
+Displays a help message.
+.IP "\fB\-V\fP, \fB\-\-version\fP" 4
+.\" ----------------------------------------------------------------------------
+Shows version.
+.SH "SEE ALSO"
+\fBfsck.fat\fP(8)
+.br
+.\" ----------------------------------------------------------------------------
+\fBmkfs.fat\fP(8)
+.SH HOMEPAGE
+.\" ----------------------------------------------------------------------------
+The home for the \fBdosfstools\fP project is its
+.UR https://github.com/dosfstools/dosfstools
+GitHub project page
+.UE .
+.SH AUTHORS
+\fBdosfstools\fP were written by
+.MT werner.almesberger@\:lrc.di.epfl.ch
+Werner Almesberger
+.ME ,
+.MT Roman.Hodek@\:informatik.\:uni-erlangen.de
+Roman Hodek
+.ME ,
+and others. The current maintainer is
+.MT aeb@\:debian.org
+Andreas Bombe
+.ME .
diff --git a/dosfstools/manpages/de/fsck.fat.de.8 b/dosfstools/manpages/de/fsck.fat.de.8
new file mode 100644
index 000000000..869b806a8
--- /dev/null
+++ b/dosfstools/manpages/de/fsck.fat.de.8
@@ -0,0 +1,189 @@
+.\" fsck.fat.8 - manpage for fsck.fat
+.\"
+.\" Copyright (C) 2006-2014 Daniel Baumann <daniel@debian.org>
+.\"
+.\" This program is free software: you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation, either version 3 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful,
+.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.\" GNU General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License
+.\" along with this program. If not, see <http://www.gnu.org/licenses/>.
+.\"
+.\" The complete text of the GNU General Public License
+.\" can be found in /usr/share/common-licenses/GPL-3 file.
+.\"
+.\"
+.\"*******************************************************************
+.\"
+.\" This file was generated with po4a. Translate the source file.
+.\"
+.\"*******************************************************************
+.TH FSCK.FAT 8 2015\-05\-16 3.0.28 dosfstools
+.SH NAME
+.\" ----------------------------------------------------------------------------
+\fBfsck.fat\fP \- check and repair MS\-DOS filesystems
+.SH SYNOPSIS
+.\" ----------------------------------------------------------------------------
+\fBfsck.fat\fP [\fIOPTIONS\fP] \fIDEVICE\fP
+.SH DESCRIPTION
+\fBfsck.fat\fP verifies the consistency of MS\-DOS filesystems and optionally
+tries to repair them.
+.PP
+The following filesystem problems can be corrected (in this order):
+.IP * 4
+FAT contains invalid cluster numbers. Cluster is changed to EOF.
+.IP * 4
+File's cluster chain contains a loop. The loop is broken.
+.IP * 4
+Bad clusters (read errors). The clusters are marked bad and they are
+removed from files owning them. This check is optional.
+.IP * 4
+Directories with a large number of bad entries (probably corrupt). The
+directory can be deleted.
+.IP * 4
+Files . and .. are non\-directories. They can be deleted or renamed.
+.IP * 4
+Directories . and .. in root directory. They are deleted.
+.IP * 4
+Bad filenames. They can be renamed.
+.IP * 4
+Duplicate directory entries. They can be deleted or renamed.
+.IP * 4
+Directories with non\-zero size field. Size is set to zero.
+.IP * 4
+Directory . does not point to parent directory. The start pointer is
+adjusted.
+.IP * 4
+Directory .. does not point to parent of parent directory. The start
+pointer is adjusted.
+.IP * 4
+Start cluster number of a file is invalid. The file is truncated.
+.IP * 4
+File contains bad or free clusters. The file is truncated.
+.IP * 4
+File's cluster chain is longer than indicated by the size fields. The file
+is truncated.
+.IP * 4
+Two or more files share the same cluster(s). All but one of the files are
+truncated. If the file being truncated is a directory file that has already
+been read, the filesystem check is restarted after truncation.
+.IP * 4
+File's cluster chain is shorter than indicated by the size fields. The file
+is truncated.
+.IP * 4
+Clusters are marked as used but are not owned by a file. They are marked as
+free.
+.PP
+Additionally, the following problems are detected, but not repaired:
+.IP * 4
+Invalid parameters in boot sector
+.IP * 4
+Absence of . and .. entries in non\-root directories
+.PP
+.\" ----------------------------------------------------------------------------
+When \fBfsck.fat\fP checks a filesystem, it accumulates all changes in memory
+and performs them only after all checks are complete. This can be disabled
+with the \fB\-w\fP option.
+.SH OPTIONS
+.IP \fB\-a\fP 4
+Automatically repair the filesystem. No user intervention is necessary.
+Whenever there is more than one method to solve a problem, the least
+destructive approach is used.
+.IP \fB\-A\fP 4
+Use Atari variation of the MS\-DOS filesystem. This is default if
+\fBfsck.fat\fP is run on an Atari, then this option turns off Atari format.
+There are some minor differences in Atari format: Some boot sector fields
+are interpreted slightly different, and the special FAT entries for
+end\-of\-file and bad cluster can be different. Under MS\-DOS 0xfff8 is used
+for EOF and Atari employs 0xffff by default, but both systems recognize all
+values from 0xfff8...0xffff as end\-of\-file. MS\-DOS uses only 0xfff7 for bad
+clusters, where on Atari values 0xfff0...0xfff7 are for this purpose (but
+the standard value is still 0xfff7).
+.IP \fB\-b\fP 4
+Make read\-only boot sector check.
+.IP "\fB\-d\fP \fIPATH\fP" 4
+Delete the specified file. If more than one file with that name exist, the
+first one is deleted. This option can be given more than once.
+.IP \fB\-f\fP 4
+Salvage unused cluster chains to files. By default, unused clusters are
+added to the free disk space except in auto mode (\fB\-a\fP).
+.IP \fB\-l\fP 4
+List path names of files being processed.
+.IP \fB\-n\fP 4
+No\-operation mode: non\-interactively check for errors, but don't write
+anything to the filesystem.
+.IP \fB\-p\fP 4
+Same as \fB\-a\fP, for compatibility with other *fsck.
+.IP \fB\-r\fP 4
+Interactively repair the filesystem. The user is asked for advice whenever
+there is more than one approach to fix an inconsistency. This is the
+default mode and the option is only retained for backwards compatibility.
+.IP \fB\-t\fP 4
+Mark unreadable clusters as bad.
+.IP "\fB\-u\fP \fIPATH\fP" 4
+Try to undelete the specified file. \fBfsck.fat\fP tries to allocate a chain
+of contiguous unallocated clusters beginning with the start cluster of the
+undeleted file. This option can be given more than once.
+.IP \fB\-v\fP 4
+Verbose mode. Generates slightly more output.
+.IP \fB\-V\fP 4
+Perform a verification pass. The filesystem check is repeated after the
+first run. The second pass should never report any fixable errors. It may
+take considerably longer than the first pass, because the first pass may
+have generated long list of modifications that have to be scanned for each
+disk read.
+.IP \fB\-w\fP 4
+Write changes to disk immediately.
+.IP \fB\-y\fP 4
+.\" ----------------------------------------------------------------------------
+Same as \fB\-a\fP (automatically repair filesystem) for compatibility with other
+fsck tools.
+.SH "EXIT STATUS"
+.IP 0 4
+No recoverable errors have been detected.
+.IP 1 4
+Recoverable errors have been detected or \fBfsck.fat\fP has discovered an
+internal inconsistency.
+.IP 2 4
+.\" ----------------------------------------------------------------------------
+Usage error. \fBfsck.fat\fP did not access the filesystem.
+.SH FILES
+.IP "fsck0000.rec, fsck0001.rec, ..." 4
+.\" ----------------------------------------------------------------------------
+When recovering from a corrupted filesystem, \fBfsck.fat\fP dumps recovered
+data into files named 'fsckNNNN.rec' in the top level directory of the
+filesystem.
+.SH BUGS
+.\" ----------------------------------------------------------------------------
+Does not create . and .. files where necessary. Does not remove entirely
+empty directories. Should give more diagnostic messages. Undeleting files
+should use a more sophisticated algorithm.
+.SH "SEE ALSO"
+\fBfatlabel\fP(8)
+.br
+.\" ----------------------------------------------------------------------------
+\fBmkfs.fat\fP(8)
+.SH HOMEPAGE
+.\" ----------------------------------------------------------------------------
+The home for the \fBdosfstools\fP project is its
+.UR https://github.com/dosfstools/dosfstools
+GitHub project page
+.UE .
+.SH AUTHORS
+\fBdosfstools\fP were written by
+.MT werner.almesberger@\:lrc.di.epfl.ch
+Werner Almesberger
+.ME ,
+.MT Roman.Hodek@\:informatik.\:uni-erlangen.de
+Roman Hodek
+.ME ,
+and others. The current maintainer is
+.MT aeb@\:debian.org
+Andreas Bombe
+.ME .
diff --git a/dosfstools/manpages/de/mkfs.fat.de.8 b/dosfstools/manpages/de/mkfs.fat.de.8
new file mode 100644
index 000000000..a1b51d45b
--- /dev/null
+++ b/dosfstools/manpages/de/mkfs.fat.de.8
@@ -0,0 +1,172 @@
+.\" mkfs.fat.8 - manpage for fs.fatck
+.\"
+.\" Copyright (C) 2006-2014 Daniel Baumann <daniel@debian.org>
+.\"
+.\" This program is free software: you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation, either version 3 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful,
+.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.\" GNU General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License
+.\" along with this program. If not, see <http://www.gnu.org/licenses/>.
+.\"
+.\" The complete text of the GNU General Public License
+.\" can be found in /usr/share/common-licenses/GPL-3 file.
+.\"
+.\"
+.\"*******************************************************************
+.\"
+.\" This file was generated with po4a. Translate the source file.
+.\"
+.\"*******************************************************************
+.TH MKFS.FAT 8 2015\-05\-16 3.0.28 dosfstools
+.SH NAME
+.\" ----------------------------------------------------------------------------
+\fBmkfs.fat\fP \- create an MS\-DOS filesystem under Linux
+.SH SYNOPSIS
+.\" ----------------------------------------------------------------------------
+\fBmkfs.fat\fP [\fIOPTIONS\fP] \fIDEVICE\fP [\fIBLOCK\-COUNT\fP]
+.SH DESCRIPTION
+.\" ----------------------------------------------------------------------------
+\fBmkfs.fat\fP is used to create an MS\-DOS filesystem under Linux on a device
+(usually a disk partition). \fIDEVICE\fP is the special file corresponding to
+the device (e.g. /dev/sdXX). \fIBLOCK\-COUNT\fP is the number of blocks on the
+device. If omitted, \fBmkfs.fat\fP automatically determines the filesystem
+size.
+.SH OPTIONS
+.IP \fB\-a\fP 4
+Normally, for any filesystem except very small ones, \fBmkfs.fat\fP will align
+all the data structures to cluster size, to make sure that as long as the
+partition is properly aligned, so will all the data structures in the
+filesystem. This option disables alignment; this may provide a handful of
+additional clusters of storage at the expense of a significant performance
+degradation on RAIDs, flash media or large\-sector hard disks.
+.IP "\fB \-A\fP" 4
+Use Atari variation of the MS\-DOS filesystem. This is default if
+\fBmkfs.fat\fP is run on an Atari, then this option turns off Atari format.
+There are some differences when using Atari format: If not directed
+otherwise by the user, \fBmkfs.fat\fP will always use 2 sectors per cluster,
+since GEMDOS doesn't like other values very much. It will also obey the
+maximum number of sectors GEMDOS can handle. Larger filesystems are managed
+by raising the logical sector size. Under Atari format, an Atari\-compatible
+serial number for the filesystem is generated, and a 12 bit FAT is used only
+for filesystems that have one of the usual floppy sizes (720k, 1.2M, 1.44M,
+2.88M), a 16 bit FAT otherwise. This can be overridden with the \fB\-F\fP
+option. Some PC\-specific boot sector fields aren't written, and a boot
+message (option \fB\-m\fP) is ignored.
+.IP "\fB\-b\fP \fISECTOR\-OF\-BACKUP\fP" 4
+Selects the location of the backup boot sector for FAT32. Default depends
+on number of reserved sectors, but usually is sector 6. The backup must be
+within the range of reserved sectors.
+.IP \fB\-c\fP 4
+Check the device for bad blocks before creating the filesystem.
+.IP \fB\-C\fP 4
+Create the file given as \fIDEVICE\fP on the command line, and write the
+to\-be\-created filesystem to it. This can be used to create the new
+filesystem in a file instead of on a real device, and to avoid using \fBdd\fP
+in advance to create a file of appropriate size. With this option, the
+\fIBLOCK\-COUNT\fP must be given, because otherwise the intended size of the
+filesystem wouldn't be known. The file created is a sparse file, which
+actually only contains the meta\-data areas (boot sector, FATs, and root
+directory). The data portions won't be stored on the disk, but the file
+nevertheless will have the correct size. The resulting file can be copied
+later to a floppy disk or other device, or mounted through a loop device.
+.IP "\fB\-D\fP \fIDRIVE\-NUMBER\fP" 4
+Specify the BIOS drive number to be stored in the FAT boot sector. This
+value is usually 0x80 for hard disks and 0x00 for floppy devices or
+partitions to be used for floppy emulation.
+.IP "\fB\-f\fP \fINUMBER\-OF\-FATS\fP" 4
+Specify the number of file allocation tables in the filesystem. The default
+is 2.
+.IP "\fB\-F\fP \fIFAT\-SIZE\fP" 4
+Specifies the type of file allocation tables used (12, 16 or 32 bit). If
+nothing is specified, \fBmkfs.fat\fP will automatically select between 12, 16
+and 32 bit, whatever fits better for the filesystem size.
+.IP "\fB\-h\fP \fINUMBER\-OF\-HIDDEN\-SECTORS\fP" 4
+Select the number of hidden sectors in the volume. Apparently some digital
+cameras get indigestion if you feed them a CF card without such hidden
+sectors, this option allows you to satisfy them.
+.IP "\fB\-i\fP \fIVOLUME\-ID\fP" 4
+Sets the volume ID of the newly created filesystem; \fIVOLUME\-ID\fP is a 32\-bit
+hexadecimal number (for example, 2e24ec82). The default is a number which
+depends on the filesystem creation time.
+.IP \fB\-I\fP 4
+It is typical for fixed disk devices to be partitioned so, by default, you
+are not permitted to create a filesystem across the entire device.
+\fBmkfs.fat\fP will complain and tell you that it refuses to work. This is
+different when using MO disks. One doesn't always need partitions on MO
+disks. The filesystem can go directly to the whole disk. Under other OSes
+this is known as the 'superfloppy' format. This switch will force
+\fBmkfs.fat\fP to work properly.
+.IP "\fB\-l\fP \fIFILENAME\fP" 4
+Read the bad blocks list from \fIFILENAME\fP.
+.IP "\fB\-m\fP \fIMESSAGE\-FILE\fP" 4
+Sets the message the user receives on attempts to boot this filesystem
+without having properly installed an operating system. The message file
+must not exceed 418 bytes once line feeds have been converted to carriage
+return\-line feed combinations, and tabs have been expanded. If the filename
+is a hyphen (\-), the text is taken from standard input.
+.IP "\fB\-M\fP \fIFAT\-MEDIA\-TYPE\fP" 4
+Specify the media type to be stored in the FAT boot sector. This value is
+usually 0xF8 for hard disks and is 0xF0 or a value from 0xF9 to 0xFF for
+floppies or partitions to be used for floppy emulation.
+.IP "\fB\-n\fP \fIVOLUME\-NAME\fP" 4
+Sets the volume name (label) of the filesystem. The volume name can be up
+to 11 characters long. The default is no label.
+.IP "\fB\-r\fP \fIROOT\-DIR\-ENTRIES\fP" 4
+Select the number of entries available in the root directory. The default
+is 112 or 224 for floppies and 512 for hard disks.
+.IP "\fB\-R\fP \fINUMBER\-OF\-RESERVED\-SECTORS\fP" 4
+Select the number of reserved sectors. With FAT32 format at least 2
+reserved sectors are needed, the default is 32. Otherwise the default is 1
+(only the boot sector).
+.IP "\fB\-s\fP \fISECTORS\-PER\-CLUSTER\fP" 4
+Specify the number of disk sectors per cluster. Must be a power of 2,
+i.e. 1, 2, 4, 8, ... 128.
+.IP "\fB\-S\fP \fILOGICAL\-SECTOR\-SIZE\fP" 4
+Specify the number of bytes per logical sector. Must be a power of 2 and
+greater than or equal to 512, i.e. 512, 1024, 2048, 4096, 8192, 16384, or
+32768.
+.IP \fB\-v\fP 4
+Verbose execution.
+.IP \fB\-\-invariant\fP 4
+Use constants for normally randomly generated or time based data such as
+volume ID and creation time. Multiple runs of \fBmkfs.fat\fP on the same
+device create identical results with this option. Its main purpose is
+testing \fBmkfs.fat\fP.
+.IP \fB\-\-help\fP 4
+.\" ----------------------------------------------------------------------------
+Display option summary and exit.
+.SH BUGS
+.\" ----------------------------------------------------------------------------
+\fBmkfs.fat\fP can not create boot\-able filesystems. This isn't as easy as you
+might think at first glance for various reasons and has been discussed a lot
+already. \fBmkfs.fat\fP simply will not support it ;)
+.SH "SEE ALSO"
+\fBfatlabel\fP(8)
+.br
+.\" ----------------------------------------------------------------------------
+\fBfsck.fat\fP(8)
+.SH HOMEPAGE
+.\" ----------------------------------------------------------------------------
+The home for the \fBdosfstools\fP project is its
+.UR https://github.com/dosfstools/dosfstools
+GitHub project page
+.UE .
+.SH AUTHORS
+\fBdosfstools\fP were written by
+.MT werner.almesberger@\:lrc.di.epfl.ch
+Werner Almesberger
+.ME ,
+.MT Roman.Hodek@\:informatik.\:uni-erlangen.de
+Roman Hodek
+.ME ,
+and others. The current maintainer is
+.MT aeb@\:debian.org
+Andreas Bombe
+.ME .
diff --git a/dosfstools/manpages/en/fatlabel.8 b/dosfstools/manpages/en/fatlabel.8
new file mode 100644
index 000000000..c00a79517
--- /dev/null
+++ b/dosfstools/manpages/en/fatlabel.8
@@ -0,0 +1,65 @@
+.\" fatlabel.8 - manpage for fatlabel
+.\"
+.\" Copyright (C) 2006-2014 Daniel Baumann <daniel@debian.org>
+.\"
+.\" This program is free software: you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation, either version 3 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful,
+.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.\" GNU General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License
+.\" along with this program. If not, see <http://www.gnu.org/licenses/>.
+.\"
+.\" The complete text of the GNU General Public License
+.\" can be found in /usr/share/common-licenses/GPL-3 file.
+.\"
+.\"
+.TH FATLABEL 8 2015\-05\-16 3.0.28 "dosfstools"
+.SH NAME
+\fBfatlabel\fR \- set or get MS\-DOS filesystem label
+.\" ----------------------------------------------------------------------------
+.SH SYNOPSIS
+\fBfatlabel\fR \fIDEVICE\fR [\fILABEL\fR]
+.\" ----------------------------------------------------------------------------
+.SH DESCRIPTION
+\fBfatlabel\fR set or gets a MS\-DOS filesystem label from a given device.
+.PP
+If \fILABEL\fR is omitted, then the label name of the specified device is
+written on the standard output.
+A label can't be longer than 11 bytes.
+.\" ----------------------------------------------------------------------------
+.SH OPTIONS
+.IP "\fB\-h\fR, \fB\-\-help\fR" 4
+Displays a help message.
+.IP "\fB\-V\fR, \fB\-\-version\fR" 4
+Shows version.
+.\" ----------------------------------------------------------------------------
+.SH SEE ALSO
+\fBfsck.fat\fR(8)
+.br
+\fBmkfs.fat\fR(8)
+.\" ----------------------------------------------------------------------------
+.SH HOMEPAGE
+The home for the \fBdosfstools\fR project is its
+.UR https://github.com/dosfstools/dosfstools
+GitHub project page
+.UE .
+.\" ----------------------------------------------------------------------------
+.SH AUTHORS
+\fBdosfstools\fR were written by
+.MT werner.almesberger@\:lrc.di.epfl.ch
+Werner Almesberger
+.ME ,
+.MT Roman.Hodek@\:informatik.\:uni-erlangen.de
+Roman Hodek
+.ME ,
+and others.
+The current maintainer is
+.MT aeb@\:debian.org
+Andreas Bombe
+.ME .
diff --git a/dosfstools/manpages/en/fsck.fat.8 b/dosfstools/manpages/en/fsck.fat.8
new file mode 100644
index 000000000..f2d44d080
--- /dev/null
+++ b/dosfstools/manpages/en/fsck.fat.8
@@ -0,0 +1,206 @@
+.\" fsck.fat.8 - manpage for fsck.fat
+.\"
+.\" Copyright (C) 2006-2014 Daniel Baumann <daniel@debian.org>
+.\"
+.\" This program is free software: you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation, either version 3 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful,
+.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.\" GNU General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License
+.\" along with this program. If not, see <http://www.gnu.org/licenses/>.
+.\"
+.\" The complete text of the GNU General Public License
+.\" can be found in /usr/share/common-licenses/GPL-3 file.
+.\"
+.\"
+.TH FSCK.FAT 8 2015\-05\-16 3.0.28 "dosfstools"
+.SH NAME
+\fBfsck.fat\fR \- check and repair MS\-DOS filesystems
+.\" ----------------------------------------------------------------------------
+.SH SYNOPSIS
+\fBfsck.fat\fR [\fIOPTIONS\fR] \fIDEVICE\fR
+.\" ----------------------------------------------------------------------------
+.SH DESCRIPTION
+\fBfsck.fat\fR verifies the consistency of MS\-DOS filesystems and optionally
+tries to repair them.
+.PP
+The following filesystem problems can be corrected (in this order):
+.IP "*" 4
+FAT contains invalid cluster numbers.
+Cluster is changed to EOF.
+.IP "*" 4
+File's cluster chain contains a loop.
+The loop is broken.
+.IP "*" 4
+Bad clusters (read errors).
+The clusters are marked bad and they are removed from files owning them.
+This check is optional.
+.IP "*" 4
+Directories with a large number of bad entries (probably corrupt).
+The directory can be deleted.
+.IP "*" 4
+Files . and .. are non\-directories.
+They can be deleted or renamed.
+.IP "*" 4
+Directories . and .. in root directory.
+They are deleted.
+.IP "*" 4
+Bad filenames.
+They can be renamed.
+.IP "*" 4
+Duplicate directory entries.
+They can be deleted or renamed.
+.IP "*" 4
+Directories with non\-zero size field.
+Size is set to zero.
+.IP "*" 4
+Directory . does not point to parent directory.
+The start pointer is adjusted.
+.IP "*" 4
+Directory .. does not point to parent of parent directory.
+The start pointer is adjusted.
+.IP "*" 4
+Start cluster number of a file is invalid.
+The file is truncated.
+.IP "*" 4
+File contains bad or free clusters.
+The file is truncated.
+.IP "*" 4
+File's cluster chain is longer than indicated by the size fields.
+The file is truncated.
+.IP "*" 4
+Two or more files share the same cluster(s).
+All but one of the files are truncated.
+If the file being truncated is a directory file that has already been read, the
+filesystem check is restarted after truncation.
+.IP "*" 4
+File's cluster chain is shorter than indicated by the size fields.
+The file is truncated.
+.IP "*" 4
+Clusters are marked as used but are not owned by a file.
+They are marked as free.
+.PP
+Additionally, the following problems are detected, but not repaired:
+.IP "*" 4
+Invalid parameters in boot sector
+.IP "*" 4
+Absence of . and .. entries in non\-root directories
+.PP
+When \fBfsck.fat\fR checks a filesystem, it accumulates all changes in memory
+and performs them only after all checks are complete.
+This can be disabled with the \fB\-w\fR option.
+.\" ----------------------------------------------------------------------------
+.SH OPTIONS
+.IP "\fB\-a\fR" 4
+Automatically repair the filesystem.
+No user intervention is necessary.
+Whenever there is more than one method to solve a problem, the least
+destructive approach is used.
+.IP "\fB\-A\fR" 4
+Use Atari variation of the MS\-DOS filesystem.
+This is default if \fBfsck.fat\fR is run on an Atari, then this option turns
+off Atari format.
+There are some minor differences in Atari format:
+Some boot sector fields are interpreted slightly different, and the special FAT
+entries for end\-of\-file and bad cluster can be different.
+Under MS\-DOS 0xfff8 is used for EOF and Atari employs 0xffff by default, but
+both systems recognize all values from 0xfff8...0xffff as end\-of\-file.
+MS\-DOS uses only 0xfff7 for bad clusters, where on Atari values 0xfff0...0xfff7
+are for this purpose (but the standard value is still 0xfff7).
+.IP "\fB-b\fR" 4
+Make read-only boot sector check.
+.IP "\fB\-d\fR \fIPATH\fR" 4
+Delete the specified file.
+If more than one file with that name exist, the first one is deleted.
+This option can be given more than once.
+.IP "\fB\-f\fR" 4
+Salvage unused cluster chains to files.
+By default, unused clusters are added to the free disk space except in auto mode
+(\fB\-a\fR).
+.IP "\fB\-l\fR" 4
+List path names of files being processed.
+.IP "\fB\-n\fR" 4
+No\-operation mode: non\-interactively check for errors, but don't write
+anything to the filesystem.
+.IP "\fB\-p\fR" 4
+Same as \fB\-a\fR, for compatibility with other *fsck.
+.IP "\fB\-r\fR" 4
+Interactively repair the filesystem.
+The user is asked for advice whenever there is more than one approach to fix an
+inconsistency.
+This is the default mode and the option is only retained for backwards
+compatibility.
+.IP "\fB\-t\fR" 4
+Mark unreadable clusters as bad.
+.IP "\fB\-u\fR \fIPATH\fR" 4
+Try to undelete the specified file.
+\fBfsck.fat\fR tries to allocate a chain of contiguous unallocated clusters
+beginning with the start cluster of the undeleted file.
+This option can be given more than once.
+.IP "\fB\-v\fR" 4
+Verbose mode.
+Generates slightly more output.
+.IP "\fB\-V\fR" 4
+Perform a verification pass.
+The filesystem check is repeated after the first run.
+The second pass should never report any fixable errors.
+It may take considerably longer than the first pass, because the first pass may
+have generated long list of modifications that have to be scanned for each disk
+read.
+.IP "\fB\-w\fR" 4
+Write changes to disk immediately.
+.IP "\fB\-y\fR" 4
+Same as \fB\-a\fR (automatically repair filesystem) for compatibility with other
+fsck tools.
+.\" ----------------------------------------------------------------------------
+.SH "EXIT STATUS"
+.IP "0" 4
+No recoverable errors have been detected.
+.IP "1" 4
+Recoverable errors have been detected or \fBfsck.fat\fR has discovered an
+internal inconsistency.
+.IP "2" 4
+Usage error.
+\fBfsck.fat\fR did not access the filesystem.
+.\" ----------------------------------------------------------------------------
+.SH FILES
+.IP "fsck0000.rec, fsck0001.rec, ..." 4
+When recovering from a corrupted filesystem, \fBfsck.fat\fR dumps recovered data
+into files named 'fsckNNNN.rec' in the top level directory of the filesystem.
+.\" ----------------------------------------------------------------------------
+.SH BUGS
+Does not create . and .. files where necessary.
+Does not remove entirely empty directories.
+Should give more diagnostic messages.
+Undeleting files should use a more sophisticated algorithm.
+.\" ----------------------------------------------------------------------------
+.SH SEE ALSO
+\fBfatlabel\fR(8)
+.br
+\fBmkfs.fat\fR(8)
+.\" ----------------------------------------------------------------------------
+.SH HOMEPAGE
+The home for the \fBdosfstools\fR project is its
+.UR https://github.com/dosfstools/dosfstools
+GitHub project page
+.UE .
+.\" ----------------------------------------------------------------------------
+.SH AUTHORS
+\fBdosfstools\fR were written by
+.MT werner.almesberger@\:lrc.di.epfl.ch
+Werner Almesberger
+.ME ,
+.MT Roman.Hodek@\:informatik.\:uni-erlangen.de
+Roman Hodek
+.ME ,
+and others.
+The current maintainer is
+.MT aeb@\:debian.org
+Andreas Bombe
+.ME .
diff --git a/dosfstools/manpages/en/mkfs.fat.8 b/dosfstools/manpages/en/mkfs.fat.8
new file mode 100644
index 000000000..5a5086efc
--- /dev/null
+++ b/dosfstools/manpages/en/mkfs.fat.8
@@ -0,0 +1,178 @@
+.\" mkfs.fat.8 - manpage for fs.fatck
+.\"
+.\" Copyright (C) 2006-2014 Daniel Baumann <daniel@debian.org>
+.\"
+.\" This program is free software: you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation, either version 3 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful,
+.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.\" GNU General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License
+.\" along with this program. If not, see <http://www.gnu.org/licenses/>.
+.\"
+.\" The complete text of the GNU General Public License
+.\" can be found in /usr/share/common-licenses/GPL-3 file.
+.\"
+.\"
+.TH MKFS.FAT 8 2015\-05\-16 3.0.28 "dosfstools"
+.SH NAME
+\fBmkfs.fat\fR \- create an MS-DOS filesystem under Linux
+.\" ----------------------------------------------------------------------------
+.SH SYNOPSIS
+\fBmkfs.fat\fR [\fIOPTIONS\fR] \fIDEVICE\fR [\fIBLOCK-COUNT\fR]
+.\" ----------------------------------------------------------------------------
+.SH DESCRIPTION
+\fBmkfs.fat\fR is used to create an MS-DOS filesystem under Linux on a device
+(usually a disk partition).
+\fIDEVICE\fR is the special file corresponding to the device (e.g. /dev/sdXX).
+\fIBLOCK-COUNT\fR is the number of blocks on the device.
+If omitted, \fBmkfs.fat\fR automatically determines the filesystem size.
+.\" ----------------------------------------------------------------------------
+.SH OPTIONS
+.IP "\fB\-a\fR" 4
+Normally, for any filesystem except very small ones, \fBmkfs.fat\fR will align
+all the data structures to cluster size, to make sure that as long as the
+partition is properly aligned, so will all the data structures in the
+filesystem.
+This option disables alignment; this may provide a handful of additional
+clusters of storage at the expense of a significant performance degradation on
+RAIDs, flash media or large-sector hard disks.
+.IP "\fB \-A\fR" 4
+Use Atari variation of the MS-DOS filesystem.
+This is default if \fBmkfs.fat\fR is run on an Atari, then this option turns off
+Atari format.
+There are some differences when using Atari format:
+If not directed otherwise by the user, \fBmkfs.fat\fR will always use 2 sectors
+per cluster, since GEMDOS doesn't like other values very much.
+It will also obey the maximum number of sectors GEMDOS can handle.
+Larger filesystems are managed by raising the logical sector size.
+Under Atari format, an Atari-compatible serial number for the filesystem is
+generated, and a 12 bit FAT is used only for filesystems that have one of the
+usual floppy sizes (720k, 1.2M, 1.44M, 2.88M), a 16 bit FAT otherwise.
+This can be overridden with the \fB\-F\fR option.
+Some PC-specific boot sector fields aren't written, and a boot message (option
+\fB\-m\fR) is ignored.
+.IP "\fB\-b\fR \fISECTOR-OF-BACKUP\fR" 4
+Selects the location of the backup boot sector for FAT32.
+Default depends on number of reserved sectors, but usually is sector 6.
+The backup must be within the range of reserved sectors.
+.IP "\fB\-c" 4
+Check the device for bad blocks before creating the filesystem.
+.IP "\fB\-C\fR" 4
+Create the file given as \fIDEVICE\fR on the command line, and write the
+to-be-created filesystem to it.
+This can be used to create the new filesystem in a file instead of on a real
+device, and to avoid using \fBdd\fR in advance to create a file of appropriate
+size.
+With this option, the \fIBLOCK-COUNT\fR must be given, because otherwise the
+intended size of the filesystem wouldn't be known.
+The file created is a sparse file, which actually only contains the meta-data
+areas (boot sector, FATs, and root directory).
+The data portions won't be stored on the disk, but the file nevertheless will
+have the correct size.
+The resulting file can be copied later to a floppy disk or other device, or
+mounted through a loop device.
+.IP "\fB\-D\fR \fIDRIVE-NUMBER\fR" 4
+Specify the BIOS drive number to be stored in the FAT boot sector.
+This value is usually 0x80 for hard disks and 0x00 for floppy devices or
+partitions to be used for floppy emulation.
+.IP "\fB\-f\fR \fINUMBER-OF-FATS\fR" 4
+Specify the number of file allocation tables in the filesystem.
+The default is 2.
+.IP "\fB\-F\fR \fIFAT-SIZE\fR" 4
+Specifies the type of file allocation tables used (12, 16 or 32 bit).
+If nothing is specified, \fBmkfs.fat\fR will automatically select between 12, 16
+and 32 bit, whatever fits better for the filesystem size.
+.IP "\fB\-h\fR \fINUMBER-OF-HIDDEN-SECTORS\fR" 4
+Select the number of hidden sectors in the volume.
+Apparently some digital cameras get indigestion if you feed them a CF card
+without such hidden sectors, this option allows you to satisfy them.
+.IP "\fB\-i\fR \fIVOLUME-ID\fR" 4
+Sets the volume ID of the newly created filesystem; \fIVOLUME-ID\fR is a 32-bit
+hexadecimal number (for example, 2e24ec82).
+The default is a number which depends on the filesystem creation time.
+.IP "\fB\-I\fR" 4
+It is typical for fixed disk devices to be partitioned so, by default, you are
+not permitted to create a filesystem across the entire device.
+\fBmkfs.fat\fR will complain and tell you that it refuses to work.
+This is different when using MO disks.
+One doesn't always need partitions on MO disks.
+The filesystem can go directly to the whole disk.
+Under other OSes this is known as the 'superfloppy' format.
+This switch will force \fBmkfs.fat\fR to work properly.
+.IP "\fB\-l\fR \fIFILENAME\fR" 4
+Read the bad blocks list from \fIFILENAME\fR.
+.IP "\fB\-m\fR \fIMESSAGE-FILE\fR" 4
+Sets the message the user receives on attempts to boot this filesystem without
+having properly installed an operating system.
+The message file must not exceed 418 bytes once line feeds have been converted
+to carriage return-line feed combinations, and tabs have been expanded.
+If the filename is a hyphen (-), the text is taken from standard input.
+.IP "\fB\-M\fR \fIFAT-MEDIA-TYPE\fR" 4
+Specify the media type to be stored in the FAT boot sector.
+This value is usually 0xF8 for hard disks and is 0xF0 or a value from 0xF9 to
+0xFF for floppies or partitions to be used for floppy emulation.
+.IP "\fB\-n\fR \fIVOLUME-NAME\fR" 4
+Sets the volume name (label) of the filesystem.
+The volume name can be up to 11 characters long.
+The default is no label.
+.IP "\fB\-r\fR \fIROOT-DIR-ENTRIES\fR" 4
+Select the number of entries available in the root directory.
+The default is 112 or 224 for floppies and 512 for hard disks.
+.IP "\fB\-R\fR \fINUMBER-OF-RESERVED-SECTORS\fR" 4
+Select the number of reserved sectors.
+With FAT32 format at least 2 reserved sectors are needed, the default is 32.
+Otherwise the default is 1 (only the boot sector).
+.IP "\fB\-s\fR \fISECTORS-PER-CLUSTER\fR" 4
+Specify the number of disk sectors per cluster.
+Must be a power of 2, i.e. 1, 2, 4, 8, ... 128.
+.IP "\fB\-S\fR \fILOGICAL-SECTOR-SIZE\fR" 4
+Specify the number of bytes per logical sector.
+Must be a power of 2 and greater than or equal to 512, i.e. 512, 1024, 2048,
+4096, 8192, 16384, or 32768.
+.IP "\fB\-v\fR" 4
+Verbose execution.
+.IP "\fB\-\-invariant\fR" 4
+Use constants for normally randomly generated or time based data such as
+volume ID and creation time.
+Multiple runs of \fBmkfs.fat\fR on the same device create identical results
+with this option.
+Its main purpose is testing \fBmkfs.fat\fR.
+.IP "\fB\-\-help\fR" 4
+Display option summary and exit.
+.\" ----------------------------------------------------------------------------
+.SH BUGS
+\fBmkfs.fat\fR can not create boot-able filesystems.
+This isn't as easy as you might think at first glance for various reasons and
+has been discussed a lot already.
+\fBmkfs.fat\fR simply will not support it ;)
+.\" ----------------------------------------------------------------------------
+.SH SEE ALSO
+\fBfatlabel\fR(8)
+.br
+\fBfsck.fat\fR(8)
+.\" ----------------------------------------------------------------------------
+.SH HOMEPAGE
+The home for the \fBdosfstools\fR project is its
+.UR https://github.com/dosfstools/dosfstools
+GitHub project page
+.UE .
+.\" ----------------------------------------------------------------------------
+.SH AUTHORS
+\fBdosfstools\fR were written by
+.MT werner.almesberger@\:lrc.di.epfl.ch
+Werner Almesberger
+.ME ,
+.MT Roman.Hodek@\:informatik.\:uni-erlangen.de
+Roman Hodek
+.ME ,
+and others.
+The current maintainer is
+.MT aeb@\:debian.org
+Andreas Bombe
+.ME .
diff --git a/dosfstools/manpages/po/de/fatlabel.8.po b/dosfstools/manpages/po/de/fatlabel.8.po
new file mode 100644
index 000000000..a2b6da2e8
--- /dev/null
+++ b/dosfstools/manpages/po/de/fatlabel.8.po
@@ -0,0 +1,173 @@
+# German translations for dosfstools package
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: dosfstools VERSION\n"
+"POT-Creation-Date: 2015-05-16 00:40+0200\n"
+"PO-Revision-Date: 2013-06-06 09:34+0300\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: de\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ASCII\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. type: TH
+#: en/fatlabel.8:22
+#, no-wrap
+msgid "FATLABEL"
+msgstr ""
+
+#. type: TH
+#: en/fatlabel.8:22 en/fsck.fat.8:22 en/mkfs.fat.8:22
+#, no-wrap
+msgid "2015-05-16"
+msgstr ""
+
+#. type: TH
+#: en/fatlabel.8:22 en/fsck.fat.8:22 en/mkfs.fat.8:22
+#, no-wrap
+msgid "3.0.28"
+msgstr ""
+
+#. type: TH
+#: en/fatlabel.8:22 en/fsck.fat.8:22 en/mkfs.fat.8:22
+#, no-wrap
+msgid "dosfstools"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:23 en/fsck.fat.8:23 en/mkfs.fat.8:23
+#, no-wrap
+msgid "NAME"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fatlabel.8:26
+msgid "B<fatlabel> - set or get MS-DOS filesystem label"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:26 en/fsck.fat.8:26 en/mkfs.fat.8:26
+#, no-wrap
+msgid "SYNOPSIS"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fatlabel.8:29
+msgid "B<fatlabel> I<DEVICE> [I<LABEL>]"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:29 en/fsck.fat.8:29 en/mkfs.fat.8:29
+#, no-wrap
+msgid "DESCRIPTION"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:31
+msgid "B<fatlabel> set or gets a MS-DOS filesystem label from a given device."
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fatlabel.8:36
+msgid ""
+"If I<LABEL> is omitted, then the label name of the specified device is "
+"written on the standard output. A label can't be longer than 11 bytes."
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:36 en/fsck.fat.8:99 en/mkfs.fat.8:36
+#, no-wrap
+msgid "OPTIONS"
+msgstr ""
+
+#. type: IP
+#: en/fatlabel.8:37
+#, no-wrap
+msgid "B<-h>, B<--help>"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:39
+msgid "Displays a help message."
+msgstr ""
+
+#. type: IP
+#: en/fatlabel.8:39
+#, no-wrap
+msgid "B<-V>, B<--version>"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fatlabel.8:42
+msgid "Shows version."
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:42 en/fsck.fat.8:183 en/mkfs.fat.8:155
+#, no-wrap
+msgid "SEE ALSO"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fatlabel.8:44 en/mkfs.fat.8:160
+msgid "B<fsck.fat>(8)"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fatlabel.8:47 en/fsck.fat.8:188
+msgid "B<mkfs.fat>(8)"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:47 en/fsck.fat.8:188 en/mkfs.fat.8:160
+#, no-wrap
+msgid "HOMEPAGE"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fatlabel.8:53 en/fsck.fat.8:194 en/mkfs.fat.8:166
+msgid ""
+"The home for the B<dosfstools> project is its E<.UR https://github.com/"
+"dosfstools/dosfstools> GitHub project page E<.UE .>"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:53 en/fsck.fat.8:194 en/mkfs.fat.8:166
+#, no-wrap
+msgid "AUTHORS"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:55 en/fsck.fat.8:196 en/mkfs.fat.8:168
+msgid "B<dosfstools> were written by"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:57 en/fsck.fat.8:198 en/mkfs.fat.8:170
+msgid "Werner Almesberger"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:60 en/fsck.fat.8:201 en/mkfs.fat.8:173
+msgid "Roman Hodek"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:63 en/fsck.fat.8:204 en/mkfs.fat.8:176
+msgid "and others. The current maintainer is"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:65 en/fsck.fat.8:206 en/mkfs.fat.8:178
+msgid "Andreas Bombe"
+msgstr ""
diff --git a/dosfstools/manpages/po/de/fsck.fat.8.po b/dosfstools/manpages/po/de/fsck.fat.8.po
new file mode 100644
index 000000000..1487e9ff2
--- /dev/null
+++ b/dosfstools/manpages/po/de/fsck.fat.8.po
@@ -0,0 +1,559 @@
+# German translations for dosfstools package
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: dosfstools VERSION\n"
+"POT-Creation-Date: 2015-05-16 00:40+0200\n"
+"PO-Revision-Date: 2013-06-06 09:34+0300\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: de\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ASCII\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. type: TH
+#: en/fatlabel.8:22 en/fsck.fat.8:22 en/mkfs.fat.8:22
+#, no-wrap
+msgid "2015-05-16"
+msgstr ""
+
+#. type: TH
+#: en/fatlabel.8:22 en/fsck.fat.8:22 en/mkfs.fat.8:22
+#, no-wrap
+msgid "3.0.28"
+msgstr ""
+
+#. type: TH
+#: en/fatlabel.8:22 en/fsck.fat.8:22 en/mkfs.fat.8:22
+#, no-wrap
+msgid "dosfstools"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:23 en/fsck.fat.8:23 en/mkfs.fat.8:23
+#, no-wrap
+msgid "NAME"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:26 en/fsck.fat.8:26 en/mkfs.fat.8:26
+#, no-wrap
+msgid "SYNOPSIS"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:29 en/fsck.fat.8:29 en/mkfs.fat.8:29
+#, no-wrap
+msgid "DESCRIPTION"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:36 en/fsck.fat.8:99 en/mkfs.fat.8:36
+#, no-wrap
+msgid "OPTIONS"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:42 en/fsck.fat.8:183 en/mkfs.fat.8:155
+#, no-wrap
+msgid "SEE ALSO"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fatlabel.8:47 en/fsck.fat.8:188
+msgid "B<mkfs.fat>(8)"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:47 en/fsck.fat.8:188 en/mkfs.fat.8:160
+#, no-wrap
+msgid "HOMEPAGE"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fatlabel.8:53 en/fsck.fat.8:194 en/mkfs.fat.8:166
+msgid ""
+"The home for the B<dosfstools> project is its E<.UR https://github.com/"
+"dosfstools/dosfstools> GitHub project page E<.UE .>"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:53 en/fsck.fat.8:194 en/mkfs.fat.8:166
+#, no-wrap
+msgid "AUTHORS"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:55 en/fsck.fat.8:196 en/mkfs.fat.8:168
+msgid "B<dosfstools> were written by"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:57 en/fsck.fat.8:198 en/mkfs.fat.8:170
+msgid "Werner Almesberger"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:60 en/fsck.fat.8:201 en/mkfs.fat.8:173
+msgid "Roman Hodek"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:63 en/fsck.fat.8:204 en/mkfs.fat.8:176
+msgid "and others. The current maintainer is"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:65 en/fsck.fat.8:206 en/mkfs.fat.8:178
+msgid "Andreas Bombe"
+msgstr ""
+
+#. type: TH
+#: en/fsck.fat.8:22
+#, no-wrap
+msgid "FSCK.FAT"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fsck.fat.8:26
+msgid "B<fsck.fat> - check and repair MS-DOS filesystems"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fsck.fat.8:29
+msgid "B<fsck.fat> [I<OPTIONS>] I<DEVICE>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:32
+msgid ""
+"B<fsck.fat> verifies the consistency of MS-DOS filesystems and optionally "
+"tries to repair them."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:34
+msgid "The following filesystem problems can be corrected (in this order):"
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:34 en/fsck.fat.8:37 en/fsck.fat.8:40 en/fsck.fat.8:44
+#: en/fsck.fat.8:47 en/fsck.fat.8:50 en/fsck.fat.8:53 en/fsck.fat.8:56
+#: en/fsck.fat.8:59 en/fsck.fat.8:62 en/fsck.fat.8:65 en/fsck.fat.8:68
+#: en/fsck.fat.8:71 en/fsck.fat.8:74 en/fsck.fat.8:77 en/fsck.fat.8:82
+#: en/fsck.fat.8:85 en/fsck.fat.8:90 en/fsck.fat.8:92
+#, no-wrap
+msgid "*"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:37
+msgid "FAT contains invalid cluster numbers. Cluster is changed to EOF."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:40
+msgid "File's cluster chain contains a loop. The loop is broken."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:44
+msgid ""
+"Bad clusters (read errors). The clusters are marked bad and they are "
+"removed from files owning them. This check is optional."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:47
+msgid ""
+"Directories with a large number of bad entries (probably corrupt). The "
+"directory can be deleted."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:50
+msgid "Files . and .. are non-directories. They can be deleted or renamed."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:53
+msgid "Directories . and .. in root directory. They are deleted."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:56
+msgid "Bad filenames. They can be renamed."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:59
+msgid "Duplicate directory entries. They can be deleted or renamed."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:62
+msgid "Directories with non-zero size field. Size is set to zero."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:65
+msgid ""
+"Directory . does not point to parent directory. The start pointer is "
+"adjusted."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:68
+msgid ""
+"Directory .. does not point to parent of parent directory. The start "
+"pointer is adjusted."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:71
+msgid "Start cluster number of a file is invalid. The file is truncated."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:74
+msgid "File contains bad or free clusters. The file is truncated."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:77
+msgid ""
+"File's cluster chain is longer than indicated by the size fields. The file "
+"is truncated."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:82
+msgid ""
+"Two or more files share the same cluster(s). All but one of the files are "
+"truncated. If the file being truncated is a directory file that has already "
+"been read, the filesystem check is restarted after truncation."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:85
+msgid ""
+"File's cluster chain is shorter than indicated by the size fields. The file "
+"is truncated."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:88
+msgid ""
+"Clusters are marked as used but are not owned by a file. They are marked as "
+"free."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:90
+msgid "Additionally, the following problems are detected, but not repaired:"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:92
+msgid "Invalid parameters in boot sector"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:94
+msgid "Absence of . and .. entries in non-root directories"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fsck.fat.8:99
+msgid ""
+"When B<fsck.fat> checks a filesystem, it accumulates all changes in memory "
+"and performs them only after all checks are complete. This can be disabled "
+"with the B<-w> option."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:100 en/mkfs.fat.8:37
+#, no-wrap
+msgid "B<-a>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:105
+msgid ""
+"Automatically repair the filesystem. No user intervention is necessary. "
+"Whenever there is more than one method to solve a problem, the least "
+"destructive approach is used."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:105
+#, no-wrap
+msgid "B<-A>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:116
+msgid ""
+"Use Atari variation of the MS-DOS filesystem. This is default if B<fsck."
+"fat> is run on an Atari, then this option turns off Atari format. There are "
+"some minor differences in Atari format: Some boot sector fields are "
+"interpreted slightly different, and the special FAT entries for end-of-file "
+"and bad cluster can be different. Under MS-DOS 0xfff8 is used for EOF and "
+"Atari employs 0xffff by default, but both systems recognize all values from "
+"0xfff8...0xffff as end-of-file. MS-DOS uses only 0xfff7 for bad clusters, "
+"where on Atari values 0xfff0...0xfff7 are for this purpose (but the standard "
+"value is still 0xfff7)."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:116
+#, no-wrap
+msgid "B<-b>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:118
+msgid "Make read-only boot sector check."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:118
+#, no-wrap
+msgid "B<-d> I<PATH>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:122
+msgid ""
+"Delete the specified file. If more than one file with that name exist, the "
+"first one is deleted. This option can be given more than once."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:122
+#, no-wrap
+msgid "B<-f>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:126
+msgid ""
+"Salvage unused cluster chains to files. By default, unused clusters are "
+"added to the free disk space except in auto mode (B<-a>)."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:126
+#, no-wrap
+msgid "B<-l>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:128
+msgid "List path names of files being processed."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:128
+#, no-wrap
+msgid "B<-n>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:131
+msgid ""
+"No-operation mode: non-interactively check for errors, but don't write "
+"anything to the filesystem."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:131
+#, no-wrap
+msgid "B<-p>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:133
+msgid "Same as B<-a>, for compatibility with other *fsck."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:133
+#, no-wrap
+msgid "B<-r>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:139
+msgid ""
+"Interactively repair the filesystem. The user is asked for advice whenever "
+"there is more than one approach to fix an inconsistency. This is the "
+"default mode and the option is only retained for backwards compatibility."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:139
+#, no-wrap
+msgid "B<-t>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:141
+msgid "Mark unreadable clusters as bad."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:141
+#, no-wrap
+msgid "B<-u> I<PATH>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:146
+msgid ""
+"Try to undelete the specified file. B<fsck.fat> tries to allocate a chain "
+"of contiguous unallocated clusters beginning with the start cluster of the "
+"undeleted file. This option can be given more than once."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:146 en/mkfs.fat.8:138
+#, no-wrap
+msgid "B<-v>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:149
+msgid "Verbose mode. Generates slightly more output."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:149
+#, no-wrap
+msgid "B<-V>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:156
+msgid ""
+"Perform a verification pass. The filesystem check is repeated after the "
+"first run. The second pass should never report any fixable errors. It may "
+"take considerably longer than the first pass, because the first pass may "
+"have generated long list of modifications that have to be scanned for each "
+"disk read."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:156
+#, no-wrap
+msgid "B<-w>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:158
+msgid "Write changes to disk immediately."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:158
+#, no-wrap
+msgid "B<-y>"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fsck.fat.8:162
+msgid ""
+"Same as B<-a> (automatically repair filesystem) for compatibility with other "
+"fsck tools."
+msgstr ""
+
+#. type: SH
+#: en/fsck.fat.8:162
+#, no-wrap
+msgid "EXIT STATUS"
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:163
+#, no-wrap
+msgid "0"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:165
+msgid "No recoverable errors have been detected."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:165
+#, no-wrap
+msgid "1"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:168
+msgid ""
+"Recoverable errors have been detected or B<fsck.fat> has discovered an "
+"internal inconsistency."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:168
+#, no-wrap
+msgid "2"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fsck.fat.8:172
+msgid "Usage error. B<fsck.fat> did not access the filesystem."
+msgstr ""
+
+#. type: SH
+#: en/fsck.fat.8:172
+#, no-wrap
+msgid "FILES"
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:173
+#, no-wrap
+msgid "fsck0000.rec, fsck0001.rec, ..."
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fsck.fat.8:177
+msgid ""
+"When recovering from a corrupted filesystem, B<fsck.fat> dumps recovered "
+"data into files named 'fsckNNNN.rec' in the top level directory of the "
+"filesystem."
+msgstr ""
+
+#. type: SH
+#: en/fsck.fat.8:177 en/mkfs.fat.8:149
+#, no-wrap
+msgid "BUGS"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fsck.fat.8:183
+msgid ""
+"Does not create . and .. files where necessary. Does not remove entirely "
+"empty directories. Should give more diagnostic messages. Undeleting files "
+"should use a more sophisticated algorithm."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:185 en/mkfs.fat.8:157
+msgid "B<fatlabel>(8)"
+msgstr ""
diff --git a/dosfstools/manpages/po/de/mkfs.fat.8.po b/dosfstools/manpages/po/de/mkfs.fat.8.po
new file mode 100644
index 000000000..3344f71a1
--- /dev/null
+++ b/dosfstools/manpages/po/de/mkfs.fat.8.po
@@ -0,0 +1,481 @@
+# German translations for dosfstools package
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: dosfstools VERSION\n"
+"POT-Creation-Date: 2015-05-16 00:40+0200\n"
+"PO-Revision-Date: 2013-06-06 09:34+0300\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: de\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ASCII\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. type: TH
+#: en/fatlabel.8:22 en/fsck.fat.8:22 en/mkfs.fat.8:22
+#, no-wrap
+msgid "2015-05-16"
+msgstr ""
+
+#. type: TH
+#: en/fatlabel.8:22 en/fsck.fat.8:22 en/mkfs.fat.8:22
+#, no-wrap
+msgid "3.0.28"
+msgstr ""
+
+#. type: TH
+#: en/fatlabel.8:22 en/fsck.fat.8:22 en/mkfs.fat.8:22
+#, no-wrap
+msgid "dosfstools"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:23 en/fsck.fat.8:23 en/mkfs.fat.8:23
+#, no-wrap
+msgid "NAME"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:26 en/fsck.fat.8:26 en/mkfs.fat.8:26
+#, no-wrap
+msgid "SYNOPSIS"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:29 en/fsck.fat.8:29 en/mkfs.fat.8:29
+#, no-wrap
+msgid "DESCRIPTION"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:36 en/fsck.fat.8:99 en/mkfs.fat.8:36
+#, no-wrap
+msgid "OPTIONS"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:42 en/fsck.fat.8:183 en/mkfs.fat.8:155
+#, no-wrap
+msgid "SEE ALSO"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fatlabel.8:44 en/mkfs.fat.8:160
+msgid "B<fsck.fat>(8)"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:47 en/fsck.fat.8:188 en/mkfs.fat.8:160
+#, no-wrap
+msgid "HOMEPAGE"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fatlabel.8:53 en/fsck.fat.8:194 en/mkfs.fat.8:166
+msgid ""
+"The home for the B<dosfstools> project is its E<.UR https://github.com/"
+"dosfstools/dosfstools> GitHub project page E<.UE .>"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:53 en/fsck.fat.8:194 en/mkfs.fat.8:166
+#, no-wrap
+msgid "AUTHORS"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:55 en/fsck.fat.8:196 en/mkfs.fat.8:168
+msgid "B<dosfstools> were written by"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:57 en/fsck.fat.8:198 en/mkfs.fat.8:170
+msgid "Werner Almesberger"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:60 en/fsck.fat.8:201 en/mkfs.fat.8:173
+msgid "Roman Hodek"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:63 en/fsck.fat.8:204 en/mkfs.fat.8:176
+msgid "and others. The current maintainer is"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:65 en/fsck.fat.8:206 en/mkfs.fat.8:178
+msgid "Andreas Bombe"
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:100 en/mkfs.fat.8:37
+#, no-wrap
+msgid "B<-a>"
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:146 en/mkfs.fat.8:138
+#, no-wrap
+msgid "B<-v>"
+msgstr ""
+
+#. type: SH
+#: en/fsck.fat.8:177 en/mkfs.fat.8:149
+#, no-wrap
+msgid "BUGS"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:185 en/mkfs.fat.8:157
+msgid "B<fatlabel>(8)"
+msgstr ""
+
+#. type: TH
+#: en/mkfs.fat.8:22
+#, no-wrap
+msgid "MKFS.FAT"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/mkfs.fat.8:26
+msgid "B<mkfs.fat> - create an MS-DOS filesystem under Linux"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/mkfs.fat.8:29
+msgid "B<mkfs.fat> [I<OPTIONS>] I<DEVICE> [I<BLOCK-COUNT>]"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/mkfs.fat.8:36
+msgid ""
+"B<mkfs.fat> is used to create an MS-DOS filesystem under Linux on a device "
+"(usually a disk partition). I<DEVICE> is the special file corresponding to "
+"the device (e.g. /dev/sdXX). I<BLOCK-COUNT> is the number of blocks on the "
+"device. If omitted, B<mkfs.fat> automatically determines the filesystem "
+"size."
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:45
+msgid ""
+"Normally, for any filesystem except very small ones, B<mkfs.fat> will align "
+"all the data structures to cluster size, to make sure that as long as the "
+"partition is properly aligned, so will all the data structures in the "
+"filesystem. This option disables alignment; this may provide a handful of "
+"additional clusters of storage at the expense of a significant performance "
+"degradation on RAIDs, flash media or large-sector hard disks."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:45
+#, no-wrap
+msgid "B< -A>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:60
+msgid ""
+"Use Atari variation of the MS-DOS filesystem. This is default if B<mkfs."
+"fat> is run on an Atari, then this option turns off Atari format. There are "
+"some differences when using Atari format: If not directed otherwise by the "
+"user, B<mkfs.fat> will always use 2 sectors per cluster, since GEMDOS "
+"doesn't like other values very much. It will also obey the maximum number "
+"of sectors GEMDOS can handle. Larger filesystems are managed by raising the "
+"logical sector size. Under Atari format, an Atari-compatible serial number "
+"for the filesystem is generated, and a 12 bit FAT is used only for "
+"filesystems that have one of the usual floppy sizes (720k, 1.2M, 1.44M, "
+"2.88M), a 16 bit FAT otherwise. This can be overridden with the B<-F> "
+"option. Some PC-specific boot sector fields aren't written, and a boot "
+"message (option B<-m>) is ignored."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:60
+#, no-wrap
+msgid "B<-b> I<SECTOR-OF-BACKUP>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:64
+msgid ""
+"Selects the location of the backup boot sector for FAT32. Default depends "
+"on number of reserved sectors, but usually is sector 6. The backup must be "
+"within the range of reserved sectors."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:64
+#, no-wrap
+msgid "B<-c>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:66
+msgid "Check the device for bad blocks before creating the filesystem."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:66
+#, no-wrap
+msgid "B<-C>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:80
+msgid ""
+"Create the file given as I<DEVICE> on the command line, and write the to-be-"
+"created filesystem to it. This can be used to create the new filesystem in "
+"a file instead of on a real device, and to avoid using B<dd> in advance to "
+"create a file of appropriate size. With this option, the I<BLOCK-COUNT> "
+"must be given, because otherwise the intended size of the filesystem "
+"wouldn't be known. The file created is a sparse file, which actually only "
+"contains the meta-data areas (boot sector, FATs, and root directory). The "
+"data portions won't be stored on the disk, but the file nevertheless will "
+"have the correct size. The resulting file can be copied later to a floppy "
+"disk or other device, or mounted through a loop device."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:80
+#, no-wrap
+msgid "B<-D> I<DRIVE-NUMBER>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:84
+msgid ""
+"Specify the BIOS drive number to be stored in the FAT boot sector. This "
+"value is usually 0x80 for hard disks and 0x00 for floppy devices or "
+"partitions to be used for floppy emulation."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:84
+#, no-wrap
+msgid "B<-f> I<NUMBER-OF-FATS>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:87
+msgid ""
+"Specify the number of file allocation tables in the filesystem. The default "
+"is 2."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:87
+#, no-wrap
+msgid "B<-F> I<FAT-SIZE>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:91
+msgid ""
+"Specifies the type of file allocation tables used (12, 16 or 32 bit). If "
+"nothing is specified, B<mkfs.fat> will automatically select between 12, 16 "
+"and 32 bit, whatever fits better for the filesystem size."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:91
+#, no-wrap
+msgid "B<-h> I<NUMBER-OF-HIDDEN-SECTORS>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:95
+msgid ""
+"Select the number of hidden sectors in the volume. Apparently some digital "
+"cameras get indigestion if you feed them a CF card without such hidden "
+"sectors, this option allows you to satisfy them."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:95
+#, no-wrap
+msgid "B<-i> I<VOLUME-ID>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:99
+msgid ""
+"Sets the volume ID of the newly created filesystem; I<VOLUME-ID> is a 32-bit "
+"hexadecimal number (for example, 2e24ec82). The default is a number which "
+"depends on the filesystem creation time."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:99
+#, no-wrap
+msgid "B<-I>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:108
+msgid ""
+"It is typical for fixed disk devices to be partitioned so, by default, you "
+"are not permitted to create a filesystem across the entire device. B<mkfs."
+"fat> will complain and tell you that it refuses to work. This is different "
+"when using MO disks. One doesn't always need partitions on MO disks. The "
+"filesystem can go directly to the whole disk. Under other OSes this is "
+"known as the 'superfloppy' format. This switch will force B<mkfs.fat> to "
+"work properly."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:108
+#, no-wrap
+msgid "B<-l> I<FILENAME>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:110
+msgid "Read the bad blocks list from I<FILENAME>."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:110
+#, no-wrap
+msgid "B<-m> I<MESSAGE-FILE>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:116
+msgid ""
+"Sets the message the user receives on attempts to boot this filesystem "
+"without having properly installed an operating system. The message file "
+"must not exceed 418 bytes once line feeds have been converted to carriage "
+"return-line feed combinations, and tabs have been expanded. If the filename "
+"is a hyphen (-), the text is taken from standard input."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:116
+#, no-wrap
+msgid "B<-M> I<FAT-MEDIA-TYPE>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:120
+msgid ""
+"Specify the media type to be stored in the FAT boot sector. This value is "
+"usually 0xF8 for hard disks and is 0xF0 or a value from 0xF9 to 0xFF for "
+"floppies or partitions to be used for floppy emulation."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:120
+#, no-wrap
+msgid "B<-n> I<VOLUME-NAME>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:124
+msgid ""
+"Sets the volume name (label) of the filesystem. The volume name can be up "
+"to 11 characters long. The default is no label."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:124
+#, no-wrap
+msgid "B<-r> I<ROOT-DIR-ENTRIES>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:127
+msgid ""
+"Select the number of entries available in the root directory. The default "
+"is 112 or 224 for floppies and 512 for hard disks."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:127
+#, no-wrap
+msgid "B<-R> I<NUMBER-OF-RESERVED-SECTORS>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:131
+msgid ""
+"Select the number of reserved sectors. With FAT32 format at least 2 "
+"reserved sectors are needed, the default is 32. Otherwise the default is 1 "
+"(only the boot sector)."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:131
+#, no-wrap
+msgid "B<-s> I<SECTORS-PER-CLUSTER>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:134
+msgid ""
+"Specify the number of disk sectors per cluster. Must be a power of 2, i.e. "
+"1, 2, 4, 8, ... 128."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:134
+#, no-wrap
+msgid "B<-S> I<LOGICAL-SECTOR-SIZE>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:138
+msgid ""
+"Specify the number of bytes per logical sector. Must be a power of 2 and "
+"greater than or equal to 512, i.e. 512, 1024, 2048, 4096, 8192, 16384, or "
+"32768."
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:140
+msgid "Verbose execution."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:140
+#, no-wrap
+msgid "B<--invariant>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:146
+msgid ""
+"Use constants for normally randomly generated or time based data such as "
+"volume ID and creation time. Multiple runs of B<mkfs.fat> on the same "
+"device create identical results with this option. Its main purpose is "
+"testing B<mkfs.fat>."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:146
+#, no-wrap
+msgid "B<--help>"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/mkfs.fat.8:149
+msgid "Display option summary and exit."
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/mkfs.fat.8:155
+msgid ""
+"B<mkfs.fat> can not create boot-able filesystems. This isn't as easy as you "
+"might think at first glance for various reasons and has been discussed a lot "
+"already. B<mkfs.fat> simply will not support it ;)"
+msgstr ""
diff --git a/dosfstools/manpages/po4a.cfg b/dosfstools/manpages/po4a.cfg
new file mode 100644
index 000000000..5d16f636c
--- /dev/null
+++ b/dosfstools/manpages/po4a.cfg
@@ -0,0 +1,5 @@
+[po4a_langs] de
+[po4a_paths] pot/$master.pot $lang:po/$lang/$master.po
+[type: man] en/fatlabel.8 $lang:$lang/fatlabel.$lang.8
+[type: man] en/fsck.fat.8 $lang:$lang/fsck.fat.$lang.8
+[type: man] en/mkfs.fat.8 $lang:$lang/mkfs.fat.$lang.8
diff --git a/dosfstools/manpages/pot/fatlabel.8.pot b/dosfstools/manpages/pot/fatlabel.8.pot
new file mode 100644
index 000000000..2eafa05eb
--- /dev/null
+++ b/dosfstools/manpages/pot/fatlabel.8.pot
@@ -0,0 +1,176 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the dosfstools package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: dosfstools VERSION\n"
+"POT-Creation-Date: 2015-05-16 00:40+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: TH
+#: en/fatlabel.8:22
+#, no-wrap
+msgid "FATLABEL"
+msgstr ""
+
+#. type: TH
+#: en/fatlabel.8:22 en/fsck.fat.8:22 en/mkfs.fat.8:22
+#, no-wrap
+msgid "2015-05-16"
+msgstr ""
+
+#. type: TH
+#: en/fatlabel.8:22 en/fsck.fat.8:22 en/mkfs.fat.8:22
+#, no-wrap
+msgid "3.0.28"
+msgstr ""
+
+#. type: TH
+#: en/fatlabel.8:22 en/fsck.fat.8:22 en/mkfs.fat.8:22
+#, no-wrap
+msgid "dosfstools"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:23 en/fsck.fat.8:23 en/mkfs.fat.8:23
+#, no-wrap
+msgid "NAME"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fatlabel.8:26
+msgid "B<fatlabel> - set or get MS-DOS filesystem label"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:26 en/fsck.fat.8:26 en/mkfs.fat.8:26
+#, no-wrap
+msgid "SYNOPSIS"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fatlabel.8:29
+msgid "B<fatlabel> I<DEVICE> [I<LABEL>]"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:29 en/fsck.fat.8:29 en/mkfs.fat.8:29
+#, no-wrap
+msgid "DESCRIPTION"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:31
+msgid "B<fatlabel> set or gets a MS-DOS filesystem label from a given device."
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fatlabel.8:36
+msgid ""
+"If I<LABEL> is omitted, then the label name of the specified device is "
+"written on the standard output. A label can't be longer than 11 bytes."
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:36 en/fsck.fat.8:99 en/mkfs.fat.8:36
+#, no-wrap
+msgid "OPTIONS"
+msgstr ""
+
+#. type: IP
+#: en/fatlabel.8:37
+#, no-wrap
+msgid "B<-h>, B<--help>"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:39
+msgid "Displays a help message."
+msgstr ""
+
+#. type: IP
+#: en/fatlabel.8:39
+#, no-wrap
+msgid "B<-V>, B<--version>"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fatlabel.8:42
+msgid "Shows version."
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:42 en/fsck.fat.8:183 en/mkfs.fat.8:155
+#, no-wrap
+msgid "SEE ALSO"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fatlabel.8:44 en/mkfs.fat.8:160
+msgid "B<fsck.fat>(8)"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fatlabel.8:47 en/fsck.fat.8:188
+msgid "B<mkfs.fat>(8)"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:47 en/fsck.fat.8:188 en/mkfs.fat.8:160
+#, no-wrap
+msgid "HOMEPAGE"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fatlabel.8:53 en/fsck.fat.8:194 en/mkfs.fat.8:166
+msgid ""
+"The home for the B<dosfstools> project is its E<.UR https://github.com/"
+"dosfstools/dosfstools> GitHub project page E<.UE .>"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:53 en/fsck.fat.8:194 en/mkfs.fat.8:166
+#, no-wrap
+msgid "AUTHORS"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:55 en/fsck.fat.8:196 en/mkfs.fat.8:168
+msgid "B<dosfstools> were written by"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:57 en/fsck.fat.8:198 en/mkfs.fat.8:170
+msgid "Werner Almesberger"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:60 en/fsck.fat.8:201 en/mkfs.fat.8:173
+msgid "Roman Hodek"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:63 en/fsck.fat.8:204 en/mkfs.fat.8:176
+msgid "and others. The current maintainer is"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:65 en/fsck.fat.8:206 en/mkfs.fat.8:178
+msgid "Andreas Bombe"
+msgstr ""
diff --git a/dosfstools/manpages/pot/fsck.fat.8.pot b/dosfstools/manpages/pot/fsck.fat.8.pot
new file mode 100644
index 000000000..65ef52a66
--- /dev/null
+++ b/dosfstools/manpages/pot/fsck.fat.8.pot
@@ -0,0 +1,562 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the dosfstools package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: dosfstools VERSION\n"
+"POT-Creation-Date: 2015-05-16 00:40+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: TH
+#: en/fatlabel.8:22 en/fsck.fat.8:22 en/mkfs.fat.8:22
+#, no-wrap
+msgid "2015-05-16"
+msgstr ""
+
+#. type: TH
+#: en/fatlabel.8:22 en/fsck.fat.8:22 en/mkfs.fat.8:22
+#, no-wrap
+msgid "3.0.28"
+msgstr ""
+
+#. type: TH
+#: en/fatlabel.8:22 en/fsck.fat.8:22 en/mkfs.fat.8:22
+#, no-wrap
+msgid "dosfstools"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:23 en/fsck.fat.8:23 en/mkfs.fat.8:23
+#, no-wrap
+msgid "NAME"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:26 en/fsck.fat.8:26 en/mkfs.fat.8:26
+#, no-wrap
+msgid "SYNOPSIS"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:29 en/fsck.fat.8:29 en/mkfs.fat.8:29
+#, no-wrap
+msgid "DESCRIPTION"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:36 en/fsck.fat.8:99 en/mkfs.fat.8:36
+#, no-wrap
+msgid "OPTIONS"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:42 en/fsck.fat.8:183 en/mkfs.fat.8:155
+#, no-wrap
+msgid "SEE ALSO"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fatlabel.8:47 en/fsck.fat.8:188
+msgid "B<mkfs.fat>(8)"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:47 en/fsck.fat.8:188 en/mkfs.fat.8:160
+#, no-wrap
+msgid "HOMEPAGE"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fatlabel.8:53 en/fsck.fat.8:194 en/mkfs.fat.8:166
+msgid ""
+"The home for the B<dosfstools> project is its E<.UR https://github.com/"
+"dosfstools/dosfstools> GitHub project page E<.UE .>"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:53 en/fsck.fat.8:194 en/mkfs.fat.8:166
+#, no-wrap
+msgid "AUTHORS"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:55 en/fsck.fat.8:196 en/mkfs.fat.8:168
+msgid "B<dosfstools> were written by"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:57 en/fsck.fat.8:198 en/mkfs.fat.8:170
+msgid "Werner Almesberger"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:60 en/fsck.fat.8:201 en/mkfs.fat.8:173
+msgid "Roman Hodek"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:63 en/fsck.fat.8:204 en/mkfs.fat.8:176
+msgid "and others. The current maintainer is"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:65 en/fsck.fat.8:206 en/mkfs.fat.8:178
+msgid "Andreas Bombe"
+msgstr ""
+
+#. type: TH
+#: en/fsck.fat.8:22
+#, no-wrap
+msgid "FSCK.FAT"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fsck.fat.8:26
+msgid "B<fsck.fat> - check and repair MS-DOS filesystems"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fsck.fat.8:29
+msgid "B<fsck.fat> [I<OPTIONS>] I<DEVICE>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:32
+msgid ""
+"B<fsck.fat> verifies the consistency of MS-DOS filesystems and optionally "
+"tries to repair them."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:34
+msgid "The following filesystem problems can be corrected (in this order):"
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:34 en/fsck.fat.8:37 en/fsck.fat.8:40 en/fsck.fat.8:44
+#: en/fsck.fat.8:47 en/fsck.fat.8:50 en/fsck.fat.8:53 en/fsck.fat.8:56
+#: en/fsck.fat.8:59 en/fsck.fat.8:62 en/fsck.fat.8:65 en/fsck.fat.8:68
+#: en/fsck.fat.8:71 en/fsck.fat.8:74 en/fsck.fat.8:77 en/fsck.fat.8:82
+#: en/fsck.fat.8:85 en/fsck.fat.8:90 en/fsck.fat.8:92
+#, no-wrap
+msgid "*"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:37
+msgid "FAT contains invalid cluster numbers. Cluster is changed to EOF."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:40
+msgid "File's cluster chain contains a loop. The loop is broken."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:44
+msgid ""
+"Bad clusters (read errors). The clusters are marked bad and they are "
+"removed from files owning them. This check is optional."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:47
+msgid ""
+"Directories with a large number of bad entries (probably corrupt). The "
+"directory can be deleted."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:50
+msgid "Files . and .. are non-directories. They can be deleted or renamed."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:53
+msgid "Directories . and .. in root directory. They are deleted."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:56
+msgid "Bad filenames. They can be renamed."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:59
+msgid "Duplicate directory entries. They can be deleted or renamed."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:62
+msgid "Directories with non-zero size field. Size is set to zero."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:65
+msgid ""
+"Directory . does not point to parent directory. The start pointer is "
+"adjusted."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:68
+msgid ""
+"Directory .. does not point to parent of parent directory. The start "
+"pointer is adjusted."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:71
+msgid "Start cluster number of a file is invalid. The file is truncated."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:74
+msgid "File contains bad or free clusters. The file is truncated."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:77
+msgid ""
+"File's cluster chain is longer than indicated by the size fields. The file "
+"is truncated."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:82
+msgid ""
+"Two or more files share the same cluster(s). All but one of the files are "
+"truncated. If the file being truncated is a directory file that has already "
+"been read, the filesystem check is restarted after truncation."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:85
+msgid ""
+"File's cluster chain is shorter than indicated by the size fields. The file "
+"is truncated."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:88
+msgid ""
+"Clusters are marked as used but are not owned by a file. They are marked as "
+"free."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:90
+msgid "Additionally, the following problems are detected, but not repaired:"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:92
+msgid "Invalid parameters in boot sector"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:94
+msgid "Absence of . and .. entries in non-root directories"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fsck.fat.8:99
+msgid ""
+"When B<fsck.fat> checks a filesystem, it accumulates all changes in memory "
+"and performs them only after all checks are complete. This can be disabled "
+"with the B<-w> option."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:100 en/mkfs.fat.8:37
+#, no-wrap
+msgid "B<-a>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:105
+msgid ""
+"Automatically repair the filesystem. No user intervention is necessary. "
+"Whenever there is more than one method to solve a problem, the least "
+"destructive approach is used."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:105
+#, no-wrap
+msgid "B<-A>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:116
+msgid ""
+"Use Atari variation of the MS-DOS filesystem. This is default if B<fsck."
+"fat> is run on an Atari, then this option turns off Atari format. There are "
+"some minor differences in Atari format: Some boot sector fields are "
+"interpreted slightly different, and the special FAT entries for end-of-file "
+"and bad cluster can be different. Under MS-DOS 0xfff8 is used for EOF and "
+"Atari employs 0xffff by default, but both systems recognize all values from "
+"0xfff8...0xffff as end-of-file. MS-DOS uses only 0xfff7 for bad clusters, "
+"where on Atari values 0xfff0...0xfff7 are for this purpose (but the standard "
+"value is still 0xfff7)."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:116
+#, no-wrap
+msgid "B<-b>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:118
+msgid "Make read-only boot sector check."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:118
+#, no-wrap
+msgid "B<-d> I<PATH>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:122
+msgid ""
+"Delete the specified file. If more than one file with that name exist, the "
+"first one is deleted. This option can be given more than once."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:122
+#, no-wrap
+msgid "B<-f>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:126
+msgid ""
+"Salvage unused cluster chains to files. By default, unused clusters are "
+"added to the free disk space except in auto mode (B<-a>)."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:126
+#, no-wrap
+msgid "B<-l>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:128
+msgid "List path names of files being processed."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:128
+#, no-wrap
+msgid "B<-n>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:131
+msgid ""
+"No-operation mode: non-interactively check for errors, but don't write "
+"anything to the filesystem."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:131
+#, no-wrap
+msgid "B<-p>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:133
+msgid "Same as B<-a>, for compatibility with other *fsck."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:133
+#, no-wrap
+msgid "B<-r>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:139
+msgid ""
+"Interactively repair the filesystem. The user is asked for advice whenever "
+"there is more than one approach to fix an inconsistency. This is the "
+"default mode and the option is only retained for backwards compatibility."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:139
+#, no-wrap
+msgid "B<-t>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:141
+msgid "Mark unreadable clusters as bad."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:141
+#, no-wrap
+msgid "B<-u> I<PATH>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:146
+msgid ""
+"Try to undelete the specified file. B<fsck.fat> tries to allocate a chain "
+"of contiguous unallocated clusters beginning with the start cluster of the "
+"undeleted file. This option can be given more than once."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:146 en/mkfs.fat.8:138
+#, no-wrap
+msgid "B<-v>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:149
+msgid "Verbose mode. Generates slightly more output."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:149
+#, no-wrap
+msgid "B<-V>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:156
+msgid ""
+"Perform a verification pass. The filesystem check is repeated after the "
+"first run. The second pass should never report any fixable errors. It may "
+"take considerably longer than the first pass, because the first pass may "
+"have generated long list of modifications that have to be scanned for each "
+"disk read."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:156
+#, no-wrap
+msgid "B<-w>"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:158
+msgid "Write changes to disk immediately."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:158
+#, no-wrap
+msgid "B<-y>"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fsck.fat.8:162
+msgid ""
+"Same as B<-a> (automatically repair filesystem) for compatibility with other "
+"fsck tools."
+msgstr ""
+
+#. type: SH
+#: en/fsck.fat.8:162
+#, no-wrap
+msgid "EXIT STATUS"
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:163
+#, no-wrap
+msgid "0"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:165
+msgid "No recoverable errors have been detected."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:165
+#, no-wrap
+msgid "1"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:168
+msgid ""
+"Recoverable errors have been detected or B<fsck.fat> has discovered an "
+"internal inconsistency."
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:168
+#, no-wrap
+msgid "2"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fsck.fat.8:172
+msgid "Usage error. B<fsck.fat> did not access the filesystem."
+msgstr ""
+
+#. type: SH
+#: en/fsck.fat.8:172
+#, no-wrap
+msgid "FILES"
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:173
+#, no-wrap
+msgid "fsck0000.rec, fsck0001.rec, ..."
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fsck.fat.8:177
+msgid ""
+"When recovering from a corrupted filesystem, B<fsck.fat> dumps recovered "
+"data into files named 'fsckNNNN.rec' in the top level directory of the "
+"filesystem."
+msgstr ""
+
+#. type: SH
+#: en/fsck.fat.8:177 en/mkfs.fat.8:149
+#, no-wrap
+msgid "BUGS"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fsck.fat.8:183
+msgid ""
+"Does not create . and .. files where necessary. Does not remove entirely "
+"empty directories. Should give more diagnostic messages. Undeleting files "
+"should use a more sophisticated algorithm."
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:185 en/mkfs.fat.8:157
+msgid "B<fatlabel>(8)"
+msgstr ""
diff --git a/dosfstools/manpages/pot/mkfs.fat.8.pot b/dosfstools/manpages/pot/mkfs.fat.8.pot
new file mode 100644
index 000000000..c9d5bba96
--- /dev/null
+++ b/dosfstools/manpages/pot/mkfs.fat.8.pot
@@ -0,0 +1,484 @@
+# SOME DESCRIPTIVE TITLE
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the dosfstools package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: dosfstools VERSION\n"
+"POT-Creation-Date: 2015-05-16 00:40+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. type: TH
+#: en/fatlabel.8:22 en/fsck.fat.8:22 en/mkfs.fat.8:22
+#, no-wrap
+msgid "2015-05-16"
+msgstr ""
+
+#. type: TH
+#: en/fatlabel.8:22 en/fsck.fat.8:22 en/mkfs.fat.8:22
+#, no-wrap
+msgid "3.0.28"
+msgstr ""
+
+#. type: TH
+#: en/fatlabel.8:22 en/fsck.fat.8:22 en/mkfs.fat.8:22
+#, no-wrap
+msgid "dosfstools"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:23 en/fsck.fat.8:23 en/mkfs.fat.8:23
+#, no-wrap
+msgid "NAME"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:26 en/fsck.fat.8:26 en/mkfs.fat.8:26
+#, no-wrap
+msgid "SYNOPSIS"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:29 en/fsck.fat.8:29 en/mkfs.fat.8:29
+#, no-wrap
+msgid "DESCRIPTION"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:36 en/fsck.fat.8:99 en/mkfs.fat.8:36
+#, no-wrap
+msgid "OPTIONS"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:42 en/fsck.fat.8:183 en/mkfs.fat.8:155
+#, no-wrap
+msgid "SEE ALSO"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fatlabel.8:44 en/mkfs.fat.8:160
+msgid "B<fsck.fat>(8)"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:47 en/fsck.fat.8:188 en/mkfs.fat.8:160
+#, no-wrap
+msgid "HOMEPAGE"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/fatlabel.8:53 en/fsck.fat.8:194 en/mkfs.fat.8:166
+msgid ""
+"The home for the B<dosfstools> project is its E<.UR https://github.com/"
+"dosfstools/dosfstools> GitHub project page E<.UE .>"
+msgstr ""
+
+#. type: SH
+#: en/fatlabel.8:53 en/fsck.fat.8:194 en/mkfs.fat.8:166
+#, no-wrap
+msgid "AUTHORS"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:55 en/fsck.fat.8:196 en/mkfs.fat.8:168
+msgid "B<dosfstools> were written by"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:57 en/fsck.fat.8:198 en/mkfs.fat.8:170
+msgid "Werner Almesberger"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:60 en/fsck.fat.8:201 en/mkfs.fat.8:173
+msgid "Roman Hodek"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:63 en/fsck.fat.8:204 en/mkfs.fat.8:176
+msgid "and others. The current maintainer is"
+msgstr ""
+
+#. type: Plain text
+#: en/fatlabel.8:65 en/fsck.fat.8:206 en/mkfs.fat.8:178
+msgid "Andreas Bombe"
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:100 en/mkfs.fat.8:37
+#, no-wrap
+msgid "B<-a>"
+msgstr ""
+
+#. type: IP
+#: en/fsck.fat.8:146 en/mkfs.fat.8:138
+#, no-wrap
+msgid "B<-v>"
+msgstr ""
+
+#. type: SH
+#: en/fsck.fat.8:177 en/mkfs.fat.8:149
+#, no-wrap
+msgid "BUGS"
+msgstr ""
+
+#. type: Plain text
+#: en/fsck.fat.8:185 en/mkfs.fat.8:157
+msgid "B<fatlabel>(8)"
+msgstr ""
+
+#. type: TH
+#: en/mkfs.fat.8:22
+#, no-wrap
+msgid "MKFS.FAT"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/mkfs.fat.8:26
+msgid "B<mkfs.fat> - create an MS-DOS filesystem under Linux"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/mkfs.fat.8:29
+msgid "B<mkfs.fat> [I<OPTIONS>] I<DEVICE> [I<BLOCK-COUNT>]"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/mkfs.fat.8:36
+msgid ""
+"B<mkfs.fat> is used to create an MS-DOS filesystem under Linux on a device "
+"(usually a disk partition). I<DEVICE> is the special file corresponding to "
+"the device (e.g. /dev/sdXX). I<BLOCK-COUNT> is the number of blocks on the "
+"device. If omitted, B<mkfs.fat> automatically determines the filesystem "
+"size."
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:45
+msgid ""
+"Normally, for any filesystem except very small ones, B<mkfs.fat> will align "
+"all the data structures to cluster size, to make sure that as long as the "
+"partition is properly aligned, so will all the data structures in the "
+"filesystem. This option disables alignment; this may provide a handful of "
+"additional clusters of storage at the expense of a significant performance "
+"degradation on RAIDs, flash media or large-sector hard disks."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:45
+#, no-wrap
+msgid "B< -A>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:60
+msgid ""
+"Use Atari variation of the MS-DOS filesystem. This is default if B<mkfs."
+"fat> is run on an Atari, then this option turns off Atari format. There are "
+"some differences when using Atari format: If not directed otherwise by the "
+"user, B<mkfs.fat> will always use 2 sectors per cluster, since GEMDOS "
+"doesn't like other values very much. It will also obey the maximum number "
+"of sectors GEMDOS can handle. Larger filesystems are managed by raising the "
+"logical sector size. Under Atari format, an Atari-compatible serial number "
+"for the filesystem is generated, and a 12 bit FAT is used only for "
+"filesystems that have one of the usual floppy sizes (720k, 1.2M, 1.44M, "
+"2.88M), a 16 bit FAT otherwise. This can be overridden with the B<-F> "
+"option. Some PC-specific boot sector fields aren't written, and a boot "
+"message (option B<-m>) is ignored."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:60
+#, no-wrap
+msgid "B<-b> I<SECTOR-OF-BACKUP>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:64
+msgid ""
+"Selects the location of the backup boot sector for FAT32. Default depends "
+"on number of reserved sectors, but usually is sector 6. The backup must be "
+"within the range of reserved sectors."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:64
+#, no-wrap
+msgid "B<-c>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:66
+msgid "Check the device for bad blocks before creating the filesystem."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:66
+#, no-wrap
+msgid "B<-C>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:80
+msgid ""
+"Create the file given as I<DEVICE> on the command line, and write the to-be-"
+"created filesystem to it. This can be used to create the new filesystem in "
+"a file instead of on a real device, and to avoid using B<dd> in advance to "
+"create a file of appropriate size. With this option, the I<BLOCK-COUNT> "
+"must be given, because otherwise the intended size of the filesystem "
+"wouldn't be known. The file created is a sparse file, which actually only "
+"contains the meta-data areas (boot sector, FATs, and root directory). The "
+"data portions won't be stored on the disk, but the file nevertheless will "
+"have the correct size. The resulting file can be copied later to a floppy "
+"disk or other device, or mounted through a loop device."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:80
+#, no-wrap
+msgid "B<-D> I<DRIVE-NUMBER>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:84
+msgid ""
+"Specify the BIOS drive number to be stored in the FAT boot sector. This "
+"value is usually 0x80 for hard disks and 0x00 for floppy devices or "
+"partitions to be used for floppy emulation."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:84
+#, no-wrap
+msgid "B<-f> I<NUMBER-OF-FATS>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:87
+msgid ""
+"Specify the number of file allocation tables in the filesystem. The default "
+"is 2."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:87
+#, no-wrap
+msgid "B<-F> I<FAT-SIZE>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:91
+msgid ""
+"Specifies the type of file allocation tables used (12, 16 or 32 bit). If "
+"nothing is specified, B<mkfs.fat> will automatically select between 12, 16 "
+"and 32 bit, whatever fits better for the filesystem size."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:91
+#, no-wrap
+msgid "B<-h> I<NUMBER-OF-HIDDEN-SECTORS>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:95
+msgid ""
+"Select the number of hidden sectors in the volume. Apparently some digital "
+"cameras get indigestion if you feed them a CF card without such hidden "
+"sectors, this option allows you to satisfy them."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:95
+#, no-wrap
+msgid "B<-i> I<VOLUME-ID>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:99
+msgid ""
+"Sets the volume ID of the newly created filesystem; I<VOLUME-ID> is a 32-bit "
+"hexadecimal number (for example, 2e24ec82). The default is a number which "
+"depends on the filesystem creation time."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:99
+#, no-wrap
+msgid "B<-I>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:108
+msgid ""
+"It is typical for fixed disk devices to be partitioned so, by default, you "
+"are not permitted to create a filesystem across the entire device. B<mkfs."
+"fat> will complain and tell you that it refuses to work. This is different "
+"when using MO disks. One doesn't always need partitions on MO disks. The "
+"filesystem can go directly to the whole disk. Under other OSes this is "
+"known as the 'superfloppy' format. This switch will force B<mkfs.fat> to "
+"work properly."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:108
+#, no-wrap
+msgid "B<-l> I<FILENAME>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:110
+msgid "Read the bad blocks list from I<FILENAME>."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:110
+#, no-wrap
+msgid "B<-m> I<MESSAGE-FILE>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:116
+msgid ""
+"Sets the message the user receives on attempts to boot this filesystem "
+"without having properly installed an operating system. The message file "
+"must not exceed 418 bytes once line feeds have been converted to carriage "
+"return-line feed combinations, and tabs have been expanded. If the filename "
+"is a hyphen (-), the text is taken from standard input."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:116
+#, no-wrap
+msgid "B<-M> I<FAT-MEDIA-TYPE>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:120
+msgid ""
+"Specify the media type to be stored in the FAT boot sector. This value is "
+"usually 0xF8 for hard disks and is 0xF0 or a value from 0xF9 to 0xFF for "
+"floppies or partitions to be used for floppy emulation."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:120
+#, no-wrap
+msgid "B<-n> I<VOLUME-NAME>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:124
+msgid ""
+"Sets the volume name (label) of the filesystem. The volume name can be up "
+"to 11 characters long. The default is no label."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:124
+#, no-wrap
+msgid "B<-r> I<ROOT-DIR-ENTRIES>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:127
+msgid ""
+"Select the number of entries available in the root directory. The default "
+"is 112 or 224 for floppies and 512 for hard disks."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:127
+#, no-wrap
+msgid "B<-R> I<NUMBER-OF-RESERVED-SECTORS>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:131
+msgid ""
+"Select the number of reserved sectors. With FAT32 format at least 2 "
+"reserved sectors are needed, the default is 32. Otherwise the default is 1 "
+"(only the boot sector)."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:131
+#, no-wrap
+msgid "B<-s> I<SECTORS-PER-CLUSTER>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:134
+msgid ""
+"Specify the number of disk sectors per cluster. Must be a power of 2, i.e. "
+"1, 2, 4, 8, ... 128."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:134
+#, no-wrap
+msgid "B<-S> I<LOGICAL-SECTOR-SIZE>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:138
+msgid ""
+"Specify the number of bytes per logical sector. Must be a power of 2 and "
+"greater than or equal to 512, i.e. 512, 1024, 2048, 4096, 8192, 16384, or "
+"32768."
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:140
+msgid "Verbose execution."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:140
+#, no-wrap
+msgid "B<--invariant>"
+msgstr ""
+
+#. type: Plain text
+#: en/mkfs.fat.8:146
+msgid ""
+"Use constants for normally randomly generated or time based data such as "
+"volume ID and creation time. Multiple runs of B<mkfs.fat> on the same "
+"device create identical results with this option. Its main purpose is "
+"testing B<mkfs.fat>."
+msgstr ""
+
+#. type: IP
+#: en/mkfs.fat.8:146
+#, no-wrap
+msgid "B<--help>"
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/mkfs.fat.8:149
+msgid "Display option summary and exit."
+msgstr ""
+
+#. ----------------------------------------------------------------------------
+#. type: Plain text
+#: en/mkfs.fat.8:155
+msgid ""
+"B<mkfs.fat> can not create boot-able filesystems. This isn't as easy as you "
+"might think at first glance for various reasons and has been discussed a lot "
+"already. B<mkfs.fat> simply will not support it ;)"
+msgstr ""
diff --git a/dosfstools/src/boot.c b/dosfstools/src/boot.c
new file mode 100644
index 000000000..0c0918f8b
--- /dev/null
+++ b/dosfstools/src/boot.c
@@ -0,0 +1,568 @@
+/* boot.c - Read and analyze ia PC/MS-DOS boot sector
+
+ Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
+ Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
+ Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ The complete text of the GNU General Public License
+ can be found in /usr/share/common-licenses/GPL-3 file.
+*/
+
+/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
+ * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "common.h"
+#include "fsck.fat.h"
+#include "fat.h"
+#include "io.h"
+#include "boot.h"
+#include "check.h"
+
+#define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0)
+ /* don't divide by zero */
+
+/* cut-over cluster counts for FAT12 and FAT16 */
+#define FAT12_THRESHOLD 4085
+#define FAT16_THRESHOLD 65525
+
+static struct {
+ uint8_t media;
+ const char *descr;
+} mediabytes[] = {
+ {
+ 0xf0, "5.25\" or 3.5\" HD floppy"}, {
+ 0xf8, "hard disk"}, {
+ 0xf9, "3,5\" 720k floppy 2s/80tr/9sec or "
+ "5.25\" 1.2M floppy 2s/80tr/15sec"}, {
+ 0xfa, "5.25\" 320k floppy 1s/80tr/8sec"}, {
+ 0xfb, "3.5\" 640k floppy 2s/80tr/8sec"}, {
+ 0xfc, "5.25\" 180k floppy 1s/40tr/9sec"}, {
+ 0xfd, "5.25\" 360k floppy 2s/40tr/9sec"}, {
+ 0xfe, "5.25\" 160k floppy 1s/40tr/8sec"}, {
+0xff, "5.25\" 320k floppy 2s/40tr/8sec"},};
+
+/* Unaligned fields must first be accessed byte-wise */
+#define GET_UNALIGNED_W(f) \
+ ( (uint16_t)f[0] | ((uint16_t)f[1]<<8) )
+
+static const char *get_media_descr(unsigned char media)
+{
+ int i;
+
+ for (i = 0; i < sizeof(mediabytes) / sizeof(*mediabytes); ++i) {
+ if (mediabytes[i].media == media)
+ return (mediabytes[i].descr);
+ }
+ return ("undefined");
+}
+
+static void dump_boot(DOS_FS * fs, struct boot_sector *b, unsigned lss)
+{
+ unsigned short sectors;
+
+ printf("Boot sector contents:\n");
+ if (!atari_format) {
+ char id[9];
+ strncpy(id, (const char *)b->system_id, 8);
+ id[8] = 0;
+ printf("System ID \"%s\"\n", id);
+ } else {
+ /* On Atari, a 24 bit serial number is stored at offset 8 of the boot
+ * sector */
+ printf("Serial number 0x%x\n",
+ b->system_id[5] | (b->system_id[6] << 8) | (b->
+ system_id[7] << 16));
+ }
+ printf("Media byte 0x%02x (%s)\n", b->media, get_media_descr(b->media));
+ printf("%10d bytes per logical sector\n", GET_UNALIGNED_W(b->sector_size));
+ printf("%10d bytes per cluster\n", fs->cluster_size);
+ printf("%10d reserved sector%s\n", le16toh(b->reserved),
+ le16toh(b->reserved) == 1 ? "" : "s");
+ printf("First FAT starts at byte %llu (sector %llu)\n",
+ (unsigned long long)fs->fat_start,
+ (unsigned long long)fs->fat_start / lss);
+ printf("%10d FATs, %d bit entries\n", b->fats, fs->fat_bits);
+ printf("%10d bytes per FAT (= %u sectors)\n", fs->fat_size,
+ fs->fat_size / lss);
+ if (!fs->root_cluster) {
+ printf("Root directory starts at byte %llu (sector %llu)\n",
+ (unsigned long long)fs->root_start,
+ (unsigned long long)fs->root_start / lss);
+ printf("%10d root directory entries\n", fs->root_entries);
+ } else {
+ printf("Root directory start at cluster %lu (arbitrary size)\n",
+ (unsigned long)fs->root_cluster);
+ }
+ printf("Data area starts at byte %llu (sector %llu)\n",
+ (unsigned long long)fs->data_start,
+ (unsigned long long)fs->data_start / lss);
+ printf("%10lu data clusters (%llu bytes)\n", (unsigned long)fs->clusters,
+ (unsigned long long)fs->clusters * fs->cluster_size);
+ printf("%u sectors/track, %u heads\n", le16toh(b->secs_track),
+ le16toh(b->heads));
+ printf("%10u hidden sectors\n", atari_format ?
+ /* On Atari, the hidden field is only 16 bit wide and unused */
+ (((unsigned char *)&b->hidden)[0] |
+ ((unsigned char *)&b->hidden)[1] << 8) : le32toh(b->hidden));
+ sectors = GET_UNALIGNED_W(b->sectors);
+ printf("%10u sectors total\n", sectors ? sectors : le32toh(b->total_sect));
+}
+
+static void check_backup_boot(DOS_FS * fs, struct boot_sector *b, int lss)
+{
+ struct boot_sector b2;
+
+ if (!fs->backupboot_start) {
+ printf("There is no backup boot sector.\n");
+ if (le16toh(b->reserved) < 3) {
+ printf("And there is no space for creating one!\n");
+ return;
+ }
+ if (interactive)
+ printf("1) Create one\n2) Do without a backup\n");
+ else
+ printf(" Auto-creating backup boot block.\n");
+ if (!interactive || get_key("12", "?") == '1') {
+ int bbs;
+ /* The usual place for the backup boot sector is sector 6. Choose
+ * that or the last reserved sector. */
+ if (le16toh(b->reserved) >= 7 && le16toh(b->info_sector) != 6)
+ bbs = 6;
+ else {
+ bbs = le16toh(b->reserved) - 1;
+ if (bbs == le16toh(b->info_sector))
+ --bbs; /* this is never 0, as we checked reserved >= 3! */
+ }
+ fs->backupboot_start = bbs * lss;
+ b->backup_boot = htole16(bbs);
+ fs_write(fs->backupboot_start, sizeof(*b), b);
+ fs_write((loff_t) offsetof(struct boot_sector, backup_boot),
+ sizeof(b->backup_boot), &b->backup_boot);
+ printf("Created backup of boot sector in sector %d\n", bbs);
+ return;
+ } else
+ return;
+ }
+
+ fs_read(fs->backupboot_start, sizeof(b2), &b2);
+ if (memcmp(b, &b2, sizeof(b2)) != 0) {
+ /* there are any differences */
+ uint8_t *p, *q;
+ int i, pos, first = 1;
+ char buf[20];
+
+ printf("There are differences between boot sector and its backup.\n");
+ printf("This is mostly harmless. Differences: (offset:original/backup)\n ");
+ pos = 2;
+ for (p = (uint8_t *) b, q = (uint8_t *) & b2, i = 0; i < sizeof(b2);
+ ++p, ++q, ++i) {
+ if (*p != *q) {
+ sprintf(buf, "%s%u:%02x/%02x", first ? "" : ", ",
+ (unsigned)(p - (uint8_t *) b), *p, *q);
+ if (pos + strlen(buf) > 78)
+ printf("\n "), pos = 2;
+ printf("%s", buf);
+ pos += strlen(buf);
+ first = 0;
+ }
+ }
+ printf("\n");
+
+ if (interactive)
+ printf("1) Copy original to backup\n"
+ "2) Copy backup to original\n" "3) No action\n");
+ else
+ printf(" Not automatically fixing this.\n");
+ switch (interactive ? get_key("123", "?") : '3') {
+ case '1':
+ fs_write(fs->backupboot_start, sizeof(*b), b);
+ break;
+ case '2':
+ fs_write(0, sizeof(b2), &b2);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void init_fsinfo(struct info_sector *i)
+{
+ i->magic = htole32(0x41615252);
+ i->signature = htole32(0x61417272);
+ i->free_clusters = htole32(-1);
+ i->next_cluster = htole32(2);
+ i->boot_sign = htole16(0xaa55);
+}
+
+static void read_fsinfo(DOS_FS * fs, struct boot_sector *b, int lss)
+{
+ struct info_sector i;
+
+ if (!b->info_sector) {
+ printf("No FSINFO sector\n");
+ if (interactive)
+ printf("1) Create one\n2) Do without FSINFO\n");
+ else
+ printf(" Not automatically creating it.\n");
+ if (interactive && get_key("12", "?") == '1') {
+ /* search for a free reserved sector (not boot sector and not
+ * backup boot sector) */
+ uint32_t s;
+ for (s = 1; s < le16toh(b->reserved); ++s)
+ if (s != le16toh(b->backup_boot))
+ break;
+ if (s > 0 && s < le16toh(b->reserved)) {
+ init_fsinfo(&i);
+ fs_write((loff_t) s * lss, sizeof(i), &i);
+ b->info_sector = htole16(s);
+ fs_write((loff_t) offsetof(struct boot_sector, info_sector),
+ sizeof(b->info_sector), &b->info_sector);
+ if (fs->backupboot_start)
+ fs_write(fs->backupboot_start +
+ offsetof(struct boot_sector, info_sector),
+ sizeof(b->info_sector), &b->info_sector);
+ } else {
+ printf("No free reserved sector found -- "
+ "no space for FSINFO sector!\n");
+ return;
+ }
+ } else
+ return;
+ }
+
+ fs->fsinfo_start = le16toh(b->info_sector) * lss;
+ fs_read(fs->fsinfo_start, sizeof(i), &i);
+
+ if (i.magic != htole32(0x41615252) ||
+ i.signature != htole32(0x61417272) || i.boot_sign != htole16(0xaa55)) {
+ printf("FSINFO sector has bad magic number(s):\n");
+ if (i.magic != htole32(0x41615252))
+ printf(" Offset %llu: 0x%08x != expected 0x%08x\n",
+ (unsigned long long)offsetof(struct info_sector, magic),
+ le32toh(i.magic), 0x41615252);
+ if (i.signature != htole32(0x61417272))
+ printf(" Offset %llu: 0x%08x != expected 0x%08x\n",
+ (unsigned long long)offsetof(struct info_sector, signature),
+ le32toh(i.signature), 0x61417272);
+ if (i.boot_sign != htole16(0xaa55))
+ printf(" Offset %llu: 0x%04x != expected 0x%04x\n",
+ (unsigned long long)offsetof(struct info_sector, boot_sign),
+ le16toh(i.boot_sign), 0xaa55);
+ if (interactive)
+ printf("1) Correct\n2) Don't correct (FSINFO invalid then)\n");
+ else
+ printf(" Auto-correcting it.\n");
+ if (!interactive || get_key("12", "?") == '1') {
+ init_fsinfo(&i);
+ fs_write(fs->fsinfo_start, sizeof(i), &i);
+ } else
+ fs->fsinfo_start = 0;
+ }
+
+ if (fs->fsinfo_start)
+ fs->free_clusters = le32toh(i.free_clusters);
+}
+
+static char print_fat_dirty_state(void)
+{
+ printf("Dirty bit is set. Fs was not properly unmounted and"
+ " some data may be corrupt.\n");
+
+ if (interactive) {
+ printf("1) Remove dirty bit\n" "2) No action\n");
+ return get_key("12", "?");
+ } else
+ printf(" Automatically removing dirty bit.\n");
+ return '1';
+}
+
+static void check_fat_state_bit(DOS_FS * fs, void *b)
+{
+ if (fs->fat_bits == 32) {
+ struct boot_sector *b32 = b;
+
+ if (b32->reserved3 & FAT_STATE_DIRTY) {
+ printf("0x41: ");
+ if (print_fat_dirty_state() == '1') {
+ b32->reserved3 &= ~FAT_STATE_DIRTY;
+ fs_write(0, sizeof(*b32), b32);
+ }
+ }
+ } else {
+ struct boot_sector_16 *b16 = b;
+
+ if (b16->reserved2 & FAT_STATE_DIRTY) {
+ printf("0x25: ");
+ if (print_fat_dirty_state() == '1') {
+ b16->reserved2 &= ~FAT_STATE_DIRTY;
+ fs_write(0, sizeof(*b16), b16);
+ }
+ }
+ }
+}
+
+void read_boot(DOS_FS * fs)
+{
+ struct boot_sector b;
+ unsigned total_sectors;
+ unsigned short logical_sector_size, sectors;
+ unsigned fat_length;
+ loff_t data_size;
+
+ fs_read(0, sizeof(b), &b);
+ logical_sector_size = GET_UNALIGNED_W(b.sector_size);
+ if (!logical_sector_size)
+ die("Logical sector size is zero.");
+
+ /* This was moved up because it's the first thing that will fail */
+ /* if the platform needs special handling of unaligned multibyte accesses */
+ /* but such handling isn't being provided. See GET_UNALIGNED_W() above. */
+ if (logical_sector_size & (SECTOR_SIZE - 1))
+ die("Logical sector size (%d bytes) is not a multiple of the physical "
+ "sector size.", logical_sector_size);
+
+ fs->cluster_size = b.cluster_size * logical_sector_size;
+ if (!fs->cluster_size)
+ die("Cluster size is zero.");
+ if (b.fats != 2 && b.fats != 1)
+ die("Currently, only 1 or 2 FATs are supported, not %d.\n", b.fats);
+ fs->nfats = b.fats;
+ sectors = GET_UNALIGNED_W(b.sectors);
+ total_sectors = sectors ? sectors : le32toh(b.total_sect);
+ if (verbose)
+ printf("Checking we can access the last sector of the filesystem\n");
+ /* Can't access last odd sector anyway, so round down */
+ fs_test((loff_t) ((total_sectors & ~1) - 1) * (loff_t) logical_sector_size,
+ logical_sector_size);
+ fat_length = le16toh(b.fat_length) ?
+ le16toh(b.fat_length) : le32toh(b.fat32_length);
+ fs->fat_start = (loff_t) le16toh(b.reserved) * logical_sector_size;
+ fs->root_start = ((loff_t) le16toh(b.reserved) + b.fats * fat_length) *
+ logical_sector_size;
+ fs->root_entries = GET_UNALIGNED_W(b.dir_entries);
+ fs->data_start = fs->root_start + ROUND_TO_MULTIPLE(fs->root_entries <<
+ MSDOS_DIR_BITS,
+ logical_sector_size);
+ data_size = (loff_t) total_sectors *logical_sector_size - fs->data_start;
+ fs->clusters = data_size / fs->cluster_size;
+ fs->root_cluster = 0; /* indicates standard, pre-FAT32 root dir */
+ fs->fsinfo_start = 0; /* no FSINFO structure */
+ fs->free_clusters = -1; /* unknown */
+ if (!b.fat_length && b.fat32_length) {
+ fs->fat_bits = 32;
+ fs->root_cluster = le32toh(b.root_cluster);
+ if (!fs->root_cluster && fs->root_entries)
+ /* M$ hasn't specified this, but it looks reasonable: If
+ * root_cluster is 0 but there is a separate root dir
+ * (root_entries != 0), we handle the root dir the old way. Give a
+ * warning, but convertig to a root dir in a cluster chain seems
+ * to complex for now... */
+ printf("Warning: FAT32 root dir not in cluster chain! "
+ "Compatibility mode...\n");
+ else if (!fs->root_cluster && !fs->root_entries)
+ die("No root directory!");
+ else if (fs->root_cluster && fs->root_entries)
+ printf("Warning: FAT32 root dir is in a cluster chain, but "
+ "a separate root dir\n"
+ " area is defined. Cannot fix this easily.\n");
+ if (fs->clusters < FAT16_THRESHOLD)
+ printf("Warning: Filesystem is FAT32 according to fat_length "
+ "and fat32_length fields,\n"
+ " but has only %lu clusters, less than the required "
+ "minimum of %d.\n"
+ " This may lead to problems on some systems.\n",
+ (unsigned long)fs->clusters, FAT16_THRESHOLD);
+
+ check_fat_state_bit(fs, &b);
+ fs->backupboot_start = le16toh(b.backup_boot) * logical_sector_size;
+ check_backup_boot(fs, &b, logical_sector_size);
+
+ read_fsinfo(fs, &b, logical_sector_size);
+ } else if (!atari_format) {
+ /* On real MS-DOS, a 16 bit FAT is used whenever there would be too
+ * much clusers otherwise. */
+ fs->fat_bits = (fs->clusters >= FAT12_THRESHOLD) ? 16 : 12;
+ if (fs->clusters >= FAT16_THRESHOLD)
+ die("Too many clusters (%lu) for FAT16 filesystem.", fs->clusters);
+ check_fat_state_bit(fs, &b);
+ } else {
+ /* On Atari, things are more difficult: GEMDOS always uses 12bit FATs
+ * on floppies, and always 16 bit on harddisks. */
+ fs->fat_bits = 16; /* assume 16 bit FAT for now */
+ /* If more clusters than fat entries in 16-bit fat, we assume
+ * it's a real MSDOS FS with 12-bit fat. */
+ if (fs->clusters + 2 > fat_length * logical_sector_size * 8 / 16 ||
+ /* if it's a floppy disk --> 12bit fat */
+ device_no == 2 ||
+ /* if it's a ramdisk or loopback device and has one of the usual
+ * floppy sizes -> 12bit FAT */
+ ((device_no == 1 || device_no == 7) &&
+ (total_sectors == 720 || total_sectors == 1440 ||
+ total_sectors == 2880)))
+ fs->fat_bits = 12;
+ }
+ /* On FAT32, the high 4 bits of a FAT entry are reserved */
+ fs->eff_fat_bits = (fs->fat_bits == 32) ? 28 : fs->fat_bits;
+ fs->fat_size = fat_length * logical_sector_size;
+
+ fs->label = calloc(12, sizeof(uint8_t));
+ if (fs->fat_bits == 12 || fs->fat_bits == 16) {
+ struct boot_sector_16 *b16 = (struct boot_sector_16 *)&b;
+ if (b16->extended_sig == 0x29)
+ memmove(fs->label, b16->label, 11);
+ else
+ fs->label = NULL;
+ } else if (fs->fat_bits == 32) {
+ if (b.extended_sig == 0x29)
+ memmove(fs->label, &b.label, 11);
+ else
+ fs->label = NULL;
+ }
+
+ if (fs->clusters >
+ ((uint64_t)fs->fat_size * 8 / fs->fat_bits) - 2)
+ die("Filesystem has %d clusters but only space for %d FAT entries.",
+ fs->clusters,
+ ((unsigned long long)fs->fat_size * 8 / fs->fat_bits) - 2);
+ if (!fs->root_entries && !fs->root_cluster)
+ die("Root directory has zero size.");
+ if (fs->root_entries & (MSDOS_DPS - 1))
+ die("Root directory (%d entries) doesn't span an integral number of "
+ "sectors.", fs->root_entries);
+ if (logical_sector_size & (SECTOR_SIZE - 1))
+ die("Logical sector size (%d bytes) is not a multiple of the physical "
+ "sector size.", logical_sector_size);
+#if 0 /* linux kernel doesn't check that either */
+ /* ++roman: On Atari, these two fields are often left uninitialized */
+ if (!atari_format && (!b.secs_track || !b.heads))
+ die("Invalid disk format in boot sector.");
+#endif
+ if (verbose)
+ dump_boot(fs, &b, logical_sector_size);
+}
+
+static void write_boot_label(DOS_FS * fs, char *label)
+{
+ if (fs->fat_bits == 12 || fs->fat_bits == 16) {
+ struct boot_sector_16 b16;
+
+ fs_read(0, sizeof(b16), &b16);
+ if (b16.extended_sig != 0x29) {
+ b16.extended_sig = 0x29;
+ b16.serial = 0;
+ memmove(b16.fs_type, fs->fat_bits == 12 ? "FAT12 " : "FAT16 ",
+ 8);
+ }
+ memmove(b16.label, label, 11);
+ fs_write(0, sizeof(b16), &b16);
+ } else if (fs->fat_bits == 32) {
+ struct boot_sector b;
+
+ fs_read(0, sizeof(b), &b);
+ if (b.extended_sig != 0x29) {
+ b.extended_sig = 0x29;
+ b.serial = 0;
+ memmove(b.fs_type, "FAT32 ", 8);
+ }
+ memmove(b.label, label, 11);
+ fs_write(0, sizeof(b), &b);
+ if (fs->backupboot_start)
+ fs_write(fs->backupboot_start, sizeof(b), &b);
+ }
+}
+
+loff_t find_volume_de(DOS_FS * fs, DIR_ENT * de)
+{
+ uint32_t cluster;
+ loff_t offset;
+ int i;
+
+ if (fs->root_cluster) {
+ for (cluster = fs->root_cluster;
+ cluster != 0 && cluster != -1;
+ cluster = next_cluster(fs, cluster)) {
+ offset = cluster_start(fs, cluster);
+ for (i = 0; i * sizeof(DIR_ENT) < fs->cluster_size; i++) {
+ fs_read(offset, sizeof(DIR_ENT), de);
+ if (de->attr != VFAT_LN_ATTR && de->attr & ATTR_VOLUME)
+ return offset;
+ offset += sizeof(DIR_ENT);
+ }
+ }
+ } else {
+ for (i = 0; i < fs->root_entries; i++) {
+ offset = fs->root_start + i * sizeof(DIR_ENT);
+ fs_read(offset, sizeof(DIR_ENT), de);
+ if (de->attr != VFAT_LN_ATTR && de->attr & ATTR_VOLUME)
+ return offset;
+ }
+ }
+
+ return 0;
+}
+
+static void write_volume_label(DOS_FS * fs, char *label)
+{
+ time_t now = time(NULL);
+ struct tm *mtime = localtime(&now);
+ loff_t offset;
+ int created;
+ DIR_ENT de;
+
+ created = 0;
+ offset = find_volume_de(fs, &de);
+ if (offset == 0) {
+ created = 1;
+ offset = alloc_rootdir_entry(fs, &de, label);
+ }
+ memcpy(de.name, label, 11);
+ de.time = htole16((unsigned short)((mtime->tm_sec >> 1) +
+ (mtime->tm_min << 5) +
+ (mtime->tm_hour << 11)));
+ de.date = htole16((unsigned short)(mtime->tm_mday +
+ ((mtime->tm_mon + 1) << 5) +
+ ((mtime->tm_year - 80) << 9)));
+ if (created) {
+ de.attr = ATTR_VOLUME;
+ de.ctime_ms = 0;
+ de.ctime = de.time;
+ de.cdate = de.date;
+ de.adate = de.date;
+ de.starthi = 0;
+ de.start = 0;
+ de.size = 0;
+ }
+
+ fs_write(offset, sizeof(DIR_ENT), &de);
+}
+
+void write_label(DOS_FS * fs, char *label)
+{
+ int l = strlen(label);
+
+ while (l < 11)
+ label[l++] = ' ';
+
+ write_boot_label(fs, label);
+ write_volume_label(fs, label);
+}
diff --git a/dosfstools/src/boot.h b/dosfstools/src/boot.h
new file mode 100644
index 000000000..d52e62476
--- /dev/null
+++ b/dosfstools/src/boot.h
@@ -0,0 +1,32 @@
+/* boot.h - Read and analyze ia PC/MS-DOS boot sector
+
+ Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
+ Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ The complete text of the GNU General Public License
+ can be found in /usr/share/common-licenses/GPL-3 file.
+*/
+
+#ifndef _BOOT_H
+#define _BOOT_H
+
+void read_boot(DOS_FS * fs);
+void write_label(DOS_FS * fs, char *label);
+loff_t find_volume_de(DOS_FS * fs, DIR_ENT * de);
+
+/* Reads the boot sector from the currently open device and initializes *FS */
+
+#endif
diff --git a/dosfstools/src/check.c b/dosfstools/src/check.c
new file mode 100644
index 000000000..bbb97e4f3
--- /dev/null
+++ b/dosfstools/src/check.c
@@ -0,0 +1,1089 @@
+/* check.c - Check and repair a PC/MS-DOS filesystem
+
+ Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
+ Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
+ Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ The complete text of the GNU General Public License
+ can be found in /usr/share/common-licenses/GPL-3 file.
+*/
+
+/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
+ * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <time.h>
+
+#include "common.h"
+#include "fsck.fat.h"
+#include "io.h"
+#include "fat.h"
+#include "file.h"
+#include "lfn.h"
+#include "check.h"
+
+static DOS_FILE *root;
+
+/* get start field of a dir entry */
+#define FSTART(p,fs) \
+ ((uint32_t)le16toh(p->dir_ent.start) | \
+ (fs->fat_bits == 32 ? le16toh(p->dir_ent.starthi) << 16 : 0))
+
+#define MODIFY(p,i,v) \
+ do { \
+ if (p->offset) { \
+ p->dir_ent.i = v; \
+ fs_write(p->offset+offsetof(DIR_ENT,i), \
+ sizeof(p->dir_ent.i),&p->dir_ent.i); \
+ } \
+ } while(0)
+
+#define MODIFY_START(p,v,fs) \
+ do { \
+ uint32_t __v = (v); \
+ if (!p->offset) { \
+ /* writing to fake entry for FAT32 root dir */ \
+ if (!__v) die("Oops, deleting FAT32 root dir!"); \
+ fs->root_cluster = __v; \
+ p->dir_ent.start = htole16(__v&0xffff); \
+ p->dir_ent.starthi = htole16(__v>>16); \
+ __v = htole32(__v); \
+ fs_write((loff_t)offsetof(struct boot_sector,root_cluster), \
+ sizeof(((struct boot_sector *)0)->root_cluster), \
+ &__v); \
+ } \
+ else { \
+ MODIFY(p,start,htole16((__v)&0xffff)); \
+ if (fs->fat_bits == 32) \
+ MODIFY(p,starthi,htole16((__v)>>16)); \
+ } \
+ } while(0)
+
+loff_t alloc_rootdir_entry(DOS_FS * fs, DIR_ENT * de, const char *pattern)
+{
+ static int curr_num = 0;
+ loff_t offset;
+
+ if (fs->root_cluster) {
+ DIR_ENT d2;
+ int i = 0, got = 0;
+ uint32_t clu_num, prev = 0;
+ loff_t offset2;
+
+ clu_num = fs->root_cluster;
+ offset = cluster_start(fs, clu_num);
+ while (clu_num > 0 && clu_num != -1) {
+ fs_read(offset, sizeof(DIR_ENT), &d2);
+ if (IS_FREE(d2.name) && d2.attr != VFAT_LN_ATTR) {
+ got = 1;
+ break;
+ }
+ i += sizeof(DIR_ENT);
+ offset += sizeof(DIR_ENT);
+ if ((i % fs->cluster_size) == 0) {
+ prev = clu_num;
+ if ((clu_num = next_cluster(fs, clu_num)) == 0 || clu_num == -1)
+ break;
+ offset = cluster_start(fs, clu_num);
+ }
+ }
+ if (!got) {
+ /* no free slot, need to extend root dir: alloc next free cluster
+ * after previous one */
+ if (!prev)
+ die("Root directory has no cluster allocated!");
+ for (clu_num = prev + 1; clu_num != prev; clu_num++) {
+ FAT_ENTRY entry;
+
+ if (clu_num >= fs->clusters + 2)
+ clu_num = 2;
+ get_fat(&entry, fs->fat, clu_num, fs);
+ if (!entry.value)
+ break;
+ }
+ if (clu_num == prev)
+ die("Root directory full and no free cluster");
+ set_fat(fs, prev, clu_num);
+ set_fat(fs, clu_num, -1);
+ set_owner(fs, clu_num, get_owner(fs, fs->root_cluster));
+ /* clear new cluster */
+ memset(&d2, 0, sizeof(d2));
+ offset = cluster_start(fs, clu_num);
+ for (i = 0; i < fs->cluster_size; i += sizeof(DIR_ENT))
+ fs_write(offset + i, sizeof(d2), &d2);
+ }
+ memset(de, 0, sizeof(DIR_ENT));
+ while (1) {
+ char expanded[12];
+ sprintf(expanded, pattern, curr_num);
+ memcpy(de->name, expanded, 8);
+ memcpy(de->ext, expanded + 8, 3);
+ clu_num = fs->root_cluster;
+ i = 0;
+ offset2 = cluster_start(fs, clu_num);
+ while (clu_num > 0 && clu_num != -1) {
+ fs_read(offset2, sizeof(DIR_ENT), &d2);
+ if (offset2 != offset &&
+ !strncmp((const char *)d2.name, (const char *)de->name,
+ MSDOS_NAME))
+ break;
+ i += sizeof(DIR_ENT);
+ offset2 += sizeof(DIR_ENT);
+ if ((i % fs->cluster_size) == 0) {
+ if ((clu_num = next_cluster(fs, clu_num)) == 0 ||
+ clu_num == -1)
+ break;
+ offset2 = cluster_start(fs, clu_num);
+ }
+ }
+ if (clu_num == 0 || clu_num == -1)
+ break;
+ if (++curr_num >= 10000)
+ die("Unable to create unique name");
+ }
+ } else {
+ DIR_ENT *root;
+ int next_free = 0, scan;
+
+ root = alloc(fs->root_entries * sizeof(DIR_ENT));
+ fs_read(fs->root_start, fs->root_entries * sizeof(DIR_ENT), root);
+
+ while (next_free < fs->root_entries)
+ if (IS_FREE(root[next_free].name) &&
+ root[next_free].attr != VFAT_LN_ATTR)
+ break;
+ else
+ next_free++;
+ if (next_free == fs->root_entries)
+ die("Root directory is full.");
+ offset = fs->root_start + next_free * sizeof(DIR_ENT);
+ memset(de, 0, sizeof(DIR_ENT));
+ while (1) {
+ char expanded[12];
+ sprintf(expanded, pattern, curr_num);
+ memcpy(de->name, expanded, 8);
+ memcpy(de->ext, expanded + 8, 3);
+ for (scan = 0; scan < fs->root_entries; scan++)
+ if (scan != next_free &&
+ !strncmp((const char *)root[scan].name,
+ (const char *)de->name, MSDOS_NAME))
+ break;
+ if (scan == fs->root_entries)
+ break;
+ if (++curr_num >= 10000)
+ die("Unable to create unique name");
+ }
+ free(root);
+ }
+ ++n_files;
+ return offset;
+}
+
+/**
+ * Construct a full path (starting with '/') for the specified dentry,
+ * relative to the partition. All components are "long" names where possible.
+ *
+ * @param[in] file Information about dentry (file or directory) of interest
+ *
+ * return Pointer to static string containing file's full path
+ */
+static char *path_name(DOS_FILE * file)
+{
+ static char path[PATH_MAX * 2];
+
+ if (!file)
+ *path = 0; /* Reached the root directory */
+ else {
+ if (strlen(path_name(file->parent)) > PATH_MAX)
+ die("Path name too long.");
+ if (strcmp(path, "/") != 0)
+ strcat(path, "/");
+
+ /* Append the long name to the path,
+ * or the short name if there isn't a long one
+ */
+ strcpy(strrchr(path, 0),
+ file->lfn ? file->lfn : file_name(file->dir_ent.name));
+ }
+ return path;
+}
+
+static const int day_n[] =
+ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0 };
+/* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
+
+/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
+
+static time_t date_dos2unix(unsigned short time, unsigned short date)
+{
+ int month, year;
+ time_t secs;
+
+ month = ((date >> 5) & 15) - 1;
+ if (month < 0) {
+ /* make sure that nothing bad happens if the month bits were zero */
+ month = 0;
+ }
+ year = date >> 9;
+ secs =
+ (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
+ 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) + year * 365 -
+ ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653);
+ /* days since 1.1.70 plus 80's leap day */
+ return secs;
+}
+
+static char *file_stat(DOS_FILE * file)
+{
+ static char temp[100];
+ struct tm *tm;
+ char tmp[100];
+ time_t date;
+
+ date =
+ date_dos2unix(le16toh(file->dir_ent.time), le16toh(file->dir_ent.date));
+ tm = localtime(&date);
+ strftime(tmp, 99, "%H:%M:%S %b %d %Y", tm);
+ sprintf(temp, " Size %u bytes, date %s", le32toh(file->dir_ent.size), tmp);
+ return temp;
+}
+
+static int bad_name(DOS_FILE * file)
+{
+ int i, spc, suspicious = 0;
+ const char *bad_chars = atari_format ? "*?\\/:" : "*?<>|\"\\/:";
+ const unsigned char *name = file->dir_ent.name;
+ const unsigned char *ext = file->dir_ent.ext;
+
+ /* Do not complain about (and auto-correct) the extended attribute files
+ * of OS/2. */
+ if (strncmp((const char *)name, "EA DATA SF", 11) == 0 ||
+ strncmp((const char *)name, "WP ROOT SF", 11) == 0)
+ return 0;
+
+ /* check if we have neither a long filename nor a short name */
+ if ((file->lfn == NULL) && (file->dir_ent.lcase & FAT_NO_83NAME)) {
+ return 1;
+ }
+
+ /* don't complain about the dummy 11 bytes used by patched Linux
+ kernels */
+ if (file->dir_ent.lcase & FAT_NO_83NAME)
+ return 0;
+
+ for (i = 0; i < 8; i++) {
+ if (name[i] < ' ' || name[i] == 0x7f)
+ return 1;
+ if (name[i] > 0x7f)
+ ++suspicious;
+ if (strchr(bad_chars, name[i]))
+ return 1;
+ }
+
+ for (i = 0; i < 3; i++) {
+ if (ext[i] < ' ' || ext[i] == 0x7f)
+ return 1;
+ if (ext[i] > 0x7f)
+ ++suspicious;
+ if (strchr(bad_chars, ext[i]))
+ return 1;
+ }
+
+ spc = 0;
+ for (i = 0; i < 8; i++) {
+ if (name[i] == ' ')
+ spc = 1;
+ else if (spc)
+ /* non-space after a space not allowed, space terminates the name
+ * part */
+ return 1;
+ }
+
+ spc = 0;
+ for (i = 0; i < 3; i++) {
+ if (ext[i] == ' ')
+ spc = 1;
+ else if (spc)
+ /* non-space after a space not allowed, space terminates the ext
+ * part */
+ return 1;
+ }
+
+ /* Under GEMDOS, chars >= 128 are never allowed. */
+ if (atari_format && suspicious)
+ return 1;
+
+ /* Under MS-DOS and Windows, chars >= 128 in short names are valid
+ * (but these characters can be visualised differently depending on
+ * local codepage: CP437, CP866, etc). The chars are all basically ok,
+ * so we shouldn't auto-correct such names. */
+ return 0;
+}
+
+static void lfn_remove(loff_t from, loff_t to)
+{
+ DIR_ENT empty;
+
+ /* New dir entry is zeroed except first byte, which is set to 0xe5.
+ * This is to avoid that some FAT-reading OSes (not Linux! ;) stop reading
+ * a directory at the first zero entry...
+ */
+ memset(&empty, 0, sizeof(empty));
+ empty.name[0] = DELETED_FLAG;
+
+ for (; from < to; from += sizeof(empty)) {
+ fs_write(from, sizeof(DIR_ENT), &empty);
+ }
+}
+
+static void drop_file(DOS_FS * fs, DOS_FILE * file)
+{
+ uint32_t cluster;
+
+ MODIFY(file, name[0], DELETED_FLAG);
+ if (file->lfn)
+ lfn_remove(file->lfn_offset, file->offset);
+ for (cluster = FSTART(file, fs); cluster > 0 && cluster <
+ fs->clusters + 2; cluster = next_cluster(fs, cluster))
+ set_owner(fs, cluster, NULL);
+ --n_files;
+}
+
+static void truncate_file(DOS_FS * fs, DOS_FILE * file, uint32_t clusters)
+{
+ int deleting;
+ uint32_t walk, next;
+
+ walk = FSTART(file, fs);
+ if ((deleting = !clusters))
+ MODIFY_START(file, 0, fs);
+ while (walk > 0 && walk != -1) {
+ next = next_cluster(fs, walk);
+ if (deleting)
+ set_fat(fs, walk, 0);
+ else if ((deleting = !--clusters))
+ set_fat(fs, walk, -1);
+ walk = next;
+ }
+}
+
+static void auto_rename(DOS_FILE * file)
+{
+ DOS_FILE *first, *walk;
+ uint32_t number;
+
+ if (!file->offset)
+ return; /* cannot rename FAT32 root dir */
+ first = file->parent ? file->parent->first : root;
+ number = 0;
+ while (1) {
+ char num[8];
+ sprintf(num, "%07lu", (unsigned long)number);
+ memcpy(file->dir_ent.name, "FSCK", 4);
+ memcpy(file->dir_ent.name + 4, num, 4);
+ memcpy(file->dir_ent.ext, num + 4, 3);
+ for (walk = first; walk; walk = walk->next)
+ if (walk != file
+ && !strncmp((const char *)walk->dir_ent.name,
+ (const char *)file->dir_ent.name, MSDOS_NAME))
+ break;
+ if (!walk) {
+ if (file->dir_ent.lcase & FAT_NO_83NAME) {
+ /* as we only assign a new 8.3 filename, reset flag that 8.3 name is not
+ present */
+ file->dir_ent.lcase &= ~FAT_NO_83NAME;
+ /* reset the attributes, only keep DIR and VOLUME */
+ file->dir_ent.attr &= ~(ATTR_DIR | ATTR_VOLUME);
+ fs_write(file->offset, MSDOS_NAME + 2, file->dir_ent.name);
+ } else {
+ fs_write(file->offset, MSDOS_NAME, file->dir_ent.name);
+ }
+ if (file->lfn)
+ lfn_fix_checksum(file->lfn_offset, file->offset,
+ (const char *)file->dir_ent.name);
+ return;
+ }
+ number++;
+ if (number > 9999999) {
+ die("Too many files need repair.");
+ }
+ }
+ die("Can't generate a unique name.");
+}
+
+static void rename_file(DOS_FILE * file)
+{
+ unsigned char name[46];
+ unsigned char *walk, *here;
+
+ if (!file->offset) {
+ printf("Cannot rename FAT32 root dir\n");
+ return; /* cannot rename FAT32 root dir */
+ }
+ while (1) {
+ printf("New name: ");
+ fflush(stdout);
+ if (fgets((char *)name, 45, stdin)) {
+ if ((here = (unsigned char *)strchr((const char *)name, '\n')))
+ *here = 0;
+ for (walk = (unsigned char *)strrchr((const char *)name, 0);
+ walk >= name && (*walk == ' ' || *walk == '\t'); walk--) ;
+ walk[1] = 0;
+ for (walk = name; *walk == ' ' || *walk == '\t'; walk++) ;
+ if (file_cvt(walk, file->dir_ent.name)) {
+ if (file->dir_ent.lcase & FAT_NO_83NAME) {
+ /* as we only assign a new 8.3 filename, reset flag that 8.3 name is not
+ present */
+ file->dir_ent.lcase &= ~FAT_NO_83NAME;
+ /* reset the attributes, only keep DIR and VOLUME */
+ file->dir_ent.attr &= ~(ATTR_DIR | ATTR_VOLUME);
+ fs_write(file->offset, MSDOS_NAME + 2, file->dir_ent.name);
+ } else {
+ fs_write(file->offset, MSDOS_NAME, file->dir_ent.name);
+ }
+ if (file->lfn)
+ lfn_fix_checksum(file->lfn_offset, file->offset,
+ (const char *)file->dir_ent.name);
+ return;
+ }
+ }
+ }
+}
+
+static int handle_dot(DOS_FS * fs, DOS_FILE * file, int dots)
+{
+ const char *name;
+
+ name =
+ strncmp((const char *)file->dir_ent.name, MSDOS_DOT,
+ MSDOS_NAME) ? ".." : ".";
+ if (!(file->dir_ent.attr & ATTR_DIR)) {
+ printf("%s\n Is a non-directory.\n", path_name(file));
+ if (interactive)
+ printf("1) Drop it\n2) Auto-rename\n3) Rename\n"
+ "4) Convert to directory\n");
+ else
+ printf(" Auto-renaming it.\n");
+ switch (interactive ? get_key("1234", "?") : '2') {
+ case '1':
+ drop_file(fs, file);
+ return 1;
+ case '2':
+ auto_rename(file);
+ printf(" Renamed to %s\n", file_name(file->dir_ent.name));
+ return 0;
+ case '3':
+ rename_file(file);
+ return 0;
+ case '4':
+ MODIFY(file, size, htole32(0));
+ MODIFY(file, attr, file->dir_ent.attr | ATTR_DIR);
+ break;
+ }
+ }
+ if (!dots) {
+ printf("Root contains directory \"%s\". Dropping it.\n", name);
+ drop_file(fs, file);
+ return 1;
+ }
+ return 0;
+}
+
+static int check_file(DOS_FS * fs, DOS_FILE * file)
+{
+ DOS_FILE *owner;
+ int restart;
+ uint32_t expect, curr, this, clusters, prev, walk, clusters2;
+
+ if (file->dir_ent.attr & ATTR_DIR) {
+ if (le32toh(file->dir_ent.size)) {
+ printf("%s\n Directory has non-zero size. Fixing it.\n",
+ path_name(file));
+ MODIFY(file, size, htole32(0));
+ }
+ if (file->parent
+ && !strncmp((const char *)file->dir_ent.name, MSDOS_DOT,
+ MSDOS_NAME)) {
+ expect = FSTART(file->parent, fs);
+ if (FSTART(file, fs) != expect) {
+ printf("%s\n Start (%lu) does not point to parent (%lu)\n",
+ path_name(file), (unsigned long)FSTART(file, fs), (long)expect);
+ MODIFY_START(file, expect, fs);
+ }
+ return 0;
+ }
+ if (file->parent
+ && !strncmp((const char *)file->dir_ent.name, MSDOS_DOTDOT,
+ MSDOS_NAME)) {
+ expect =
+ file->parent->parent ? FSTART(file->parent->parent, fs) : 0;
+ if (fs->root_cluster && expect == fs->root_cluster)
+ expect = 0;
+ if (FSTART(file, fs) != expect) {
+ printf("%s\n Start (%lu) does not point to .. (%lu)\n",
+ path_name(file), (unsigned long)FSTART(file, fs), (unsigned long)expect);
+ MODIFY_START(file, expect, fs);
+ }
+ return 0;
+ }
+ if (FSTART(file, fs) == 0) {
+ printf("%s\n Start does point to root directory. Deleting dir. \n",
+ path_name(file));
+ MODIFY(file, name[0], DELETED_FLAG);
+ return 0;
+ }
+ }
+ if (FSTART(file, fs) == 1) {
+ printf("%s\n Bad start cluster 1. Truncating file.\n",
+ path_name(file));
+ if (!file->offset)
+ die("Bad FAT32 root directory! (bad start cluster 1)\n");
+ MODIFY_START(file, 0, fs);
+ }
+ if (FSTART(file, fs) >= fs->clusters + 2) {
+ printf
+ ("%s\n Start cluster beyond limit (%lu > %lu). Truncating file.\n",
+ path_name(file), (unsigned long)FSTART(file, fs), (unsigned long)(fs->clusters + 1));
+ if (!file->offset)
+ die("Bad FAT32 root directory! (start cluster beyond limit: %lu > %lu)\n",
+ (unsigned long)FSTART(file, fs), (unsigned long)(fs->clusters + 1));
+ MODIFY_START(file, 0, fs);
+ }
+ clusters = prev = 0;
+ for (curr = FSTART(file, fs) ? FSTART(file, fs) :
+ -1; curr != -1; curr = next_cluster(fs, curr)) {
+ FAT_ENTRY curEntry;
+ get_fat(&curEntry, fs->fat, curr, fs);
+
+ if (!curEntry.value || bad_cluster(fs, curr)) {
+ printf("%s\n Contains a %s cluster (%lu). Assuming EOF.\n",
+ path_name(file), curEntry.value ? "bad" : "free", (unsigned long)curr);
+ if (prev)
+ set_fat(fs, prev, -1);
+ else if (!file->offset)
+ die("FAT32 root dir starts with a bad cluster!");
+ else
+ MODIFY_START(file, 0, fs);
+ break;
+ }
+ if (!(file->dir_ent.attr & ATTR_DIR) && le32toh(file->dir_ent.size) <=
+ (uint64_t)clusters * fs->cluster_size) {
+ printf
+ ("%s\n File size is %u bytes, cluster chain length is > %lu "
+ "bytes.\n Truncating file to %u bytes.\n", path_name(file),
+ le32toh(file->dir_ent.size),
+ (uint64_t)clusters * fs->cluster_size,
+ le32toh(file->dir_ent.size));
+ truncate_file(fs, file, clusters);
+ break;
+ }
+ if ((owner = get_owner(fs, curr))) {
+ int do_trunc = 0;
+ printf("%s and\n", path_name(owner));
+ printf("%s\n share clusters.\n", path_name(file));
+ clusters2 = 0;
+ for (walk = FSTART(owner, fs); walk > 0 && walk != -1; walk =
+ next_cluster(fs, walk))
+ if (walk == curr)
+ break;
+ else
+ clusters2++;
+ restart = file->dir_ent.attr & ATTR_DIR;
+ if (!owner->offset) {
+ printf(" Truncating second to %llu bytes because first "
+ "is FAT32 root dir.\n",
+ (unsigned long long)clusters2 * fs->cluster_size);
+ do_trunc = 2;
+ } else if (!file->offset) {
+ printf(" Truncating first to %llu bytes because second "
+ "is FAT32 root dir.\n",
+ (unsigned long long)clusters * fs->cluster_size);
+ do_trunc = 1;
+ } else if (interactive)
+ printf("1) Truncate first to %llu bytes%s\n"
+ "2) Truncate second to %llu bytes\n",
+ (unsigned long long)clusters * fs->cluster_size,
+ restart ? " and restart" : "",
+ (unsigned long long)clusters2 * fs->cluster_size);
+ else
+ printf(" Truncating second to %llu bytes.\n",
+ (unsigned long long)clusters2 * fs->cluster_size);
+ if (do_trunc != 2
+ && (do_trunc == 1
+ || (interactive && get_key("12", "?") == '1'))) {
+ prev = 0;
+ clusters = 0;
+ for (this = FSTART(owner, fs); this > 0 && this != -1; this =
+ next_cluster(fs, this)) {
+ if (this == curr) {
+ if (prev)
+ set_fat(fs, prev, -1);
+ else
+ MODIFY_START(owner, 0, fs);
+ MODIFY(owner, size,
+ htole32((uint64_t)clusters *
+ fs->cluster_size));
+ if (restart)
+ return 1;
+ while (this > 0 && this != -1) {
+ set_owner(fs, this, NULL);
+ this = next_cluster(fs, this);
+ }
+ this = curr;
+ break;
+ }
+ clusters++;
+ prev = this;
+ }
+ if (this != curr)
+ die("Internal error: didn't find cluster %d in chain"
+ " starting at %d", curr, FSTART(owner, fs));
+ } else {
+ if (prev)
+ set_fat(fs, prev, -1);
+ else
+ MODIFY_START(file, 0, fs);
+ break;
+ }
+ }
+ set_owner(fs, curr, file);
+ clusters++;
+ prev = curr;
+ }
+ if (!(file->dir_ent.attr & ATTR_DIR) && le32toh(file->dir_ent.size) >
+ (uint64_t)clusters * fs->cluster_size) {
+ printf
+ ("%s\n File size is %u bytes, cluster chain length is %llu bytes."
+ "\n Truncating file to %llu bytes.\n", path_name(file),
+ le32toh(file->dir_ent.size),
+ (unsigned long long)clusters * fs->cluster_size,
+ (unsigned long long)clusters * fs->cluster_size);
+ MODIFY(file, size,
+ htole32((uint64_t)clusters * fs->cluster_size));
+ }
+ return 0;
+}
+
+static int check_files(DOS_FS * fs, DOS_FILE * start)
+{
+ while (start) {
+ if (check_file(fs, start))
+ return 1;
+ start = start->next;
+ }
+ return 0;
+}
+
+static int check_dir(DOS_FS * fs, DOS_FILE ** root, int dots)
+{
+ DOS_FILE *parent, **walk, **scan;
+ int dot, dotdot, skip, redo;
+ int good, bad;
+
+ if (!*root)
+ return 0;
+ parent = (*root)->parent;
+ good = bad = 0;
+ for (walk = root; *walk; walk = &(*walk)->next)
+ if (bad_name(*walk))
+ bad++;
+ else
+ good++;
+ if (*root && parent && good + bad > 4 && bad > good / 2) {
+ printf("%s\n Has a large number of bad entries. (%d/%d)\n",
+ path_name(parent), bad, good + bad);
+ if (!dots)
+ printf(" Not dropping root directory.\n");
+ else if (!interactive)
+ printf(" Not dropping it in auto-mode.\n");
+ else if (get_key("yn", "Drop directory ? (y/n)") == 'y') {
+ truncate_file(fs, parent, 0);
+ MODIFY(parent, name[0], DELETED_FLAG);
+ /* buglet: deleted directory stays in the list. */
+ return 1;
+ }
+ }
+ dot = dotdot = redo = 0;
+ walk = root;
+ while (*walk) {
+ if (!strncmp
+ ((const char *)((*walk)->dir_ent.name), MSDOS_DOT, MSDOS_NAME)
+ || !strncmp((const char *)((*walk)->dir_ent.name), MSDOS_DOTDOT,
+ MSDOS_NAME)) {
+ if (handle_dot(fs, *walk, dots)) {
+ *walk = (*walk)->next;
+ continue;
+ }
+ if (!strncmp
+ ((const char *)((*walk)->dir_ent.name), MSDOS_DOT, MSDOS_NAME))
+ dot++;
+ else
+ dotdot++;
+ }
+ if (!((*walk)->dir_ent.attr & ATTR_VOLUME) && bad_name(*walk)) {
+ puts(path_name(*walk));
+ printf(" Bad short file name (%s).\n",
+ file_name((*walk)->dir_ent.name));
+ if (interactive)
+ printf("1) Drop file\n2) Rename file\n3) Auto-rename\n"
+ "4) Keep it\n");
+ else
+ printf(" Auto-renaming it.\n");
+ switch (interactive ? get_key("1234", "?") : '3') {
+ case '1':
+ drop_file(fs, *walk);
+ walk = &(*walk)->next;
+ continue;
+ case '2':
+ rename_file(*walk);
+ redo = 1;
+ break;
+ case '3':
+ auto_rename(*walk);
+ printf(" Renamed to %s\n", file_name((*walk)->dir_ent.name));
+ break;
+ case '4':
+ break;
+ }
+ }
+ /* don't check for duplicates of the volume label */
+ if (!((*walk)->dir_ent.attr & ATTR_VOLUME)) {
+ scan = &(*walk)->next;
+ skip = 0;
+ while (*scan && !skip) {
+ if (!((*scan)->dir_ent.attr & ATTR_VOLUME) &&
+ !memcmp((*walk)->dir_ent.name, (*scan)->dir_ent.name,
+ MSDOS_NAME)) {
+ printf("%s\n Duplicate directory entry.\n First %s\n",
+ path_name(*walk), file_stat(*walk));
+ printf(" Second %s\n", file_stat(*scan));
+ if (interactive)
+ printf
+ ("1) Drop first\n2) Drop second\n3) Rename first\n"
+ "4) Rename second\n5) Auto-rename first\n"
+ "6) Auto-rename second\n");
+ else
+ printf(" Auto-renaming second.\n");
+ switch (interactive ? get_key("123456", "?") : '6') {
+ case '1':
+ drop_file(fs, *walk);
+ *walk = (*walk)->next;
+ skip = 1;
+ break;
+ case '2':
+ drop_file(fs, *scan);
+ *scan = (*scan)->next;
+ continue;
+ case '3':
+ rename_file(*walk);
+ printf(" Renamed to %s\n", path_name(*walk));
+ redo = 1;
+ break;
+ case '4':
+ rename_file(*scan);
+ printf(" Renamed to %s\n", path_name(*walk));
+ redo = 1;
+ break;
+ case '5':
+ auto_rename(*walk);
+ printf(" Renamed to %s\n",
+ file_name((*walk)->dir_ent.name));
+ break;
+ case '6':
+ auto_rename(*scan);
+ printf(" Renamed to %s\n",
+ file_name((*scan)->dir_ent.name));
+ break;
+ }
+ }
+ scan = &(*scan)->next;
+ }
+ if (skip)
+ continue;
+ }
+ if (!redo)
+ walk = &(*walk)->next;
+ else {
+ walk = root;
+ dot = dotdot = redo = 0;
+ }
+ }
+ if (dots && !dot)
+ printf("%s\n \".\" is missing. Can't fix this yet.\n",
+ path_name(parent));
+ if (dots && !dotdot)
+ printf("%s\n \"..\" is missing. Can't fix this yet.\n",
+ path_name(parent));
+ return 0;
+}
+
+/**
+ * Check a dentry's cluster chain for bad clusters.
+ * If requested, we verify readability and mark unreadable clusters as bad.
+ *
+ * @param[inout] fs Information about the filesystem
+ * @param[in] file dentry to check
+ * @param[in] read_test Nonzero == verify that dentry's clusters can
+ * be read
+ */
+static void test_file(DOS_FS * fs, DOS_FILE * file, int read_test)
+{
+ DOS_FILE *owner;
+ uint32_t walk, prev, clusters, next_clu;
+
+ prev = clusters = 0;
+ for (walk = FSTART(file, fs); walk > 1 && walk < fs->clusters + 2;
+ walk = next_clu) {
+ next_clu = next_cluster(fs, walk);
+
+ /* In this stage we are checking only for a loop within our own
+ * cluster chain.
+ * Cross-linking of clusters is handled in check_file()
+ */
+ if ((owner = get_owner(fs, walk))) {
+ if (owner == file) {
+ printf("%s\n Circular cluster chain. Truncating to %lu "
+ "cluster%s.\n", path_name(file), (unsigned long)clusters,
+ clusters == 1 ? "" : "s");
+ if (prev)
+ set_fat(fs, prev, -1);
+ else if (!file->offset)
+ die("Bad FAT32 root directory! (bad start cluster)\n");
+ else
+ MODIFY_START(file, 0, fs);
+ }
+ break;
+ }
+ if (bad_cluster(fs, walk))
+ break;
+ if (read_test) {
+ if (fs_test(cluster_start(fs, walk), fs->cluster_size)) {
+ prev = walk;
+ clusters++;
+ } else {
+ printf("%s\n Cluster %lu (%lu) is unreadable. Skipping it.\n",
+ path_name(file), (unsigned long)clusters, (unsigned long)walk);
+ if (prev)
+ set_fat(fs, prev, next_cluster(fs, walk));
+ else
+ MODIFY_START(file, next_cluster(fs, walk), fs);
+ set_fat(fs, walk, -2);
+ }
+ }
+ set_owner(fs, walk, file);
+ }
+ /* Revert ownership (for now) */
+ for (walk = FSTART(file, fs); walk > 1 && walk < fs->clusters + 2;
+ walk = next_cluster(fs, walk))
+ if (bad_cluster(fs, walk))
+ break;
+ else if (get_owner(fs, walk) == file)
+ set_owner(fs, walk, NULL);
+ else
+ break;
+}
+
+static void undelete(DOS_FS * fs, DOS_FILE * file)
+{
+ uint32_t clusters, left, prev, walk;
+
+ clusters = left = (le32toh(file->dir_ent.size) + fs->cluster_size - 1) /
+ fs->cluster_size;
+ prev = 0;
+
+ walk = FSTART(file, fs);
+
+ while (left && (walk >= 2) && (walk < fs->clusters + 2)) {
+
+ FAT_ENTRY curEntry;
+ get_fat(&curEntry, fs->fat, walk, fs);
+
+ if (!curEntry.value)
+ break;
+
+ left--;
+ if (prev)
+ set_fat(fs, prev, walk);
+ prev = walk;
+ walk++;
+ }
+ if (prev)
+ set_fat(fs, prev, -1);
+ else
+ MODIFY_START(file, 0, fs);
+ if (left)
+ printf("Warning: Did only undelete %lu of %lu cluster%s.\n",
+ (unsigned long)clusters - left, (unsigned long)clusters, clusters == 1 ? "" : "s");
+
+}
+
+static void new_dir(void)
+{
+ lfn_reset();
+}
+
+/**
+ * Create a description for a referenced dentry and insert it in our dentry
+ * tree. Then, go check the dentry's cluster chain for bad clusters and
+ * cluster loops.
+ *
+ * @param[inout] fs Information about the filesystem
+ * @param[out] chain
+ * @param[in] parent Information about parent directory of this file
+ * NULL == no parent ('file' is root directory)
+ * @param[in] offset Partition-relative byte offset of directory entry of interest
+ * 0 == Root directory
+ * @param cp
+ */
+static void add_file(DOS_FS * fs, DOS_FILE *** chain, DOS_FILE * parent,
+ loff_t offset, FDSC ** cp)
+{
+ DOS_FILE *new;
+ DIR_ENT de;
+ FD_TYPE type;
+
+ if (offset)
+ fs_read(offset, sizeof(DIR_ENT), &de);
+ else {
+ /* Construct a DIR_ENT for the root directory */
+ memset(&de, 0, sizeof de);
+ memcpy(de.name, " ", MSDOS_NAME);
+ de.attr = ATTR_DIR;
+ de.start = htole16(fs->root_cluster & 0xffff);
+ de.starthi = htole16((fs->root_cluster >> 16) & 0xffff);
+ }
+ if ((type = file_type(cp, (char *)de.name)) != fdt_none) {
+ if (type == fdt_undelete && (de.attr & ATTR_DIR))
+ die("Can't undelete directories.");
+ file_modify(cp, (char *)de.name);
+ fs_write(offset, 1, &de);
+ }
+ if (IS_FREE(de.name)) {
+ lfn_check_orphaned();
+ return;
+ }
+ if (de.attr == VFAT_LN_ATTR) {
+ lfn_add_slot(&de, offset);
+ return;
+ }
+ new = qalloc(&mem_queue, sizeof(DOS_FILE));
+ new->lfn = lfn_get(&de, &new->lfn_offset);
+ new->offset = offset;
+ memcpy(&new->dir_ent, &de, sizeof(de));
+ new->next = new->first = NULL;
+ new->parent = parent;
+ if (type == fdt_undelete)
+ undelete(fs, new);
+ **chain = new;
+ *chain = &new->next;
+ if (list) {
+ printf("Checking file %s", path_name(new));
+ if (new->lfn)
+ printf(" (%s)", file_name(new->dir_ent.name)); /* (8.3) */
+ printf("\n");
+ }
+ /* Don't include root directory, '.', or '..' in the total file count */
+ if (offset &&
+ strncmp((const char *)de.name, MSDOS_DOT, MSDOS_NAME) != 0 &&
+ strncmp((const char *)de.name, MSDOS_DOTDOT, MSDOS_NAME) != 0)
+ ++n_files;
+ test_file(fs, new, test); /* Bad cluster check */
+}
+
+static int subdirs(DOS_FS * fs, DOS_FILE * parent, FDSC ** cp);
+
+static int scan_dir(DOS_FS * fs, DOS_FILE * this, FDSC ** cp)
+{
+ DOS_FILE **chain;
+ int i;
+ uint32_t clu_num;
+
+ chain = &this->first;
+ i = 0;
+ clu_num = FSTART(this, fs);
+ new_dir();
+ while (clu_num > 0 && clu_num != -1) {
+ add_file(fs, &chain, this,
+ cluster_start(fs, clu_num) + (i % fs->cluster_size), cp);
+ i += sizeof(DIR_ENT);
+ if (!(i % fs->cluster_size))
+ if ((clu_num = next_cluster(fs, clu_num)) == 0 || clu_num == -1)
+ break;
+ }
+ lfn_check_orphaned();
+ if (check_dir(fs, &this->first, this->offset))
+ return 0;
+ if (check_files(fs, this->first))
+ return 1;
+ return subdirs(fs, this, cp);
+}
+
+/**
+ * Recursively scan subdirectories of the specified parent directory.
+ *
+ * @param[inout] fs Information about the filesystem
+ * @param[in] parent Identifies the directory to scan
+ * @param[in] cp
+ *
+ * @return 0 Success
+ * @return 1 Error
+ */
+static int subdirs(DOS_FS * fs, DOS_FILE * parent, FDSC ** cp)
+{
+ DOS_FILE *walk;
+
+ for (walk = parent ? parent->first : root; walk; walk = walk->next)
+ if (walk->dir_ent.attr & ATTR_DIR)
+ if (strncmp((const char *)walk->dir_ent.name, MSDOS_DOT, MSDOS_NAME)
+ && strncmp((const char *)walk->dir_ent.name, MSDOS_DOTDOT,
+ MSDOS_NAME))
+ if (scan_dir(fs, walk, file_cd(cp, (char *)walk->dir_ent.name)))
+ return 1;
+ return 0;
+}
+
+/**
+ * Scan all directory and file information for errors.
+ *
+ * @param[inout] fs Information about the filesystem
+ *
+ * @return 0 Success
+ * @return 1 Error
+ */
+int scan_root(DOS_FS * fs)
+{
+ DOS_FILE **chain;
+ int i;
+
+ root = NULL;
+ chain = &root;
+ new_dir();
+ if (fs->root_cluster) {
+ add_file(fs, &chain, NULL, 0, &fp_root);
+ } else {
+ for (i = 0; i < fs->root_entries; i++)
+ add_file(fs, &chain, NULL, fs->root_start + i * sizeof(DIR_ENT),
+ &fp_root);
+ }
+ lfn_check_orphaned();
+ (void)check_dir(fs, &root, 0);
+ if (check_files(fs, root))
+ return 1;
+ return subdirs(fs, NULL, &fp_root);
+}
diff --git a/dosfstools/src/check.h b/dosfstools/src/check.h
new file mode 100644
index 000000000..fcb6bea39
--- /dev/null
+++ b/dosfstools/src/check.h
@@ -0,0 +1,40 @@
+/* check.h - Check and repair a PC/MS-DOS filesystem
+
+ Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
+ Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ The complete text of the GNU General Public License
+ can be found in /usr/share/common-licenses/GPL-3 file.
+*/
+
+#ifndef _CHECK_H
+#define _CHECK_H
+
+loff_t alloc_rootdir_entry(DOS_FS * fs, DIR_ENT * de, const char *pattern);
+
+/* Allocate a free slot in the root directory for a new file. The file name is
+ constructed after 'pattern', which must include a %d type format for printf
+ and expand to exactly 11 characters. The name actually used is written into
+ the 'de' structure, the rest of *de is cleared. The offset returned is to
+ where in the filesystem the entry belongs. */
+
+int scan_root(DOS_FS * fs);
+
+/* Scans the root directory and recurses into all subdirectories. See check.c
+ for all the details. Returns a non-zero integer if the filesystem has to
+ be checked again. */
+
+#endif
diff --git a/dosfstools/src/common.c b/dosfstools/src/common.c
new file mode 100644
index 000000000..9d1119322
--- /dev/null
+++ b/dosfstools/src/common.c
@@ -0,0 +1,119 @@
+/* common.c - Common functions
+
+ Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
+ Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
+ Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ The complete text of the GNU General Public License
+ can be found in /usr/share/common-licenses/GPL-3 file.
+*/
+
+/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
+ * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+
+#include "common.h"
+
+typedef struct _link {
+ void *data;
+ struct _link *next;
+} LINK;
+
+void die(const char *msg, ...)
+{
+ va_list args;
+
+ va_start(args, msg);
+ vfprintf(stderr, msg, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+void pdie(const char *msg, ...)
+{
+ va_list args;
+
+ va_start(args, msg);
+ vfprintf(stderr, msg, args);
+ va_end(args);
+ fprintf(stderr, ":%s\n", strerror(errno));
+ exit(1);
+}
+
+void *alloc(int size)
+{
+ void *this;
+
+ if ((this = malloc(size)))
+ return this;
+ pdie("malloc");
+ return NULL; /* for GCC */
+}
+
+void *qalloc(void **root, int size)
+{
+ LINK *link;
+
+ link = alloc(sizeof(LINK));
+ link->next = *root;
+ *root = link;
+ return link->data = alloc(size);
+}
+
+void qfree(void **root)
+{
+ LINK *this;
+
+ while (*root) {
+ this = (LINK *) * root;
+ *root = this->next;
+ free(this->data);
+ free(this);
+ }
+}
+
+int min(int a, int b)
+{
+ return a < b ? a : b;
+}
+
+char get_key(const char *valid, const char *prompt)
+{
+ int ch, okay;
+
+ while (1) {
+ if (prompt)
+ printf("%s ", prompt);
+ fflush(stdout);
+ while (ch = getchar(), ch == ' ' || ch == '\t') ;
+ if (ch == EOF)
+ exit(1);
+ if (!strchr(valid, okay = ch))
+ okay = 0;
+ while (ch = getchar(), ch != '\n' && ch != EOF) ;
+ if (ch == EOF)
+ exit(1);
+ if (okay)
+ return okay;
+ printf("Invalid input.\n");
+ }
+}
diff --git a/dosfstools/src/common.h b/dosfstools/src/common.h
new file mode 100644
index 000000000..c15efb538
--- /dev/null
+++ b/dosfstools/src/common.h
@@ -0,0 +1,56 @@
+/* common.h - Common functions
+
+ Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
+ Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ The complete text of the GNU General Public License
+ can be found in /usr/share/common-licenses/GPL-3 file.
+*/
+
+#ifndef _COMMON_H
+#define _COMMON_H
+
+void die(const char *msg, ...) __attribute((noreturn));
+
+/* Displays a prinf-style message and terminates the program. */
+
+void pdie(const char *msg, ...) __attribute((noreturn));
+
+/* Like die, but appends an error message according to the state of errno. */
+
+void *alloc(int size);
+
+/* mallocs SIZE bytes and returns a pointer to the data. Terminates the program
+ if malloc fails. */
+
+void *qalloc(void **root, int size);
+
+/* Like alloc, but registers the data area in a list described by ROOT. */
+
+void qfree(void **root);
+
+/* Deallocates all qalloc'ed data areas described by ROOT. */
+
+int min(int a, int b);
+
+/* Returns the smaller integer value of a and b. */
+
+char get_key(const char *valid, const char *prompt);
+
+/* Displays PROMPT and waits for user input. Only characters in VALID are
+ accepted. Terminates the program on EOF. Returns the character. */
+
+#endif
diff --git a/dosfstools/src/fat.c b/dosfstools/src/fat.c
new file mode 100644
index 000000000..5a92f5684
--- /dev/null
+++ b/dosfstools/src/fat.c
@@ -0,0 +1,558 @@
+/* fat.c - Read/write access to the FAT
+
+ Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
+ Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
+ Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ The complete text of the GNU General Public License
+ can be found in /usr/share/common-licenses/GPL-3 file.
+*/
+
+/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
+ * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "fsck.fat.h"
+#include "io.h"
+#include "check.h"
+#include "fat.h"
+
+/**
+ * Fetch the FAT entry for a specified cluster.
+ *
+ * @param[out] entry Cluster to which cluster of interest is linked
+ * @param[in] fat FAT table for the partition
+ * @param[in] cluster Cluster of interest
+ * @param[in] fs Information from the FAT boot sectors (bits per FAT entry)
+ */
+void get_fat(FAT_ENTRY * entry, void *fat, uint32_t cluster, DOS_FS * fs)
+{
+ unsigned char *ptr;
+
+ switch (fs->fat_bits) {
+ case 12:
+ ptr = &((unsigned char *)fat)[cluster * 3 / 2];
+ entry->value = 0xfff & (cluster & 1 ? (ptr[0] >> 4) | (ptr[1] << 4) :
+ (ptr[0] | ptr[1] << 8));
+ break;
+ case 16:
+ entry->value = le16toh(((unsigned short *)fat)[cluster]);
+ break;
+ case 32:
+ /* According to M$, the high 4 bits of a FAT32 entry are reserved and
+ * are not part of the cluster number. So we cut them off. */
+ {
+ uint32_t e = le32toh(((unsigned int *)fat)[cluster]);
+ entry->value = e & 0xfffffff;
+ entry->reserved = e >> 28;
+ }
+ break;
+ default:
+ die("Bad FAT entry size: %d bits.", fs->fat_bits);
+ }
+}
+
+/**
+ * Build a bookkeeping structure from the partition's FAT table.
+ * If the partition has multiple FATs and they don't agree, try to pick a winner,
+ * and queue a command to overwrite the loser.
+ * One error that is fixed here is a cluster that links to something out of range.
+ *
+ * @param[inout] fs Information about the filesystem
+ */
+void read_fat(DOS_FS * fs)
+{
+ int eff_size, alloc_size;
+ uint32_t i;
+ void *first, *second = NULL;
+ int first_ok, second_ok;
+ uint32_t total_num_clusters;
+
+ /* Clean up from previous pass */
+ if (fs->fat)
+ free(fs->fat);
+ if (fs->cluster_owner)
+ free(fs->cluster_owner);
+ fs->fat = NULL;
+ fs->cluster_owner = NULL;
+
+ total_num_clusters = fs->clusters + 2UL;
+ eff_size = (total_num_clusters * fs->fat_bits + 7) / 8ULL;
+
+ if (fs->fat_bits != 12)
+ alloc_size = eff_size;
+ else
+ /* round up to an even number of FAT entries to avoid special
+ * casing the last entry in get_fat() */
+ alloc_size = (total_num_clusters * 12 + 23) / 24 * 3;
+
+ first = alloc(alloc_size);
+ fs_read(fs->fat_start, eff_size, first);
+ if (fs->nfats > 1) {
+ second = alloc(alloc_size);
+ fs_read(fs->fat_start + fs->fat_size, eff_size, second);
+ }
+ if (second && memcmp(first, second, eff_size) != 0) {
+ FAT_ENTRY first_media, second_media;
+ get_fat(&first_media, first, 0, fs);
+ get_fat(&second_media, second, 0, fs);
+ first_ok = (first_media.value & FAT_EXTD(fs)) == FAT_EXTD(fs);
+ second_ok = (second_media.value & FAT_EXTD(fs)) == FAT_EXTD(fs);
+ if (first_ok && !second_ok) {
+ printf("FATs differ - using first FAT.\n");
+ fs_write(fs->fat_start + fs->fat_size, eff_size, first);
+ }
+ if (!first_ok && second_ok) {
+ printf("FATs differ - using second FAT.\n");
+ fs_write(fs->fat_start, eff_size, second);
+ memcpy(first, second, eff_size);
+ }
+ if (first_ok && second_ok) {
+ if (interactive) {
+ printf("FATs differ but appear to be intact. Use which FAT ?\n"
+ "1) Use first FAT\n2) Use second FAT\n");
+ if (get_key("12", "?") == '1') {
+ fs_write(fs->fat_start + fs->fat_size, eff_size, first);
+ } else {
+ fs_write(fs->fat_start, eff_size, second);
+ memcpy(first, second, eff_size);
+ }
+ } else {
+ printf("FATs differ but appear to be intact. Using first "
+ "FAT.\n");
+ fs_write(fs->fat_start + fs->fat_size, eff_size, first);
+ }
+ }
+ if (!first_ok && !second_ok) {
+ printf("Both FATs appear to be corrupt. Giving up.\n");
+ exit(1);
+ }
+ }
+ if (second) {
+ free(second);
+ }
+ fs->fat = (unsigned char *)first;
+
+ fs->cluster_owner = alloc(total_num_clusters * sizeof(DOS_FILE *));
+ memset(fs->cluster_owner, 0, (total_num_clusters * sizeof(DOS_FILE *)));
+
+ /* Truncate any cluster chains that link to something out of range */
+ for (i = 2; i < fs->clusters + 2; i++) {
+ FAT_ENTRY curEntry;
+ get_fat(&curEntry, fs->fat, i, fs);
+ if (curEntry.value == 1) {
+ printf("Cluster %ld out of range (1). Setting to EOF.\n", (long)(i - 2));
+ set_fat(fs, i, -1);
+ }
+ if (curEntry.value >= fs->clusters + 2 &&
+ (curEntry.value < FAT_MIN_BAD(fs))) {
+ printf("Cluster %ld out of range (%ld > %ld). Setting to EOF.\n",
+ (long)(i - 2), (long)curEntry.value, (long)(fs->clusters + 2 - 1));
+ set_fat(fs, i, -1);
+ }
+ }
+}
+
+/**
+ * Update the FAT entry for a specified cluster
+ * (i.e., change the cluster it links to).
+ * Queue a command to write out this change.
+ *
+ * @param[in,out] fs Information about the filesystem
+ * @param[in] cluster Cluster to change
+ * @param[in] new Cluster to link to
+ * Special values:
+ * 0 == free cluster
+ * -1 == end-of-chain
+ * -2 == bad cluster
+ */
+void set_fat(DOS_FS * fs, uint32_t cluster, int32_t new)
+{
+ unsigned char *data = NULL;
+ int size;
+ loff_t offs;
+
+ if (new == -1)
+ new = FAT_EOF(fs);
+ else if ((long)new == -2)
+ new = FAT_BAD(fs);
+ switch (fs->fat_bits) {
+ case 12:
+ data = fs->fat + cluster * 3 / 2;
+ offs = fs->fat_start + cluster * 3 / 2;
+ if (cluster & 1) {
+ FAT_ENTRY prevEntry;
+ get_fat(&prevEntry, fs->fat, cluster - 1, fs);
+ data[0] = ((new & 0xf) << 4) | (prevEntry.value >> 8);
+ data[1] = new >> 4;
+ } else {
+ FAT_ENTRY subseqEntry;
+ get_fat(&subseqEntry, fs->fat, cluster + 1, fs);
+ data[0] = new & 0xff;
+ data[1] = (new >> 8) | (cluster == fs->clusters - 1 ? 0 :
+ (0xff & subseqEntry.value) << 4);
+ }
+ size = 2;
+ break;
+ case 16:
+ data = fs->fat + cluster * 2;
+ offs = fs->fat_start + cluster * 2;
+ *(unsigned short *)data = htole16(new);
+ size = 2;
+ break;
+ case 32:
+ {
+ FAT_ENTRY curEntry;
+ get_fat(&curEntry, fs->fat, cluster, fs);
+
+ data = fs->fat + cluster * 4;
+ offs = fs->fat_start + cluster * 4;
+ /* According to M$, the high 4 bits of a FAT32 entry are reserved and
+ * are not part of the cluster number. So we never touch them. */
+ *(uint32_t *)data = htole32((new & 0xfffffff) |
+ (curEntry.reserved << 28));
+ size = 4;
+ }
+ break;
+ default:
+ die("Bad FAT entry size: %d bits.", fs->fat_bits);
+ }
+ fs_write(offs, size, data);
+ if (fs->nfats > 1) {
+ fs_write(offs + fs->fat_size, size, data);
+ }
+}
+
+int bad_cluster(DOS_FS * fs, uint32_t cluster)
+{
+ FAT_ENTRY curEntry;
+ get_fat(&curEntry, fs->fat, cluster, fs);
+
+ return FAT_IS_BAD(fs, curEntry.value);
+}
+
+/**
+ * Get the cluster to which the specified cluster is linked.
+ * If the linked cluster is marked bad, abort.
+ *
+ * @param[in] fs Information about the filesystem
+ * @param[in] cluster Cluster to follow
+ *
+ * @return -1 'cluster' is at the end of the chain
+ * @return Other values Next cluster in this chain
+ */
+uint32_t next_cluster(DOS_FS * fs, uint32_t cluster)
+{
+ uint32_t value;
+ FAT_ENTRY curEntry;
+
+ get_fat(&curEntry, fs->fat, cluster, fs);
+
+ value = curEntry.value;
+ if (FAT_IS_BAD(fs, value))
+ die("Internal error: next_cluster on bad cluster");
+ return FAT_IS_EOF(fs, value) ? -1 : value;
+}
+
+loff_t cluster_start(DOS_FS * fs, uint32_t cluster)
+{
+ return fs->data_start + ((loff_t) cluster -
+ 2) * (uint64_t)fs->cluster_size;
+}
+
+/**
+ * Update internal bookkeeping to show that the specified cluster belongs
+ * to the specified dentry.
+ *
+ * @param[in,out] fs Information about the filesystem
+ * @param[in] cluster Cluster being assigned
+ * @param[in] owner Information on dentry that owns this cluster
+ * (may be NULL)
+ */
+void set_owner(DOS_FS * fs, uint32_t cluster, DOS_FILE * owner)
+{
+ if (fs->cluster_owner == NULL)
+ die("Internal error: attempt to set owner in non-existent table");
+
+ if (owner && fs->cluster_owner[cluster]
+ && (fs->cluster_owner[cluster] != owner))
+ die("Internal error: attempt to change file owner");
+ fs->cluster_owner[cluster] = owner;
+}
+
+DOS_FILE *get_owner(DOS_FS * fs, uint32_t cluster)
+{
+ if (fs->cluster_owner == NULL)
+ return NULL;
+ else
+ return fs->cluster_owner[cluster];
+}
+
+void fix_bad(DOS_FS * fs)
+{
+ uint32_t i;
+
+ if (verbose)
+ printf("Checking for bad clusters.\n");
+ for (i = 2; i < fs->clusters + 2; i++) {
+ FAT_ENTRY curEntry;
+ get_fat(&curEntry, fs->fat, i, fs);
+
+ if (!get_owner(fs, i) && !FAT_IS_BAD(fs, curEntry.value))
+ if (!fs_test(cluster_start(fs, i), fs->cluster_size)) {
+ printf("Cluster %lu is unreadable.\n", (unsigned long)i);
+ set_fat(fs, i, -2);
+ }
+ }
+}
+
+void reclaim_free(DOS_FS * fs)
+{
+ int reclaimed;
+ uint32_t i;
+
+ if (verbose)
+ printf("Checking for unused clusters.\n");
+ reclaimed = 0;
+ for (i = 2; i < fs->clusters + 2; i++) {
+ FAT_ENTRY curEntry;
+ get_fat(&curEntry, fs->fat, i, fs);
+
+ if (!get_owner(fs, i) && curEntry.value &&
+ !FAT_IS_BAD(fs, curEntry.value)) {
+ set_fat(fs, i, 0);
+ reclaimed++;
+ }
+ }
+ if (reclaimed)
+ printf("Reclaimed %d unused cluster%s (%llu bytes).\n", (int)reclaimed,
+ reclaimed == 1 ? "" : "s",
+ (unsigned long long)reclaimed * fs->cluster_size);
+}
+
+/**
+ * Assign the specified owner to all orphan chains (except cycles).
+ * Break cross-links between orphan chains.
+ *
+ * @param[in,out] fs Information about the filesystem
+ * @param[in] owner dentry to be assigned ownership of orphans
+ * @param[in,out] num_refs For each orphan cluster [index], how many
+ * clusters link to it.
+ * @param[in] start_cluster Where to start scanning for orphans
+ */
+static void tag_free(DOS_FS * fs, DOS_FILE * owner, uint32_t *num_refs,
+ uint32_t start_cluster)
+{
+ int prev;
+ uint32_t i, walk;
+
+ if (start_cluster == 0)
+ start_cluster = 2;
+
+ for (i = start_cluster; i < fs->clusters + 2; i++) {
+ FAT_ENTRY curEntry;
+ get_fat(&curEntry, fs->fat, i, fs);
+
+ /* If the current entry is the head of an un-owned chain... */
+ if (curEntry.value && !FAT_IS_BAD(fs, curEntry.value) &&
+ !get_owner(fs, i) && !num_refs[i]) {
+ prev = 0;
+ /* Walk the chain, claiming ownership as we go */
+ for (walk = i; walk != -1; walk = next_cluster(fs, walk)) {
+ if (!get_owner(fs, walk)) {
+ set_owner(fs, walk, owner);
+ } else {
+ /* We've run into cross-links between orphaned chains,
+ * or a cycle with a tail.
+ * Terminate this orphan chain (break the link)
+ */
+ set_fat(fs, prev, -1);
+
+ /* This is not necessary because 'walk' is owned and thus
+ * will never become the head of a chain (the only case
+ * that would matter during reclaim to files).
+ * It's easier to decrement than to prove that it's
+ * unnecessary.
+ */
+ num_refs[walk]--;
+ break;
+ }
+ prev = walk;
+ }
+ }
+ }
+}
+
+/**
+ * Recover orphan chains to files, handling any cycles or cross-links.
+ *
+ * @param[in,out] fs Information about the filesystem
+ */
+void reclaim_file(DOS_FS * fs)
+{
+ DOS_FILE orphan;
+ int reclaimed, files;
+ int changed = 0;
+ uint32_t i, next, walk;
+ uint32_t *num_refs = NULL; /* Only for orphaned clusters */
+ uint32_t total_num_clusters;
+
+ if (verbose)
+ printf("Reclaiming unconnected clusters.\n");
+
+ total_num_clusters = fs->clusters + 2UL;
+ num_refs = alloc(total_num_clusters * sizeof(uint32_t));
+ memset(num_refs, 0, (total_num_clusters * sizeof(uint32_t)));
+
+ /* Guarantee that all orphan chains (except cycles) end cleanly
+ * with an end-of-chain mark.
+ */
+
+ for (i = 2; i < total_num_clusters; i++) {
+ FAT_ENTRY curEntry;
+ get_fat(&curEntry, fs->fat, i, fs);
+
+ next = curEntry.value;
+ if (!get_owner(fs, i) && next && next < fs->clusters + 2) {
+ /* Cluster is linked, but not owned (orphan) */
+ FAT_ENTRY nextEntry;
+ get_fat(&nextEntry, fs->fat, next, fs);
+
+ /* Mark it end-of-chain if it links into an owned cluster,
+ * a free cluster, or a bad cluster.
+ */
+ if (get_owner(fs, next) || !nextEntry.value ||
+ FAT_IS_BAD(fs, nextEntry.value))
+ set_fat(fs, i, -1);
+ else
+ num_refs[next]++;
+ }
+ }
+
+ /* Scan until all the orphans are accounted for,
+ * and all cycles and cross-links are broken
+ */
+ do {
+ tag_free(fs, &orphan, num_refs, changed);
+ changed = 0;
+
+ /* Any unaccounted-for orphans must be part of a cycle */
+ for (i = 2; i < total_num_clusters; i++) {
+ FAT_ENTRY curEntry;
+ get_fat(&curEntry, fs->fat, i, fs);
+
+ if (curEntry.value && !FAT_IS_BAD(fs, curEntry.value) &&
+ !get_owner(fs, i)) {
+ if (!num_refs[curEntry.value]--)
+ die("Internal error: num_refs going below zero");
+ set_fat(fs, i, -1);
+ changed = curEntry.value;
+ printf("Broke cycle at cluster %lu in free chain.\n", (unsigned long)i);
+
+ /* If we've created a new chain head,
+ * tag_free() can claim it
+ */
+ if (num_refs[curEntry.value] == 0)
+ break;
+ }
+ }
+ }
+ while (changed);
+
+ /* Now we can start recovery */
+ files = reclaimed = 0;
+ for (i = 2; i < total_num_clusters; i++)
+ /* If this cluster is the head of an orphan chain... */
+ if (get_owner(fs, i) == &orphan && !num_refs[i]) {
+ DIR_ENT de;
+ loff_t offset;
+ files++;
+ offset = alloc_rootdir_entry(fs, &de, "FSCK%04dREC");
+ de.start = htole16(i & 0xffff);
+ if (fs->fat_bits == 32)
+ de.starthi = htole16(i >> 16);
+ for (walk = i; walk > 0 && walk != -1;
+ walk = next_cluster(fs, walk)) {
+ de.size = htole32(le32toh(de.size) + fs->cluster_size);
+ reclaimed++;
+ }
+ fs_write(offset, sizeof(DIR_ENT), &de);
+ }
+ if (reclaimed)
+ printf("Reclaimed %d unused cluster%s (%llu bytes) in %d chain%s.\n",
+ reclaimed, reclaimed == 1 ? "" : "s",
+ (unsigned long long)reclaimed * fs->cluster_size, files,
+ files == 1 ? "" : "s");
+
+ free(num_refs);
+}
+
+uint32_t update_free(DOS_FS * fs)
+{
+ uint32_t i;
+ uint32_t free = 0;
+ int do_set = 0;
+
+ for (i = 2; i < fs->clusters + 2; i++) {
+ FAT_ENTRY curEntry;
+ get_fat(&curEntry, fs->fat, i, fs);
+
+ if (!get_owner(fs, i) && !FAT_IS_BAD(fs, curEntry.value))
+ ++free;
+ }
+
+ if (!fs->fsinfo_start)
+ return free;
+
+ if (verbose)
+ printf("Checking free cluster summary.\n");
+ if (fs->free_clusters != 0xFFFFFFFF) {
+ if (free != fs->free_clusters) {
+ printf("Free cluster summary wrong (%ld vs. really %ld)\n",
+ (long)fs->free_clusters, (long)free);
+ if (interactive)
+ printf("1) Correct\n2) Don't correct\n");
+ else
+ printf(" Auto-correcting.\n");
+ if (!interactive || get_key("12", "?") == '1')
+ do_set = 1;
+ }
+ } else {
+ printf("Free cluster summary uninitialized (should be %ld)\n", (long)free);
+ if (rw) {
+ if (interactive)
+ printf("1) Set it\n2) Leave it uninitialized\n");
+ else
+ printf(" Auto-setting.\n");
+ if (!interactive || get_key("12", "?") == '1')
+ do_set = 1;
+ }
+ }
+
+ if (do_set) {
+ uint32_t le_free = htole32(free);
+ fs->free_clusters = free;
+ fs_write(fs->fsinfo_start + offsetof(struct info_sector, free_clusters),
+ sizeof(le_free), &le_free);
+ }
+
+ return free;
+}
diff --git a/dosfstools/src/fat.h b/dosfstools/src/fat.h
new file mode 100644
index 000000000..b50ed4a96
--- /dev/null
+++ b/dosfstools/src/fat.h
@@ -0,0 +1,85 @@
+/* fat.h - Read/write access to the FAT
+
+ Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
+ Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ THe complete text of the GNU General Public License
+ can be found in /usr/share/common-licenses/GPL-3 file.
+*/
+
+#ifndef _FAT_H
+#define _FAT_H
+
+void read_fat(DOS_FS * fs);
+
+/* Loads the FAT of the filesystem described by FS. Initializes the FAT,
+ replaces broken FATs and rejects invalid cluster entries. */
+
+void get_fat(FAT_ENTRY * entry, void *fat, uint32_t cluster, DOS_FS * fs);
+
+/* Retrieve the FAT entry (next chained cluster) for CLUSTER. */
+
+void set_fat(DOS_FS * fs, uint32_t cluster, int32_t new);
+
+/* Changes the value of the CLUSTERth cluster of the FAT of FS to NEW. Special
+ values of NEW are -1 (EOF, 0xff8 or 0xfff8) and -2 (bad sector, 0xff7 or
+ 0xfff7) */
+
+int bad_cluster(DOS_FS * fs, uint32_t cluster);
+
+/* Returns a non-zero integer if the CLUSTERth cluster is marked as bad or zero
+ otherwise. */
+
+uint32_t next_cluster(DOS_FS * fs, uint32_t cluster);
+
+/* Returns the number of the cluster following CLUSTER, or -1 if this is the
+ last cluster of the respective cluster chain. CLUSTER must not be a bad
+ cluster. */
+
+loff_t cluster_start(DOS_FS * fs, uint32_t cluster);
+
+/* Returns the byte offset of CLUSTER, relative to the respective device. */
+
+void set_owner(DOS_FS * fs, uint32_t cluster, DOS_FILE * owner);
+
+/* Sets the owner pointer of the respective cluster to OWNER. If OWNER was NULL
+ before, it can be set to NULL or any non-NULL value. Otherwise, only NULL is
+ accepted as the new value. */
+
+DOS_FILE *get_owner(DOS_FS * fs, uint32_t cluster);
+
+/* Returns the owner of the repective cluster or NULL if the cluster has no
+ owner. */
+
+void fix_bad(DOS_FS * fs);
+
+/* Scans the disk for currently unused bad clusters and marks them as bad. */
+
+void reclaim_free(DOS_FS * fs);
+
+/* Marks all allocated, but unused clusters as free. */
+
+void reclaim_file(DOS_FS * fs);
+
+/* Scans the FAT for chains of allocated, but unused clusters and creates files
+ for them in the root directory. Also tries to fix all inconsistencies (e.g.
+ loops, shared clusters, etc.) in the process. */
+
+uint32_t update_free(DOS_FS * fs);
+
+/* Updates free cluster count in FSINFO sector. */
+
+#endif
diff --git a/dosfstools/src/fatlabel.c b/dosfstools/src/fatlabel.c
new file mode 100644
index 000000000..1484ba527
--- /dev/null
+++ b/dosfstools/src/fatlabel.c
@@ -0,0 +1,144 @@
+/* fatlabel.c - User interface
+
+ Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
+ Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
+ Copyright (C) 2007 Red Hat, Inc.
+ Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ The complete text of the GNU General Public License
+ can be found in /usr/share/common-licenses/GPL-3 file.
+*/
+
+#include "version.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <ctype.h>
+
+#include "common.h"
+#include "fsck.fat.h"
+#include "io.h"
+#include "boot.h"
+#include "fat.h"
+#include "file.h"
+#include "check.h"
+
+int interactive = 0, rw = 0, list = 0, test = 0, verbose = 0, write_immed = 0;
+int atari_format = 0;
+unsigned n_files = 0;
+void *mem_queue = NULL;
+
+static void usage(int error)
+{
+ FILE *f = error ? stderr : stdout;
+ int status = error ? 1 : 0;
+
+ fprintf(f, "usage: fatlabel device [label]\n");
+ exit(status);
+}
+
+/*
+ * ++roman: On m68k, check if this is an Atari; if yes, turn on Atari variant
+ * of MS-DOS filesystem by default.
+ */
+static void check_atari(void)
+{
+#ifdef __mc68000__
+ FILE *f;
+ char line[128], *p;
+
+ if (!(f = fopen("/proc/hardware", "r"))) {
+ perror("/proc/hardware");
+ return;
+ }
+
+ while (fgets(line, sizeof(line), f)) {
+ if (strncmp(line, "Model:", 6) == 0) {
+ p = line + 6;
+ p += strspn(p, " \t");
+ if (strncmp(p, "Atari ", 6) == 0)
+ atari_format = 1;
+ break;
+ }
+ }
+ fclose(f);
+#endif
+}
+
+int main(int argc, char *argv[])
+{
+ DOS_FS fs = { 0 };
+ rw = 0;
+
+ int i;
+
+ char *device = NULL;
+ char label[12] = { 0 };
+
+ loff_t offset;
+ DIR_ENT de;
+
+ check_atari();
+
+ if (argc < 2 || argc > 3)
+ usage(1);
+
+ if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
+ usage(0);
+ else if (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")) {
+ printf("fatlabel " VERSION " (" VERSION_DATE ")\n");
+ exit(0);
+ }
+
+ device = argv[1];
+ if (argc == 3) {
+ strncpy(label, argv[2], 11);
+ if (strlen(argv[2]) > 11) {
+ fprintf(stderr,
+ "fatlabel: labels can be no longer than 11 characters\n");
+ exit(1);
+ }
+ for (i = 0; label[i] && i < 11; i++)
+ /* don't know if here should be more strict !uppercase(label[i]) */
+ if (islower(label[i])) {
+ fprintf(stderr,
+ "fatlabel: warning - lowercase labels might not work properly with DOS or Windows\n");
+ break;
+ }
+ rw = 1;
+ }
+
+ fs_open(device, rw);
+ read_boot(&fs);
+ if (fs.fat_bits == 32)
+ read_fat(&fs);
+ if (!rw) {
+ offset = find_volume_de(&fs, &de);
+ if (offset == 0)
+ fprintf(stdout, "%s\n", fs.label);
+ else
+ fprintf(stdout, "%.8s%.3s\n", de.name, de.ext);
+ exit(0);
+ }
+
+ write_label(&fs, label);
+ fs_close(rw);
+ return 0;
+}
diff --git a/dosfstools/src/file.c b/dosfstools/src/file.c
new file mode 100644
index 000000000..dffcec1cd
--- /dev/null
+++ b/dosfstools/src/file.c
@@ -0,0 +1,276 @@
+/* file.c - Additional file attributes
+
+ Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
+ Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
+ Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ The complete text of the GNU General Public License
+ can be found in /usr/share/common-licenses/GPL-3 file.
+*/
+
+/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
+ * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "file.h"
+#include "msdos_fs.h"
+
+FDSC *fp_root = NULL;
+
+static void put_char(char **p, unsigned char c)
+{
+ if ((c >= ' ' && c < 0x7f) || c >= 0xa0)
+ *(*p)++ = c;
+ else {
+ *(*p)++ = '\\';
+ *(*p)++ = '0' + (c >> 6);
+ *(*p)++ = '0' + ((c >> 3) & 7);
+ *(*p)++ = '0' + (c & 7);
+ }
+}
+
+/**
+ * Construct the "pretty-printed" representation of the name in a short directory entry.
+ *
+ * @param[in] fixed Pointer to name[0] of a DIR_ENT
+ *
+ * @return Pointer to static string containing pretty "8.3" equivalent of the
+ * name in the directory entry.
+ */
+char *file_name(unsigned char *fixed)
+{
+ static char path[MSDOS_NAME * 4 + 2];
+ char *p;
+ int i, j;
+
+ p = path;
+ for (i = j = 0; i < 8; i++)
+ if (fixed[i] != ' ') {
+ while (j++ < i)
+ *p++ = ' ';
+ put_char(&p, fixed[i]);
+ }
+ if (strncmp((const char *)(fixed + 8), " ", 3)) {
+ *p++ = '.';
+ for (i = j = 0; i < 3; i++)
+ if (fixed[i + 8] != ' ') {
+ while (j++ < i)
+ *p++ = ' ';
+ put_char(&p, fixed[i + 8]);
+ }
+ }
+ *p = 0;
+ return path;
+}
+
+int file_cvt(unsigned char *name, unsigned char *fixed)
+{
+ unsigned char c;
+ int size, ext, cnt;
+
+ size = 8;
+ ext = 0;
+ while (*name) {
+ c = *name;
+ if (c < ' ' || c > 0x7e || strchr("*?<>|\"/", c)) {
+ printf("Invalid character in name. Use \\ooo for special "
+ "characters.\n");
+ return 0;
+ }
+ if (c == '.') {
+ if (ext) {
+ printf("Duplicate dots in name.\n");
+ return 0;
+ }
+ while (size--)
+ *fixed++ = ' ';
+ size = 3;
+ ext = 1;
+ name++;
+ continue;
+ }
+ if (c == '\\') {
+ c = 0;
+ for (cnt = 3; cnt; cnt--) {
+ if (*name < '0' || *name > '7') {
+ printf("Invalid octal character.\n");
+ return 0;
+ }
+ c = c * 8 + *name++ - '0';
+ }
+ if (cnt < 4) {
+ printf("Expected three octal digits.\n");
+ return 0;
+ }
+ name += 3;
+ }
+ if (islower(c))
+ c = toupper(c);
+ if (size) {
+ *fixed++ = c;
+ size--;
+ }
+ name++;
+ }
+ if (*name || size == 8)
+ return 0;
+ if (!ext) {
+ while (size--)
+ *fixed++ = ' ';
+ size = 3;
+ }
+ while (size--)
+ *fixed++ = ' ';
+ return 1;
+}
+
+void file_add(char *path, FD_TYPE type)
+{
+ FDSC **current, *walk;
+ char name[MSDOS_NAME];
+ char *here;
+
+ current = &fp_root;
+ if (*path != '/')
+ die("%s: Absolute path required.", path);
+ path++;
+ while (1) {
+ if ((here = strchr(path, '/')))
+ *here = 0;
+ if (!file_cvt((unsigned char *)path, (unsigned char *)name))
+ exit(2);
+ for (walk = *current; walk; walk = walk->next)
+ if (!here && (!strncmp(name, walk->name, MSDOS_NAME) || (type ==
+ fdt_undelete
+ &&
+ !strncmp
+ (name + 1,
+ walk->name
+ + 1,
+ MSDOS_NAME
+ - 1))))
+ die("Ambiguous name: \"%s\"", path);
+ else if (here && !strncmp(name, walk->name, MSDOS_NAME))
+ break;
+ if (!walk) {
+ walk = alloc(sizeof(FDSC));
+ strncpy(walk->name, name, MSDOS_NAME);
+ walk->type = here ? fdt_none : type;
+ walk->first = NULL;
+ walk->next = *current;
+ *current = walk;
+ }
+ current = &walk->first;
+ if (!here)
+ break;
+ *here = '/';
+ path = here + 1;
+ }
+}
+
+FDSC **file_cd(FDSC ** curr, char *fixed)
+{
+ FDSC **walk;
+
+ if (!curr || !*curr)
+ return NULL;
+ for (walk = curr; *walk; walk = &(*walk)->next)
+ if (!strncmp((*walk)->name, fixed, MSDOS_NAME) && (*walk)->first)
+ return &(*walk)->first;
+ return NULL;
+}
+
+static FDSC **file_find(FDSC ** dir, char *fixed)
+{
+ if (!dir || !*dir)
+ return NULL;
+ if (*(unsigned char *)fixed == DELETED_FLAG) {
+ while (*dir) {
+ if (!strncmp((*dir)->name + 1, fixed + 1, MSDOS_NAME - 1)
+ && !(*dir)->first)
+ return dir;
+ dir = &(*dir)->next;
+ }
+ return NULL;
+ }
+ while (*dir) {
+ if (!strncmp((*dir)->name, fixed, MSDOS_NAME) && !(*dir)->first)
+ return dir;
+ dir = &(*dir)->next;
+ }
+ return NULL;
+}
+
+/* Returns the attribute of the file FIXED in directory CURR or FDT_NONE if no
+ such file exists or if CURR is NULL. */
+FD_TYPE file_type(FDSC ** curr, char *fixed)
+{
+ FDSC **this;
+
+ if ((this = file_find(curr, fixed)))
+ return (*this)->type;
+ return fdt_none;
+}
+
+void file_modify(FDSC ** curr, char *fixed)
+{
+ FDSC **this, *next;
+
+ if (!(this = file_find(curr, fixed)))
+ die("Internal error: file_find failed");
+ switch ((*this)->type) {
+ case fdt_drop:
+ printf("Dropping %s\n", file_name((unsigned char *)fixed));
+ *(unsigned char *)fixed = DELETED_FLAG;
+ break;
+ case fdt_undelete:
+ *fixed = *(*this)->name;
+ printf("Undeleting %s\n", file_name((unsigned char *)fixed));
+ break;
+ default:
+ die("Internal error: file_modify");
+ }
+ next = (*this)->next;
+ free(*this);
+ *this = next;
+}
+
+static void report_unused(FDSC * this)
+{
+ FDSC *next;
+
+ while (this) {
+ next = this->next;
+ if (this->first)
+ report_unused(this->first);
+ else if (this->type != fdt_none)
+ printf("Warning: did not %s file %s\n", this->type == fdt_drop ?
+ "drop" : "undelete", file_name((unsigned char *)this->name));
+ free(this);
+ this = next;
+ }
+}
+
+void file_unused(void)
+{
+ report_unused(fp_root);
+}
diff --git a/dosfstools/src/file.h b/dosfstools/src/file.h
new file mode 100644
index 000000000..eaaf356be
--- /dev/null
+++ b/dosfstools/src/file.h
@@ -0,0 +1,72 @@
+/* file.h - Additional file attributes
+
+ Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
+ Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ The complete text of the GNU General Public License
+ can be found in /usr/share/common-licenses/GPL-3 file.
+*/
+
+#ifndef _FILE_H
+#define _FILE_H
+
+#include "msdos_fs.h"
+
+typedef enum { fdt_none, fdt_drop, fdt_undelete } FD_TYPE;
+
+typedef struct _fptr {
+ char name[MSDOS_NAME];
+ FD_TYPE type;
+ struct _fptr *first; /* first entry */
+ struct _fptr *next; /* next file in directory */
+} FDSC;
+
+extern FDSC *fp_root;
+
+char *file_name(unsigned char *fixed);
+
+/* Returns a pointer to a pretty-printed representation of a fixed MS-DOS file
+ name. */
+
+int file_cvt(unsigned char *name, unsigned char *fixed);
+
+/* Converts a pretty-printed file name to the fixed MS-DOS format. Returns a
+ non-zero integer on success, zero on failure. */
+
+void file_add(char *path, FD_TYPE type);
+
+/* Define special attributes for a path. TYPE can be either FDT_DROP or
+ FDT_UNDELETE. */
+
+FDSC **file_cd(FDSC ** curr, char *fixed);
+
+/* Returns a pointer to the directory descriptor of the subdirectory FIXED of
+ CURR, or NULL if no such subdirectory exists. */
+
+FD_TYPE file_type(FDSC ** curr, char *fixed);
+
+/* Returns the attribute of the file FIXED in directory CURR or FDT_NONE if no
+ such file exists or if CURR is NULL. */
+
+void file_modify(FDSC ** curr, char *fixed);
+
+/* Performs the necessary operation on the entry of CURR that is named FIXED. */
+
+void file_unused(void);
+
+/* Displays warnings for all unused file attributes. */
+
+#endif
diff --git a/dosfstools/src/fsck.fat.c b/dosfstools/src/fsck.fat.c
new file mode 100644
index 000000000..2bc3dc216
--- /dev/null
+++ b/dosfstools/src/fsck.fat.c
@@ -0,0 +1,215 @@
+/* fsck.fat.c - User interface
+
+ Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
+ Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
+ Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ The complete text of the GNU General Public License
+ can be found in /usr/share/common-licenses/GPL-3 file.
+*/
+
+/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
+ * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
+
+#include "version.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#include "common.h"
+#include "fsck.fat.h"
+#include "io.h"
+#include "boot.h"
+#include "fat.h"
+#include "file.h"
+#include "check.h"
+
+int interactive = 0, rw = 0, list = 0, test = 0, verbose = 0, write_immed = 0;
+int atari_format = 0, boot_only = 0;
+unsigned n_files = 0;
+void *mem_queue = NULL;
+
+static void usage(char *name)
+{
+ fprintf(stderr, "usage: %s [-aAbflrtvVwy] [-d path -d ...] "
+ "[-u path -u ...]\n%15sdevice\n", name, "");
+ fprintf(stderr, " -a automatically repair the filesystem\n");
+ fprintf(stderr, " -A toggle Atari filesystem format\n");
+ fprintf(stderr, " -b make read-only boot sector check\n");
+ fprintf(stderr, " -d path drop that file\n");
+ fprintf(stderr, " -f salvage unused chains to files\n");
+ fprintf(stderr, " -l list path names\n");
+ fprintf(stderr,
+ " -n no-op, check non-interactively without changing\n");
+ fprintf(stderr, " -p same as -a, for compat with other *fsck\n");
+ fprintf(stderr, " -r interactively repair the filesystem (default)\n");
+ fprintf(stderr, " -t test for bad clusters\n");
+ fprintf(stderr, " -u path try to undelete that (non-directory) file\n");
+ fprintf(stderr, " -v verbose mode\n");
+ fprintf(stderr, " -V perform a verification pass\n");
+ fprintf(stderr, " -w write changes to disk immediately\n");
+ fprintf(stderr, " -y same as -a, for compat with other *fsck\n");
+ exit(2);
+}
+
+/*
+ * ++roman: On m68k, check if this is an Atari; if yes, turn on Atari variant
+ * of MS-DOS filesystem by default.
+ */
+static void check_atari(void)
+{
+#ifdef __mc68000__
+ FILE *f;
+ char line[128], *p;
+
+ if (!(f = fopen("/proc/hardware", "r"))) {
+ perror("/proc/hardware");
+ return;
+ }
+
+ while (fgets(line, sizeof(line), f)) {
+ if (strncmp(line, "Model:", 6) == 0) {
+ p = line + 6;
+ p += strspn(p, " \t");
+ if (strncmp(p, "Atari ", 6) == 0)
+ atari_format = 1;
+ break;
+ }
+ }
+ fclose(f);
+#endif
+}
+
+int main(int argc, char **argv)
+{
+ DOS_FS fs;
+ int salvage_files, verify, c;
+ uint32_t free_clusters = 0;
+
+ memset(&fs, 0, sizeof(fs));
+ salvage_files = verify = 0;
+ rw = interactive = 1;
+ check_atari();
+
+ while ((c = getopt(argc, argv, "Aad:bflnprtu:vVwy")) != -1)
+ switch (c) {
+ case 'A': /* toggle Atari format */
+ atari_format = !atari_format;
+ break;
+ case 'a':
+ case 'p':
+ case 'y':
+ rw = 1;
+ interactive = 0;
+ salvage_files = 1;
+ break;
+ case 'b':
+ rw = 0;
+ interactive = 0;
+ boot_only = 1;
+ break;
+ case 'd':
+ file_add(optarg, fdt_drop);
+ break;
+ case 'f':
+ salvage_files = 1;
+ break;
+ case 'l':
+ list = 1;
+ break;
+ case 'n':
+ rw = 0;
+ interactive = 0;
+ break;
+ case 'r':
+ rw = 1;
+ interactive = 1;
+ break;
+ case 't':
+ test = 1;
+ break;
+ case 'u':
+ file_add(optarg, fdt_undelete);
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 'V':
+ verify = 1;
+ break;
+ case 'w':
+ write_immed = 1;
+ break;
+ default:
+ usage(argv[0]);
+ }
+ if ((test || write_immed) && !rw) {
+ fprintf(stderr, "-t and -w can not be used in read only mode\n");
+ exit(2);
+ }
+ if (optind != argc - 1)
+ usage(argv[0]);
+
+ printf("fsck.fat " VERSION " (" VERSION_DATE ")\n");
+ fs_open(argv[optind], rw);
+
+ read_boot(&fs);
+ if (boot_only)
+ goto exit;
+
+ if (verify)
+ printf("Starting check/repair pass.\n");
+ while (read_fat(&fs), scan_root(&fs))
+ qfree(&mem_queue);
+ if (test)
+ fix_bad(&fs);
+ if (salvage_files)
+ reclaim_file(&fs);
+ else
+ reclaim_free(&fs);
+ free_clusters = update_free(&fs);
+ file_unused();
+ qfree(&mem_queue);
+ if (verify) {
+ n_files = 0;
+ printf("Starting verification pass.\n");
+ read_fat(&fs);
+ scan_root(&fs);
+ reclaim_free(&fs);
+ qfree(&mem_queue);
+ }
+
+exit:
+ if (fs_changed()) {
+ if (rw) {
+ if (interactive)
+ rw = get_key("yn", "Perform changes ? (y/n)") == 'y';
+ else
+ printf("Performing changes.\n");
+ } else
+ printf("Leaving filesystem unchanged.\n");
+ }
+
+ if (!boot_only)
+ printf("%s: %u files, %lu/%lu clusters\n", argv[optind],
+ n_files, (unsigned long)fs.clusters - free_clusters, (unsigned long)fs.clusters);
+
+ return fs_close(rw) ? 1 : 0;
+}
diff --git a/dosfstools/src/fsck.fat.h b/dosfstools/src/fsck.fat.h
new file mode 100644
index 000000000..e5f617871
--- /dev/null
+++ b/dosfstools/src/fsck.fat.h
@@ -0,0 +1,191 @@
+/* fsck.fat.h - Common data structures and global variables
+
+ Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
+ Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
+ Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ The complete text of the GNU General Public License
+ can be found in /usr/share/common-licenses/GPL-3 file.
+*/
+
+/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
+ * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
+
+#ifndef _DOSFSCK_H
+#define _DOSFSCK_H
+
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <endian.h>
+
+#include "msdos_fs.h"
+
+#define VFAT_LN_ATTR (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME)
+
+#define FAT_STATE_DIRTY 0x01
+
+/* ++roman: Use own definition of boot sector structure -- the kernel headers'
+ * name for it is msdos_boot_sector in 2.0 and fat_boot_sector in 2.1 ... */
+struct boot_sector {
+ uint8_t ignored[3]; /* Boot strap short or near jump */
+ uint8_t system_id[8]; /* Name - can be used to special case
+ partition manager volumes */
+ uint8_t sector_size[2]; /* bytes per logical sector */
+ uint8_t cluster_size; /* sectors/cluster */
+ uint16_t reserved; /* reserved sectors */
+ uint8_t fats; /* number of FATs */
+ uint8_t dir_entries[2]; /* root directory entries */
+ uint8_t sectors[2]; /* number of sectors */
+ uint8_t media; /* media code (unused) */
+ uint16_t fat_length; /* sectors/FAT */
+ uint16_t secs_track; /* sectors per track */
+ uint16_t heads; /* number of heads */
+ uint32_t hidden; /* hidden sectors (unused) */
+ uint32_t total_sect; /* number of sectors (if sectors == 0) */
+
+ /* The following fields are only used by FAT32 */
+ uint32_t fat32_length; /* sectors/FAT */
+ uint16_t flags; /* bit 8: fat mirroring, low 4: active fat */
+ uint8_t version[2]; /* major, minor filesystem version */
+ uint32_t root_cluster; /* first cluster in root directory */
+ uint16_t info_sector; /* filesystem info sector */
+ uint16_t backup_boot; /* backup boot sector */
+ uint8_t reserved2[12]; /* Unused */
+
+ uint8_t drive_number; /* Logical Drive Number */
+ uint8_t reserved3; /* Unused */
+
+ uint8_t extended_sig; /* Extended Signature (0x29) */
+ uint32_t serial; /* Serial number */
+ uint8_t label[11]; /* FS label */
+ uint8_t fs_type[8]; /* FS Type */
+
+ /* fill up to 512 bytes */
+ uint8_t junk[422];
+} __attribute__ ((packed));
+
+struct boot_sector_16 {
+ uint8_t ignored[3]; /* Boot strap short or near jump */
+ uint8_t system_id[8]; /* Name - can be used to special case
+ partition manager volumes */
+ uint8_t sector_size[2]; /* bytes per logical sector */
+ uint8_t cluster_size; /* sectors/cluster */
+ uint16_t reserved; /* reserved sectors */
+ uint8_t fats; /* number of FATs */
+ uint8_t dir_entries[2]; /* root directory entries */
+ uint8_t sectors[2]; /* number of sectors */
+ uint8_t media; /* media code (unused) */
+ uint16_t fat_length; /* sectors/FAT */
+ uint16_t secs_track; /* sectors per track */
+ uint16_t heads; /* number of heads */
+ uint32_t hidden; /* hidden sectors (unused) */
+ uint32_t total_sect; /* number of sectors (if sectors == 0) */
+
+ uint8_t drive_number; /* Logical Drive Number */
+ uint8_t reserved2; /* Unused */
+
+ uint8_t extended_sig; /* Extended Signature (0x29) */
+ uint32_t serial; /* Serial number */
+ uint8_t label[11]; /* FS label */
+ uint8_t fs_type[8]; /* FS Type */
+
+ /* fill up to 512 bytes */
+ uint8_t junk[450];
+} __attribute__ ((packed));
+
+struct info_sector {
+ uint32_t magic; /* Magic for info sector ('RRaA') */
+ uint8_t junk[0x1dc];
+ uint32_t reserved1; /* Nothing as far as I can tell */
+ uint32_t signature; /* 0x61417272 ('rrAa') */
+ uint32_t free_clusters; /* Free cluster count. -1 if unknown */
+ uint32_t next_cluster; /* Most recently allocated cluster. */
+ uint32_t reserved2[3];
+ uint16_t reserved3;
+ uint16_t boot_sign;
+};
+
+typedef struct {
+ uint8_t name[8], ext[3]; /* name and extension */
+ uint8_t attr; /* attribute bits */
+ uint8_t lcase; /* Case for base and extension */
+ uint8_t ctime_ms; /* Creation time, milliseconds */
+ uint16_t ctime; /* Creation time */
+ uint16_t cdate; /* Creation date */
+ uint16_t adate; /* Last access date */
+ uint16_t starthi; /* High 16 bits of cluster in FAT32 */
+ uint16_t time, date, start; /* time, date and first cluster */
+ uint32_t size; /* file size (in bytes) */
+} __attribute__ ((packed)) DIR_ENT;
+
+typedef struct _dos_file {
+ DIR_ENT dir_ent;
+ char *lfn;
+ loff_t offset;
+ loff_t lfn_offset;
+ struct _dos_file *parent; /* parent directory */
+ struct _dos_file *next; /* next entry */
+ struct _dos_file *first; /* first entry (directory only) */
+} DOS_FILE;
+
+typedef struct {
+ uint32_t value;
+ uint32_t reserved;
+} FAT_ENTRY;
+
+typedef struct {
+ int nfats;
+ loff_t fat_start;
+ unsigned int fat_size; /* unit is bytes */
+ unsigned int fat_bits; /* size of a FAT entry */
+ unsigned int eff_fat_bits; /* # of used bits in a FAT entry */
+ uint32_t root_cluster; /* 0 for old-style root dir */
+ loff_t root_start;
+ unsigned int root_entries;
+ loff_t data_start;
+ unsigned int cluster_size;
+ uint32_t clusters;
+ loff_t fsinfo_start; /* 0 if not present */
+ long free_clusters;
+ loff_t backupboot_start; /* 0 if not present */
+ unsigned char *fat;
+ DOS_FILE **cluster_owner;
+ char *label;
+} DOS_FS;
+
+extern int interactive, rw, list, verbose, test, write_immed;
+extern int atari_format;
+extern unsigned n_files;
+extern void *mem_queue;
+
+/* value to use as end-of-file marker */
+#define FAT_EOF(fs) ((atari_format ? 0xfff : 0xff8) | FAT_EXTD(fs))
+#define FAT_IS_EOF(fs,v) ((uint32_t)(v) >= (0xff8|FAT_EXTD(fs)))
+/* value to mark bad clusters */
+#define FAT_BAD(fs) (0xff7 | FAT_EXTD(fs))
+/* range of values used for bad clusters */
+#define FAT_MIN_BAD(fs) ((atari_format ? 0xff0 : 0xff7) | FAT_EXTD(fs))
+#define FAT_MAX_BAD(fs) ((atari_format ? 0xff7 : 0xff7) | FAT_EXTD(fs))
+#define FAT_IS_BAD(fs,v) ((v) >= FAT_MIN_BAD(fs) && (v) <= FAT_MAX_BAD(fs))
+
+/* return -16 as a number with fs->fat_bits bits */
+#define FAT_EXTD(fs) (((1 << fs->eff_fat_bits)-1) & ~0xf)
+
+/* marker for files with no 8.3 name */
+#define FAT_NO_83NAME 32
+
+#endif
diff --git a/dosfstools/src/io.c b/dosfstools/src/io.c
new file mode 100644
index 000000000..450432c8e
--- /dev/null
+++ b/dosfstools/src/io.c
@@ -0,0 +1,232 @@
+/* io.c - Virtual disk input/output
+
+ Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
+ Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
+ Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ The complete text of the GNU General Public License
+ can be found in /usr/share/common-licenses/GPL-3 file.
+*/
+
+/*
+ * Thu Feb 26 01:15:36 CET 1998: Martin Schulze <joey@infodrom.north.de>
+ * Fixed nasty bug that caused every file with a name like
+ * xxxxxxxx.xxx to be treated as bad name that needed to be fixed.
+ */
+
+/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
+ * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
+
+#define _LARGEFILE64_SOURCE
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/fd.h>
+
+#include "fsck.fat.h"
+#include "common.h"
+#include "io.h"
+
+typedef struct _change {
+ void *data;
+ loff_t pos;
+ int size;
+ struct _change *next;
+} CHANGE;
+
+static CHANGE *changes, *last;
+static int fd, did_change = 0;
+
+unsigned device_no;
+
+#ifdef __DJGPP__
+#include "volume.h" /* DOS lowlevel disk access functions */
+loff_t llseek(int fd, loff_t offset, int whence)
+{
+ if ((whence != SEEK_SET) || (fd == 4711))
+ return -1; /* only those supported */
+ return VolumeSeek(offset);
+}
+
+#define open OpenVolume
+#define close CloseVolume
+#define read(a,b,c) ReadVolume(b,c)
+#define write(a,b,c) WriteVolume(b,c)
+#else
+loff_t llseek(int fd, loff_t offset, int whence)
+{
+ return (loff_t) lseek64(fd, (off64_t) offset, whence);
+}
+#endif
+
+void fs_open(char *path, int rw)
+{
+ struct stat stbuf;
+
+ if ((fd = open(path, rw ? O_RDWR : O_RDONLY)) < 0) {
+ perror("open");
+ exit(6);
+ }
+ changes = last = NULL;
+ did_change = 0;
+
+#ifndef _DJGPP_
+ if (fstat(fd, &stbuf) < 0)
+ pdie("fstat %s", path);
+ device_no = S_ISBLK(stbuf.st_mode) ? (stbuf.st_rdev >> 8) & 0xff : 0;
+#else
+ if (IsWorkingOnImageFile()) {
+ if (fstat(GetVolumeHandle(), &stbuf) < 0)
+ pdie("fstat image %s", path);
+ device_no = 0;
+ } else {
+ /* return 2 for floppy, 1 for ramdisk, 7 for loopback */
+ /* used by boot.c in Atari mode: floppy always FAT12, */
+ /* loopback / ramdisk only FAT12 if usual floppy size, */
+ /* harddisk always FAT16 on Atari... */
+ device_no = (GetVolumeHandle() < 2) ? 2 : 1;
+ /* telling "floppy" for A:/B:, "ramdisk" for the rest */
+ }
+#endif
+}
+
+/**
+ * Read data from the partition, accounting for any pending updates that are
+ * queued for writing.
+ *
+ * @param[in] pos Byte offset, relative to the beginning of the partition,
+ * at which to read
+ * @param[in] size Number of bytes to read
+ * @param[out] data Where to put the data read
+ */
+void fs_read(loff_t pos, int size, void *data)
+{
+ CHANGE *walk;
+ int got;
+
+ if (llseek(fd, pos, 0) != pos)
+ pdie("Seek to %lld", pos);
+ if ((got = read(fd, data, size)) < 0)
+ pdie("Read %d bytes at %lld", size, pos);
+ if (got != size)
+ die("Got %d bytes instead of %d at %lld", got, size, pos);
+ for (walk = changes; walk; walk = walk->next) {
+ if (walk->pos < pos + size && walk->pos + walk->size > pos) {
+ if (walk->pos < pos)
+ memcpy(data, (char *)walk->data + pos - walk->pos, min(size,
+ walk->
+ size -
+ pos +
+ walk->
+ pos));
+ else
+ memcpy((char *)data + walk->pos - pos, walk->data,
+ min(walk->size, size + pos - walk->pos));
+ }
+ }
+}
+
+int fs_test(loff_t pos, int size)
+{
+ void *scratch;
+ int okay;
+
+ if (llseek(fd, pos, 0) != pos)
+ pdie("Seek to %lld", pos);
+ scratch = alloc(size);
+ okay = read(fd, scratch, size) == size;
+ free(scratch);
+ return okay;
+}
+
+void fs_write(loff_t pos, int size, void *data)
+{
+ CHANGE *new;
+ int did;
+
+ if (write_immed) {
+ did_change = 1;
+ if (llseek(fd, pos, 0) != pos)
+ pdie("Seek to %lld", pos);
+ if ((did = write(fd, data, size)) == size)
+ return;
+ if (did < 0)
+ pdie("Write %d bytes at %lld", size, pos);
+ die("Wrote %d bytes instead of %d at %lld", did, size, pos);
+ }
+ new = alloc(sizeof(CHANGE));
+ new->pos = pos;
+ memcpy(new->data = alloc(new->size = size), data, size);
+ new->next = NULL;
+ if (last)
+ last->next = new;
+ else
+ changes = new;
+ last = new;
+}
+
+static void fs_flush(void)
+{
+ CHANGE *this;
+ int size;
+
+ while (changes) {
+ this = changes;
+ changes = changes->next;
+ if (llseek(fd, this->pos, 0) != this->pos)
+ fprintf(stderr,
+ "Seek to %lld failed: %s\n Did not write %d bytes.\n",
+ (long long)this->pos, strerror(errno), this->size);
+ else if ((size = write(fd, this->data, this->size)) < 0)
+ fprintf(stderr, "Writing %d bytes at %lld failed: %s\n", this->size,
+ (long long)this->pos, strerror(errno));
+ else if (size != this->size)
+ fprintf(stderr, "Wrote %d bytes instead of %d bytes at %lld."
+ "\n", size, this->size, (long long)this->pos);
+ free(this->data);
+ free(this);
+ }
+}
+
+int fs_close(int write)
+{
+ CHANGE *next;
+ int changed;
+
+ changed = ! !changes;
+ if (write)
+ fs_flush();
+ else
+ while (changes) {
+ next = changes->next;
+ free(changes->data);
+ free(changes);
+ changes = next;
+ }
+ if (close(fd) < 0)
+ pdie("closing filesystem");
+ return changed || did_change;
+}
+
+int fs_changed(void)
+{
+ return ! !changes || did_change;
+}
diff --git a/dosfstools/src/io.h b/dosfstools/src/io.h
new file mode 100644
index 000000000..d23d07ee3
--- /dev/null
+++ b/dosfstools/src/io.h
@@ -0,0 +1,71 @@
+/* io.h - Virtual disk input/output
+
+ Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
+ Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
+ Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ The complete text of the GNU General Public License
+ can be found in /usr/share/common-licenses/GPL-3 file.
+*/
+
+/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
+ * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
+
+#ifndef _IO_H
+#define _IO_H
+
+#include <fcntl.h> /* for loff_t */
+
+loff_t llseek(int fd, loff_t offset, int whence);
+
+/* lseek() analogue for large offsets. */
+
+void fs_open(char *path, int rw);
+
+/* Opens the filesystem PATH. If RW is zero, the filesystem is opened
+ read-only, otherwise, it is opened read-write. */
+
+void fs_read(loff_t pos, int size, void *data);
+
+/* Reads SIZE bytes starting at POS into DATA. Performs all applicable
+ changes. */
+
+int fs_test(loff_t pos, int size);
+
+/* Returns a non-zero integer if SIZE bytes starting at POS can be read without
+ errors. Otherwise, it returns zero. */
+
+void fs_write(loff_t pos, int size, void *data);
+
+/* If write_immed is non-zero, SIZE bytes are written from DATA to the disk,
+ starting at POS. If write_immed is zero, the change is added to a list in
+ memory. */
+
+int fs_close(int write);
+
+/* Closes the filesystem, performs all pending changes if WRITE is non-zero
+ and removes the list of changes. Returns a non-zero integer if the file
+ system has been changed since the last fs_open, zero otherwise. */
+
+int fs_changed(void);
+
+/* Determines whether the filesystem has changed. See fs_close. */
+
+extern unsigned device_no;
+
+/* Major number of device (0 if file) and size (in 512 byte sectors) */
+
+#endif
diff --git a/dosfstools/src/lfn.c b/dosfstools/src/lfn.c
new file mode 100644
index 000000000..2601172ee
--- /dev/null
+++ b/dosfstools/src/lfn.c
@@ -0,0 +1,528 @@
+/* lfn.c - Functions for handling VFAT long filenames
+
+ Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
+ Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ The complete text of the GNU General Public License
+ can be found in /usr/share/common-licenses/GPL-3 file.
+*/
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <time.h>
+
+#include "common.h"
+#include "io.h"
+#include "fsck.fat.h"
+#include "lfn.h"
+#include "file.h"
+
+typedef struct {
+ uint8_t id; /* sequence number for slot */
+ uint8_t name0_4[10]; /* first 5 characters in name */
+ uint8_t attr; /* attribute byte */
+ uint8_t reserved; /* always 0 */
+ uint8_t alias_checksum; /* checksum for 8.3 alias */
+ uint8_t name5_10[12]; /* 6 more characters in name */
+ uint16_t start; /* starting cluster number, 0 in long slots */
+ uint8_t name11_12[4]; /* last 2 characters in name */
+} LFN_ENT;
+
+#define LFN_ID_START 0x40
+#define LFN_ID_SLOTMASK 0x1f
+
+#define CHARS_PER_LFN 13
+
+/* These modul-global vars represent the state of the LFN parser */
+unsigned char *lfn_unicode = NULL;
+unsigned char lfn_checksum;
+int lfn_slot = -1;
+loff_t *lfn_offsets = NULL;
+int lfn_parts = 0;
+
+static unsigned char fat_uni2esc[64] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
+ 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
+ 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
+ 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
+ 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
+ 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
+ 'u', 'v', 'w', 'x', 'y', 'z', '+', '-'
+};
+
+/* This defines which unicode chars are directly convertable to ISO-8859-1 */
+#define UNICODE_CONVERTABLE(cl,ch) (ch == 0 && (cl < 0x80 || cl >= 0xa0))
+
+/* for maxlen param */
+#define UNTIL_0 INT_MAX
+
+/* Convert name part in 'lfn' from unicode to ASCII */
+#define CNV_THIS_PART(lfn) \
+ ({ \
+ unsigned char __part_uni[CHARS_PER_LFN*2]; \
+ copy_lfn_part( __part_uni, lfn ); \
+ cnv_unicode( __part_uni, CHARS_PER_LFN, 0 ); \
+ })
+
+/* Convert name parts collected so far (from previous slots) from unicode to
+ * ASCII */
+#define CNV_PARTS_SO_FAR() \
+ (cnv_unicode( lfn_unicode+(lfn_slot*CHARS_PER_LFN*2), \
+ lfn_parts*CHARS_PER_LFN, 0 ))
+
+#define BYTES_TO_WCHAR(cl,ch) ((wchar_t)((unsigned)(cl) + ((unsigned)(ch) << 8)))
+static size_t mbslen(wchar_t x)
+{
+ wchar_t wstr[] = { x, 0 };
+ return wcstombs(NULL, wstr, 0);
+}
+
+static size_t wctombs(char *dest, wchar_t x)
+{
+ wchar_t wstr[] = { x, 0 };
+ size_t size = wcstombs(NULL, wstr, 0);
+ if (size != (size_t) - 1)
+ size = wcstombs(dest, wstr, size + 1);
+ return size;
+}
+
+/* This function converts an unicode string to a normal ASCII string, assuming
+ * ISO-8859-1 charset. Characters not in 8859-1 are converted to the same
+ * escape notation as used by the kernel, i.e. the uuencode-like ":xxx" */
+static char *cnv_unicode(const unsigned char *uni, int maxlen, int use_q)
+{
+ const unsigned char *up;
+ unsigned char *out, *cp;
+ int len, val;
+ size_t x;
+
+ for (len = 0, up = uni; (up - uni) / 2 < maxlen && (up[0] || up[1]);
+ up += 2) {
+ if ((x = mbslen(BYTES_TO_WCHAR(up[0], up[1]))) != (size_t) - 1)
+ len += x;
+ else if (UNICODE_CONVERTABLE(up[0], up[1]))
+ ++len;
+ else
+ len += 4;
+ }
+ cp = out = use_q ? qalloc(&mem_queue, len + 1) : alloc(len + 1);
+
+ for (up = uni; (up - uni) / 2 < maxlen && (up[0] || up[1]); up += 2) {
+ if ((x =
+ wctombs((char *)cp, BYTES_TO_WCHAR(up[0], up[1]))) != (size_t) - 1)
+ cp += x;
+ else if (UNICODE_CONVERTABLE(up[0], up[1]))
+ *cp++ = up[0];
+ else {
+ /* here the same escape notation is used as in the Linux kernel */
+ *cp++ = ':';
+ val = (up[1] << 8) + up[0];
+ cp[2] = fat_uni2esc[val & 0x3f];
+ val >>= 6;
+ cp[1] = fat_uni2esc[val & 0x3f];
+ val >>= 6;
+ cp[0] = fat_uni2esc[val & 0x3f];
+ cp += 3;
+ }
+ }
+ *cp = 0;
+
+ return (char *)out;
+}
+
+static void copy_lfn_part(unsigned char *dst, LFN_ENT * lfn)
+{
+ memcpy(dst, lfn->name0_4, 10);
+ memcpy(dst + 10, lfn->name5_10, 12);
+ memcpy(dst + 22, lfn->name11_12, 4);
+}
+
+static void clear_lfn_slots(int start, int end)
+{
+ int i;
+ LFN_ENT empty;
+
+ /* New dir entry is zeroed except first byte, which is set to 0xe5.
+ * This is to avoid that some FAT-reading OSes (not Linux! ;) stop reading
+ * a directory at the first zero entry...
+ */
+ memset(&empty, 0, sizeof(empty));
+ empty.id = DELETED_FLAG;
+
+ for (i = start; i <= end; ++i) {
+ fs_write(lfn_offsets[i], sizeof(LFN_ENT), &empty);
+ }
+}
+
+void lfn_fix_checksum(loff_t from, loff_t to, const char *short_name)
+{
+ int i;
+ uint8_t sum;
+ for (sum = 0, i = 0; i < 11; i++)
+ sum = (((sum & 1) << 7) | ((sum & 0xfe) >> 1)) + short_name[i];
+
+ for (; from < to; from += sizeof(LFN_ENT)) {
+ fs_write(from + offsetof(LFN_ENT, alias_checksum), sizeof(sum), &sum);
+ }
+}
+
+void lfn_reset(void)
+{
+ if (lfn_unicode)
+ free(lfn_unicode);
+ lfn_unicode = NULL;
+ if (lfn_offsets)
+ free(lfn_offsets);
+ lfn_offsets = NULL;
+ lfn_slot = -1;
+}
+
+/* This function is only called with de->attr == VFAT_LN_ATTR. It stores part
+ * of the long name. */
+void lfn_add_slot(DIR_ENT * de, loff_t dir_offset)
+{
+ LFN_ENT *lfn = (LFN_ENT *) de;
+ int slot = lfn->id & LFN_ID_SLOTMASK;
+ unsigned offset;
+
+ if (lfn_slot == 0)
+ lfn_check_orphaned();
+
+ if (de->attr != VFAT_LN_ATTR)
+ die("lfn_add_slot called with non-LFN directory entry");
+
+ if (lfn->id & LFN_ID_START && slot != 0) {
+ if (lfn_slot != -1) {
+ int can_clear = 0;
+ /* There is already a LFN "in progess", so it is an error that a
+ * new start entry is here. */
+ /* Causes: 1) if slot# == expected: start bit set mysteriously, 2)
+ * old LFN overwritten by new one */
+ /* Fixes: 1) delete previous LFN 2) if slot# == expected and
+ * checksum ok: clear start bit */
+ /* XXX: Should delay that until next LFN known (then can better
+ * display the name) */
+ printf("A new long file name starts within an old one.\n");
+ if (slot == lfn_slot && lfn->alias_checksum == lfn_checksum) {
+ char *part1 = CNV_THIS_PART(lfn);
+ char *part2 = CNV_PARTS_SO_FAR();
+ printf(" It could be that the LFN start bit is wrong here\n"
+ " if \"%s\" seems to match \"%s\".\n", part1, part2);
+ free(part1);
+ free(part2);
+ can_clear = 1;
+ }
+ if (interactive) {
+ printf("1: Delete previous LFN\n2: Leave it as it is.\n");
+ if (can_clear)
+ printf("3: Clear start bit and concatenate LFNs\n");
+ } else
+ printf(" Not auto-correcting this.\n");
+ if (interactive) {
+ switch (get_key(can_clear ? "123" : "12", "?")) {
+ case '1':
+ clear_lfn_slots(0, lfn_parts - 1);
+ lfn_reset();
+ break;
+ case '2':
+ break;
+ case '3':
+ lfn->id &= ~LFN_ID_START;
+ fs_write(dir_offset + offsetof(LFN_ENT, id),
+ sizeof(lfn->id), &lfn->id);
+ break;
+ }
+ }
+ }
+ lfn_slot = slot;
+ lfn_checksum = lfn->alias_checksum;
+ lfn_unicode = alloc((lfn_slot * CHARS_PER_LFN + 1) * 2);
+ lfn_offsets = alloc(lfn_slot * sizeof(loff_t));
+ lfn_parts = 0;
+ } else if (lfn_slot == -1 && slot != 0) {
+ /* No LFN in progress, but slot found; start bit missing */
+ /* Causes: 1) start bit got lost, 2) Previous slot with start bit got
+ * lost */
+ /* Fixes: 1) delete LFN, 2) set start bit */
+ char *part = CNV_THIS_PART(lfn);
+ printf("Long filename fragment \"%s\" found outside a LFN "
+ "sequence.\n (Maybe the start bit is missing on the "
+ "last fragment)\n", part);
+ if (interactive) {
+ printf("1: Delete fragment\n2: Leave it as it is.\n"
+ "3: Set start bit\n");
+ } else
+ printf(" Not auto-correcting this.\n");
+ switch (interactive ? get_key("123", "?") : '2') {
+ case '1':
+ if (!lfn_offsets)
+ lfn_offsets = alloc(sizeof(loff_t));
+ lfn_offsets[0] = dir_offset;
+ clear_lfn_slots(0, 0);
+ lfn_reset();
+ return;
+ case '2':
+ lfn_reset();
+ return;
+ case '3':
+ lfn->id |= LFN_ID_START;
+ fs_write(dir_offset + offsetof(LFN_ENT, id),
+ sizeof(lfn->id), &lfn->id);
+ lfn_slot = slot;
+ lfn_checksum = lfn->alias_checksum;
+ lfn_unicode = alloc((lfn_slot * CHARS_PER_LFN + 1) * 2);
+ lfn_offsets = alloc(lfn_slot * sizeof(loff_t));
+ lfn_parts = 0;
+ break;
+ }
+ } else if (slot != lfn_slot) {
+ /* wrong sequence number */
+ /* Causes: 1) seq-no destroyed */
+ /* Fixes: 1) delete LFN, 2) fix number (maybe only if following parts
+ * are ok?, maybe only if checksum is ok?) (Attention: space
+ * for name was allocated before!) */
+ int can_fix = 0;
+ printf("Unexpected long filename sequence number "
+ "(%d vs. expected %d).\n", slot, lfn_slot);
+ if (lfn->alias_checksum == lfn_checksum && lfn_slot > 0) {
+ char *part1 = CNV_THIS_PART(lfn);
+ char *part2 = CNV_PARTS_SO_FAR();
+ printf(" It could be that just the number is wrong\n"
+ " if \"%s\" seems to match \"%s\".\n", part1, part2);
+ free(part1);
+ free(part2);
+ can_fix = 1;
+ }
+ if (interactive) {
+ printf
+ ("1: Delete LFN\n2: Leave it as it is (and ignore LFN so far)\n");
+ if (can_fix)
+ printf("3: Correct sequence number\n");
+ } else
+ printf(" Not auto-correcting this.\n");
+ switch (interactive ? get_key(can_fix ? "123" : "12", "?") : '2') {
+ case '1':
+ if (!lfn_offsets) {
+ lfn_offsets = alloc(sizeof(loff_t));
+ lfn_parts = 0;
+ }
+ lfn_offsets[lfn_parts++] = dir_offset;
+ clear_lfn_slots(0, lfn_parts - 1);
+ lfn_reset();
+ return;
+ case '2':
+ lfn_reset();
+ return;
+ case '3':
+ lfn->id = (lfn->id & ~LFN_ID_SLOTMASK) | lfn_slot;
+ fs_write(dir_offset + offsetof(LFN_ENT, id),
+ sizeof(lfn->id), &lfn->id);
+ break;
+ }
+ }
+
+ if (lfn->alias_checksum != lfn_checksum) {
+ /* checksum mismatch */
+ /* Causes: 1) checksum field here destroyed */
+ /* Fixes: 1) delete LFN, 2) fix checksum */
+ printf("Checksum in long filename part wrong "
+ "(%02x vs. expected %02x).\n",
+ lfn->alias_checksum, lfn_checksum);
+ if (interactive) {
+ printf("1: Delete LFN\n2: Leave it as it is.\n"
+ "3: Correct checksum\n");
+ } else
+ printf(" Not auto-correcting this.\n");
+ if (interactive) {
+ switch (get_key("123", "?")) {
+ case '1':
+ lfn_offsets[lfn_parts++] = dir_offset;
+ clear_lfn_slots(0, lfn_parts - 1);
+ lfn_reset();
+ return;
+ case '2':
+ break;
+ case '3':
+ lfn->alias_checksum = lfn_checksum;
+ fs_write(dir_offset + offsetof(LFN_ENT, alias_checksum),
+ sizeof(lfn->alias_checksum), &lfn->alias_checksum);
+ break;
+ }
+ }
+ }
+
+ if (lfn_slot != -1) {
+ lfn_slot--;
+ offset = lfn_slot * CHARS_PER_LFN * 2;
+ copy_lfn_part(lfn_unicode + offset, lfn);
+ if (lfn->id & LFN_ID_START)
+ lfn_unicode[offset + 26] = lfn_unicode[offset + 27] = 0;
+ lfn_offsets[lfn_parts++] = dir_offset;
+ }
+
+ if (lfn->reserved != 0) {
+ printf("Reserved field in VFAT long filename slot is not 0 "
+ "(but 0x%02x).\n", lfn->reserved);
+ if (interactive)
+ printf("1: Fix.\n2: Leave it.\n");
+ else
+ printf("Auto-setting to 0.\n");
+ if (!interactive || get_key("12", "?") == '1') {
+ lfn->reserved = 0;
+ fs_write(dir_offset + offsetof(LFN_ENT, reserved),
+ sizeof(lfn->reserved), &lfn->reserved);
+ }
+ }
+ if (lfn->start != htole16(0)) {
+ printf("Start cluster field in VFAT long filename slot is not 0 "
+ "(but 0x%04x).\n", lfn->start);
+ if (interactive)
+ printf("1: Fix.\n2: Leave it.\n");
+ else
+ printf("Auto-setting to 0.\n");
+ if (!interactive || get_key("12", "?") == '1') {
+ lfn->start = htole16(0);
+ fs_write(dir_offset + offsetof(LFN_ENT, start),
+ sizeof(lfn->start), &lfn->start);
+ }
+ }
+}
+
+/* This function is always called when de->attr != VFAT_LN_ATTR is found, to
+ * retrieve the previously constructed LFN. */
+char *lfn_get(DIR_ENT * de, loff_t * lfn_offset)
+{
+ char *lfn;
+ uint8_t sum;
+ int i;
+
+ *lfn_offset = 0;
+ if (de->attr == VFAT_LN_ATTR)
+ die("lfn_get called with LFN directory entry");
+
+#if 0
+ if (de->lcase)
+ printf("lcase=%02x\n", de->lcase);
+#endif
+
+ if (lfn_slot == -1)
+ /* no long name for this file */
+ return NULL;
+
+ if (lfn_slot != 0) {
+ /* The long name isn't finished yet. */
+ /* Causes: 1) LFN slot overwritten by non-VFAT aware tool */
+ /* Fixes: 1) delete LFN 2) move overwriting entry to somewhere else
+ * and let user enter missing part of LFN (hard to do :-()
+ * 3) renumber entries and truncate name */
+ char *long_name = CNV_PARTS_SO_FAR();
+ char *short_name = file_name(de->name);
+ printf("Unfinished long file name \"%s\".\n"
+ " (Start may have been overwritten by %s)\n",
+ long_name, short_name);
+ free(long_name);
+ if (interactive) {
+ printf("1: Delete LFN\n2: Leave it as it is.\n"
+ "3: Fix numbering (truncates long name and attaches "
+ "it to short name %s)\n", short_name);
+ } else
+ printf(" Not auto-correcting this.\n");
+ switch (interactive ? get_key("123", "?") : '2') {
+ case '1':
+ clear_lfn_slots(0, lfn_parts - 1);
+ lfn_reset();
+ return NULL;
+ case '2':
+ lfn_reset();
+ return NULL;
+ case '3':
+ for (i = 0; i < lfn_parts; ++i) {
+ uint8_t id = (lfn_parts - i) | (i == 0 ? LFN_ID_START : 0);
+ fs_write(lfn_offsets[i] + offsetof(LFN_ENT, id),
+ sizeof(id), &id);
+ }
+ memmove(lfn_unicode, lfn_unicode + lfn_slot * CHARS_PER_LFN * 2,
+ lfn_parts * CHARS_PER_LFN * 2);
+ break;
+ }
+ }
+
+ for (sum = 0, i = 0; i < 8; i++)
+ sum = (((sum & 1) << 7) | ((sum & 0xfe) >> 1)) + de->name[i];
+ for (i = 0; i < 3; i++)
+ sum = (((sum & 1) << 7) | ((sum & 0xfe) >> 1)) + de->ext[i];
+ if (sum != lfn_checksum) {
+ /* checksum doesn't match, long name doesn't apply to this alias */
+ /* Causes: 1) alias renamed */
+ /* Fixes: 1) Fix checksum in LFN entries */
+ char *long_name = CNV_PARTS_SO_FAR();
+ char *short_name = file_name(de->name);
+ printf("Wrong checksum for long file name \"%s\".\n"
+ " (Short name %s may have changed without updating the long name)\n",
+ long_name, short_name);
+ free(long_name);
+ if (interactive) {
+ printf("1: Delete LFN\n2: Leave it as it is.\n"
+ "3: Fix checksum (attaches to short name %s)\n", short_name);
+ } else
+ printf(" Not auto-correcting this.\n");
+ if (interactive) {
+ switch (get_key("123", "?")) {
+ case '1':
+ clear_lfn_slots(0, lfn_parts - 1);
+ lfn_reset();
+ return NULL;
+ case '2':
+ lfn_reset();
+ return NULL;
+ case '3':
+ for (i = 0; i < lfn_parts; ++i) {
+ fs_write(lfn_offsets[i] + offsetof(LFN_ENT, alias_checksum),
+ sizeof(sum), &sum);
+ }
+ break;
+ }
+ }
+ }
+
+ *lfn_offset = lfn_offsets[0];
+ lfn = cnv_unicode(lfn_unicode, UNTIL_0, 1);
+ lfn_reset();
+ return (lfn);
+}
+
+void lfn_check_orphaned(void)
+{
+ char *long_name;
+
+ if (lfn_slot == -1)
+ return;
+
+ long_name = CNV_PARTS_SO_FAR();
+ printf("Orphaned long file name part \"%s\"\n", long_name);
+ if (interactive)
+ printf("1: Delete.\n2: Leave it.\n");
+ else
+ printf(" Auto-deleting.\n");
+ if (!interactive || get_key("12", "?") == '1') {
+ clear_lfn_slots(0, lfn_parts - 1);
+ }
+ lfn_reset();
+}
diff --git a/dosfstools/src/lfn.h b/dosfstools/src/lfn.h
new file mode 100644
index 000000000..e5c3991ff
--- /dev/null
+++ b/dosfstools/src/lfn.h
@@ -0,0 +1,39 @@
+/* lfn.h - Functions for handling VFAT long filenames
+
+ Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
+ Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ The complete text of the GNU General Public License
+ can be found in /usr/share/common-licenses/GPL-3 file.
+*/
+
+#ifndef _LFN_H
+#define _LFN_H
+
+void lfn_reset(void);
+/* Reset the state of the LFN parser. */
+
+void lfn_add_slot(DIR_ENT * de, loff_t dir_offset);
+/* Process a dir slot that is a VFAT LFN entry. */
+
+char *lfn_get(DIR_ENT * de, loff_t * lfn_offset);
+/* Retrieve the long name for the proper dir entry. */
+
+void lfn_check_orphaned(void);
+
+void lfn_fix_checksum(loff_t from, loff_t to, const char *short_name);
+
+#endif
diff --git a/dosfstools/src/mkfs.fat.c b/dosfstools/src/mkfs.fat.c
new file mode 100644
index 000000000..2dad23630
--- /dev/null
+++ b/dosfstools/src/mkfs.fat.c
@@ -0,0 +1,1757 @@
+/* mkfs.fat.c - utility to create FAT/MS-DOS filesystems
+
+ Copyright (C) 1991 Linus Torvalds <torvalds@klaava.helsinki.fi>
+ Copyright (C) 1992-1993 Remy Card <card@masi.ibp.fr>
+ Copyright (C) 1993-1994 David Hudson <dave@humbug.demon.co.uk>
+ Copyright (C) 1998 H. Peter Anvin <hpa@zytor.com>
+ Copyright (C) 1998-2005 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
+ Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ The complete text of the GNU General Public License
+ can be found in /usr/share/common-licenses/GPL-3 file.
+*/
+
+/* Description: Utility to allow an MS-DOS filesystem to be created
+ under Linux. A lot of the basic structure of this program has been
+ borrowed from Remy Card's "mke2fs" code.
+
+ As far as possible the aim here is to make the "mkfs.fat" command
+ look almost identical to the other Linux filesystem make utilties,
+ eg bad blocks are still specified as blocks, not sectors, but when
+ it comes down to it, DOS is tied to the idea of a sector (512 bytes
+ as a rule), and not the block. For example the boot block does not
+ occupy a full cluster.
+
+ Fixes/additions May 1998 by Roman Hodek
+ <Roman.Hodek@informatik.uni-erlangen.de>:
+ - Atari format support
+ - New options -A, -S, -C
+ - Support for filesystems > 2GB
+ - FAT32 support */
+
+/* Include the header files */
+
+#include "version.h"
+
+#include <fcntl.h>
+#include <linux/hdreg.h>
+#include <sys/mount.h>
+#include <linux/fs.h>
+#include <linux/fd.h>
+#include <endian.h>
+#include <mntent.h>
+#include <signal.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <time.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdint.h>
+#include <endian.h>
+#include <getopt.h>
+
+#include "msdos_fs.h"
+
+/* In earlier versions, an own llseek() was used, but glibc lseek() is
+ * sufficient (or even better :) for 64 bit offsets in the meantime */
+#define llseek lseek64
+
+/* Constant definitions */
+
+#define TRUE 1 /* Boolean constants */
+#define FALSE 0
+
+#define TEST_BUFFER_BLOCKS 16
+#define HARD_SECTOR_SIZE 512
+#define SECTORS_PER_BLOCK ( BLOCK_SIZE / HARD_SECTOR_SIZE )
+
+#define NO_NAME "NO NAME "
+
+/* Macro definitions */
+
+/* Report a failure message and return a failure error code */
+
+#define die( str ) fatal_error( "%s: " str "\n" )
+
+/* Mark a cluster in the FAT as bad */
+
+#define mark_sector_bad( sector ) mark_FAT_sector( sector, FAT_BAD )
+
+/* Compute ceil(a/b) */
+
+static inline int cdiv(int a, int b)
+{
+ return (a + b - 1) / b;
+}
+
+/* FAT values */
+#define FAT_EOF (atari_format ? 0x0fffffff : 0x0ffffff8)
+#define FAT_BAD 0x0ffffff7
+
+#define MSDOS_EXT_SIGN 0x29 /* extended boot sector signature */
+#define MSDOS_FAT12_SIGN "FAT12 " /* FAT12 filesystem signature */
+#define MSDOS_FAT16_SIGN "FAT16 " /* FAT16 filesystem signature */
+#define MSDOS_FAT32_SIGN "FAT32 " /* FAT32 filesystem signature */
+
+#define BOOT_SIGN 0xAA55 /* Boot sector magic number */
+
+#define MAX_CLUST_12 ((1 << 12) - 16)
+#define MAX_CLUST_16 ((1 << 16) - 16)
+#define MIN_CLUST_32 65529
+/* M$ says the high 4 bits of a FAT32 FAT entry are reserved and don't belong
+ * to the cluster number. So the max. cluster# is based on 2^28 */
+#define MAX_CLUST_32 ((1 << 28) - 16)
+
+#define FAT12_THRESHOLD 4085
+
+#define OLDGEMDOS_MAX_SECTORS 32765
+#define GEMDOS_MAX_SECTORS 65531
+#define GEMDOS_MAX_SECTOR_SIZE (16*1024)
+
+#define BOOTCODE_SIZE 448
+#define BOOTCODE_FAT32_SIZE 420
+
+/* __attribute__ ((packed)) is used on all structures to make gcc ignore any
+ * alignments */
+
+struct msdos_volume_info {
+ uint8_t drive_number; /* BIOS drive number */
+ uint8_t RESERVED; /* Unused */
+ uint8_t ext_boot_sign; /* 0x29 if fields below exist (DOS 3.3+) */
+ uint8_t volume_id[4]; /* Volume ID number */
+ uint8_t volume_label[11]; /* Volume label */
+ uint8_t fs_type[8]; /* Typically FAT12 or FAT16 */
+} __attribute__ ((packed));
+
+struct msdos_boot_sector {
+ uint8_t boot_jump[3]; /* Boot strap short or near jump */
+ uint8_t system_id[8]; /* Name - can be used to special case
+ partition manager volumes */
+ uint8_t sector_size[2]; /* bytes per logical sector */
+ uint8_t cluster_size; /* sectors/cluster */
+ uint16_t reserved; /* reserved sectors */
+ uint8_t fats; /* number of FATs */
+ uint8_t dir_entries[2]; /* root directory entries */
+ uint8_t sectors[2]; /* number of sectors */
+ uint8_t media; /* media code (unused) */
+ uint16_t fat_length; /* sectors/FAT */
+ uint16_t secs_track; /* sectors per track */
+ uint16_t heads; /* number of heads */
+ uint32_t hidden; /* hidden sectors (unused) */
+ uint32_t total_sect; /* number of sectors (if sectors == 0) */
+ union {
+ struct {
+ struct msdos_volume_info vi;
+ uint8_t boot_code[BOOTCODE_SIZE];
+ } __attribute__ ((packed)) _oldfat;
+ struct {
+ uint32_t fat32_length; /* sectors/FAT */
+ uint16_t flags; /* bit 8: fat mirroring, low 4: active fat */
+ uint8_t version[2]; /* major, minor filesystem version */
+ uint32_t root_cluster; /* first cluster in root directory */
+ uint16_t info_sector; /* filesystem info sector */
+ uint16_t backup_boot; /* backup boot sector */
+ uint16_t reserved2[6]; /* Unused */
+ struct msdos_volume_info vi;
+ uint8_t boot_code[BOOTCODE_FAT32_SIZE];
+ } __attribute__ ((packed)) _fat32;
+ } __attribute__ ((packed)) fstype;
+ uint16_t boot_sign;
+} __attribute__ ((packed));
+#define fat32 fstype._fat32
+#define oldfat fstype._oldfat
+
+struct fat32_fsinfo {
+ uint32_t reserved1; /* Nothing as far as I can tell */
+ uint32_t signature; /* 0x61417272L */
+ uint32_t free_clusters; /* Free cluster count. -1 if unknown */
+ uint32_t next_cluster; /* Most recently allocated cluster.
+ * Unused under Linux. */
+ uint32_t reserved2[4];
+};
+
+/* The "boot code" we put into the filesystem... it writes a message and
+ tells the user to try again */
+
+unsigned char dummy_boot_jump[3] = { 0xeb, 0x3c, 0x90 };
+
+unsigned char dummy_boot_jump_m68k[2] = { 0x60, 0x1c };
+
+#define MSG_OFFSET_OFFSET 3
+char dummy_boot_code[BOOTCODE_SIZE] = "\x0e" /* push cs */
+ "\x1f" /* pop ds */
+ "\xbe\x5b\x7c" /* mov si, offset message_txt */
+ /* write_msg: */
+ "\xac" /* lodsb */
+ "\x22\xc0" /* and al, al */
+ "\x74\x0b" /* jz key_press */
+ "\x56" /* push si */
+ "\xb4\x0e" /* mov ah, 0eh */
+ "\xbb\x07\x00" /* mov bx, 0007h */
+ "\xcd\x10" /* int 10h */
+ "\x5e" /* pop si */
+ "\xeb\xf0" /* jmp write_msg */
+ /* key_press: */
+ "\x32\xe4" /* xor ah, ah */
+ "\xcd\x16" /* int 16h */
+ "\xcd\x19" /* int 19h */
+ "\xeb\xfe" /* foo: jmp foo */
+ /* message_txt: */
+ "This is not a bootable disk. Please insert a bootable floppy and\r\n"
+ "press any key to try again ... \r\n";
+
+#define MESSAGE_OFFSET 29 /* Offset of message in above code */
+
+/* Global variables - the root of all evil :-) - see these and weep! */
+
+static const char *program_name = "mkfs.fat"; /* Name of the program */
+static char *device_name = NULL; /* Name of the device on which to create the filesystem */
+static int atari_format = 0; /* Use Atari variation of MS-DOS FS format */
+static int check = FALSE; /* Default to no readablity checking */
+static int verbose = 0; /* Default to verbose mode off */
+static long volume_id; /* Volume ID number */
+static time_t create_time; /* Creation time */
+static char volume_name[] = NO_NAME; /* Volume name */
+static uint64_t blocks; /* Number of blocks in filesystem */
+static int sector_size = 512; /* Size of a logical sector */
+static int sector_size_set = 0; /* User selected sector size */
+static int backup_boot = 0; /* Sector# of backup boot sector */
+static int reserved_sectors = 0; /* Number of reserved sectors */
+static int badblocks = 0; /* Number of bad blocks in the filesystem */
+static int nr_fats = 2; /* Default number of FATs to produce */
+static int size_fat = 0; /* Size in bits of FAT entries */
+static int size_fat_by_user = 0; /* 1 if FAT size user selected */
+static int dev = -1; /* FS block device file handle */
+static int ignore_full_disk = 0; /* Ignore warning about 'full' disk devices */
+static off_t currently_testing = 0; /* Block currently being tested (if autodetect bad blocks) */
+static struct msdos_boot_sector bs; /* Boot sector data */
+static int start_data_sector; /* Sector number for the start of the data area */
+static int start_data_block; /* Block number for the start of the data area */
+static unsigned char *fat; /* File allocation table */
+static unsigned alloced_fat_length; /* # of FAT sectors we can keep in memory */
+static unsigned char *info_sector; /* FAT32 info sector */
+static struct msdos_dir_entry *root_dir; /* Root directory */
+static int size_root_dir; /* Size of the root directory in bytes */
+static int sectors_per_cluster = 0; /* Number of sectors per disk cluster */
+static int root_dir_entries = 0; /* Number of root directory entries */
+static char *blank_sector; /* Blank sector - all zeros */
+static int hidden_sectors = 0; /* Number of hidden sectors */
+static int hidden_sectors_by_user = 0; /* -h option invoked */
+static int drive_number_option = 0; /* drive number */
+static int drive_number_by_user = 0; /* drive number option invoked */
+static int fat_media_byte = 0; /* media byte in header and starting FAT */
+static int malloc_entire_fat = FALSE; /* Whether we should malloc() the entire FAT or not */
+static int align_structures = TRUE; /* Whether to enforce alignment */
+static int orphaned_sectors = 0; /* Sectors that exist in the last block of filesystem */
+static int invariant = 0; /* Whether to set normally randomized or
+ current time based values to
+ constants */
+
+/* Function prototype definitions */
+
+static void fatal_error(const char *fmt_string) __attribute__ ((noreturn));
+static void mark_FAT_cluster(int cluster, unsigned int value);
+static void mark_FAT_sector(int sector, unsigned int value);
+static long do_check(char *buffer, int try, off_t current_block);
+static void alarm_intr(int alnum);
+static void check_blocks(void);
+static void get_list_blocks(char *filename);
+static int valid_offset(int fd, loff_t offset);
+static uint64_t count_blocks(char *filename, int *remainder);
+static void check_mount(char *device_name);
+static void establish_params(int device_num, int size);
+static void setup_tables(void);
+static void write_tables(void);
+
+/* The function implementations */
+
+/* Handle the reporting of fatal errors. Volatile to let gcc know that this doesn't return */
+
+static void fatal_error(const char *fmt_string)
+{
+ fprintf(stderr, fmt_string, program_name, device_name);
+ exit(1); /* The error exit code is 1! */
+}
+
+/* Mark the specified cluster as having a particular value */
+
+static void mark_FAT_cluster(int cluster, unsigned int value)
+{
+ switch (size_fat) {
+ case 12:
+ value &= 0x0fff;
+ if (((cluster * 3) & 0x1) == 0) {
+ fat[3 * cluster / 2] = (unsigned char)(value & 0x00ff);
+ fat[(3 * cluster / 2) + 1] =
+ (unsigned char)((fat[(3 * cluster / 2) + 1] & 0x00f0)
+ | ((value & 0x0f00) >> 8));
+ } else {
+ fat[3 * cluster / 2] =
+ (unsigned char)((fat[3 * cluster / 2] & 0x000f) |
+ ((value & 0x000f) << 4));
+ fat[(3 * cluster / 2) + 1] = (unsigned char)((value & 0x0ff0) >> 4);
+ }
+ break;
+
+ case 16:
+ value &= 0xffff;
+ fat[2 * cluster] = (unsigned char)(value & 0x00ff);
+ fat[(2 * cluster) + 1] = (unsigned char)(value >> 8);
+ break;
+
+ case 32:
+ value &= 0xfffffff;
+ fat[4 * cluster] = (unsigned char)(value & 0x000000ff);
+ fat[(4 * cluster) + 1] = (unsigned char)((value & 0x0000ff00) >> 8);
+ fat[(4 * cluster) + 2] = (unsigned char)((value & 0x00ff0000) >> 16);
+ fat[(4 * cluster) + 3] = (unsigned char)((value & 0xff000000) >> 24);
+ break;
+
+ default:
+ die("Bad FAT size (not 12, 16, or 32)");
+ }
+}
+
+/* Mark a specified sector as having a particular value in it's FAT entry */
+
+static void mark_FAT_sector(int sector, unsigned int value)
+{
+ int cluster;
+
+ cluster = (sector - start_data_sector) / (int)(bs.cluster_size) /
+ (sector_size / HARD_SECTOR_SIZE);
+ if (cluster < 0)
+ die("Invalid cluster number in mark_FAT_sector: probably bug!");
+
+ mark_FAT_cluster(cluster, value);
+}
+
+/* Perform a test on a block. Return the number of blocks that could be read successfully */
+
+static long do_check(char *buffer, int try, off_t current_block)
+{
+ long got;
+
+ if (llseek(dev, current_block * BLOCK_SIZE, SEEK_SET) /* Seek to the correct location */
+ !=current_block * BLOCK_SIZE)
+ die("seek failed during testing for blocks");
+
+ got = read(dev, buffer, try * BLOCK_SIZE); /* Try reading! */
+ if (got < 0)
+ got = 0;
+
+ if (got & (BLOCK_SIZE - 1))
+ printf("Unexpected values in do_check: probably bugs\n");
+ got /= BLOCK_SIZE;
+
+ return got;
+}
+
+/* Alarm clock handler - display the status of the quest for bad blocks! Then retrigger the alarm for five senconds
+ later (so we can come here again) */
+
+static void alarm_intr(int alnum)
+{
+ (void)alnum;
+
+ if (currently_testing >= blocks)
+ return;
+
+ signal(SIGALRM, alarm_intr);
+ alarm(5);
+ if (!currently_testing)
+ return;
+
+ printf("%lld... ", (unsigned long long)currently_testing);
+ fflush(stdout);
+}
+
+static void check_blocks(void)
+{
+ int try, got;
+ int i;
+ static char blkbuf[BLOCK_SIZE * TEST_BUFFER_BLOCKS];
+
+ if (verbose) {
+ printf("Searching for bad blocks ");
+ fflush(stdout);
+ }
+ currently_testing = 0;
+ if (verbose) {
+ signal(SIGALRM, alarm_intr);
+ alarm(5);
+ }
+ try = TEST_BUFFER_BLOCKS;
+ while (currently_testing < blocks) {
+ if (currently_testing + try > blocks)
+ try = blocks - currently_testing;
+ got = do_check(blkbuf, try, currently_testing);
+ currently_testing += got;
+ if (got == try) {
+ try = TEST_BUFFER_BLOCKS;
+ continue;
+ } else
+ try = 1;
+ if (currently_testing < start_data_block)
+ die("bad blocks before data-area: cannot make fs");
+
+ for (i = 0; i < SECTORS_PER_BLOCK; i++) /* Mark all of the sectors in the block as bad */
+ mark_sector_bad(currently_testing * SECTORS_PER_BLOCK + i);
+ badblocks++;
+ currently_testing++;
+ }
+
+ if (verbose)
+ printf("\n");
+
+ if (badblocks)
+ printf("%d bad block%s\n", badblocks, (badblocks > 1) ? "s" : "");
+}
+
+static void get_list_blocks(char *filename)
+{
+ int i;
+ FILE *listfile;
+ long blockno;
+
+ listfile = fopen(filename, "r");
+ if (listfile == (FILE *) NULL)
+ die("Can't open file of bad blocks");
+
+ while (!feof(listfile)) {
+ fscanf(listfile, "%ld\n", &blockno);
+ for (i = 0; i < SECTORS_PER_BLOCK; i++) /* Mark all of the sectors in the block as bad */
+ mark_sector_bad(blockno * SECTORS_PER_BLOCK + i);
+ badblocks++;
+ }
+ fclose(listfile);
+
+ if (badblocks)
+ printf("%d bad block%s\n", badblocks, (badblocks > 1) ? "s" : "");
+}
+
+/* Given a file descriptor and an offset, check whether the offset is a valid offset for the file - return FALSE if it
+ isn't valid or TRUE if it is */
+
+static int valid_offset(int fd, loff_t offset)
+{
+ char ch;
+
+ if (llseek(fd, offset, SEEK_SET) < 0)
+ return FALSE;
+ if (read(fd, &ch, 1) < 1)
+ return FALSE;
+ return TRUE;
+}
+
+/* Given a filename, look to see how many blocks of BLOCK_SIZE are present, returning the answer */
+
+static uint64_t count_blocks(char *filename, int *remainder)
+{
+ loff_t high, low;
+ int fd;
+
+ if ((fd = open(filename, O_RDONLY)) < 0) {
+ perror(filename);
+ exit(1);
+ }
+
+ /* first try SEEK_END, which should work on most devices nowadays */
+ if ((low = llseek(fd, 0, SEEK_END)) <= 0) {
+ low = 0;
+ for (high = 1; valid_offset(fd, high); high *= 2)
+ low = high;
+ while (low < high - 1) {
+ const loff_t mid = (low + high) / 2;
+ if (valid_offset(fd, mid))
+ low = mid;
+ else
+ high = mid;
+ }
+ ++low;
+ }
+
+ close(fd);
+ *remainder = (low % BLOCK_SIZE) / sector_size;
+ return (low / BLOCK_SIZE);
+}
+
+/* Check to see if the specified device is currently mounted - abort if it is */
+
+static void check_mount(char *device_name)
+{
+/* older versions of Bionic don't have setmntent (4.x) or an incomplete impl (5.x) */
+#ifdef MOUNTED
+ FILE *f;
+ struct mntent *mnt;
+
+ if ((f = setmntent(MOUNTED, "r")) == NULL)
+ return;
+ while ((mnt = getmntent(f)) != NULL)
+ if (strcmp(device_name, mnt->mnt_fsname) == 0)
+ die("%s contains a mounted filesystem.");
+ endmntent(f);
+#endif
+}
+
+/* Establish the geometry and media parameters for the device */
+
+static void establish_params(int device_num, int size)
+{
+ long loop_size;
+ struct hd_geometry geometry;
+ struct floppy_struct param;
+ int def_root_dir_entries = 512;
+
+ if ((0 == device_num) || ((device_num & 0xff00) == 0x0200))
+ /* file image or floppy disk */
+ {
+ if (0 == device_num) {
+ param.size = size / 512;
+ switch (param.size) {
+ case 720:
+ param.sect = 9;
+ param.head = 2;
+ break;
+ case 1440:
+ param.sect = 9;
+ param.head = 2;
+ break;
+ case 2400:
+ param.sect = 15;
+ param.head = 2;
+ break;
+ case 2880:
+ param.sect = 18;
+ param.head = 2;
+ break;
+ case 5760:
+ param.sect = 36;
+ param.head = 2;
+ break;
+ default:
+ /* fake values */
+ param.sect = 32;
+ param.head = 64;
+ break;
+ }
+
+ } else { /* is a floppy diskette */
+
+ if (ioctl(dev, FDGETPRM, &param)) /* Can we get the diskette geometry? */
+ die("unable to get diskette geometry for '%s'");
+ }
+ bs.secs_track = htole16(param.sect); /* Set up the geometry information */
+ bs.heads = htole16(param.head);
+ switch (param.size) { /* Set up the media descriptor byte */
+ case 720: /* 5.25", 2, 9, 40 - 360K */
+ bs.media = (char)0xfd;
+ bs.cluster_size = (char)2;
+ def_root_dir_entries = 112;
+ break;
+
+ case 1440: /* 3.5", 2, 9, 80 - 720K */
+ bs.media = (char)0xf9;
+ bs.cluster_size = (char)2;
+ def_root_dir_entries = 112;
+ break;
+
+ case 2400: /* 5.25", 2, 15, 80 - 1200K */
+ bs.media = (char)0xf9;
+ bs.cluster_size = (char)(atari_format ? 2 : 1);
+ def_root_dir_entries = 224;
+ break;
+
+ case 5760: /* 3.5", 2, 36, 80 - 2880K */
+ bs.media = (char)0xf0;
+ bs.cluster_size = (char)2;
+ def_root_dir_entries = 224;
+ break;
+
+ case 2880: /* 3.5", 2, 18, 80 - 1440K */
+floppy_default:
+ bs.media = (char)0xf0;
+ bs.cluster_size = (char)(atari_format ? 2 : 1);
+ def_root_dir_entries = 224;
+ break;
+
+ default: /* Anything else */
+ if (0 == device_num)
+ goto def_hd_params;
+ else
+ goto floppy_default;
+ }
+ } else if ((device_num & 0xff00) == 0x0700) { /* This is a loop device */
+ if (ioctl(dev, BLKGETSIZE, &loop_size))
+ die("unable to get loop device size");
+
+ switch (loop_size) { /* Assuming the loop device -> floppy later */
+ case 720: /* 5.25", 2, 9, 40 - 360K */
+ bs.secs_track = le16toh(9);
+ bs.heads = le16toh(2);
+ bs.media = (char)0xfd;
+ bs.cluster_size = (char)2;
+ def_root_dir_entries = 112;
+ break;
+
+ case 1440: /* 3.5", 2, 9, 80 - 720K */
+ bs.secs_track = le16toh(9);
+ bs.heads = le16toh(2);
+ bs.media = (char)0xf9;
+ bs.cluster_size = (char)2;
+ def_root_dir_entries = 112;
+ break;
+
+ case 2400: /* 5.25", 2, 15, 80 - 1200K */
+ bs.secs_track = le16toh(15);
+ bs.heads = le16toh(2);
+ bs.media = (char)0xf9;
+ bs.cluster_size = (char)(atari_format ? 2 : 1);
+ def_root_dir_entries = 224;
+ break;
+
+ case 5760: /* 3.5", 2, 36, 80 - 2880K */
+ bs.secs_track = le16toh(36);
+ bs.heads = le16toh(2);
+ bs.media = (char)0xf0;
+ bs.cluster_size = (char)2;
+ bs.dir_entries[0] = (char)224;
+ bs.dir_entries[1] = (char)0;
+ break;
+
+ case 2880: /* 3.5", 2, 18, 80 - 1440K */
+ bs.secs_track = le16toh(18);
+ bs.heads = le16toh(2);
+ bs.media = (char)0xf0;
+ bs.cluster_size = (char)(atari_format ? 2 : 1);
+ def_root_dir_entries = 224;
+ break;
+
+ default: /* Anything else: default hd setup */
+ printf("Loop device does not match a floppy size, using "
+ "default hd params\n");
+ bs.secs_track = htole16(32); /* these are fake values... */
+ bs.heads = htole16(64);
+ goto def_hd_params;
+ }
+ } else
+ /* Must be a hard disk then! */
+ {
+ /* Can we get the drive geometry? (Note I'm not too sure about */
+ /* whether to use HDIO_GETGEO or HDIO_REQ) */
+ if (ioctl(dev, HDIO_GETGEO, &geometry) || geometry.sectors == 0
+ || geometry.heads == 0) {
+ printf("unable to get drive geometry, using default 255/63\n");
+ bs.secs_track = htole16(63);
+ bs.heads = htole16(255);
+ } else {
+ bs.secs_track = htole16(geometry.sectors); /* Set up the geometry information */
+ bs.heads = htole16(geometry.heads);
+ if (!hidden_sectors_by_user)
+ hidden_sectors = htole32(geometry.start);
+ }
+def_hd_params:
+ bs.media = (char)0xf8; /* Set up the media descriptor for a hard drive */
+ if (!size_fat && blocks * SECTORS_PER_BLOCK > 1064960) {
+ if (verbose)
+ printf("Auto-selecting FAT32 for large filesystem\n");
+ size_fat = 32;
+ }
+ if (size_fat == 32) {
+ /* For FAT32, try to do the same as M$'s format command
+ * (see http://www.win.tue.nl/~aeb/linux/fs/fat/fatgen103.pdf p. 20):
+ * fs size <= 260M: 0.5k clusters
+ * fs size <= 8G: 4k clusters
+ * fs size <= 16G: 8k clusters
+ * fs size <= 32G: 16k clusters
+ * fs size > 32G: 32k clusters
+ */
+ uint32_t sz_mb =
+ (blocks + (1 << (20 - BLOCK_SIZE_BITS)) - 1) >> (20 -
+ BLOCK_SIZE_BITS);
+ bs.cluster_size =
+ sz_mb > 32 * 1024 ? 64 : sz_mb > 16 * 1024 ? 32 : sz_mb >
+ 8 * 1024 ? 16 : sz_mb > 260 ? 8 : 1;
+ } else {
+ /* FAT12 and FAT16: start at 4 sectors per cluster */
+ bs.cluster_size = (char)4;
+ }
+ }
+
+ if (!root_dir_entries)
+ root_dir_entries = def_root_dir_entries;
+}
+
+/*
+ * If alignment is enabled, round the first argument up to the second; the
+ * latter must be a power of two.
+ */
+static unsigned int align_object(unsigned int sectors, unsigned int clustsize)
+{
+ if (align_structures)
+ return (sectors + clustsize - 1) & ~(clustsize - 1);
+ else
+ return sectors;
+}
+
+/* Create the filesystem data tables */
+
+static void setup_tables(void)
+{
+ unsigned num_sectors;
+ unsigned cluster_count = 0, fat_length;
+ struct tm *ctime;
+ struct msdos_volume_info *vi =
+ (size_fat == 32 ? &bs.fat32.vi : &bs.oldfat.vi);
+
+ if (atari_format) {
+ /* On Atari, the first few bytes of the boot sector are assigned
+ * differently: The jump code is only 2 bytes (and m68k machine code
+ * :-), then 6 bytes filler (ignored), then 3 byte serial number. */
+ bs.boot_jump[2] = 'm';
+ memcpy((char *)bs.system_id, "kdosf", strlen("kdosf"));
+ } else
+ memcpy((char *)bs.system_id, "mkfs.fat", strlen("mkfs.fat"));
+ if (sectors_per_cluster)
+ bs.cluster_size = (char)sectors_per_cluster;
+
+ if (fat_media_byte)
+ bs.media = (char) fat_media_byte;
+
+ if (bs.media == 0xf8)
+ vi->drive_number=0x80;
+ else
+ vi->drive_number=0x00;
+
+ if (drive_number_by_user)
+ vi->drive_number= (char) drive_number_option;
+
+ if (size_fat == 32) {
+ /* Under FAT32, the root dir is in a cluster chain, and this is
+ * signalled by bs.dir_entries being 0. */
+ root_dir_entries = 0;
+ }
+
+ if (atari_format) {
+ bs.system_id[5] = (unsigned char)(volume_id & 0x000000ff);
+ bs.system_id[6] = (unsigned char)((volume_id & 0x0000ff00) >> 8);
+ bs.system_id[7] = (unsigned char)((volume_id & 0x00ff0000) >> 16);
+ } else {
+ vi->volume_id[0] = (unsigned char)(volume_id & 0x000000ff);
+ vi->volume_id[1] = (unsigned char)((volume_id & 0x0000ff00) >> 8);
+ vi->volume_id[2] = (unsigned char)((volume_id & 0x00ff0000) >> 16);
+ vi->volume_id[3] = (unsigned char)(volume_id >> 24);
+ }
+
+ if (!atari_format) {
+ memcpy(vi->volume_label, volume_name, 11);
+
+ memcpy(bs.boot_jump, dummy_boot_jump, 3);
+ /* Patch in the correct offset to the boot code */
+ bs.boot_jump[1] = ((size_fat == 32 ?
+ (char *)&bs.fat32.boot_code :
+ (char *)&bs.oldfat.boot_code) - (char *)&bs) - 2;
+
+ if (size_fat == 32) {
+ int offset = (char *)&bs.fat32.boot_code -
+ (char *)&bs + MESSAGE_OFFSET + 0x7c00;
+ if (dummy_boot_code[BOOTCODE_FAT32_SIZE - 1])
+ printf("Warning: message too long; truncated\n");
+ dummy_boot_code[BOOTCODE_FAT32_SIZE - 1] = 0;
+ memcpy(bs.fat32.boot_code, dummy_boot_code, BOOTCODE_FAT32_SIZE);
+ bs.fat32.boot_code[MSG_OFFSET_OFFSET] = offset & 0xff;
+ bs.fat32.boot_code[MSG_OFFSET_OFFSET + 1] = offset >> 8;
+ } else {
+ memcpy(bs.oldfat.boot_code, dummy_boot_code, BOOTCODE_SIZE);
+ }
+ bs.boot_sign = htole16(BOOT_SIGN);
+ } else {
+ memcpy(bs.boot_jump, dummy_boot_jump_m68k, 2);
+ }
+ if (verbose >= 2)
+ printf("Boot jump code is %02x %02x\n",
+ bs.boot_jump[0], bs.boot_jump[1]);
+
+ if (!reserved_sectors)
+ reserved_sectors = (size_fat == 32) ? 32 : 1;
+ else {
+ if (size_fat == 32 && reserved_sectors < 2)
+ die("On FAT32 at least 2 reserved sectors are needed.");
+ }
+ bs.reserved = htole16(reserved_sectors);
+ if (verbose >= 2)
+ printf("Using %d reserved sectors\n", reserved_sectors);
+ bs.fats = (char)nr_fats;
+ if (!atari_format || size_fat == 32)
+ bs.hidden = htole32(hidden_sectors);
+ else {
+ /* In Atari format, hidden is a 16 bit field */
+ uint16_t hidden = htole16(hidden_sectors);
+ if (hidden_sectors & ~0xffff)
+ die("#hidden doesn't fit in 16bit field of Atari format\n");
+ memcpy(&bs.hidden, &hidden, 2);
+ }
+
+ num_sectors =
+ (long long)(blocks * BLOCK_SIZE / sector_size) + orphaned_sectors;
+
+ if (!atari_format) {
+ unsigned fatdata1216; /* Sectors for FATs + data area (FAT12/16) */
+ unsigned fatdata32; /* Sectors for FATs + data area (FAT32) */
+ unsigned fatlength12, fatlength16, fatlength32;
+ unsigned maxclust12, maxclust16, maxclust32;
+ unsigned clust12, clust16, clust32;
+ int maxclustsize;
+ unsigned root_dir_sectors = cdiv(root_dir_entries * 32, sector_size);
+
+ /*
+ * If the filesystem is 8192 sectors or less (4 MB with 512-byte
+ * sectors, i.e. floppy size), don't align the data structures.
+ */
+ if (num_sectors <= 8192) {
+ if (align_structures && verbose >= 2)
+ printf("Disabling alignment due to tiny filesystem\n");
+
+ align_structures = FALSE;
+ }
+
+ if (sectors_per_cluster)
+ bs.cluster_size = maxclustsize = sectors_per_cluster;
+ else
+ /* An initial guess for bs.cluster_size should already be set */
+ maxclustsize = 128;
+
+ do {
+ fatdata32 = num_sectors - reserved_sectors;
+ fatdata1216 = fatdata32
+ - align_object(root_dir_sectors, bs.cluster_size);
+
+ if (verbose >= 2)
+ printf("Trying with %d sectors/cluster:\n", bs.cluster_size);
+
+ /* The factor 2 below avoids cut-off errors for nr_fats == 1.
+ * The "nr_fats*3" is for the reserved first two FAT entries */
+ clust12 = 2 * ((long long)fatdata1216 * sector_size + nr_fats * 3) /
+ (2 * (int)bs.cluster_size * sector_size + nr_fats * 3);
+ fatlength12 = cdiv(((clust12 + 2) * 3 + 1) >> 1, sector_size);
+ fatlength12 = align_object(fatlength12, bs.cluster_size);
+ /* Need to recalculate number of clusters, since the unused parts of the
+ * FATS and data area together could make up space for an additional,
+ * not really present cluster. */
+ clust12 = (fatdata1216 - nr_fats * fatlength12) / bs.cluster_size;
+ maxclust12 = (fatlength12 * 2 * sector_size) / 3;
+ if (maxclust12 > MAX_CLUST_12)
+ maxclust12 = MAX_CLUST_12;
+ if (verbose >= 2)
+ printf("FAT12: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n",
+ clust12, fatlength12, maxclust12, MAX_CLUST_12);
+ if (clust12 > maxclust12 - 2) {
+ clust12 = 0;
+ if (verbose >= 2)
+ printf("FAT12: too much clusters\n");
+ }
+
+ clust16 = ((long long)fatdata1216 * sector_size + nr_fats * 4) /
+ ((int)bs.cluster_size * sector_size + nr_fats * 2);
+ fatlength16 = cdiv((clust16 + 2) * 2, sector_size);
+ fatlength16 = align_object(fatlength16, bs.cluster_size);
+ /* Need to recalculate number of clusters, since the unused parts of the
+ * FATS and data area together could make up space for an additional,
+ * not really present cluster. */
+ clust16 = (fatdata1216 - nr_fats * fatlength16) / bs.cluster_size;
+ maxclust16 = (fatlength16 * sector_size) / 2;
+ if (maxclust16 > MAX_CLUST_16)
+ maxclust16 = MAX_CLUST_16;
+ if (verbose >= 2)
+ printf("FAT16: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n",
+ clust16, fatlength16, maxclust16, MAX_CLUST_16);
+ if (clust16 > maxclust16 - 2) {
+ if (verbose >= 2)
+ printf("FAT16: too much clusters\n");
+ clust16 = 0;
+ }
+ /* The < 4078 avoids that the filesystem will be misdetected as having a
+ * 12 bit FAT. */
+ if (clust16 < FAT12_THRESHOLD
+ && !(size_fat_by_user && size_fat == 16)) {
+ if (verbose >= 2)
+ printf(clust16 < FAT12_THRESHOLD ?
+ "FAT16: would be misdetected as FAT12\n" :
+ "FAT16: too much clusters\n");
+ clust16 = 0;
+ }
+
+ clust32 = ((long long)fatdata32 * sector_size + nr_fats * 8) /
+ ((int)bs.cluster_size * sector_size + nr_fats * 4);
+ fatlength32 = cdiv((clust32 + 2) * 4, sector_size);
+ /* Need to recalculate number of clusters, since the unused parts of the
+ * FATS and data area together could make up space for an additional,
+ * not really present cluster. */
+ clust32 = (fatdata32 - nr_fats * fatlength32) / bs.cluster_size;
+ maxclust32 = (fatlength32 * sector_size) / 4;
+ if (maxclust32 > MAX_CLUST_32)
+ maxclust32 = MAX_CLUST_32;
+ if (clust32 && clust32 < MIN_CLUST_32
+ && !(size_fat_by_user && size_fat == 32)) {
+ clust32 = 0;
+ if (verbose >= 2)
+ printf("FAT32: not enough clusters (%d)\n", MIN_CLUST_32);
+ }
+ if (verbose >= 2)
+ printf("FAT32: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n",
+ clust32, fatlength32, maxclust32, MAX_CLUST_32);
+ if (clust32 > maxclust32) {
+ clust32 = 0;
+ if (verbose >= 2)
+ printf("FAT32: too much clusters\n");
+ }
+
+ if ((clust12 && (size_fat == 0 || size_fat == 12)) ||
+ (clust16 && (size_fat == 0 || size_fat == 16)) ||
+ (clust32 && size_fat == 32))
+ break;
+
+ bs.cluster_size <<= 1;
+ } while (bs.cluster_size && bs.cluster_size <= maxclustsize);
+
+ /* Use the optimal FAT size if not specified;
+ * FAT32 is (not yet) choosen automatically */
+ if (!size_fat) {
+ size_fat = (clust16 > clust12) ? 16 : 12;
+ if (verbose >= 2)
+ printf("Choosing %d bits for FAT\n", size_fat);
+ }
+
+ switch (size_fat) {
+ case 12:
+ cluster_count = clust12;
+ fat_length = fatlength12;
+ bs.fat_length = htole16(fatlength12);
+ memcpy(vi->fs_type, MSDOS_FAT12_SIGN, 8);
+ break;
+
+ case 16:
+ if (clust16 < FAT12_THRESHOLD) {
+ if (size_fat_by_user) {
+ fprintf(stderr, "WARNING: Not enough clusters for a "
+ "16 bit FAT! The filesystem will be\n"
+ "misinterpreted as having a 12 bit FAT without "
+ "mount option \"fat=16\".\n");
+ } else {
+ fprintf(stderr, "This filesystem has an unfortunate size. "
+ "A 12 bit FAT cannot provide\n"
+ "enough clusters, but a 16 bit FAT takes up a little "
+ "bit more space so that\n"
+ "the total number of clusters becomes less than the "
+ "threshold value for\n"
+ "distinction between 12 and 16 bit FATs.\n");
+ die("Make the filesystem a bit smaller manually.");
+ }
+ }
+ cluster_count = clust16;
+ fat_length = fatlength16;
+ bs.fat_length = htole16(fatlength16);
+ memcpy(vi->fs_type, MSDOS_FAT16_SIGN, 8);
+ break;
+
+ case 32:
+ if (clust32 < MIN_CLUST_32)
+ fprintf(stderr,
+ "WARNING: Not enough clusters for a 32 bit FAT!\n");
+ cluster_count = clust32;
+ fat_length = fatlength32;
+ bs.fat_length = htole16(0);
+ bs.fat32.fat32_length = htole32(fatlength32);
+ memcpy(vi->fs_type, MSDOS_FAT32_SIGN, 8);
+ root_dir_entries = 0;
+ break;
+
+ default:
+ die("FAT not 12, 16 or 32 bits");
+ }
+
+ /* Adjust the number of root directory entries to help enforce alignment */
+ if (align_structures) {
+ root_dir_entries = align_object(root_dir_sectors, bs.cluster_size)
+ * (sector_size >> 5);
+ }
+ } else {
+ unsigned clusters, maxclust, fatdata;
+
+ /* GEMDOS always uses a 12 bit FAT on floppies, and always a 16 bit FAT on
+ * hard disks. So use 12 bit if the size of the filesystem suggests that
+ * this fs is for a floppy disk, if the user hasn't explicitly requested a
+ * size.
+ */
+ if (!size_fat)
+ size_fat = (num_sectors == 1440 || num_sectors == 2400 ||
+ num_sectors == 2880 || num_sectors == 5760) ? 12 : 16;
+ if (verbose >= 2)
+ printf("Choosing %d bits for FAT\n", size_fat);
+
+ /* Atari format: cluster size should be 2, except explicitly requested by
+ * the user, since GEMDOS doesn't like other cluster sizes very much.
+ * Instead, tune the sector size for the FS to fit.
+ */
+ bs.cluster_size = sectors_per_cluster ? sectors_per_cluster : 2;
+ if (!sector_size_set) {
+ while (num_sectors > GEMDOS_MAX_SECTORS) {
+ num_sectors >>= 1;
+ sector_size <<= 1;
+ }
+ }
+ if (verbose >= 2)
+ printf("Sector size must be %d to have less than %d log. sectors\n",
+ sector_size, GEMDOS_MAX_SECTORS);
+
+ /* Check if there are enough FAT indices for how much clusters we have */
+ do {
+ fatdata = num_sectors - cdiv(root_dir_entries * 32, sector_size) -
+ reserved_sectors;
+ /* The factor 2 below avoids cut-off errors for nr_fats == 1 and
+ * size_fat == 12
+ * The "2*nr_fats*size_fat/8" is for the reserved first two FAT entries
+ */
+ clusters =
+ (2 *
+ ((long long)fatdata * sector_size -
+ 2 * nr_fats * size_fat / 8)) / (2 * ((int)bs.cluster_size *
+ sector_size +
+ nr_fats * size_fat / 8));
+ fat_length = cdiv((clusters + 2) * size_fat / 8, sector_size);
+ /* Need to recalculate number of clusters, since the unused parts of the
+ * FATS and data area together could make up space for an additional,
+ * not really present cluster. */
+ clusters = (fatdata - nr_fats * fat_length) / bs.cluster_size;
+ maxclust = (fat_length * sector_size * 8) / size_fat;
+ if (verbose >= 2)
+ printf("ss=%d: #clu=%d, fat_len=%d, maxclu=%d\n",
+ sector_size, clusters, fat_length, maxclust);
+
+ /* last 10 cluster numbers are special (except FAT32: 4 high bits rsvd);
+ * first two numbers are reserved */
+ if (maxclust <=
+ (size_fat == 32 ? MAX_CLUST_32 : (1 << size_fat) - 0x10)
+ && clusters <= maxclust - 2)
+ break;
+ if (verbose >= 2)
+ printf(clusters > maxclust - 2 ?
+ "Too many clusters\n" : "FAT too big\n");
+
+ /* need to increment sector_size once more to */
+ if (sector_size_set)
+ die("With this sector size, the maximum number of FAT entries "
+ "would be exceeded.");
+ num_sectors >>= 1;
+ sector_size <<= 1;
+ } while (sector_size <= GEMDOS_MAX_SECTOR_SIZE);
+
+ if (sector_size > GEMDOS_MAX_SECTOR_SIZE)
+ die("Would need a sector size > 16k, which GEMDOS can't work with");
+
+ cluster_count = clusters;
+ if (size_fat != 32)
+ bs.fat_length = htole16(fat_length);
+ else {
+ bs.fat_length = 0;
+ bs.fat32.fat32_length = htole32(fat_length);
+ }
+ }
+
+ bs.sector_size[0] = (char)(sector_size & 0x00ff);
+ bs.sector_size[1] = (char)((sector_size & 0xff00) >> 8);
+
+ bs.dir_entries[0] = (char)(root_dir_entries & 0x00ff);
+ bs.dir_entries[1] = (char)((root_dir_entries & 0xff00) >> 8);
+
+ if (size_fat == 32) {
+ /* set up additional FAT32 fields */
+ bs.fat32.flags = htole16(0);
+ bs.fat32.version[0] = 0;
+ bs.fat32.version[1] = 0;
+ bs.fat32.root_cluster = htole32(2);
+ bs.fat32.info_sector = htole16(1);
+ if (!backup_boot)
+ backup_boot = (reserved_sectors >= 7) ? 6 :
+ (reserved_sectors >= 2) ? reserved_sectors - 1 : 0;
+ else {
+ if (backup_boot == 1)
+ die("Backup boot sector must be after sector 1");
+ else if (backup_boot >= reserved_sectors)
+ die("Backup boot sector must be a reserved sector");
+ }
+ if (verbose >= 2)
+ printf("Using sector %d as backup boot sector (0 = none)\n",
+ backup_boot);
+ bs.fat32.backup_boot = htole16(backup_boot);
+ memset(&bs.fat32.reserved2, 0, sizeof(bs.fat32.reserved2));
+ }
+
+ if (atari_format) {
+ /* Just some consistency checks */
+ if (num_sectors >= GEMDOS_MAX_SECTORS)
+ die("GEMDOS can't handle more than 65531 sectors");
+ else if (num_sectors >= OLDGEMDOS_MAX_SECTORS)
+ printf("Warning: More than 32765 sector need TOS 1.04 "
+ "or higher.\n");
+ }
+ if (num_sectors >= 65536) {
+ bs.sectors[0] = (char)0;
+ bs.sectors[1] = (char)0;
+ bs.total_sect = htole32(num_sectors);
+ } else {
+ bs.sectors[0] = (char)(num_sectors & 0x00ff);
+ bs.sectors[1] = (char)((num_sectors & 0xff00) >> 8);
+ if (!atari_format)
+ bs.total_sect = htole32(0);
+ }
+
+ if (!atari_format)
+ vi->ext_boot_sign = MSDOS_EXT_SIGN;
+
+ if (!cluster_count) {
+ if (sectors_per_cluster) /* If yes, die if we'd spec'd sectors per cluster */
+ die("Too many clusters for filesystem - try more sectors per cluster");
+ else
+ die("Attempting to create a too large filesystem");
+ }
+
+ /* The two following vars are in hard sectors, i.e. 512 byte sectors! */
+ start_data_sector = (reserved_sectors + nr_fats * fat_length) *
+ (sector_size / HARD_SECTOR_SIZE);
+ start_data_block = (start_data_sector + SECTORS_PER_BLOCK - 1) /
+ SECTORS_PER_BLOCK;
+
+ if (blocks < start_data_block + 32) /* Arbitrary undersize filesystem! */
+ die("Too few blocks for viable filesystem");
+
+ if (verbose) {
+ printf("%s has %d head%s and %d sector%s per track,\n",
+ device_name, le16toh(bs.heads),
+ (le16toh(bs.heads) != 1) ? "s" : "", le16toh(bs.secs_track),
+ (le16toh(bs.secs_track) != 1) ? "s" : "");
+ printf("hidden sectors 0x%04x;\n", hidden_sectors);
+ printf("logical sector size is %d,\n", sector_size);
+ printf("using 0x%02x media descriptor, with %d sectors;\n",
+ (int)(bs.media), num_sectors);
+ printf("drive number 0x%02x;\n", (int) (vi->drive_number));
+ printf("filesystem has %d %d-bit FAT%s and %d sector%s per cluster.\n",
+ (int)(bs.fats), size_fat, (bs.fats != 1) ? "s" : "",
+ (int)(bs.cluster_size), (bs.cluster_size != 1) ? "s" : "");
+ printf("FAT size is %d sector%s, and provides %d cluster%s.\n",
+ fat_length, (fat_length != 1) ? "s" : "",
+ cluster_count, (cluster_count != 1) ? "s" : "");
+ printf("There %s %u reserved sector%s.\n",
+ (reserved_sectors != 1) ? "are" : "is",
+ reserved_sectors, (reserved_sectors != 1) ? "s" : "");
+
+ if (size_fat != 32) {
+ unsigned root_dir_entries =
+ bs.dir_entries[0] + ((bs.dir_entries[1]) * 256);
+ unsigned root_dir_sectors =
+ cdiv(root_dir_entries * 32, sector_size);
+ printf("Root directory contains %u slots and uses %u sectors.\n",
+ root_dir_entries, root_dir_sectors);
+ }
+ printf("Volume ID is %08lx, ", volume_id &
+ (atari_format ? 0x00ffffff : 0xffffffff));
+ if (strcmp(volume_name, NO_NAME))
+ printf("volume label %s.\n", volume_name);
+ else
+ printf("no volume label.\n");
+ }
+
+ /* Make the file allocation tables! */
+
+ if (malloc_entire_fat)
+ alloced_fat_length = fat_length;
+ else
+ alloced_fat_length = 1;
+
+ if ((fat =
+ (unsigned char *)malloc(alloced_fat_length * sector_size)) == NULL)
+ die("unable to allocate space for FAT image in memory");
+
+ memset(fat, 0, alloced_fat_length * sector_size);
+
+ mark_FAT_cluster(0, 0xffffffff); /* Initial fat entries */
+ mark_FAT_cluster(1, 0xffffffff);
+ fat[0] = (unsigned char)bs.media; /* Put media type in first byte! */
+ if (size_fat == 32) {
+ /* Mark cluster 2 as EOF (used for root dir) */
+ mark_FAT_cluster(2, FAT_EOF);
+ }
+
+ /* Make the root directory entries */
+
+ size_root_dir = (size_fat == 32) ?
+ bs.cluster_size * sector_size :
+ (((int)bs.dir_entries[1] * 256 + (int)bs.dir_entries[0]) *
+ sizeof(struct msdos_dir_entry));
+ if ((root_dir = (struct msdos_dir_entry *)malloc(size_root_dir)) == NULL) {
+ free(fat); /* Tidy up before we die! */
+ die("unable to allocate space for root directory in memory");
+ }
+
+ memset(root_dir, 0, size_root_dir);
+ if (memcmp(volume_name, NO_NAME, 11)) {
+ struct msdos_dir_entry *de = &root_dir[0];
+ memcpy(de->name, volume_name, 8);
+ memcpy(de->ext, volume_name + 8, 3);
+ de->attr = ATTR_VOLUME;
+ if (!invariant)
+ ctime = localtime(&create_time);
+ else
+ ctime = gmtime(&create_time);
+ de->time = htole16((unsigned short)((ctime->tm_sec >> 1) +
+ (ctime->tm_min << 5) +
+ (ctime->tm_hour << 11)));
+ de->date =
+ htole16((unsigned short)(ctime->tm_mday +
+ ((ctime->tm_mon + 1) << 5) +
+ ((ctime->tm_year - 80) << 9)));
+ de->ctime_cs = 0;
+ de->ctime = de->time;
+ de->cdate = de->date;
+ de->adate = de->date;
+ de->starthi = htole16(0);
+ de->start = htole16(0);
+ de->size = htole32(0);
+ }
+
+ if (size_fat == 32) {
+ /* For FAT32, create an info sector */
+ struct fat32_fsinfo *info;
+
+ if (!(info_sector = malloc(sector_size)))
+ die("Out of memory");
+ memset(info_sector, 0, sector_size);
+ /* fsinfo structure is at offset 0x1e0 in info sector by observation */
+ info = (struct fat32_fsinfo *)(info_sector + 0x1e0);
+
+ /* Info sector magic */
+ info_sector[0] = 'R';
+ info_sector[1] = 'R';
+ info_sector[2] = 'a';
+ info_sector[3] = 'A';
+
+ /* Magic for fsinfo structure */
+ info->signature = htole32(0x61417272);
+ /* We've allocated cluster 2 for the root dir. */
+ info->free_clusters = htole32(cluster_count - 1);
+ info->next_cluster = htole32(2);
+
+ /* Info sector also must have boot sign */
+ *(uint16_t *) (info_sector + 0x1fe) = htole16(BOOT_SIGN);
+ }
+
+ if (!(blank_sector = malloc(sector_size)))
+ die("Out of memory");
+ memset(blank_sector, 0, sector_size);
+}
+
+/* Write the new filesystem's data tables to wherever they're going to end up! */
+
+#define error(str) \
+ do { \
+ free (fat); \
+ if (info_sector) free (info_sector); \
+ free (root_dir); \
+ die (str); \
+ } while(0)
+
+#define seekto(pos,errstr) \
+ do { \
+ loff_t __pos = (pos); \
+ if (llseek (dev, __pos, SEEK_SET) != __pos) \
+ error ("seek to " errstr " failed whilst writing tables"); \
+ } while(0)
+
+#define writebuf(buf,size,errstr) \
+ do { \
+ int __size = (size); \
+ if (write (dev, buf, __size) != __size) \
+ error ("failed whilst writing " errstr); \
+ } while(0)
+
+static void write_tables(void)
+{
+ int x;
+ int fat_length;
+
+ fat_length = (size_fat == 32) ?
+ le32toh(bs.fat32.fat32_length) : le16toh(bs.fat_length);
+
+ seekto(0, "start of device");
+ /* clear all reserved sectors */
+ for (x = 0; x < reserved_sectors; ++x)
+ writebuf(blank_sector, sector_size, "reserved sector");
+ /* seek back to sector 0 and write the boot sector */
+ seekto(0, "boot sector");
+ writebuf((char *)&bs, sizeof(struct msdos_boot_sector), "boot sector");
+ /* on FAT32, write the info sector and backup boot sector */
+ if (size_fat == 32) {
+ seekto(le16toh(bs.fat32.info_sector) * sector_size, "info sector");
+ writebuf(info_sector, 512, "info sector");
+ if (backup_boot != 0) {
+ seekto(backup_boot * sector_size, "backup boot sector");
+ writebuf((char *)&bs, sizeof(struct msdos_boot_sector),
+ "backup boot sector");
+ }
+ }
+ /* seek to start of FATS and write them all */
+ seekto(reserved_sectors * sector_size, "first FAT");
+ for (x = 1; x <= nr_fats; x++) {
+ int y;
+ int blank_fat_length = fat_length - alloced_fat_length;
+ writebuf(fat, alloced_fat_length * sector_size, "FAT");
+ for (y = 0; y < blank_fat_length; y++)
+ writebuf(blank_sector, sector_size, "FAT");
+ }
+ /* Write the root directory directly after the last FAT. This is the root
+ * dir area on FAT12/16, and the first cluster on FAT32. */
+ writebuf((char *)root_dir, size_root_dir, "root directory");
+
+ if (blank_sector)
+ free(blank_sector);
+ if (info_sector)
+ free(info_sector);
+ free(root_dir); /* Free up the root directory space from setup_tables */
+ free(fat); /* Free up the fat table space reserved during setup_tables */
+}
+
+/* Report the command usage and exit with the given error code */
+
+static void usage(int exitval)
+{
+ fprintf(stderr, "\
+Usage: mkfs.fat [-a][-A][-c][-C][-v][-I][-l bad-block-file][-b backup-boot-sector]\n\
+ [-m boot-msg-file][-n volume-name][-i volume-id]\n\
+ [-s sectors-per-cluster][-S logical-sector-size][-f number-of-FATs]\n\
+ [-h hidden-sectors][-F fat-size][-r root-dir-entries][-R reserved-sectors]\n\
+ [-M FAT-media-byte][-D drive_number]\n\
+ [--invariant]\n\
+ [--help]\n\
+ /dev/name [blocks]\n");
+ exit(exitval);
+}
+
+/*
+ * ++roman: On m68k, check if this is an Atari; if yes, turn on Atari variant
+ * of MS-DOS filesystem by default.
+ */
+static void check_atari(void)
+{
+#ifdef __mc68000__
+ FILE *f;
+ char line[128], *p;
+
+ if (!(f = fopen("/proc/hardware", "r"))) {
+ perror("/proc/hardware");
+ return;
+ }
+
+ while (fgets(line, sizeof(line), f)) {
+ if (strncmp(line, "Model:", 6) == 0) {
+ p = line + 6;
+ p += strspn(p, " \t");
+ if (strncmp(p, "Atari ", 6) == 0)
+ atari_format = 1;
+ break;
+ }
+ }
+ fclose(f);
+#endif
+}
+
+/* The "main" entry point into the utility - we pick up the options and attempt to process them in some sort of sensible
+ way. In the event that some/all of the options are invalid we need to tell the user so that something can be done! */
+
+int main(int argc, char **argv)
+{
+ int c;
+ char *tmp;
+ char *listfile = NULL;
+ FILE *msgfile;
+ struct stat statbuf;
+ int i = 0, pos, ch;
+ int create = 0;
+ uint64_t cblocks = 0;
+ int min_sector_size;
+ int bad_block_count = 0;
+ struct timeval create_timeval;
+
+ enum {OPT_HELP=1000, OPT_INVARIANT,};
+ const struct option long_options[] = {
+ {"help", no_argument, NULL, OPT_HELP},
+ {"invariant", no_argument, NULL, OPT_INVARIANT},
+ {0,}
+ };
+
+ if (argc && *argv) { /* What's the program name? */
+ char *p;
+ program_name = *argv;
+ if ((p = strrchr(program_name, '/')))
+ program_name = p + 1;
+ }
+
+ gettimeofday(&create_timeval, NULL);
+ create_time = create_timeval.tv_sec;
+ volume_id = (uint32_t) ((create_timeval.tv_sec << 20) | create_timeval.tv_usec); /* Default volume ID = creation time, fudged for more uniqueness */
+ check_atari();
+
+ printf("mkfs.fat " VERSION " (" VERSION_DATE ")\n");
+
+ while ((c = getopt_long(argc, argv, "aAb:cCf:D:F:Ii:l:m:M:n:r:R:s:S:h:v",
+ long_options, NULL)) != -1)
+ /* Scan the command line for options */
+ switch (c) {
+ case 'A': /* toggle Atari format */
+ atari_format = !atari_format;
+ break;
+
+ case 'a': /* a : skip alignment */
+ align_structures = FALSE;
+ break;
+
+ case 'b': /* b : location of backup boot sector */
+ backup_boot = (int)strtol(optarg, &tmp, 0);
+ if (*tmp || backup_boot < 2 || backup_boot > 0xffff) {
+ printf("Bad location for backup boot sector : %s\n", optarg);
+ usage(1);
+ }
+ break;
+
+ case 'c': /* c : Check FS as we build it */
+ check = TRUE;
+ malloc_entire_fat = TRUE; /* Need to be able to mark clusters bad */
+ break;
+
+ case 'C': /* C : Create a new file */
+ create = TRUE;
+ break;
+
+ case 'D': /* D : Choose Drive Number */
+ drive_number_option = (int) strtol (optarg, &tmp, 0);
+ if (*tmp || (drive_number_option != 0 && drive_number_option != 0x80)) {
+ printf ("Drive number must be 0 or 0x80: %s\n", optarg);
+ usage(1);
+ }
+ drive_number_by_user=1;
+ break;
+
+ case 'f': /* f : Choose number of FATs */
+ nr_fats = (int)strtol(optarg, &tmp, 0);
+ if (*tmp || nr_fats < 1 || nr_fats > 4) {
+ printf("Bad number of FATs : %s\n", optarg);
+ usage(1);
+ }
+ break;
+
+ case 'F': /* F : Choose FAT size */
+ size_fat = (int)strtol(optarg, &tmp, 0);
+ if (*tmp || (size_fat != 12 && size_fat != 16 && size_fat != 32)) {
+ printf("Bad FAT type : %s\n", optarg);
+ usage(1);
+ }
+ size_fat_by_user = 1;
+ break;
+
+ case 'h': /* h : number of hidden sectors */
+ hidden_sectors = (int)strtol(optarg, &tmp, 0);
+ if (*tmp || hidden_sectors < 0) {
+ printf("Bad number of hidden sectors : %s\n", optarg);
+ usage(1);
+ }
+ hidden_sectors_by_user = 1;
+ break;
+
+ case 'I':
+ ignore_full_disk = 1;
+ break;
+
+ case 'i': /* i : specify volume ID */
+ volume_id = strtoul(optarg, &tmp, 16);
+ if (*tmp) {
+ printf("Volume ID must be a hexadecimal number\n");
+ usage(1);
+ }
+ break;
+
+ case 'l': /* l : Bad block filename */
+ listfile = optarg;
+ malloc_entire_fat = TRUE; /* Need to be able to mark clusters bad */
+ break;
+
+ case 'm': /* m : Set boot message */
+ if (strcmp(optarg, "-")) {
+ msgfile = fopen(optarg, "r");
+ if (!msgfile)
+ perror(optarg);
+ } else
+ msgfile = stdin;
+
+ if (msgfile) {
+ /* The boot code ends at offset 448 and needs a null terminator */
+ i = MESSAGE_OFFSET;
+ pos = 0; /* We are at beginning of line */
+ do {
+ ch = getc(msgfile);
+ switch (ch) {
+ case '\r': /* Ignore CRs */
+ case '\0': /* and nulls */
+ break;
+
+ case '\n': /* LF -> CR+LF if necessary */
+ if (pos) { /* If not at beginning of line */
+ dummy_boot_code[i++] = '\r';
+ pos = 0;
+ }
+ dummy_boot_code[i++] = '\n';
+ break;
+
+ case '\t': /* Expand tabs */
+ do {
+ dummy_boot_code[i++] = ' ';
+ pos++;
+ }
+ while (pos % 8 && i < BOOTCODE_SIZE - 1);
+ break;
+
+ case EOF:
+ dummy_boot_code[i++] = '\0'; /* Null terminator */
+ break;
+
+ default:
+ dummy_boot_code[i++] = ch; /* Store character */
+ pos++; /* Advance position */
+ break;
+ }
+ }
+ while (ch != EOF && i < BOOTCODE_SIZE - 1);
+
+ /* Fill up with zeros */
+ while (i < BOOTCODE_SIZE - 1)
+ dummy_boot_code[i++] = '\0';
+ dummy_boot_code[BOOTCODE_SIZE - 1] = '\0'; /* Just in case */
+
+ if (ch != EOF)
+ printf("Warning: message too long; truncated\n");
+
+ if (msgfile != stdin)
+ fclose(msgfile);
+ }
+ break;
+
+ case 'M': /* M : FAT Media byte */
+ fat_media_byte = (int)strtol(optarg, &tmp, 0);
+ if (*tmp) {
+ printf("Bad number for media descriptor : %s\n", optarg);
+ usage(1);
+ }
+ if (fat_media_byte != 0xf0 && (fat_media_byte < 0xf8 || fat_media_byte > 0xff)) {
+ printf("FAT Media byte must either be between 0xF8 and 0xFF or be 0xF0 : %s\n", optarg);
+ usage(1);
+ }
+ break;
+
+ case 'n': /* n : Volume name */
+ sprintf(volume_name, "%-11.11s", optarg);
+ for (i = 0; volume_name[i] && i < 11; i++)
+ /* don't know if here should be more strict !uppercase(label[i]) */
+ if (islower(volume_name[i])) {
+ fprintf(stderr,
+ "mkfs.fat: warning - lowercase labels might not work properly with DOS or Windows\n");
+ break;
+ }
+
+ break;
+
+ case 'r': /* r : Root directory entries */
+ root_dir_entries = (int)strtol(optarg, &tmp, 0);
+ if (*tmp || root_dir_entries < 16 || root_dir_entries > 32768) {
+ printf("Bad number of root directory entries : %s\n", optarg);
+ usage(1);
+ }
+ break;
+
+ case 'R': /* R : number of reserved sectors */
+ reserved_sectors = (int)strtol(optarg, &tmp, 0);
+ if (*tmp || reserved_sectors < 1 || reserved_sectors > 0xffff) {
+ printf("Bad number of reserved sectors : %s\n", optarg);
+ usage(1);
+ }
+ break;
+
+ case 's': /* s : Sectors per cluster */
+ sectors_per_cluster = (int)strtol(optarg, &tmp, 0);
+ if (*tmp || (sectors_per_cluster != 1 && sectors_per_cluster != 2
+ && sectors_per_cluster != 4 && sectors_per_cluster != 8
+ && sectors_per_cluster != 16
+ && sectors_per_cluster != 32
+ && sectors_per_cluster != 64
+ && sectors_per_cluster != 128)) {
+ printf("Bad number of sectors per cluster : %s\n", optarg);
+ usage(1);
+ }
+ break;
+
+ case 'S': /* S : Sector size */
+ sector_size = (int)strtol(optarg, &tmp, 0);
+ if (*tmp || (sector_size != 512 && sector_size != 1024 &&
+ sector_size != 2048 && sector_size != 4096 &&
+ sector_size != 8192 && sector_size != 16384 &&
+ sector_size != 32768)) {
+ printf("Bad logical sector size : %s\n", optarg);
+ usage(1);
+ }
+ sector_size_set = 1;
+ break;
+
+ case 'v': /* v : Verbose execution */
+ ++verbose;
+ break;
+
+ case OPT_HELP:
+ usage(0);
+ break;
+
+ case OPT_INVARIANT:
+ invariant = 1;
+ volume_id = 0x1234abcd;
+ create_time = 1426325213;
+ break;
+
+ default:
+ printf("Unknown option: %c\n", c);
+ usage(1);
+ }
+ if (optind < argc) {
+ device_name = argv[optind]; /* Determine the number of blocks in the FS */
+
+ if (!device_name) {
+ printf("No device specified.\n");
+ usage(1);
+ }
+
+ if (!create)
+ cblocks = count_blocks(device_name, &orphaned_sectors); /* Have a look and see! */
+ }
+ if (optind == argc - 2) { /* Either check the user specified number */
+ blocks = strtoull(argv[optind + 1], &tmp, 0);
+ if (!create && blocks != cblocks) {
+ fprintf(stderr, "Warning: block count mismatch: ");
+ fprintf(stderr, "found %llu but assuming %llu.\n", (unsigned long long)cblocks, (unsigned long long)blocks);
+ }
+ if (*tmp)
+ bad_block_count = 1;
+ } else if (optind == argc - 1) { /* Or use value found */
+ if (create)
+ die("Need intended size with -C.");
+ blocks = cblocks;
+ } else {
+ fprintf(stderr, "No device specified!\n");
+ usage(1);
+ }
+ if (bad_block_count) {
+ printf("Bad block count : %s\n", argv[optind + 1]);
+ usage(1);
+ }
+
+ if (check && listfile) /* Auto and specified bad block handling are mutually */
+ die("-c and -l are incompatible"); /* exclusive of each other! */
+
+ if (!create) {
+ check_mount(device_name); /* Is the device already mounted? */
+ dev = open(device_name, O_EXCL | O_RDWR); /* Is it a suitable device to build the FS on? */
+ if (dev < 0) {
+ fprintf(stderr, "%s: unable to open %s: %s\n", program_name,
+ device_name, strerror(errno));
+ exit(1); /* The error exit code is 1! */
+ }
+ } else {
+ /* create the file */
+ dev = open(device_name, O_EXCL | O_RDWR | O_CREAT, 0666);
+ if (dev < 0) {
+ if (errno == EEXIST)
+ die("file %s already exists");
+ else
+ die("unable to create %s");
+ }
+ /* expand to desired size */
+ if (ftruncate(dev, blocks * BLOCK_SIZE))
+ die("unable to resize %s");
+ }
+
+ if (fstat(dev, &statbuf) < 0)
+ die("unable to stat %s");
+ if (!S_ISBLK(statbuf.st_mode)) {
+ statbuf.st_rdev = 0;
+ check = 0;
+ } else
+ /*
+ * Ignore any 'full' fixed disk devices, if -I is not given.
+ * On a MO-disk one doesn't need partitions. The filesytem can go
+ * directly to the whole disk. Under other OSes this is known as
+ * the 'superfloppy' format. As I don't know how to find out if
+ * this is a MO disk I introduce a -I (ignore) switch. -Joey
+ */
+ if (!ignore_full_disk && ((statbuf.st_rdev & 0xffffff3f) == 0x0300 || /* hda, hdb */
+ (statbuf.st_rdev & 0xffffff0f) == 0x0800 || /* sd */
+ (statbuf.st_rdev & 0xffffff3f) == 0x0d00 || /* xd */
+ (statbuf.st_rdev & 0xffffff3f) == 0x1600) /* hdc, hdd */
+ )
+ die("Device partition expected, not making filesystem on entire device '%s' (use -I to override)");
+
+ if (sector_size_set) {
+ if (ioctl(dev, BLKSSZGET, &min_sector_size) >= 0)
+ if (sector_size < min_sector_size) {
+ sector_size = min_sector_size;
+ fprintf(stderr,
+ "Warning: sector size was set to %d (minimal for this device)\n",
+ sector_size);
+ }
+ } else {
+ if (ioctl(dev, BLKSSZGET, &min_sector_size) >= 0) {
+ sector_size = min_sector_size;
+ sector_size_set = 1;
+ }
+ }
+
+ if (sector_size > 4096)
+ fprintf(stderr,
+ "Warning: sector size is set to %d > 4096, such filesystem will not propably mount\n",
+ sector_size);
+
+ establish_params(statbuf.st_rdev, statbuf.st_size);
+ /* Establish the media parameters */
+
+ setup_tables(); /* Establish the filesystem tables */
+
+ if (check) /* Determine any bad block locations and mark them */
+ check_blocks();
+ else if (listfile)
+ get_list_blocks(listfile);
+
+ write_tables(); /* Write the filesystem tables away! */
+
+ exit(0); /* Terminate with no errors! */
+}
diff --git a/dosfstools/src/msdos_fs.h b/dosfstools/src/msdos_fs.h
new file mode 100644
index 000000000..54b2a3446
--- /dev/null
+++ b/dosfstools/src/msdos_fs.h
@@ -0,0 +1,61 @@
+/* msdos_fs.h - MS-DOS filesystem constants/structures
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ The complete text of the GNU General Public License
+ can be found in /usr/share/common-licenses/GPL-3 file.
+*/
+
+#ifndef _MSDOS_FS_H
+#define _MSDOS_FS_H
+
+#include <stdint.h>
+
+#define SECTOR_SIZE 512 /* sector size (bytes) */
+#define MSDOS_DPS (SECTOR_SIZE / sizeof(struct msdos_dir_entry))
+#define MSDOS_DPS_BITS 4 /* log2(MSDOS_DPS) */
+#define MSDOS_DIR_BITS 5 /* log2(sizeof(struct msdos_dir_entry)) */
+
+#define ATTR_NONE 0 /* no attribute bits */
+#define ATTR_RO 1 /* read-only */
+#define ATTR_HIDDEN 2 /* hidden */
+#define ATTR_SYS 4 /* system */
+#define ATTR_VOLUME 8 /* volume label */
+#define ATTR_DIR 16 /* directory */
+#define ATTR_ARCH 32 /* archived */
+
+/* attribute bits that are copied "as is" */
+#define ATTR_UNUSED (ATTR_VOLUME | ATTR_ARCH | ATTR_SYS | ATTR_HIDDEN)
+
+#define DELETED_FLAG 0xe5 /* marks file as deleted when in name[0] */
+#define IS_FREE(n) (!*(n) || *(n) == DELETED_FLAG)
+
+#define MSDOS_NAME 11 /* maximum name length */
+#define MSDOS_DOT ". " /* ".", padded to MSDOS_NAME chars */
+#define MSDOS_DOTDOT ".. " /* "..", padded to MSDOS_NAME chars */
+
+struct msdos_dir_entry {
+ uint8_t name[8], ext[3]; /* name and extension */
+ uint8_t attr; /* attribute bits */
+ uint8_t lcase; /* Case for base and extension */
+ uint8_t ctime_cs; /* Creation time, centiseconds (0-199) */
+ uint16_t ctime; /* Creation time */
+ uint16_t cdate; /* Creation date */
+ uint16_t adate; /* Last access date */
+ uint16_t starthi; /* High 16 bits of cluster in FAT32 */
+ uint16_t time, date, start; /* time, date and first cluster */
+ uint32_t size; /* file size (in bytes) */
+} __attribute__ ((packed));
+
+#endif /* _MSDOS_FS_H */
diff --git a/dosfstools/src/version.h b/dosfstools/src/version.h
new file mode 100644
index 000000000..f0716d346
--- /dev/null
+++ b/dosfstools/src/version.h
@@ -0,0 +1,29 @@
+/* version.h
+
+ Copyright (C) 1998-2005 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
+ Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ The complete text of the GNU General Public License
+ can be found in /usr/share/common-licenses/GPL-3 file.
+*/
+
+#ifndef _version_h
+#define _version_h
+
+#define VERSION "3.0.28"
+#define VERSION_DATE "2015-05-16"
+
+#endif