summaryrefslogtreecommitdiffstats
path: root/exfat/libexfat
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--exfat/libexfat/COPYING339
-rw-r--r--exfat/libexfat/byteorder.h85
-rw-r--r--exfat/libexfat/cluster.c25
-rw-r--r--exfat/libexfat/compiler.h8
-rw-r--r--exfat/libexfat/exfat.h4
-rw-r--r--exfat/libexfat/exfatfs.h6
-rw-r--r--exfat/libexfat/io.c86
-rw-r--r--exfat/libexfat/log.c2
-rw-r--r--exfat/libexfat/lookup.c2
-rw-r--r--exfat/libexfat/mount.c75
-rw-r--r--exfat/libexfat/node.c220
-rw-r--r--exfat/libexfat/platform.h73
-rw-r--r--exfat/libexfat/time.c2
-rw-r--r--exfat/libexfat/utf.c2
-rw-r--r--exfat/libexfat/utils.c2
-rw-r--r--exfat/libexfat/version.h4
16 files changed, 586 insertions, 349 deletions
diff --git a/exfat/libexfat/COPYING b/exfat/libexfat/COPYING
new file mode 100644
index 000000000..d159169d1
--- /dev/null
+++ b/exfat/libexfat/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/exfat/libexfat/byteorder.h b/exfat/libexfat/byteorder.h
index dd039f283..10746e1ef 100644
--- a/exfat/libexfat/byteorder.h
+++ b/exfat/libexfat/byteorder.h
@@ -3,7 +3,7 @@
Endianness stuff. exFAT uses little-endian byte order.
Free exFAT implementation.
- Copyright (C) 2010-2014 Andrew Nayenko
+ Copyright (C) 2010-2013 Andrew Nayenko
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
@@ -23,15 +23,68 @@
#ifndef BYTEORDER_H_INCLUDED
#define BYTEORDER_H_INCLUDED
+#define __GLIBC__
#include <stdint.h>
-#include "platform.h"
+
+#if defined(__GLIBC__)
+
+#include <endian.h>
+#include <byteswap.h>
+
+#elif defined(__APPLE__)
+
+#include <machine/endian.h>
+#include <libkern/OSByteOrder.h>
+#define bswap_16(x) OSSwapInt16(x)
+#define bswap_32(x) OSSwapInt32(x)
+#define bswap_64(x) OSSwapInt64(x)
+#define __BYTE_ORDER BYTE_ORDER
+#define __LITTLE_ENDIAN LITTLE_ENDIAN
+#define __BIG_ENDIAN BIG_ENDIAN
+
+#elif defined(__FreeBSD__) || defined(__DragonFlyBSD__) || defined(__NetBSD__)
+
+#include <sys/endian.h>
+#define bswap_16(x) bswap16(x)
+#define bswap_32(x) bswap32(x)
+#define bswap_64(x) bswap64(x)
+#define __BYTE_ORDER _BYTE_ORDER
+#define __LITTLE_ENDIAN _LITTLE_ENDIAN
+#define __BIG_ENDIAN _BIG_ENDIAN
+
+#elif defined(__OpenBSD__)
+
+#include <machine/endian.h>
+#define bswap_16(x) swap16(x)
+#define bswap_32(x) swap32(x)
+#define bswap_64(x) swap64(x)
+#define __BYTE_ORDER _BYTE_ORDER
+#define __LITTLE_ENDIAN _LITTLE_ENDIAN
+#define __BIG_ENDIAN _BIG_ENDIAN
+
+#elif defined(__sun)
+
+#include <sys/byteorder.h>
+#define bswap_16(x) BSWAP_16(x)
+#define bswap_32(x) BSWAP_32(x)
+#define bswap_64(x) BSWAP_64(x)
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+#ifdef _LITTLE_ENDIAN
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#else
+#define __BYTE_ORDER __BIG_ENDIAN
+#endif
+
+#else
+#error No byte order macros available for your platform
+#endif
typedef struct { uint16_t __u16; } le16_t;
typedef struct { uint32_t __u32; } le32_t;
typedef struct { uint64_t __u64; } le64_t;
-#if EXFAT_BYTE_ORDER == EXFAT_LITTLE_ENDIAN
-
+#if __BYTE_ORDER == __LITTLE_ENDIAN
static inline uint16_t le16_to_cpu(le16_t v) { return v.__u16; }
static inline uint32_t le32_to_cpu(le32_t v) { return v.__u32; }
static inline uint64_t le64_to_cpu(le64_t v) { return v.__u64; }
@@ -39,27 +92,17 @@ static inline uint64_t le64_to_cpu(le64_t v) { return v.__u64; }
static inline le16_t cpu_to_le16(uint16_t v) { le16_t t = {v}; return t; }
static inline le32_t cpu_to_le32(uint32_t v) { le32_t t = {v}; return t; }
static inline le64_t cpu_to_le64(uint64_t v) { le64_t t = {v}; return t; }
-
-typedef size_t bitmap_t;
-
-#elif EXFAT_BYTE_ORDER == EXFAT_BIG_ENDIAN
-
-static inline uint16_t le16_to_cpu(le16_t v)
- { return exfat_bswap16(v.__u16); }
-static inline uint32_t le32_to_cpu(le32_t v)
- { return exfat_bswap32(v.__u32); }
-static inline uint64_t le64_to_cpu(le64_t v)
- { return exfat_bswap64(v.__u64); }
+#elif __BYTE_ORDER == __BIG_ENDIAN
+static inline uint16_t le16_to_cpu(le16_t v) { return bswap_16(v.__u16); }
+static inline uint32_t le32_to_cpu(le32_t v) { return bswap_32(v.__u32); }
+static inline uint64_t le64_to_cpu(le64_t v) { return bswap_64(v.__u64); }
static inline le16_t cpu_to_le16(uint16_t v)
- { le16_t t = {exfat_bswap16(v)}; return t; }
+ { le16_t t = {bswap_16(v)}; return t; }
static inline le32_t cpu_to_le32(uint32_t v)
- { le32_t t = {exfat_bswap32(v)}; return t; }
+ { le32_t t = {bswap_32(v)}; return t; }
static inline le64_t cpu_to_le64(uint64_t v)
- { le64_t t = {exfat_bswap64(v)}; return t; }
-
-typedef unsigned char bitmap_t;
-
+ { le64_t t = {bswap_64(v)}; return t; }
#else
#error Wow! You have a PDP machine?!
#endif
diff --git a/exfat/libexfat/cluster.c b/exfat/libexfat/cluster.c
index 80e3792dd..2215636c6 100644
--- a/exfat/libexfat/cluster.c
+++ b/exfat/libexfat/cluster.c
@@ -3,7 +3,7 @@
exFAT file system implementation library.
Free exFAT implementation.
- Copyright (C) 2010-2014 Andrew Nayenko
+ Copyright (C) 2010-2013 Andrew Nayenko
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
@@ -83,9 +83,9 @@ cluster_t exfat_next_cluster(const struct exfat* ef,
return cluster + 1;
fat_offset = s2o(ef, le32_to_cpu(ef->sb->fat_sector_start))
+ cluster * sizeof(cluster_t);
+ /* FIXME handle I/O error */
if (exfat_pread(ef->dev, &next, sizeof(next), fat_offset) < 0)
- return EXFAT_CLUSTER_BAD; /* the caller should handle this and print
- appropriate error message */
+ exfat_bug("failed to read the next cluster after %#x", cluster);
return le32_to_cpu(next);
}
@@ -136,23 +136,8 @@ static cluster_t find_bit_and_set(bitmap_t* bitmap, size_t start, size_t end)
return EXFAT_CLUSTER_END;
}
-static int flush_nodes(struct exfat* ef, struct exfat_node* node)
-{
- struct exfat_node* p;
-
- for (p = node->child; p != NULL; p = p->next)
- {
- int rc = flush_nodes(ef, p);
- if (rc != 0)
- return rc;
- }
- return exfat_flush_node(ef, node);
-}
-
int exfat_flush(struct exfat* ef)
{
- int rc = flush_nodes(ef, ef->root);
-
if (ef->cmap.dirty)
{
if (exfat_pwrite(ef->dev, ef->cmap.chunk,
@@ -164,8 +149,7 @@ int exfat_flush(struct exfat* ef)
}
ef->cmap.dirty = false;
}
-
- return rc;
+ return 0;
}
static bool set_next_cluster(const struct exfat* ef, bool contiguous,
@@ -332,7 +316,6 @@ static int shrink_file(struct exfat* ef, struct exfat_node* node,
{
previous = node->start_cluster;
node->start_cluster = EXFAT_CLUSTER_FREE;
- node->flags |= EXFAT_ATTRIB_DIRTY;
}
node->fptr_index = 0;
node->fptr_cluster = node->start_cluster;
diff --git a/exfat/libexfat/compiler.h b/exfat/libexfat/compiler.h
index 473726d3a..6edd8ec7f 100644
--- a/exfat/libexfat/compiler.h
+++ b/exfat/libexfat/compiler.h
@@ -4,7 +4,7 @@
showstopper.
Free exFAT implementation.
- Copyright (C) 2010-2014 Andrew Nayenko
+ Copyright (C) 2010-2013 Andrew Nayenko
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
@@ -24,12 +24,6 @@
#ifndef COMPILER_H_INCLUDED
#define COMPILER_H_INCLUDED
-/*
-#if __STDC_VERSION__ < 199901L
-#error C99-compliant compiler is required
-#endif
-*/
-
#if defined(__clang__)
#define PRINTF __attribute__((format(printf, 1, 2)))
diff --git a/exfat/libexfat/exfat.h b/exfat/libexfat/exfat.h
index 69fb45d45..ff58e8414 100644
--- a/exfat/libexfat/exfat.h
+++ b/exfat/libexfat/exfat.h
@@ -4,7 +4,7 @@
implementation.
Free exFAT implementation.
- Copyright (C) 2010-2014 Andrew Nayenko
+ Copyright (C) 2010-2013 Andrew Nayenko
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
@@ -51,6 +51,7 @@
#define ROUND_UP(x, d) (DIV_ROUND_UP(x, d) * (d))
#define UTF8_BYTES(c) ((c) * 6) /* UTF-8 character can occupy up to 6 bytes */
+typedef size_t bitmap_t;
#define BMAP_SIZE(count) (ROUND_UP(count, sizeof(bitmap_t) * 8) / 8)
#define BMAP_BLOCK(index) ((index) / sizeof(bitmap_t) / 8)
#define BMAP_MASK(index) ((bitmap_t) 1 << ((index) % (sizeof(bitmap_t) * 8)))
@@ -193,7 +194,6 @@ size_t utf16_length(const le16_t* str);
struct exfat_node* exfat_get_node(struct exfat_node* node);
void exfat_put_node(struct exfat* ef, struct exfat_node* node);
-int exfat_cleanup_node(struct exfat* ef, struct exfat_node* node);
int exfat_cache_directory(struct exfat* ef, struct exfat_node* dir);
void exfat_reset_cache(struct exfat* ef);
int exfat_flush_node(struct exfat* ef, struct exfat_node* node);
diff --git a/exfat/libexfat/exfatfs.h b/exfat/libexfat/exfatfs.h
index fbec79f60..a436daa63 100644
--- a/exfat/libexfat/exfatfs.h
+++ b/exfat/libexfat/exfatfs.h
@@ -3,7 +3,7 @@
Definitions of structures and constants used in exFAT file system.
Free exFAT implementation.
- Copyright (C) 2010-2014 Andrew Nayenko
+ Copyright (C) 2010-2013 Andrew Nayenko
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
@@ -153,10 +153,10 @@ struct exfat_entry_meta2 /* file or directory info (part 2) */
uint8_t name_length;
le16_t name_hash;
le16_t __unknown2;
- le64_t valid_size; /* in bytes, less or equal to size */
+ le64_t real_size; /* in bytes, equals to size */
uint8_t __unknown3[4];
le32_t start_cluster;
- le64_t size; /* in bytes */
+ le64_t size; /* in bytes, equals to real_size */
}
PACKED;
STATIC_ASSERT(sizeof(struct exfat_entry_meta2) == 32);
diff --git a/exfat/libexfat/io.c b/exfat/libexfat/io.c
index a861bddd7..306c5dd06 100644
--- a/exfat/libexfat/io.c
+++ b/exfat/libexfat/io.c
@@ -3,7 +3,7 @@
exFAT file system implementation library.
Free exFAT implementation.
- Copyright (C) 2010-2014 Andrew Nayenko
+ Copyright (C) 2010-2013 Andrew Nayenko
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
@@ -24,19 +24,13 @@
#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/mount.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
-#include <errno.h>
-#if defined(__APPLE__)
+#ifdef __APPLE__
#include <sys/disk.h>
-#elif defined(__OpenBSD__)
-#include <sys/param.h>
-#include <sys/disklabel.h>
-#include <sys/dkio.h>
-#include <sys/ioctl.h>
#endif
-#include <sys/mount.h>
#ifdef USE_UBLIO
#include <sys/uio.h>
#include <ublio.h>
@@ -71,7 +65,6 @@ static int open_rw(const char* spec)
if (fd != -1 && ioctl(fd, BLKROGET, &ro) == 0 && ro)
{
close(fd);
- errno = EROFS;
return -1;
}
#endif
@@ -100,8 +93,7 @@ struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode)
if (dev->fd == -1)
{
free(dev);
- exfat_error("failed to open '%s' in read-only mode: %s", spec,
- strerror(errno));
+ exfat_error("failed to open `%s' in read-only mode", spec);
return NULL;
}
dev->mode = EXFAT_MODE_RO;
@@ -111,8 +103,7 @@ struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode)
if (dev->fd == -1)
{
free(dev);
- exfat_error("failed to open '%s' in read-write mode: %s", spec,
- strerror(errno));
+ exfat_error("failed to open `%s' in read-write mode", spec);
return NULL;
}
dev->mode = EXFAT_MODE_RW;
@@ -128,11 +119,11 @@ struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode)
if (dev->fd != -1)
{
dev->mode = EXFAT_MODE_RO;
- exfat_warn("'%s' is write-protected, mounting read-only", spec);
+ exfat_warn("`%s' is write-protected, mounting read-only", spec);
break;
}
free(dev);
- exfat_error("failed to open '%s': %s", spec, strerror(errno));
+ exfat_error("failed to open `%s'", spec);
return NULL;
}
@@ -140,7 +131,7 @@ struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode)
{
close(dev->fd);
free(dev);
- exfat_error("failed to fstat '%s'", spec);
+ exfat_error("failed to fstat `%s'", spec);
return NULL;
}
if (!S_ISBLK(stbuf.st_mode) &&
@@ -149,11 +140,11 @@ struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode)
{
close(dev->fd);
free(dev);
- exfat_error("'%s' is neither a device, nor a regular file", spec);
+ exfat_error("`%s' is neither a device, nor a regular file", spec);
return NULL;
}
-#if defined(__APPLE__)
+#ifdef __APPLE__
if (!S_ISREG(stbuf.st_mode))
{
uint32_t block_size = 0;
@@ -176,32 +167,6 @@ struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode)
dev->size = blocks * block_size;
}
else
-#elif defined(__OpenBSD__)
- if (!S_ISREG(stbuf.st_mode))
- {
- struct disklabel lab;
- struct partition* pp;
- char* partition;
-
- if (ioctl(dev->fd, DIOCGDINFO, &lab) == -1)
- {
- close(dev->fd);
- free(dev);
- exfat_error("failed to get disklabel");
- return NULL;
- }
-
- /* Don't need to check that partition letter is valid as we won't get
- this far otherwise. */
- partition = strchr(spec, '\0') - 1;
- pp = &(lab.d_partitions[*partition - 'a']);
- dev->size = DL_GETPSIZE(pp) * lab.d_secsize;
-
- if (pp->p_fstype != FS_NTFS)
- exfat_warn("partition type is not 0x07 (NTFS/exFAT); "
- "you can fix this with fdisk(8)");
- }
- else
#endif
{
/* works for Linux, FreeBSD, Solaris */
@@ -210,14 +175,14 @@ struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode)
{
close(dev->fd);
free(dev);
- exfat_error("failed to get size of '%s'", spec);
+ exfat_error("failed to get size of `%s'", spec);
return NULL;
}
if (exfat_seek(dev, 0, SEEK_SET) == -1)
{
close(dev->fd);
free(dev);
- exfat_error("failed to seek to the beginning of '%s'", spec);
+ exfat_error("failed to seek to the beginning of `%s'", spec);
return NULL;
}
}
@@ -245,41 +210,32 @@ struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode)
int exfat_close(struct exfat_dev* dev)
{
- int rc = 0;
-
#ifdef USE_UBLIO
if (ublio_close(dev->ufh) != 0)
- {
exfat_error("failed to close ublio");
- rc = -EIO;
- }
#endif
if (close(dev->fd) != 0)
{
- exfat_error("failed to close device: %s", strerror(errno));
- rc = -EIO;
+ free(dev);
+ exfat_error("failed to close device");
+ return 1;
}
free(dev);
- return rc;
+ return 0;
}
int exfat_fsync(struct exfat_dev* dev)
{
- int rc = 0;
-
#ifdef USE_UBLIO
if (ublio_fsync(dev->ufh) != 0)
- {
- exfat_error("ublio fsync failed");
- rc = -EIO;
- }
-#endif
+#else
if (fsync(dev->fd) != 0)
+#endif
{
- exfat_error("fsync failed: %s", strerror(errno));
- rc = -EIO;
+ exfat_error("fsync failed");
+ return 1;
}
- return rc;
+ return 0;
}
enum exfat_mode exfat_get_mode(const struct exfat_dev* dev)
diff --git a/exfat/libexfat/log.c b/exfat/libexfat/log.c
index 9c29550c6..7e541aafb 100644
--- a/exfat/libexfat/log.c
+++ b/exfat/libexfat/log.c
@@ -3,7 +3,7 @@
exFAT file system implementation library.
Free exFAT implementation.
- Copyright (C) 2010-2014 Andrew Nayenko
+ Copyright (C) 2010-2013 Andrew Nayenko
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
diff --git a/exfat/libexfat/lookup.c b/exfat/libexfat/lookup.c
index 51915e630..00cd5335e 100644
--- a/exfat/libexfat/lookup.c
+++ b/exfat/libexfat/lookup.c
@@ -3,7 +3,7 @@
exFAT file system implementation library.
Free exFAT implementation.
- Copyright (C) 2010-2014 Andrew Nayenko
+ Copyright (C) 2010-2013 Andrew Nayenko
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
diff --git a/exfat/libexfat/mount.c b/exfat/libexfat/mount.c
index 027f8b0e0..928c561dc 100644
--- a/exfat/libexfat/mount.c
+++ b/exfat/libexfat/mount.c
@@ -3,7 +3,7 @@
exFAT file system implementation library.
Free exFAT implementation.
- Copyright (C) 2010-2014 Andrew Nayenko
+ Copyright (C) 2010-2013 Andrew Nayenko
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
@@ -24,7 +24,6 @@
#include <string.h>
#include <stdlib.h>
#include <errno.h>
-#include <inttypes.h>
#include <unistd.h>
#include <sys/types.h>
@@ -40,12 +39,6 @@ static uint64_t rootdir_size(const struct exfat* ef)
to indicate this */
rootdir_cluster = exfat_next_cluster(ef, ef->root, rootdir_cluster);
}
- if (rootdir_cluster != EXFAT_CLUSTER_END)
- {
- exfat_error("bad cluster %#x while reading root directory",
- rootdir_cluster);
- return 0;
- }
return clusters * CLUSTER_SIZE(*ef->sb);
}
@@ -98,7 +91,7 @@ static void parse_options(struct exfat* ef, const char* options)
ef->noatime = match_option(options, "noatime");
}
-static bool verify_vbr_checksum(struct exfat_dev* dev, void* sector,
+static int verify_vbr_checksum(struct exfat_dev* dev, void* sector,
off64_t sector_size)
{
uint32_t vbr_checksum;
@@ -107,7 +100,7 @@ static bool verify_vbr_checksum(struct exfat_dev* dev, void* sector,
if (exfat_pread(dev, sector, sector_size, 0) < 0)
{
exfat_error("failed to read boot sector");
- return false;
+ return 1;
}
vbr_checksum = exfat_vbr_start_checksum(sector, sector_size);
for (i = 1; i < 11; i++)
@@ -115,7 +108,7 @@ static bool verify_vbr_checksum(struct exfat_dev* dev, void* sector,
if (exfat_pread(dev, sector, sector_size, i * sector_size) < 0)
{
exfat_error("failed to read VBR sector");
- return false;
+ return 1;
}
vbr_checksum = exfat_vbr_add_checksum(sector, sector_size,
vbr_checksum);
@@ -123,16 +116,16 @@ static bool verify_vbr_checksum(struct exfat_dev* dev, void* sector,
if (exfat_pread(dev, sector, sector_size, i * sector_size) < 0)
{
exfat_error("failed to read VBR checksum sector");
- return false;
+ return 1;
}
for (i = 0; i < sector_size / sizeof(vbr_checksum); i++)
if (le32_to_cpu(((const le32_t*) sector)[i]) != vbr_checksum)
{
exfat_error("invalid VBR checksum 0x%x (expected 0x%x)",
le32_to_cpu(((const le32_t*) sector)[i]), vbr_checksum);
- return false;
+ return 1;
}
- return true;
+ return 0;
}
static int commit_super_block(const struct exfat* ef)
@@ -208,26 +201,8 @@ int exfat_mount(struct exfat* ef, const char* spec, const char* options)
exfat_error("exFAT file system is not found");
return -EIO;
}
- ef->zero_cluster = malloc(CLUSTER_SIZE(*ef->sb));
- if (ef->zero_cluster == NULL)
- {
- exfat_close(ef->dev);
- free(ef->sb);
- exfat_error("failed to allocate zero sector");
- return -ENOMEM;
- }
- /* use zero_cluster as a temporary buffer for VBR checksum verification */
- if (!verify_vbr_checksum(ef->dev, ef->zero_cluster, SECTOR_SIZE(*ef->sb)))
- {
- free(ef->zero_cluster);
- exfat_close(ef->dev);
- free(ef->sb);
- return -EIO;
- }
- memset(ef->zero_cluster, 0, CLUSTER_SIZE(*ef->sb));
if (ef->sb->version.major != 1 || ef->sb->version.minor != 0)
{
- free(ef->zero_cluster);
exfat_close(ef->dev);
exfat_error("unsupported exFAT version: %hhu.%hhu",
ef->sb->version.major, ef->sb->version.minor);
@@ -236,34 +211,39 @@ int exfat_mount(struct exfat* ef, const char* spec, const char* options)
}
if (ef->sb->fat_count != 1)
{
- free(ef->zero_cluster);
exfat_close(ef->dev);
- exfat_error("unsupported FAT count: %hhu", ef->sb->fat_count);
free(ef->sb);
+ exfat_error("unsupported FAT count: %hhu", ef->sb->fat_count);
return -EIO;
}
/* officially exFAT supports cluster size up to 32 MB */
if ((int) ef->sb->sector_bits + (int) ef->sb->spc_bits > 25)
{
- free(ef->zero_cluster);
exfat_close(ef->dev);
+ free(ef->sb);
exfat_error("too big cluster size: 2^%d",
(int) ef->sb->sector_bits + (int) ef->sb->spc_bits);
- free(ef->sb);
return -EIO;
}
- if (le64_to_cpu(ef->sb->sector_count) * SECTOR_SIZE(*ef->sb) >
- exfat_get_size(ef->dev))
+
+ ef->zero_cluster = malloc(CLUSTER_SIZE(*ef->sb));
+ if (ef->zero_cluster == NULL)
+ {
+ exfat_close(ef->dev);
+ free(ef->sb);
+ exfat_error("failed to allocate zero sector");
+ return -ENOMEM;
+ }
+ /* use zero_cluster as a temporary buffer for VBR checksum verification */
+ if (verify_vbr_checksum(ef->dev, ef->zero_cluster,
+ SECTOR_SIZE(*ef->sb)) != 0)
{
free(ef->zero_cluster);
- exfat_error("file system is larger than underlying device: "
- "%"PRIu64" > %"PRIu64,
- le64_to_cpu(ef->sb->sector_count) * SECTOR_SIZE(*ef->sb),
- exfat_get_size(ef->dev));
exfat_close(ef->dev);
free(ef->sb);
return -EIO;
}
+ memset(ef->zero_cluster, 0, CLUSTER_SIZE(*ef->sb));
ef->root = malloc(sizeof(struct exfat_node));
if (ef->root == NULL)
@@ -280,14 +260,6 @@ int exfat_mount(struct exfat* ef, const char* spec, const char* options)
ef->root->fptr_cluster = ef->root->start_cluster;
ef->root->name[0] = cpu_to_le16('\0');
ef->root->size = rootdir_size(ef);
- if (ef->root->size == 0)
- {
- free(ef->root);
- free(ef->zero_cluster);
- exfat_close(ef->dev);
- free(ef->sb);
- return -EIO;
- }
/* exFAT does not have time attributes for the root directory */
ef->root->mtime = 0;
ef->root->atime = 0;
@@ -342,12 +314,11 @@ static void finalize_super_block(struct exfat* ef)
ef->sb->allocated_percent = ((total - free) * 100 + total / 2) / total;
}
- commit_super_block(ef); /* ignore return code */
+ commit_super_block(ef);
}
void exfat_unmount(struct exfat* ef)
{
- exfat_flush(ef); /* ignore return code */
exfat_put_node(ef, ef->root);
exfat_reset_cache(ef);
free(ef->root);
diff --git a/exfat/libexfat/node.c b/exfat/libexfat/node.c
index 1d663870c..56205fced 100644
--- a/exfat/libexfat/node.c
+++ b/exfat/libexfat/node.c
@@ -3,7 +3,7 @@
exFAT file system implementation library.
Free exFAT implementation.
- Copyright (C) 2010-2014 Andrew Nayenko
+ Copyright (C) 2010-2013 Andrew Nayenko
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
@@ -44,47 +44,31 @@ struct exfat_node* exfat_get_node(struct exfat_node* node)
void exfat_put_node(struct exfat* ef, struct exfat_node* node)
{
- char buffer[UTF8_BYTES(EXFAT_NAME_MAX) + 1];
-
- --node->references;
- if (node->references < 0)
+ if (--node->references < 0)
{
+ char buffer[UTF8_BYTES(EXFAT_NAME_MAX) + 1];
exfat_get_name(node, buffer, sizeof(buffer) - 1);
- exfat_bug("reference counter of '%s' is below zero", buffer);
+ exfat_bug("reference counter of `%s' is below zero", buffer);
}
- else if (node->references == 0 && node != ef->root)
+
+ if (node->references == 0)
{
- if (node->flags & EXFAT_ATTRIB_DIRTY)
+ /* FIXME handle I/O error */
+ if (exfat_flush_node(ef, node) != 0)
+ exfat_bug("node flush failed");
+ if (node->flags & EXFAT_ATTRIB_UNLINKED)
{
- exfat_get_name(node, buffer, sizeof(buffer) - 1);
- exfat_warn("dirty node '%s' with zero references", buffer);
+ /* free all clusters and node structure itself */
+ exfat_truncate(ef, node, 0, true);
+ free(node);
}
+ /* FIXME handle I/O error */
+ if (exfat_flush(ef) != 0)
+ exfat_bug("flush failed");
}
}
/**
- * This function must be called on rmdir and unlink (after the last
- * exfat_put_node()) to free clusters.
- */
-int exfat_cleanup_node(struct exfat* ef, struct exfat_node* node)
-{
- int rc = 0;
-
- if (node->references != 0)
- exfat_bug("unable to cleanup a node with %d references",
- node->references);
-
- if (node->flags & EXFAT_ATTRIB_UNLINKED)
- {
- /* free all clusters and node structure itself */
- rc = exfat_truncate(ef, node, 0, true);
- /* free the node even in case of error or its memory will be lost */
- free(node);
- }
- return rc;
-}
-
-/**
* Cluster + offset from the beginning of the directory to absolute offset.
*/
static off64_t co2o(struct exfat* ef, cluster_t cluster, off64_t offset)
@@ -124,7 +108,7 @@ static void closedir(struct iterator* it)
it->chunk = NULL;
}
-static bool fetch_next_entry(struct exfat* ef, const struct exfat_node* parent,
+static int fetch_next_entry(struct exfat* ef, const struct exfat_node* parent,
struct iterator* it)
{
/* move iterator to the next entry in the directory */
@@ -135,23 +119,23 @@ static bool fetch_next_entry(struct exfat* ef, const struct exfat_node* parent,
/* reached the end of directory; the caller should check this
condition too */
if (it->offset >= parent->size)
- return true;
+ return 0;
it->cluster = exfat_next_cluster(ef, parent, it->cluster);
if (CLUSTER_INVALID(it->cluster))
{
exfat_error("invalid cluster 0x%x while reading directory",
it->cluster);
- return false;
+ return 1;
}
if (exfat_pread(ef->dev, it->chunk, CLUSTER_SIZE(*ef->sb),
exfat_c2o(ef, it->cluster)) < 0)
{
exfat_error("failed to read the next directory cluster %#x",
it->cluster);
- return false;
+ return 1;
}
}
- return true;
+ return 0;
}
static struct exfat_node* allocate_node(void)
@@ -193,40 +177,6 @@ static const struct exfat_entry* get_entry_ptr(const struct exfat* ef,
(it->chunk + it->offset % CLUSTER_SIZE(*ef->sb));
}
-static bool check_node(const struct exfat_node* node, uint16_t actual_checksum,
- uint16_t reference_checksum, uint64_t valid_size)
-{
- char buffer[UTF8_BYTES(EXFAT_NAME_MAX) + 1];
-
- /*
- Validate checksum first. If it's invalid all other fields probably
- contain just garbage.
- */
- if (actual_checksum != reference_checksum)
- {
- exfat_get_name(node, buffer, sizeof(buffer) - 1);
- exfat_error("'%s' has invalid checksum (%#hx != %#hx)", buffer,
- actual_checksum, reference_checksum);
- return false;
- }
-
- /*
- exFAT does not support sparse files but allows files with uninitialized
- clusters. For such files valid_size means initialized data size and
- cannot be greater than file size. See SetFileValidData() function
- description in MSDN.
- */
- if (valid_size > node->size)
- {
- exfat_get_name(node, buffer, sizeof(buffer) - 1);
- exfat_error("'%s' has valid size (%"PRIu64") greater than size "
- "(%"PRIu64")", buffer, valid_size, node->size);
- return false;
- }
-
- return true;
-}
-
/*
* Reads one entry in directory at position pointed by iterator and fills
* node structure.
@@ -246,7 +196,7 @@ static int readdir(struct exfat* ef, const struct exfat_node* parent,
le16_t* namep = NULL;
uint16_t reference_checksum = 0;
uint16_t actual_checksum = 0;
- uint64_t valid_size = 0;
+ uint64_t real_size = 0;
*node = NULL;
@@ -317,7 +267,7 @@ static int readdir(struct exfat* ef, const struct exfat_node* parent,
}
init_node_meta2(*node, meta2);
actual_checksum = exfat_add_checksum(entry, actual_checksum);
- valid_size = le64_to_cpu(meta2->valid_size);
+ real_size = le64_to_cpu(meta2->real_size);
/* empty files must be marked as non-contiguous */
if ((*node)->size == 0 && (meta2->flags & EXFAT_FLAG_CONTIGUOUS))
{
@@ -352,10 +302,37 @@ static int readdir(struct exfat* ef, const struct exfat_node* parent,
namep += EXFAT_ENAME_MAX;
if (--continuations == 0)
{
- if (!check_node(*node, actual_checksum, reference_checksum,
- valid_size))
+ /*
+ There are two fields that contain file size. Maybe they
+ plan to add compression support in the future and one of
+ those fields is visible (uncompressed) size and the other
+ is real (compressed) size. Anyway, currently it looks like
+ exFAT does not support compression and both fields must be
+ equal.
+
+ There is an exception though: pagefile.sys (its real_size
+ is always 0).
+ */
+ if (real_size != (*node)->size)
+ {
+ char buffer[UTF8_BYTES(EXFAT_NAME_MAX) + 1];
+
+ exfat_get_name(*node, buffer, sizeof(buffer) - 1);
+ exfat_error("`%s' real size does not equal to size "
+ "(%"PRIu64" != %"PRIu64")", buffer,
+ real_size, (*node)->size);
goto error;
- if (!fetch_next_entry(ef, parent, it))
+ }
+ if (actual_checksum != reference_checksum)
+ {
+ char buffer[UTF8_BYTES(EXFAT_NAME_MAX) + 1];
+
+ exfat_get_name(*node, buffer, sizeof(buffer) - 1);
+ exfat_error("`%s' has invalid checksum (0x%hx != 0x%hx)",
+ buffer, actual_checksum, reference_checksum);
+ goto error;
+ }
+ if (fetch_next_entry(ef, parent, it) != 0)
goto error;
return 0; /* entry completed */
}
@@ -462,7 +439,7 @@ static int readdir(struct exfat* ef, const struct exfat_node* parent,
break;
}
- if (!fetch_next_entry(ef, parent, it))
+ if (fetch_next_entry(ef, parent, it) != 0)
goto error;
}
/* we never reach here */
@@ -543,8 +520,6 @@ static void tree_detach(struct exfat_node* node)
static void reset_cache(struct exfat* ef, struct exfat_node* node)
{
- char buffer[UTF8_BYTES(EXFAT_NAME_MAX) + 1];
-
while (node->child)
{
struct exfat_node* p = node->child;
@@ -555,15 +530,11 @@ static void reset_cache(struct exfat* ef, struct exfat_node* node)
node->flags &= ~EXFAT_ATTRIB_CACHED;
if (node->references != 0)
{
+ char buffer[UTF8_BYTES(EXFAT_NAME_MAX) + 1];
exfat_get_name(node, buffer, sizeof(buffer) - 1);
- exfat_warn("non-zero reference counter (%d) for '%s'",
+ exfat_warn("non-zero reference counter (%d) for `%s'",
node->references, buffer);
}
- if (node != ef->root && (node->flags & EXFAT_ATTRIB_DIRTY))
- {
- exfat_get_name(node, buffer, sizeof(buffer) - 1);
- exfat_bug("node '%s' is dirty", buffer);
- }
while (node->references)
exfat_put_node(ef, node);
}
@@ -573,21 +544,13 @@ void exfat_reset_cache(struct exfat* ef)
reset_cache(ef, ef->root);
}
-static bool next_entry(struct exfat* ef, const struct exfat_node* parent,
+static void next_entry(struct exfat* ef, const struct exfat_node* parent,
cluster_t* cluster, off64_t* offset)
{
*offset += sizeof(struct exfat_entry);
if (*offset % CLUSTER_SIZE(*ef->sb) == 0)
- {
+ /* next cluster cannot be invalid */
*cluster = exfat_next_cluster(ef, parent, *cluster);
- if (CLUSTER_INVALID(*cluster))
- {
- exfat_error("invalid cluster %#x while getting next entry",
- *cluster);
- return false;
- }
- }
- return true;
}
int exfat_flush_node(struct exfat* ef, struct exfat_node* node)
@@ -610,8 +573,7 @@ int exfat_flush_node(struct exfat* ef, struct exfat_node* node)
cluster = node->entry_cluster;
offset = node->entry_offset;
meta1_offset = co2o(ef, cluster, offset);
- if (!next_entry(ef, node->parent, &cluster, &offset))
- return -EIO;
+ next_entry(ef, node->parent, &cluster, &offset);
meta2_offset = co2o(ef, cluster, offset);
if (exfat_pread(ef->dev, &meta1, sizeof(meta1), meta1_offset) < 0)
@@ -632,7 +594,7 @@ int exfat_flush_node(struct exfat* ef, struct exfat_node* node)
}
if (meta2.type != EXFAT_ENTRY_FILE_INFO)
exfat_bug("invalid type of meta2: 0x%hhx", meta2.type);
- meta2.size = meta2.valid_size = cpu_to_le64(node->size);
+ meta2.size = meta2.real_size = cpu_to_le64(node->size);
meta2.start_cluster = cpu_to_le32(node->start_cluster);
meta2.flags = EXFAT_FLAG_ALWAYS1;
/* empty files must not be marked as contiguous */
@@ -671,8 +633,7 @@ static bool erase_entry(struct exfat* ef, struct exfat_node* node)
return false;
}
- if (!next_entry(ef, node->parent, &cluster, &offset))
- return false;
+ next_entry(ef, node->parent, &cluster, &offset);
entry_type = EXFAT_ENTRY_FILE_INFO & ~EXFAT_ENTRY_VALID;
if (exfat_pwrite(ef->dev, &entry_type, 1, co2o(ef, cluster, offset)) < 0)
{
@@ -682,8 +643,7 @@ static bool erase_entry(struct exfat* ef, struct exfat_node* node)
while (name_entries--)
{
- if (!next_entry(ef, node->parent, &cluster, &offset))
- return false;
+ next_entry(ef, node->parent, &cluster, &offset);
entry_type = EXFAT_ENTRY_FILE_NAME & ~EXFAT_ENTRY_VALID;
if (exfat_pwrite(ef->dev, &entry_type, 1,
co2o(ef, cluster, offset)) < 0)
@@ -702,6 +662,7 @@ static int shrink_directory(struct exfat* ef, struct exfat_node* dir,
const struct exfat_node* last_node;
uint64_t entries = 0;
uint64_t new_size;
+ int rc;
if (!(dir->flags & EXFAT_ATTRIB_DIR))
exfat_bug("attempted to shrink a file");
@@ -737,7 +698,10 @@ static int shrink_directory(struct exfat* ef, struct exfat_node* dir,
new_size = CLUSTER_SIZE(*ef->sb);
if (new_size == dir->size)
return 0;
- return exfat_truncate(ef, dir, new_size, true);
+ rc = exfat_truncate(ef, dir, new_size, true);
+ if (rc != 0)
+ return rc;
+ return 0;
}
static int delete(struct exfat* ef, struct exfat_node* node)
@@ -755,15 +719,9 @@ static int delete(struct exfat* ef, struct exfat_node* node)
exfat_update_mtime(parent);
tree_detach(node);
rc = shrink_directory(ef, parent, deleted_offset);
- node->flags |= EXFAT_ATTRIB_UNLINKED;
- if (rc != 0)
- {
- exfat_flush_node(ef, parent);
- exfat_put_node(ef, parent);
- return rc;
- }
- rc = exfat_flush_node(ef, parent);
exfat_put_node(ef, parent);
+ /* file clusters will be freed when node reference counter becomes 0 */
+ node->flags |= EXFAT_ATTRIB_UNLINKED;
return rc;
}
@@ -776,14 +734,10 @@ int exfat_unlink(struct exfat* ef, struct exfat_node* node)
int exfat_rmdir(struct exfat* ef, struct exfat_node* node)
{
- int rc;
-
if (!(node->flags & EXFAT_ATTRIB_DIR))
return -ENOTDIR;
/* check that directory is empty */
- rc = exfat_cache_directory(ef, node);
- if (rc != 0)
- return rc;
+ exfat_cache_directory(ef, node);
if (node->child)
return -ENOTEMPTY;
return delete(ef, node);
@@ -832,7 +786,7 @@ static int find_slot(struct exfat* ef, struct exfat_node* dir,
return rc;
}
}
- if (!fetch_next_entry(ef, dir, &it))
+ if (fetch_next_entry(ef, dir, &it) != 0)
{
closedir(&it);
return -EIO;
@@ -884,8 +838,7 @@ static int write_entry(struct exfat* ef, struct exfat_node* dir,
exfat_error("failed to write meta1 entry");
return -EIO;
}
- if (!next_entry(ef, dir, &cluster, &offset))
- return -EIO;
+ next_entry(ef, dir, &cluster, &offset);
if (exfat_pwrite(ef->dev, &meta2, sizeof(meta2),
co2o(ef, cluster, offset)) < 0)
{
@@ -898,8 +851,7 @@ static int write_entry(struct exfat* ef, struct exfat_node* dir,
memcpy(name_entry.name, node->name + i * EXFAT_ENAME_MAX,
MIN(EXFAT_ENAME_MAX, EXFAT_NAME_MAX - i * EXFAT_ENAME_MAX) *
sizeof(le16_t));
- if (!next_entry(ef, dir, &cluster, &offset))
- return -EIO;
+ next_entry(ef, dir, &cluster, &offset);
if (exfat_pwrite(ef->dev, &name_entry, sizeof(name_entry),
co2o(ef, cluster, offset)) < 0)
{
@@ -943,12 +895,6 @@ static int create(struct exfat* ef, const char* path, uint16_t attrib)
return rc;
}
rc = write_entry(ef, dir, name, cluster, offset, attrib);
- if (rc != 0)
- {
- exfat_put_node(ef, dir);
- return rc;
- }
- rc = exfat_flush_node(ef, dir);
exfat_put_node(ef, dir);
return rc;
}
@@ -977,13 +923,6 @@ int exfat_mkdir(struct exfat* ef, const char* path)
exfat_put_node(ef, node);
return rc;
}
- rc = exfat_flush_node(ef, node);
- if (rc != 0)
- {
- delete(ef, node);
- exfat_put_node(ef, node);
- return rc;
- }
exfat_put_node(ef, node);
return 0;
}
@@ -1006,8 +945,7 @@ static int rename_entry(struct exfat* ef, struct exfat_node* dir,
exfat_error("failed to read meta1 entry on rename");
return -EIO;
}
- if (!next_entry(ef, node->parent, &old_cluster, &old_offset))
- return -EIO;
+ next_entry(ef, node->parent, &old_cluster, &old_offset);
if (exfat_pread(ef->dev, &meta2, sizeof(meta2),
co2o(ef, old_cluster, old_offset)) < 0)
{
@@ -1031,8 +969,7 @@ static int rename_entry(struct exfat* ef, struct exfat_node* dir,
exfat_error("failed to write meta1 entry on rename");
return -EIO;
}
- if (!next_entry(ef, dir, &new_cluster, &new_offset))
- return -EIO;
+ next_entry(ef, dir, &new_cluster, &new_offset);
if (exfat_pwrite(ef->dev, &meta2, sizeof(meta2),
co2o(ef, new_cluster, new_offset)) < 0)
{
@@ -1045,8 +982,7 @@ static int rename_entry(struct exfat* ef, struct exfat_node* dir,
struct exfat_entry_name name_entry = {EXFAT_ENTRY_FILE_NAME, 0};
memcpy(name_entry.name, name + i * EXFAT_ENAME_MAX,
EXFAT_ENAME_MAX * sizeof(le16_t));
- if (!next_entry(ef, dir, &new_cluster, &new_offset))
- return -EIO;
+ next_entry(ef, dir, &new_cluster, &new_offset);
if (exfat_pwrite(ef->dev, &name_entry, sizeof(name_entry),
co2o(ef, new_cluster, new_offset)) < 0)
{
@@ -1140,7 +1076,7 @@ int exfat_rename(struct exfat* ef, const char* old_path, const char* new_path)
rc = rename_entry(ef, dir, node, name, cluster, offset);
exfat_put_node(ef, dir);
exfat_put_node(ef, node);
- return rc;
+ return 0;
}
void exfat_utimes(struct exfat_node* node, const struct timespec tv[2])
@@ -1192,7 +1128,7 @@ static int find_label(struct exfat* ef, cluster_t* cluster, off64_t* offset)
return 0;
}
- if (!fetch_next_entry(ef, ef->root, &it))
+ if (fetch_next_entry(ef, ef->root, &it) != 0)
{
closedir(&it);
return -EIO;
diff --git a/exfat/libexfat/platform.h b/exfat/libexfat/platform.h
index c81e10e9e..320f757e8 100644
--- a/exfat/libexfat/platform.h
+++ b/exfat/libexfat/platform.h
@@ -3,12 +3,11 @@
OS-specific code (libc-specific in fact). Note that systems with the
same kernel can use different libc implementations.
- Free exFAT implementation.
- Copyright (C) 2010-2014 Andrew Nayenko
+ Copyright (C) 2010-2013 Andrew Nayenko
- This program is free software; you can redistribute it and/or modify
+ This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 2 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
@@ -16,9 +15,8 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PLATFORM_H_INCLUDED
@@ -28,37 +26,54 @@
#include <endian.h>
#include <byteswap.h>
-#define exfat_bswap16(x) bswap_16(x)
-#define exfat_bswap32(x) bswap_32(x)
-#define exfat_bswap64(x) bswap_64(x)
-#define EXFAT_BYTE_ORDER __BYTE_ORDER
-#define EXFAT_LITTLE_ENDIAN __LITTLE_ENDIAN
-#define EXFAT_BIG_ENDIAN __BIG_ENDIAN
#elif defined(__APPLE__)
#include <machine/endian.h>
#include <libkern/OSByteOrder.h>
-#define exfat_bswap16(x) OSSwapInt16(x)
-#define exfat_bswap32(x) OSSwapInt32(x)
-#define exfat_bswap64(x) OSSwapInt64(x)
-#define EXFAT_BYTE_ORDER BYTE_ORDER
-#define EXFAT_LITTLE_ENDIAN LITTLE_ENDIAN
-#define EXFAT_BIG_ENDIAN BIG_ENDIAN
+#define bswap_16(x) OSSwapInt16(x)
+#define bswap_32(x) OSSwapInt32(x)
+#define bswap_64(x) OSSwapInt64(x)
+#define __BYTE_ORDER BYTE_ORDER
+#define __LITTLE_ENDIAN LITTLE_ENDIAN
+#define __BIG_ENDIAN BIG_ENDIAN
-#endif
-//#elif defined(__FreeBSD__) || defined(__DragonFlyBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+#elif defined(__FreeBSD__) || defined(__DragonFlyBSD__) || defined(__NetBSD__)
#include <sys/endian.h>
-#define exfat_bswap16(x) bswap16(x)
-#define exfat_bswap32(x) bswap32(x)
-#define exfat_bswap64(x) bswap64(x)
-#define EXFAT_BYTE_ORDER _BYTE_ORDER
-#define EXFAT_LITTLE_ENDIAN _LITTLE_ENDIAN
-#define EXFAT_BIG_ENDIAN _BIG_ENDIAN
+#define bswap_16(x) bswap16(x)
+#define bswap_32(x) bswap32(x)
+#define bswap_64(x) bswap64(x)
+#define __BYTE_ORDER _BYTE_ORDER
+#define __LITTLE_ENDIAN _LITTLE_ENDIAN
+#define __BIG_ENDIAN _BIG_ENDIAN
+
+#elif defined(__OpenBSD__)
+
+#include <machine/endian.h>
+#define bswap_16(x) swap16(x)
+#define bswap_32(x) swap32(x)
+#define bswap_64(x) swap64(x)
+#define __BYTE_ORDER _BYTE_ORDER
+#define __LITTLE_ENDIAN _LITTLE_ENDIAN
+#define __BIG_ENDIAN _BIG_ENDIAN
+
+#elif defined(__sun)
+
+#include <sys/byteorder.h>
+#define bswap_16(x) BSWAP_16(x)
+#define bswap_32(x) BSWAP_32(x)
+#define bswap_64(x) BSWAP_64(x)
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+#ifdef _LITTLE_ENDIAN
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#else
+#define __BYTE_ORDER __BIG_ENDIAN
+#endif
-/*
#else
#error Unknown platform
-*/
+#endif
+
#endif /* ifndef PLATFORM_H_INCLUDED */
diff --git a/exfat/libexfat/time.c b/exfat/libexfat/time.c
index b264a999a..43c5fa4d9 100644
--- a/exfat/libexfat/time.c
+++ b/exfat/libexfat/time.c
@@ -3,7 +3,7 @@
exFAT file system implementation library.
Free exFAT implementation.
- Copyright (C) 2010-2014 Andrew Nayenko
+ Copyright (C) 2010-2013 Andrew Nayenko
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
diff --git a/exfat/libexfat/utf.c b/exfat/libexfat/utf.c
index 70fa856fc..3b7e26b2f 100644
--- a/exfat/libexfat/utf.c
+++ b/exfat/libexfat/utf.c
@@ -3,7 +3,7 @@
exFAT file system implementation library.
Free exFAT implementation.
- Copyright (C) 2010-2014 Andrew Nayenko
+ Copyright (C) 2010-2013 Andrew Nayenko
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
diff --git a/exfat/libexfat/utils.c b/exfat/libexfat/utils.c
index c0ecd56cc..ef87692b4 100644
--- a/exfat/libexfat/utils.c
+++ b/exfat/libexfat/utils.c
@@ -3,7 +3,7 @@
exFAT file system implementation library.
Free exFAT implementation.
- Copyright (C) 2010-2014 Andrew Nayenko
+ Copyright (C) 2010-2013 Andrew Nayenko
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
diff --git a/exfat/libexfat/version.h b/exfat/libexfat/version.h
index 20c1147ae..062fa0480 100644
--- a/exfat/libexfat/version.h
+++ b/exfat/libexfat/version.h
@@ -3,7 +3,7 @@
Version constants.
Free exFAT implementation.
- Copyright (C) 2010-2014 Andrew Nayenko
+ Copyright (C) 2010-2013 Andrew Nayenko
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
@@ -24,7 +24,7 @@
#define VERSION_H_INCLUDED
#define EXFAT_VERSION_MAJOR 1
-#define EXFAT_VERSION_MINOR 1
+#define EXFAT_VERSION_MINOR 0
#define EXFAT_VERSION_PATCH 0
#endif /* ifndef VERSION_H_INCLUDED */