diff options
Diffstat (limited to 'exfat/libexfat')
-rw-r--r-- | exfat/libexfat/Android.mk | 5 | ||||
-rw-r--r-- | exfat/libexfat/COPYING | 339 | ||||
-rw-r--r-- | exfat/libexfat/android_config.h | 37 | ||||
-rw-r--r-- | exfat/libexfat/byteorder.h | 86 | ||||
-rw-r--r-- | exfat/libexfat/cluster.c | 44 | ||||
-rw-r--r-- | exfat/libexfat/compiler.h | 6 | ||||
-rw-r--r-- | exfat/libexfat/exfat.h | 37 | ||||
-rw-r--r-- | exfat/libexfat/exfatfs.h | 8 | ||||
-rw-r--r-- | exfat/libexfat/io.c | 114 | ||||
-rw-r--r-- | exfat/libexfat/log.c | 6 | ||||
-rw-r--r-- | exfat/libexfat/lookup.c | 2 | ||||
-rw-r--r-- | exfat/libexfat/mount.c | 112 | ||||
-rw-r--r-- | exfat/libexfat/node.c | 270 | ||||
-rw-r--r-- | exfat/libexfat/platform.h | 70 | ||||
-rw-r--r-- | exfat/libexfat/time.c | 2 | ||||
-rw-r--r-- | exfat/libexfat/utf.c | 2 | ||||
-rw-r--r-- | exfat/libexfat/utils.c | 6 | ||||
-rw-r--r-- | exfat/libexfat/version.h | 30 |
18 files changed, 492 insertions, 684 deletions
diff --git a/exfat/libexfat/Android.mk b/exfat/libexfat/Android.mk index a280abb0e..5476486ee 100644 --- a/exfat/libexfat/Android.mk +++ b/exfat/libexfat/Android.mk @@ -1,12 +1,11 @@ LOCAL_PATH := $(call my-dir) - include $(CLEAR_VARS) LOCAL_MODULE := libexfat_twrp LOCAL_MODULE_TAGS := optional LOCAL_CFLAGS = -D_FILE_OFFSET_BITS=64 -LOCAL_SRC_FILES = cluster.c io.c log.c lookup.c mount.c node.c time.c utf.c utils.c -LOCAL_C_INCLUDES += $(LOCAL_PATH) \ +LOCAL_SRC_FILES = cluster.c io.c log.c lookup.c mount.c node.c time.c utf.c utils.c +LOCAL_C_INCLUDES += $(LOCAL_PATH) LOCAL_SHARED_LIBRARIES += libc include $(BUILD_SHARED_LIBRARY) diff --git a/exfat/libexfat/COPYING b/exfat/libexfat/COPYING deleted file mode 100644 index d159169d1..000000000 --- a/exfat/libexfat/COPYING +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU 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/android_config.h b/exfat/libexfat/android_config.h new file mode 100644 index 000000000..09c3346f8 --- /dev/null +++ b/exfat/libexfat/android_config.h @@ -0,0 +1,37 @@ +/* libexfat/config.h. Generated from config.h.in by configure. */ +/* libexfat/config.h.in. Generated from configure.ac by autoheader. */ + +/* Name of package */ +#define PACKAGE "exfat" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "relan@users.noreply.github.com" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "Free exFAT implementation" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "Free exFAT implementation 1.2.2" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "exfat" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "https://github.com/relan/exfat" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.2.2" + +/* Version number of package */ +#define VERSION "1.2.2" + +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef _DARWIN_USE_64_BIT_INODE +# define _DARWIN_USE_64_BIT_INODE 1 +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ diff --git a/exfat/libexfat/byteorder.h b/exfat/libexfat/byteorder.h index 10746e1ef..472cb487c 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-2013 Andrew Nayenko + Copyright (C) 2010-2015 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,68 +23,16 @@ #ifndef BYTEORDER_H_INCLUDED #define BYTEORDER_H_INCLUDED -#define __GLIBC__ +#include "platform.h" #include <stdint.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 +#include <stddef.h> typedef struct { uint16_t __u16; } le16_t; typedef struct { uint32_t __u32; } le32_t; typedef struct { uint64_t __u64; } le64_t; -#if __BYTE_ORDER == __LITTLE_ENDIAN +#if EXFAT_BYTE_ORDER == EXFAT_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; } @@ -92,17 +40,27 @@ 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; } -#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); } + +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); } static inline le16_t cpu_to_le16(uint16_t v) - { le16_t t = {bswap_16(v)}; return t; } + { le16_t t = {exfat_bswap16(v)}; return t; } static inline le32_t cpu_to_le32(uint32_t v) - { le32_t t = {bswap_32(v)}; return t; } + { le32_t t = {exfat_bswap32(v)}; return t; } static inline le64_t cpu_to_le64(uint64_t v) - { le64_t t = {bswap_64(v)}; return t; } + { le64_t t = {exfat_bswap64(v)}; return t; } + +typedef unsigned char bitmap_t; + #else #error Wow! You have a PDP machine?! #endif diff --git a/exfat/libexfat/cluster.c b/exfat/libexfat/cluster.c index 2215636c6..fc3657b53 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-2013 Andrew Nayenko + Copyright (C) 2010-2015 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 @@ -28,7 +28,7 @@ /* * Sector to absolute offset. */ -static off64_t s2o(const struct exfat* ef, off64_t sector) +static off_t s2o(const struct exfat* ef, off_t sector) { return sector << ef->sb->sector_bits; } @@ -36,18 +36,18 @@ static off64_t s2o(const struct exfat* ef, off64_t sector) /* * Cluster to sector. */ -static off64_t c2s(const struct exfat* ef, cluster_t cluster) +static off_t c2s(const struct exfat* ef, cluster_t cluster) { if (cluster < EXFAT_FIRST_DATA_CLUSTER) exfat_bug("invalid cluster number %u", cluster); return le32_to_cpu(ef->sb->cluster_sector_start) + - ((off64_t) (cluster - EXFAT_FIRST_DATA_CLUSTER) << ef->sb->spc_bits); + ((off_t) (cluster - EXFAT_FIRST_DATA_CLUSTER) << ef->sb->spc_bits); } /* * Cluster to absolute offset. */ -off64_t exfat_c2o(const struct exfat* ef, cluster_t cluster) +off_t exfat_c2o(const struct exfat* ef, cluster_t cluster) { return s2o(ef, c2s(ef, cluster)); } @@ -55,7 +55,7 @@ off64_t exfat_c2o(const struct exfat* ef, cluster_t cluster) /* * Sector to cluster. */ -static cluster_t s2c(const struct exfat* ef, off64_t sector) +static cluster_t s2c(const struct exfat* ef, off_t sector) { return ((sector - le32_to_cpu(ef->sb->cluster_sector_start)) >> ef->sb->spc_bits) + EXFAT_FIRST_DATA_CLUSTER; @@ -74,7 +74,7 @@ cluster_t exfat_next_cluster(const struct exfat* ef, const struct exfat_node* node, cluster_t cluster) { le32_t next; - off64_t fat_offset; + off_t fat_offset; if (cluster < EXFAT_FIRST_DATA_CLUSTER) exfat_bug("bad cluster 0x%x", cluster); @@ -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) - exfat_bug("failed to read the next cluster after %#x", cluster); + return EXFAT_CLUSTER_BAD; /* the caller should handle this and print + appropriate error message */ return le32_to_cpu(next); } @@ -136,6 +136,24 @@ 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_nodes(struct exfat* ef) +{ + return flush_nodes(ef, ef->root); +} + int exfat_flush(struct exfat* ef) { if (ef->cmap.dirty) @@ -149,13 +167,14 @@ int exfat_flush(struct exfat* ef) } ef->cmap.dirty = false; } + return 0; } static bool set_next_cluster(const struct exfat* ef, bool contiguous, cluster_t current, cluster_t next) { - off64_t fat_offset; + off_t fat_offset; le32_t next_le32; if (contiguous) @@ -316,6 +335,7 @@ 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; @@ -339,7 +359,7 @@ static int shrink_file(struct exfat* ef, struct exfat_node* node, return 0; } -static bool erase_raw(struct exfat* ef, size_t size, off64_t offset) +static bool erase_raw(struct exfat* ef, size_t size, off_t offset) { if (exfat_pwrite(ef->dev, ef->zero_cluster, size, offset) < 0) { @@ -452,7 +472,7 @@ static int find_used_clusters(const struct exfat* ef, return 0; } -int exfat_find_used_sectors(const struct exfat* ef, off64_t* a, off64_t* b) +int exfat_find_used_sectors(const struct exfat* ef, off_t* a, off_t* b) { cluster_t ca, cb; diff --git a/exfat/libexfat/compiler.h b/exfat/libexfat/compiler.h index 6edd8ec7f..3b092a9b9 100644 --- a/exfat/libexfat/compiler.h +++ b/exfat/libexfat/compiler.h @@ -4,7 +4,7 @@ showstopper. Free exFAT implementation. - Copyright (C) 2010-2013 Andrew Nayenko + Copyright (C) 2010-2015 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,6 +24,10 @@ #ifndef COMPILER_H_INCLUDED #define COMPILER_H_INCLUDED +#if defined(__STDC_VERSION__) && (__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 ff58e8414..5beba7cba 100644 --- a/exfat/libexfat/exfat.h +++ b/exfat/libexfat/exfat.h @@ -4,7 +4,7 @@ implementation. Free exFAT implementation. - Copyright (C) 2010-2013 Andrew Nayenko + Copyright (C) 2010-2015 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,15 +24,19 @@ #ifndef EXFAT_H_INCLUDED #define EXFAT_H_INCLUDED +#if defined(__ANDROID__) +#include "android_config.h" +#else +#include "config.h" +#endif +#include "compiler.h" +#include "exfatfs.h" #include <stdio.h> #include <stdlib.h> #include <time.h> #include <stdbool.h> #include <sys/stat.h> #include <sys/types.h> -#include "compiler.h" -#include "exfatfs.h" -#include "version.h" #define EXFAT_NAME_MAX 256 #define EXFAT_ATTRIB_CONTIGUOUS 0x10000 @@ -51,7 +55,6 @@ #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))) @@ -62,6 +65,10 @@ typedef size_t bitmap_t; #define BMAP_CLR(bitmap, index) \ ((bitmap)[BMAP_BLOCK(index)] &= ~BMAP_MASK(index)) +/* The size of off_t type must be 64 bits. File systems larger than 2 GB will + be corrupted with 32-bit off_t. */ +STATIC_ASSERT(sizeof(off_t) == 8); + struct exfat_node { struct exfat_node* parent; @@ -73,7 +80,7 @@ struct exfat_node uint32_t fptr_index; cluster_t fptr_cluster; cluster_t entry_cluster; - off64_t entry_offset; + off_t entry_offset; cluster_t start_cluster; int flags; uint64_t size; @@ -139,18 +146,18 @@ struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode); int exfat_close(struct exfat_dev* dev); int exfat_fsync(struct exfat_dev* dev); enum exfat_mode exfat_get_mode(const struct exfat_dev* dev); -off64_t exfat_get_size(const struct exfat_dev* dev); -off64_t exfat_seek(struct exfat_dev* dev, off64_t offset, int whence); +off_t exfat_get_size(const struct exfat_dev* dev); +off_t exfat_seek(struct exfat_dev* dev, off_t offset, int whence); ssize_t exfat_read(struct exfat_dev* dev, void* buffer, size_t size); ssize_t exfat_write(struct exfat_dev* dev, const void* buffer, size_t size); ssize_t exfat_pread(struct exfat_dev* dev, void* buffer, size_t size, - off64_t offset); + off_t offset); ssize_t exfat_pwrite(struct exfat_dev* dev, const void* buffer, size_t size, - off64_t offset); + off_t offset); ssize_t exfat_generic_pread(const struct exfat* ef, struct exfat_node* node, - void* buffer, size_t size, off64_t offset); + void* buffer, size_t size, off_t offset); ssize_t exfat_generic_pwrite(struct exfat* ef, struct exfat_node* node, - const void* buffer, size_t size, off64_t offset); + const void* buffer, size_t size, off_t offset); int exfat_opendir(struct exfat* ef, struct exfat_node* dir, struct exfat_iterator* it); @@ -161,16 +168,17 @@ int exfat_lookup(struct exfat* ef, struct exfat_node** node, int exfat_split(struct exfat* ef, struct exfat_node** parent, struct exfat_node** node, le16_t* name, const char* path); -off64_t exfat_c2o(const struct exfat* ef, cluster_t cluster); +off_t exfat_c2o(const struct exfat* ef, cluster_t cluster); cluster_t exfat_next_cluster(const struct exfat* ef, const struct exfat_node* node, cluster_t cluster); cluster_t exfat_advance_cluster(const struct exfat* ef, struct exfat_node* node, uint32_t count); +int exfat_flush_nodes(struct exfat* ef); int exfat_flush(struct exfat* ef); int exfat_truncate(struct exfat* ef, struct exfat_node* node, uint64_t size, bool erase); uint32_t exfat_count_free_clusters(const struct exfat* ef); -int exfat_find_used_sectors(const struct exfat* ef, off64_t* a, off64_t* b); +int exfat_find_used_sectors(const struct exfat* ef, off_t* a, off_t* b); void exfat_stat(const struct exfat* ef, const struct exfat_node* node, struct stat* stbuf); @@ -194,6 +202,7 @@ 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 a436daa63..eca2cacea 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-2013 Andrew Nayenko + Copyright (C) 2010-2015 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,6 +24,7 @@ #define EXFATFS_H_INCLUDED #include "byteorder.h" +#include "compiler.h" typedef uint32_t cluster_t; /* cluster number */ @@ -69,6 +70,7 @@ STATIC_ASSERT(sizeof(struct exfat_super_block) == 512); #define EXFAT_ENTRY_VALID 0x80 #define EXFAT_ENTRY_CONTINUED 0x40 +#define EXFAT_ENTRY_OPTIONAL 0x20 #define EXFAT_ENTRY_BITMAP (0x01 | EXFAT_ENTRY_VALID) #define EXFAT_ENTRY_UPCASE (0x02 | EXFAT_ENTRY_VALID) @@ -153,10 +155,10 @@ struct exfat_entry_meta2 /* file or directory info (part 2) */ uint8_t name_length; le16_t name_hash; le16_t __unknown2; - le64_t real_size; /* in bytes, equals to size */ + le64_t valid_size; /* in bytes, less or equal to size */ uint8_t __unknown3[4]; le32_t start_cluster; - le64_t size; /* in bytes, equals to real_size */ + le64_t size; /* in bytes */ } PACKED; STATIC_ASSERT(sizeof(struct exfat_entry_meta2) == 32); diff --git a/exfat/libexfat/io.c b/exfat/libexfat/io.c index 306c5dd06..3d7aaad2e 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-2013 Andrew Nayenko + Copyright (C) 2010-2015 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,13 +24,19 @@ #include <inttypes.h> #include <sys/types.h> #include <sys/stat.h> -#include <sys/mount.h> #include <fcntl.h> #include <unistd.h> #include <string.h> -#ifdef __APPLE__ +#include <errno.h> +#if defined(__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> @@ -40,9 +46,9 @@ struct exfat_dev { int fd; enum exfat_mode mode; - off64_t size; /* in bytes */ + off_t size; /* in bytes */ #ifdef USE_UBLIO - off64_t pos; + off_t pos; ublio_filehandle_t ufh; #endif }; @@ -65,6 +71,7 @@ static int open_rw(const char* spec) if (fd != -1 && ioctl(fd, BLKROGET, &ro) == 0 && ro) { close(fd); + errno = EROFS; return -1; } #endif @@ -93,7 +100,8 @@ 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", spec); + exfat_error("failed to open '%s' in read-only mode: %s", spec, + strerror(errno)); return NULL; } dev->mode = EXFAT_MODE_RO; @@ -103,7 +111,8 @@ 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", spec); + exfat_error("failed to open '%s' in read-write mode: %s", spec, + strerror(errno)); return NULL; } dev->mode = EXFAT_MODE_RW; @@ -119,11 +128,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'", spec); + exfat_error("failed to open '%s': %s", spec, strerror(errno)); return NULL; } @@ -131,7 +140,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) && @@ -140,11 +149,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; } -#ifdef __APPLE__ +#if defined(__APPLE__) if (!S_ISREG(stbuf.st_mode)) { uint32_t block_size = 0; @@ -167,6 +176,32 @@ 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 */ @@ -175,14 +210,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; } } @@ -210,32 +245,41 @@ 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) { - free(dev); - exfat_error("failed to close device"); - return 1; + exfat_error("failed to close device: %s", strerror(errno)); + rc = -EIO; } free(dev); - return 0; + return rc; } int exfat_fsync(struct exfat_dev* dev) { + int rc = 0; + #ifdef USE_UBLIO if (ublio_fsync(dev->ufh) != 0) -#else - if (fsync(dev->fd) != 0) + { + exfat_error("ublio fsync failed"); + rc = -EIO; + } #endif + if (fsync(dev->fd) != 0) { - exfat_error("fsync failed"); - return 1; + exfat_error("fsync failed: %s", strerror(errno)); + rc = -EIO; } - return 0; + return rc; } enum exfat_mode exfat_get_mode(const struct exfat_dev* dev) @@ -243,18 +287,18 @@ enum exfat_mode exfat_get_mode(const struct exfat_dev* dev) return dev->mode; } -off64_t exfat_get_size(const struct exfat_dev* dev) +off_t exfat_get_size(const struct exfat_dev* dev) { return dev->size; } -off64_t exfat_seek(struct exfat_dev* dev, off64_t offset, int whence) +off_t exfat_seek(struct exfat_dev* dev, off_t offset, int whence) { #ifdef USE_UBLIO /* XXX SEEK_CUR will be handled incorrectly */ - return dev->pos = lseek64(dev->fd, offset, whence); + return dev->pos = lseek(dev->fd, offset, whence); #else - return lseek64(dev->fd, offset, whence); + return lseek(dev->fd, offset, whence); #endif } @@ -283,31 +327,31 @@ ssize_t exfat_write(struct exfat_dev* dev, const void* buffer, size_t size) } ssize_t exfat_pread(struct exfat_dev* dev, void* buffer, size_t size, - off64_t offset) + off_t offset) { #ifdef USE_UBLIO return ublio_pread(dev->ufh, buffer, size, offset); #else - return pread64(dev->fd, buffer, size, offset); + return pread(dev->fd, buffer, size, offset); #endif } ssize_t exfat_pwrite(struct exfat_dev* dev, const void* buffer, size_t size, - off64_t offset) + off_t offset) { #ifdef USE_UBLIO return ublio_pwrite(dev->ufh, buffer, size, offset); #else - return pwrite64(dev->fd, buffer, size, offset); + return pwrite(dev->fd, buffer, size, offset); #endif } ssize_t exfat_generic_pread(const struct exfat* ef, struct exfat_node* node, - void* buffer, size_t size, off64_t offset) + void* buffer, size_t size, off_t offset) { cluster_t cluster; char* bufp = buffer; - off64_t lsize, loffset, remainder; + off_t lsize, loffset, remainder; if (offset >= node->size) return 0; @@ -348,11 +392,11 @@ ssize_t exfat_generic_pread(const struct exfat* ef, struct exfat_node* node, } ssize_t exfat_generic_pwrite(struct exfat* ef, struct exfat_node* node, - const void* buffer, size_t size, off64_t offset) + const void* buffer, size_t size, off_t offset) { cluster_t cluster; const char* bufp = buffer; - off64_t lsize, loffset, remainder; + off_t lsize, loffset, remainder; if (offset > node->size) if (exfat_truncate(ef, node, offset, true) != 0) diff --git a/exfat/libexfat/log.c b/exfat/libexfat/log.c index 7e541aafb..38c79d456 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-2013 Andrew Nayenko + Copyright (C) 2010-2015 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 @@ -47,7 +47,11 @@ void exfat_bug(const char* format, ...) vsyslog(LOG_CRIT, format, aq); va_end(aq); +#if defined(__ANDROID__) + exit(-1); +#else abort(); +#endif } /* diff --git a/exfat/libexfat/lookup.c b/exfat/libexfat/lookup.c index 00cd5335e..d5bb3899b 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-2013 Andrew Nayenko + Copyright (C) 2010-2015 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 928c561dc..0d6ce9ead 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-2013 Andrew Nayenko + Copyright (C) 2010-2015 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,22 +24,38 @@ #include <string.h> #include <stdlib.h> #include <errno.h> +#include <inttypes.h> #include <unistd.h> #include <sys/types.h> static uint64_t rootdir_size(const struct exfat* ef) { - uint64_t clusters = 0; + uint32_t clusters = 0; + uint32_t clusters_max = le32_to_cpu(ef->sb->cluster_count); cluster_t rootdir_cluster = le32_to_cpu(ef->sb->rootdir_cluster); - while (!CLUSTER_INVALID(rootdir_cluster)) + /* Iterate all clusters of the root directory to calculate its size. + It can't be contiguous because there is no flag to indicate this. */ + do { - clusters++; - /* root directory cannot be contiguous because there is no flag - to indicate this */ + if (clusters == clusters_max) /* infinite loop detected */ + { + exfat_error("root directory cannot occupy all %d clusters", + clusters); + return 0; + } + if (CLUSTER_INVALID(rootdir_cluster)) + { + exfat_error("bad cluster %#x while reading root directory", + rootdir_cluster); + return 0; + } rootdir_cluster = exfat_next_cluster(ef, ef->root, rootdir_cluster); + clusters++; } - return clusters * CLUSTER_SIZE(*ef->sb); + while (rootdir_cluster != EXFAT_CLUSTER_END); + + return (uint64_t) clusters * CLUSTER_SIZE(*ef->sb); } static const char* get_option(const char* options, const char* option_name) @@ -77,13 +93,11 @@ static bool match_option(const char* options, const char* option_name) static void parse_options(struct exfat* ef, const char* options) { - int sys_umask = umask(0); int opt_umask; - umask(sys_umask); /* restore umask */ - opt_umask = get_int_option(options, "umask", 8, sys_umask); - ef->dmask = get_int_option(options, "dmask", 8, opt_umask) & 0777; - ef->fmask = get_int_option(options, "fmask", 8, opt_umask) & 0777; + opt_umask = get_int_option(options, "umask", 8, 0); + ef->dmask = get_int_option(options, "dmask", 8, opt_umask); + ef->fmask = get_int_option(options, "fmask", 8, opt_umask); ef->uid = get_int_option(options, "uid", 10, geteuid()); ef->gid = get_int_option(options, "gid", 10, getegid()); @@ -91,8 +105,8 @@ static void parse_options(struct exfat* ef, const char* options) ef->noatime = match_option(options, "noatime"); } -static int verify_vbr_checksum(struct exfat_dev* dev, void* sector, - off64_t sector_size) +static bool verify_vbr_checksum(struct exfat_dev* dev, void* sector, + off_t sector_size) { uint32_t vbr_checksum; int i; @@ -100,7 +114,7 @@ static int 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 1; + return false; } vbr_checksum = exfat_vbr_start_checksum(sector, sector_size); for (i = 1; i < 11; i++) @@ -108,7 +122,7 @@ static int 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 1; + return false; } vbr_checksum = exfat_vbr_add_checksum(sector, sector_size, vbr_checksum); @@ -116,16 +130,16 @@ static int 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 1; + return false; } 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 1; + return false; } - return 0; + return true; } static int commit_super_block(const struct exfat* ef) @@ -201,31 +215,23 @@ int exfat_mount(struct exfat* ef, const char* spec, const char* options) exfat_error("exFAT file system is not found"); return -EIO; } - if (ef->sb->version.major != 1 || ef->sb->version.minor != 0) + /* sector cannot be smaller than 512 bytes */ + if (ef->sb->sector_bits < 9) { exfat_close(ef->dev); - exfat_error("unsupported exFAT version: %hhu.%hhu", - ef->sb->version.major, ef->sb->version.minor); + exfat_error("too small sector size: 2^%hhd", ef->sb->sector_bits); free(ef->sb); return -EIO; } - if (ef->sb->fat_count != 1) - { - exfat_close(ef->dev); - 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) { exfat_close(ef->dev); + exfat_error("too big cluster size: 2^(%hhd+%hhd)", + ef->sb->sector_bits, ef->sb->spc_bits); free(ef->sb); - exfat_error("too big cluster size: 2^%d", - (int) ef->sb->sector_bits + (int) ef->sb->spc_bits); return -EIO; } - ef->zero_cluster = malloc(CLUSTER_SIZE(*ef->sb)); if (ef->zero_cluster == NULL) { @@ -235,8 +241,7 @@ int exfat_mount(struct exfat* ef, const char* spec, const char* options) 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) + if (!verify_vbr_checksum(ef->dev, ef->zero_cluster, SECTOR_SIZE(*ef->sb))) { free(ef->zero_cluster); exfat_close(ef->dev); @@ -244,6 +249,33 @@ int exfat_mount(struct exfat* ef, const char* spec, const char* options) 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); + free(ef->sb); + return -EIO; + } + 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); + return -EIO; + } + if (le64_to_cpu(ef->sb->sector_count) * SECTOR_SIZE(*ef->sb) > + exfat_get_size(ef->dev)) + { + /* this can cause I/O errors later but we don't fail mounting to let + user rescue data */ + exfat_warn("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)); + } ef->root = malloc(sizeof(struct exfat_node)); if (ef->root == NULL) @@ -260,6 +292,14 @@ 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; @@ -314,11 +354,13 @@ static void finalize_super_block(struct exfat* ef) ef->sb->allocated_percent = ((total - free) * 100 + total / 2) / total; } - commit_super_block(ef); + commit_super_block(ef); /* ignore return code */ } void exfat_unmount(struct exfat* ef) { + exfat_flush_nodes(ef); /* ignore return code */ + 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 56205fced..d05f20dc1 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-2013 Andrew Nayenko + Copyright (C) 2010-2015 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 @@ -29,7 +29,7 @@ struct iterator { cluster_t cluster; - off64_t offset; + off_t offset; int contiguous; char* chunk; }; @@ -44,34 +44,50 @@ struct exfat_node* exfat_get_node(struct exfat_node* node) void exfat_put_node(struct exfat* ef, struct exfat_node* node) { - if (--node->references < 0) + char buffer[UTF8_BYTES(EXFAT_NAME_MAX) + 1]; + + --node->references; + 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); } - - if (node->references == 0) + else if (node->references == 0 && node != ef->root) { - /* FIXME handle I/O error */ - if (exfat_flush_node(ef, node) != 0) - exfat_bug("node flush failed"); - if (node->flags & EXFAT_ATTRIB_UNLINKED) + if (node->flags & EXFAT_ATTRIB_DIRTY) { - /* free all clusters and node structure itself */ - exfat_truncate(ef, node, 0, true); - free(node); + exfat_get_name(node, buffer, sizeof(buffer) - 1); + exfat_warn("dirty node '%s' with zero references", buffer); } - /* 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) +static off_t co2o(struct exfat* ef, cluster_t cluster, off_t offset) { return exfat_c2o(ef, cluster) + offset % CLUSTER_SIZE(*ef->sb); } @@ -108,7 +124,7 @@ static void closedir(struct iterator* it) it->chunk = NULL; } -static int fetch_next_entry(struct exfat* ef, const struct exfat_node* parent, +static bool fetch_next_entry(struct exfat* ef, const struct exfat_node* parent, struct iterator* it) { /* move iterator to the next entry in the directory */ @@ -119,23 +135,23 @@ static int 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 0; + return true; 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 1; + return false; } 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 1; + return false; } } - return 0; + return true; } static struct exfat_node* allocate_node(void) @@ -177,6 +193,40 @@ 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. @@ -196,7 +246,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 real_size = 0; + uint64_t valid_size = 0; *node = NULL; @@ -267,7 +317,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); - real_size = le64_to_cpu(meta2->real_size); + valid_size = le64_to_cpu(meta2->valid_size); /* empty files must be marked as non-contiguous */ if ((*node)->size == 0 && (meta2->flags & EXFAT_FLAG_CONTIGUOUS)) { @@ -302,37 +352,10 @@ static int readdir(struct exfat* ef, const struct exfat_node* parent, namep += EXFAT_ENAME_MAX; if (--continuations == 0) { - /* - 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); + if (!check_node(*node, actual_checksum, reference_checksum, + valid_size)) goto error; - } - 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) + if (!fetch_next_entry(ef, parent, it)) goto error; return 0; /* entry completed */ } @@ -431,15 +454,25 @@ static int readdir(struct exfat* ef, const struct exfat_node* parent, break; default: - if (entry->type & EXFAT_ENTRY_VALID) + if (!(entry->type & EXFAT_ENTRY_VALID)) + break; /* deleted entry, ignore it */ + if (!(entry->type & EXFAT_ENTRY_OPTIONAL)) + { + exfat_error("unknown entry type %#hhx", entry->type); + goto error; + } + /* optional entry, warn and skip */ + exfat_warn("unknown entry type %#hhx", entry->type); + if (continuations == 0) { - exfat_error("unknown entry type 0x%hhx", entry->type); + exfat_error("unexpected continuation"); goto error; } + --continuations; break; } - if (fetch_next_entry(ef, parent, it) != 0) + if (!fetch_next_entry(ef, parent, it)) goto error; } /* we never reach here */ @@ -520,6 +553,8 @@ 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; @@ -530,11 +565,15 @@ 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); } @@ -544,20 +583,28 @@ void exfat_reset_cache(struct exfat* ef) reset_cache(ef, ef->root); } -static void next_entry(struct exfat* ef, const struct exfat_node* parent, - cluster_t* cluster, off64_t* offset) +static bool next_entry(struct exfat* ef, const struct exfat_node* parent, + cluster_t* cluster, off_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) { cluster_t cluster; - off64_t offset; - off64_t meta1_offset, meta2_offset; + off_t offset; + off_t meta1_offset, meta2_offset; struct exfat_entry_meta1 meta1; struct exfat_entry_meta2 meta2; @@ -573,7 +620,8 @@ 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); - next_entry(ef, node->parent, &cluster, &offset); + if (!next_entry(ef, node->parent, &cluster, &offset)) + return -EIO; meta2_offset = co2o(ef, cluster, offset); if (exfat_pread(ef->dev, &meta1, sizeof(meta1), meta1_offset) < 0) @@ -594,7 +642,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.real_size = cpu_to_le64(node->size); + meta2.size = meta2.valid_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 */ @@ -616,13 +664,13 @@ int exfat_flush_node(struct exfat* ef, struct exfat_node* node) } node->flags &= ~EXFAT_ATTRIB_DIRTY; - return 0; + return exfat_flush(ef); } static bool erase_entry(struct exfat* ef, struct exfat_node* node) { cluster_t cluster = node->entry_cluster; - off64_t offset = node->entry_offset; + off_t offset = node->entry_offset; int name_entries = DIV_ROUND_UP(utf16_length(node->name), EXFAT_ENAME_MAX); uint8_t entry_type; @@ -633,7 +681,8 @@ static bool erase_entry(struct exfat* ef, struct exfat_node* node) return false; } - next_entry(ef, node->parent, &cluster, &offset); + if (!next_entry(ef, node->parent, &cluster, &offset)) + return false; entry_type = EXFAT_ENTRY_FILE_INFO & ~EXFAT_ENTRY_VALID; if (exfat_pwrite(ef->dev, &entry_type, 1, co2o(ef, cluster, offset)) < 0) { @@ -643,7 +692,8 @@ static bool erase_entry(struct exfat* ef, struct exfat_node* node) while (name_entries--) { - next_entry(ef, node->parent, &cluster, &offset); + if (!next_entry(ef, node->parent, &cluster, &offset)) + return false; entry_type = EXFAT_ENTRY_FILE_NAME & ~EXFAT_ENTRY_VALID; if (exfat_pwrite(ef->dev, &entry_type, 1, co2o(ef, cluster, offset)) < 0) @@ -656,13 +706,12 @@ static bool erase_entry(struct exfat* ef, struct exfat_node* node) } static int shrink_directory(struct exfat* ef, struct exfat_node* dir, - off64_t deleted_offset) + off_t deleted_offset) { const struct exfat_node* node; 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"); @@ -698,16 +747,13 @@ static int shrink_directory(struct exfat* ef, struct exfat_node* dir, new_size = CLUSTER_SIZE(*ef->sb); if (new_size == dir->size) return 0; - rc = exfat_truncate(ef, dir, new_size, true); - if (rc != 0) - return rc; - return 0; + return exfat_truncate(ef, dir, new_size, true); } static int delete(struct exfat* ef, struct exfat_node* node) { struct exfat_node* parent = node->parent; - off64_t deleted_offset = node->entry_offset; + off_t deleted_offset = node->entry_offset; int rc; exfat_get_node(parent); @@ -719,9 +765,15 @@ static int delete(struct exfat* ef, struct exfat_node* node) exfat_update_mtime(parent); tree_detach(node); rc = shrink_directory(ef, parent, deleted_offset); - exfat_put_node(ef, parent); - /* file clusters will be freed when node reference counter becomes 0 */ 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); return rc; } @@ -734,10 +786,14 @@ 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 */ - exfat_cache_directory(ef, node); + rc = exfat_cache_directory(ef, node); + if (rc != 0) + return rc; if (node->child) return -ENOTEMPTY; return delete(ef, node); @@ -752,7 +808,7 @@ static int grow_directory(struct exfat* ef, struct exfat_node* dir, } static int find_slot(struct exfat* ef, struct exfat_node* dir, - cluster_t* cluster, off64_t* offset, int subentries) + cluster_t* cluster, off_t* offset, int subentries) { struct iterator it; int rc; @@ -786,7 +842,7 @@ static int find_slot(struct exfat* ef, struct exfat_node* dir, return rc; } } - if (fetch_next_entry(ef, dir, &it) != 0) + if (!fetch_next_entry(ef, dir, &it)) { closedir(&it); return -EIO; @@ -797,7 +853,7 @@ static int find_slot(struct exfat* ef, struct exfat_node* dir, } static int write_entry(struct exfat* ef, struct exfat_node* dir, - const le16_t* name, cluster_t cluster, off64_t offset, uint16_t attrib) + const le16_t* name, cluster_t cluster, off_t offset, uint16_t attrib) { struct exfat_node* node; struct exfat_entry_meta1 meta1; @@ -838,7 +894,8 @@ static int write_entry(struct exfat* ef, struct exfat_node* dir, exfat_error("failed to write meta1 entry"); return -EIO; } - next_entry(ef, dir, &cluster, &offset); + if (!next_entry(ef, dir, &cluster, &offset)) + return -EIO; if (exfat_pwrite(ef->dev, &meta2, sizeof(meta2), co2o(ef, cluster, offset)) < 0) { @@ -851,7 +908,8 @@ 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)); - next_entry(ef, dir, &cluster, &offset); + if (!next_entry(ef, dir, &cluster, &offset)) + return -EIO; if (exfat_pwrite(ef->dev, &name_entry, sizeof(name_entry), co2o(ef, cluster, offset)) < 0) { @@ -873,7 +931,7 @@ static int create(struct exfat* ef, const char* path, uint16_t attrib) struct exfat_node* dir; struct exfat_node* existing; cluster_t cluster = EXFAT_CLUSTER_BAD; - off64_t offset = -1; + off_t offset = -1; le16_t name[EXFAT_NAME_MAX + 1]; int rc; @@ -895,6 +953,12 @@ 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; } @@ -909,7 +973,7 @@ int exfat_mkdir(struct exfat* ef, const char* path) int rc; struct exfat_node* node; - rc = create(ef, path, EXFAT_ATTRIB_ARCH | EXFAT_ATTRIB_DIR); + rc = create(ef, path, EXFAT_ATTRIB_DIR); if (rc != 0) return rc; rc = exfat_lookup(ef, &node, path); @@ -923,18 +987,25 @@ 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; } static int rename_entry(struct exfat* ef, struct exfat_node* dir, struct exfat_node* node, const le16_t* name, cluster_t new_cluster, - off64_t new_offset) + off_t new_offset) { struct exfat_entry_meta1 meta1; struct exfat_entry_meta2 meta2; cluster_t old_cluster = node->entry_cluster; - off64_t old_offset = node->entry_offset; + off_t old_offset = node->entry_offset; const size_t name_length = utf16_length(name); const int name_entries = DIV_ROUND_UP(name_length, EXFAT_ENAME_MAX); int i; @@ -945,7 +1016,8 @@ static int rename_entry(struct exfat* ef, struct exfat_node* dir, exfat_error("failed to read meta1 entry on rename"); return -EIO; } - next_entry(ef, node->parent, &old_cluster, &old_offset); + if (!next_entry(ef, node->parent, &old_cluster, &old_offset)) + return -EIO; if (exfat_pread(ef->dev, &meta2, sizeof(meta2), co2o(ef, old_cluster, old_offset)) < 0) { @@ -969,7 +1041,8 @@ static int rename_entry(struct exfat* ef, struct exfat_node* dir, exfat_error("failed to write meta1 entry on rename"); return -EIO; } - next_entry(ef, dir, &new_cluster, &new_offset); + if (!next_entry(ef, dir, &new_cluster, &new_offset)) + return -EIO; if (exfat_pwrite(ef->dev, &meta2, sizeof(meta2), co2o(ef, new_cluster, new_offset)) < 0) { @@ -982,7 +1055,8 @@ 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)); - next_entry(ef, dir, &new_cluster, &new_offset); + if (!next_entry(ef, dir, &new_cluster, &new_offset)) + return -EIO; if (exfat_pwrite(ef->dev, &name_entry, sizeof(name_entry), co2o(ef, new_cluster, new_offset)) < 0) { @@ -1003,7 +1077,7 @@ int exfat_rename(struct exfat* ef, const char* old_path, const char* new_path) struct exfat_node* existing; struct exfat_node* dir; cluster_t cluster = EXFAT_CLUSTER_BAD; - off64_t offset = -1; + off_t offset = -1; le16_t name[EXFAT_NAME_MAX + 1]; int rc; @@ -1076,7 +1150,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 0; + return rc; } void exfat_utimes(struct exfat_node* node, const struct timespec tv[2]) @@ -1103,7 +1177,7 @@ const char* exfat_get_label(struct exfat* ef) return ef->label; } -static int find_label(struct exfat* ef, cluster_t* cluster, off64_t* offset) +static int find_label(struct exfat* ef, cluster_t* cluster, off_t* offset) { struct iterator it; int rc; @@ -1128,7 +1202,7 @@ static int find_label(struct exfat* ef, cluster_t* cluster, off64_t* offset) return 0; } - if (fetch_next_entry(ef, ef->root, &it) != 0) + if (!fetch_next_entry(ef, ef->root, &it)) { closedir(&it); return -EIO; @@ -1141,7 +1215,7 @@ int exfat_set_label(struct exfat* ef, const char* label) le16_t label_utf16[EXFAT_ENAME_MAX + 1]; int rc; cluster_t cluster; - off64_t offset; + off_t offset; struct exfat_entry_label entry; memset(label_utf16, 0, sizeof(label_utf16)); diff --git a/exfat/libexfat/platform.h b/exfat/libexfat/platform.h index 320f757e8..d2ad6d134 100644 --- a/exfat/libexfat/platform.h +++ b/exfat/libexfat/platform.h @@ -3,11 +3,12 @@ OS-specific code (libc-specific in fact). Note that systems with the same kernel can use different libc implementations. - Copyright (C) 2010-2013 Andrew Nayenko + Free exFAT implementation. + Copyright (C) 2010-2015 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 3 of the License, or + 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, @@ -15,62 +16,45 @@ 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/>. + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef PLATFORM_H_INCLUDED #define PLATFORM_H_INCLUDED -#if defined(__GLIBC__) +#if defined(__linux__) || defined(__GLIBC__) || defined(__GNU__) #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 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 +#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 -#elif defined(__FreeBSD__) || defined(__DragonFlyBSD__) || defined(__NetBSD__) +#elif defined(__ANDROID__) || defined(__FreeBSD__) || defined(__DragonFlyBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #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 +#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 #else #error Unknown platform diff --git a/exfat/libexfat/time.c b/exfat/libexfat/time.c index 43c5fa4d9..45c4aff65 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-2013 Andrew Nayenko + Copyright (C) 2010-2015 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 3b7e26b2f..6f14882e8 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-2013 Andrew Nayenko + Copyright (C) 2010-2015 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 ef87692b4..388f360d9 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-2013 Andrew Nayenko + Copyright (C) 2010-2015 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 @@ -161,8 +161,8 @@ void exfat_print_info(const struct exfat_super_block* sb, uint32_t free_clusters) { struct exfat_human_bytes hb; - off64_t total_space = le64_to_cpu(sb->sector_count) * SECTOR_SIZE(*sb); - off64_t avail_space = (off64_t) free_clusters * CLUSTER_SIZE(*sb); + off_t total_space = le64_to_cpu(sb->sector_count) * SECTOR_SIZE(*sb); + off_t avail_space = (off_t) free_clusters * CLUSTER_SIZE(*sb); printf("File system version %hhu.%hhu\n", sb->version.major, sb->version.minor); diff --git a/exfat/libexfat/version.h b/exfat/libexfat/version.h deleted file mode 100644 index 062fa0480..000000000 --- a/exfat/libexfat/version.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - version.h (12.06.10) - Version constants. - - Free exFAT implementation. - 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 - 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. -*/ - -#ifndef VERSION_H_INCLUDED -#define VERSION_H_INCLUDED - -#define EXFAT_VERSION_MAJOR 1 -#define EXFAT_VERSION_MINOR 0 -#define EXFAT_VERSION_PATCH 0 - -#endif /* ifndef VERSION_H_INCLUDED */ |