fatsort-0.9.15.245/0000775000076400007640000000000011626405034013122 5ustar feanorfeanorfatsort-0.9.15.245/README0000664000076400007640000000005611626223123014000 0ustar feanorfeanorPlease have a look at man page man/fatsort.1. fatsort-0.9.15.245/LICENSE.txt0000664000076400007640000004313110437646431014756 0ustar feanorfeanor GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 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. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. fatsort-0.9.15.245/src/0000775000076400007640000000000011626405034013711 5ustar feanorfeanorfatsort-0.9.15.245/src/misc.h0000664000076400007640000000200210703712006015002 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains/describes miscellaneous functions. */ #ifndef __misc_h__ #define __misc_h__ // info messages that can be muted with a command line option void infomsg(char *str, ...); #endif // __misc_h__ fatsort-0.9.15.245/src/stringlist.c0000664000076400007640000000566011626221353016266 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains/describes functions to manage string lists. */ #include "stringlist.h" #include #include #include #include "errors.h" #include "mallocv.h" struct sStringList *newStringList() { /* create a new string list */ struct sStringList *stringList; // create the dummy head element stringList = malloc(sizeof(struct sStringList)); if (stringList == NULL) { stderror(); return NULL; } stringList->str = NULL; stringList->next = NULL; return stringList; } int32_t addStringToStringList(struct sStringList *stringList, char *str) { /* insert new string into string list */ assert(stringList != NULL); assert(stringList->str == NULL); assert(str != NULL); int32_t len; // find end of list while (stringList->next != NULL) { stringList = stringList->next; } // allocate memory for new entry stringList->next=malloc(sizeof(struct sStringList)); if (stringList->next == NULL) { stderror(); return -1; } stringList->next->next = NULL; len=strlen(str); // allocate memory for string stringList->next->str=malloc(len+1); if (stringList->next->str == NULL) { stderror(); return -1; } strncpy(stringList->next->str, str, len); stringList->next->str[len] = '\0'; return 0; } int32_t matchesStringList(struct sStringList *stringList, char *str) { /* evaluates whether str is contained in stringList */ assert(stringList != NULL); assert(stringList->str == NULL); assert(str != NULL); int32_t ret=0; // not in list stringList=stringList->next; while (stringList != NULL) { if (strncmp(stringList->str, str, strlen(stringList->str)) == 0) { // contains a top level string of str ret=RETURN_SUB_MATCH; } if (strcmp(stringList->str, str) == 0) { // contains str exactly, so return immediately return RETURN_EXACT_MATCH; } stringList = stringList->next; } return ret; } void freeStringList(struct sStringList *stringList) { /* free directory list */ assert(stringList != NULL); struct sStringList *tmp; while (stringList != NULL) { if (stringList->str) free(stringList->str); tmp=stringList; stringList=stringList->next; free(tmp); } } fatsort-0.9.15.245/src/sort.c0000664000076400007640000004636011626221353015055 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains/describes functions for sorting of FAT filesystems. */ #include "sort.h" #include "platform.h" #include #include #include #include #include #include #include #include #include "entrylist.h" #include "errors.h" #include "options.h" #include "endianness.h" #include "clusterchain.h" #include "signal.h" #include "misc.h" #include "fileio.h" #include "platform.h" #include "stringlist.h" #include "mallocv.h" // used to check if device is mounted #if defined(__LINUX__) #include #elif defined (__BSD__) #include #include #include #endif u_int32_t check_mounted(char *filename) { /* check if filesystem is already mounted */ #if defined(__LINUX__) FILE *fd; struct mntent *mnt; u_int32_t ret = 0; char rp_filename[MAXPATHLEN], rp_mnt_fsname[MAXPATHLEN]; if ((fd = setmntent("/etc/mtab", "r")) == NULL) { stderror(); return -1; } // get real path if (realpath(filename, rp_filename) == NULL) { myerror("Unable to get realpath of filename!"); return -1; } while ((mnt = getmntent(fd)) != NULL) { if (realpath(mnt->mnt_fsname, rp_mnt_fsname) != NULL) { if (strcmp(rp_mnt_fsname, rp_filename) == 0) { ret = 1; break; } } } if (endmntent(fd) != 1) { myerror("Closing mtab failed!"); return -1; } return ret; #elif defined(__BSD__) struct statfs *mntbuf; int i, mntsize; u_int32_t ret = 0; char rp_filename[MAXPATHLEN], rp_mnt_fsname[MAXPATHLEN]; // get real path if (realpath(filename, rp_filename) == NULL) { myerror("Unable to get realpath of filename!"); return -1; } mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); if (mntsize == 0) { stderror(); return -1; } for (i = mntsize - 1; i >= 0; i--) { realpath(mntbuf[i].f_mntfromname, rp_mnt_fsname); if (strcmp(rp_mnt_fsname, rp_filename) == 0) { ret = 1; break; } } return ret; #else // ok, we don't know how to check this on an unknown platform myerror("Don't know how to check if filesystem is mounted! Use option '-f' to sort nonetheless."); return -1; #endif } void parseLongFilenamePart(struct sLongDirEntry *lde, char *str) { /* retrieves a part of a long filename from a directory entry (thanks to M$ for this ugly hack...) */ assert(lde != NULL); assert(str != NULL); iconv_t cd; size_t incount; size_t outcount; char *outptr = &(str[0]); char utf16str[28]; char *inptr=&(utf16str[0]); size_t ret; str[0]='\0'; memcpy(utf16str, (&lde->LDIR_Ord+1), 10); memcpy(utf16str+10, (&lde->LDIR_Ord+14), 12); memcpy(utf16str+22, (&lde->LDIR_Ord+28), 4); memset(utf16str+26, 0, 2); incount=26; outcount=MAX_PATH_LEN; cd = iconv_open("UTF-8", "UTF-16LE"); if (cd == (iconv_t)-1) { myerror("iconv_open failed!"); return; } while (incount != 0) { if ((ret=iconv(cd, &inptr, &incount, &outptr, &outcount)) == -1) { myerror("iconv failed! %d", ret); return; } } outptr[0]='\0'; // we get a segfault lateron when this function is called // no idea yet // iconv_close(cd); return; } void parseShortFilename(struct sShortDirEntry *sde, char *str) { /* parses the short name of a file */ assert(sde != NULL); assert(str != NULL); char *s; strncpy(str, sde->DIR_Name, 8); str[8]='\0'; s=strchr(str, ' '); if (s!=NULL) s[0]='\0'; if ((char)(*(sde->DIR_Name+8)) != ' ') { strcat(str, "."); strncat(str, sde->DIR_Name+8, 3); str[12]='\0'; } } int32_t parseClusterChain(FILE *fd, struct sBootSector *bs, struct sClusterChain *chain, struct sDirEntryList *list, u_int32_t *direntries) { /* parses a cluster chain and puts found directory entries to list */ assert(fd != NULL); assert(bs != NULL); assert(chain != NULL); assert(list != NULL); assert(direntries != NULL); int32_t j, ret; u_int32_t maxEntries, entries=0; union sDirEntry de; struct sDirEntryList *lnde; struct sLongDirEntryList *llist; char tmp[MAX_PATH_LEN+1], dummy[MAX_PATH_LEN+1], sname[MAX_PATH_LEN+1], lname[MAX_PATH_LEN+1]; *direntries=0; maxEntries = bs->BS_SecPerClus * SwapInt16(bs->BS_BytesPerSec) / DIR_ENTRY_SIZE; chain=chain->next; // head element llist = NULL; lname[0]='\0'; while (chain != NULL) { fs_seek(fd, getClusterOffset(bs, chain->cluster), SEEK_SET); for (j=1;j<=maxEntries;j++) { entries++; ret=parseEntry(fd, &de); if (ret == -1) { myerror("Failed to parse directory entry!"); return -1; } else if (ret == 0) { //break; return 0; } else if (ret == 2) { parseLongFilenamePart(&de.LongDirEntry, tmp); // insert long dir entry in list llist=insertLongDirEntryList(&de.LongDirEntry, llist); if (llist == NULL) { myerror("Failed to insert LongDirEntry!"); return -1; } strncpy(dummy, tmp, MAX_PATH_LEN); dummy[MAX_PATH_LEN]='\0'; strncat(dummy, lname, MAX_PATH_LEN - strlen(dummy)); dummy[MAX_PATH_LEN]='\0'; strncpy(lname, dummy, MAX_PATH_LEN); dummy[MAX_PATH_LEN]='\0'; } else { parseShortFilename(&de.ShortDirEntry, sname); if (OPT_LIST && strcmp(sname, ".") && strcmp(sname, "..") && (sname[0] != DE_FREE) && !(de.ShortDirEntry.DIR_Atrr & ATTR_VOLUME_ID)) { printf("%s\n", (lname[0] != '\0') ? lname : sname); } lnde=newDirEntry(sname, lname, &de.ShortDirEntry, llist, entries); if (lnde == NULL) { myerror("Failed to create DirEntry!"); return -1; } insertDirEntryList(lnde, list); (*direntries)++; entries=0; llist = NULL; lname[0]='\0'; } } chain=chain->next; } return 0; } int32_t parseDirEntry(FILE *fd, struct sDirEntryList *list, u_int32_t *entries) { /* parses an entry of a directory structure */ assert(fd != NULL); assert(list != NULL); assert(entries != NULL); char sname[MAX_PATH_LEN+1], lname[MAX_PATH_LEN+1], tmp[MAX_PATH_LEN+1], dummy[MAX_PATH_LEN+1]; union sDirEntry de; struct sDirEntryList *lnde; u_int32_t count=0; struct sLongDirEntryList *llist = NULL; // read a directory entry from file if ((fs_read(&de, DIR_ENTRY_SIZE, 1, fd)<1)) { myerror("Failed to read from file!"); return -1; } // if directory entry is empty, return if (de.LongDirEntry.LDIR_Ord == 0) { return 1; } lname[0]='\0'; *entries=0; while (((de.LongDirEntry.LDIR_Attr & ATTR_LONG_NAME_MASK) == ATTR_LONG_NAME) ){ parseLongFilenamePart(&de.LongDirEntry, tmp); // insert long dir entry in list llist=insertLongDirEntryList(&de.LongDirEntry, llist); if (llist == NULL) { myerror("Failed to insert LongDirEntry!"); return -1; } count++; (*entries)++; strncpy(dummy, tmp, MAX_PATH_LEN); dummy[MAX_PATH_LEN]='\0'; strncat(dummy, lname, MAX_PATH_LEN - strlen(dummy)); dummy[MAX_PATH_LEN]='\0'; strncpy(lname, dummy, MAX_PATH_LEN); dummy[MAX_PATH_LEN]='\0'; if (fs_read(&de, DIR_ENTRY_SIZE, 1, fd)<1) { myerror("Failed to read from file!"); return -1; } } /* short-filename directory entry appears after long-filename directory entries well, i should check such things in some future version */ parseShortFilename(&de.ShortDirEntry, sname); (*entries)++; lnde = newDirEntry(sname, lname, &de.ShortDirEntry, llist, *entries); if (lnde == NULL) { myerror("Failed to create DirEntry!"); return -1; } insertDirEntryList(lnde, list); if (OPT_LIST && strcmp(sname, ".") && strcmp (sname, "..") && (sname[0] != DE_FREE) && !(de.ShortDirEntry.DIR_Atrr & ATTR_VOLUME_ID)) { printf("%s\n", (lname[0] != '\0') ? lname : sname); } return 0; } int32_t writeList(FILE *fd, struct sDirEntryList *list) { /* writes directory entries to file */ assert(fd != NULL); assert(list != NULL); struct sLongDirEntryList *tmp; // no signal handling while writing (atomic action) start_critical_section(); while(list->next!=NULL) { tmp=list->next->ldel; while(tmp != NULL) { if (fs_write(tmp->lde, DIR_ENTRY_SIZE, 1, fd)<1) { stderror(); return -1; } tmp=tmp->next; } if (fs_write(list->next->sde, DIR_ENTRY_SIZE, 1, fd)<1) { stderror(); return -1; } list=list->next; } // end of critical section end_critical_section(); return 0; } int32_t getClusterChain(FILE *fd, struct sBootSector *bs, u_int32_t startCluster, struct sClusterChain *chain) { /* retrieves an array of all clusters in a cluster chain starting with startCluster */ assert(fd != NULL); assert(bs != NULL); assert(chain != NULL); u_int32_t cluster; u_int32_t data,i=0; int32_t FATType; cluster=startCluster; FATType=getFATType(bs); if (FATType == FATTYPE_FAT12) { myerror("FAT12 is not supported!"); return -1; } else if (FATType == FATTYPE_FAT16) { do { if (i == MAX_CHAIN_LENGTH) { myerror("Cluster chain is too long!"); return -1; } if (insertCluster(chain, cluster) == -1) { myerror("Failed to insert cluster!"); return -1; } i++; if (getFATEntry(fd, bs, cluster, &data)) { myerror("Failed to get FAT entry!"); return -1; } cluster=data; } while (cluster < 0xfff8); // end of cluster } else if (FATType == FATTYPE_FAT32){ do { if (i == MAX_CHAIN_LENGTH) { myerror("Cluster chain is too long!"); return -1; } if (insertCluster(chain, cluster) == -1) { myerror("Failed to insert cluster!"); return -1; } i++; if (getFATEntry(fd, bs, cluster, &data)) { myerror("Failed to get FAT entry"); return -1; } cluster=data; } while (((cluster & 0x0fffffff) != 0x0ff8fff8) && ((cluster & 0x0fffffff) < 0x0ffffff8)); // end of cluster } else { myerror("Failed to get FAT type!"); return -1; } return i; } int32_t writeClusterChain(FILE *fd, struct sBootSector *bs, struct sDirEntryList *list, struct sClusterChain *chain) { /* writes all entries from list to the cluster chain */ assert(fd != NULL); assert(bs != NULL); assert(list != NULL); assert(chain != NULL); int32_t i=0, entries=0; u_int32_t MaxEntries; struct sLongDirEntryList *tmp; struct sDirEntryList *p=list->next; char empty[DIR_ENTRY_SIZE]={0}; chain=chain->next; // we don't need to look at the head element MaxEntries = bs->BS_SecPerClus * SwapInt16(bs->BS_BytesPerSec) / DIR_ENTRY_SIZE; if (fs_seek(fd, getClusterOffset(bs, chain->cluster), SEEK_SET)==-1) { myerror("Seek error!"); return -1; } // no signal handling while writing (atomic action) start_critical_section(); while(p != NULL) { if (entries+p->entries <= MaxEntries) { tmp=p->ldel; for (i=1;ientries;i++) { if (fs_write(tmp->lde, DIR_ENTRY_SIZE, 1, fd)<1) { stderror(); return -1; } tmp=tmp->next; } if (fs_write(p->sde, DIR_ENTRY_SIZE, 1, fd)<1) { stderror(); return -1; } entries+=p->entries; } else { tmp=p->ldel; for (i=1;i<=MaxEntries-entries;i++) { if (fs_write(tmp->lde, DIR_ENTRY_SIZE, 1, fd)<1) { stderror(); return -1; } tmp=tmp->next; } chain=chain->next; entries=p->entries - (MaxEntries - entries); // next cluster if (fs_seek(fd, getClusterOffset(bs, chain->cluster), SEEK_SET)==-1) { myerror("Seek error!"); return -1; } while(tmp!=NULL) { if (fs_write(tmp->lde, DIR_ENTRY_SIZE, 1, fd)<1) { stderror(); return -1; } tmp=tmp->next; } if (fs_write(p->sde, DIR_ENTRY_SIZE, 1, fd)<1) { stderror(); return -1; } } p=p->next; } if (entries < MaxEntries) { if (fs_write(empty, DIR_ENTRY_SIZE, 1, fd)<1) { stderror(); return -1; } } // end of critical section end_critical_section(); return 0; } int32_t sort_fs(char *filename) { /* sort FAT file system */ assert(filename != NULL); FILE *fd; u_int32_t rfd=0; struct sBootSector bs; int32_t FATType; int32_t ret; if (OPT_FORCE) { if ((fd=fopen(filename, (OPT_LIST) ? "rb" : "r+b")) == NULL) { stderror(); return -1; } } else { // this check is only done for user convenience // open would fail too if device is mounted, but without specific error message ret=check_mounted(filename); switch (ret) { case 0: break; // filesystem not mounted case 1: // filesystem mounted myerror("Filesystem is mounted!"); return -1; case -1: // unable to check myerror("Could not check if filesystem is mounted!"); return -1; } // opens the device exclusively. This is not mandatory! e.g. mkfs.vfat ignores it! if ((rfd=open(filename, (OPT_LIST) ? O_RDONLY | O_EXCL : O_RDWR | O_EXCL)) == -1) { stderror(); return -1; } // connect the file descriptor to a stream if ((fd=fdopen(rfd, (OPT_LIST) ? "rb" : "r+b")) == NULL) { stderror(); return -1; } } // read boot sector if (read_bootsector(fd, &bs)) { myerror("Failed to read boot sector!"); return -1; } FATType = getFATType(&bs); if (FATType == FATTYPE_FAT12) { // FAT12 // sorry, too complicated ;) myerror("FAT12 is not supported!"); return -1; } else if (FATType == FATTYPE_FAT16) { // FAT16 // root directory has fixed size and position infomsg("File system: FAT16.\n\n"); if (sort_FAT16_rootdir(fd, &bs) == -1) { myerror("Failed to sort FAT16 root directory!"); return -1; } } else if (FATType == FATTYPE_FAT32) { // FAT32 // root directory lies in cluster chain, // so sort it like all other directories infomsg("File system: FAT32.\n\n"); if (sortClusterChain(fd, &bs, SwapInt32(bs.FATxx.FAT32.BS_RootClus), "/") == -1) { myerror("Failed to sort first cluster chain!"); return -1; } } else { myerror("Failed to get FAT type!"); return -1; } fs_close(fd); close(rfd); return 0; } int32_t sortClusterChain(FILE *fd, struct sBootSector *bs, u_int32_t cluster, char *path) { /* sorts directory entries in a cluster */ assert(fd != NULL); assert(bs != NULL); assert(path != NULL); u_int32_t clen, value, c, direntries; struct sClusterChain *ClusterChain=newClusterChain(); char newpath[MAX_PATH_LEN+1]={0}; struct sDirEntryList *list = newDirEntryList(); struct sDirEntryList *p; if ((clen=getClusterChain(fd, bs, cluster, ClusterChain)) == -1 ) { myerror("Failed to get cluster chain!"); return -1; } if (!OPT_LIST) { if (parseClusterChain(fd, bs, ClusterChain, list, &direntries) == -1) { myerror("Failed to parse cluster chain!"); return -1; } // sort matching directories if (matchesDirPathLists(OPT_INCL_DIRS, OPT_INCL_DIRS_REC, OPT_EXCL_DIRS, OPT_EXCL_DIRS_REC, path)) { if (OPT_RANDOM) randomizeDirEntryList(list, direntries); infomsg("Sorting directory %s\n", path); if (writeClusterChain(fd, bs, list, ClusterChain) == -1) { myerror("Failed to write cluster chain!"); return -1; } } } else { printf("%s\n", path); if (parseClusterChain(fd, bs, ClusterChain, list, &direntries) == -1) { myerror("Failed to parse cluster chain!"); return -1; } printf("\n"); } freeClusterChain(ClusterChain); // sort sub directories p=list->next; while (p != NULL) { if ((p->sde->DIR_Atrr & ATTR_DIRECTORY) && (p->sde->DIR_Name[0] != DE_FREE) && !(p->sde->DIR_Atrr & ATTR_VOLUME_ID) && (strcmp(p->sname, ".")) && strcmp(p->sname, "..")) { c=(SwapInt16(p->sde->DIR_FstClusHI) * 65536 + SwapInt16(p->sde->DIR_FstClusLO)); if (getFATEntry(fd, bs, c, &value) == -1) { myerror("Failed to get FAT entry!"); return -1; } strncpy(newpath, path, MAX_PATH_LEN - strlen(newpath)); newpath[MAX_PATH_LEN]='\0'; if ((p->lname != NULL) && (p->lname[0] != '\0')) { strncat(newpath, p->lname, MAX_PATH_LEN - strlen(newpath)); newpath[MAX_PATH_LEN]='\0'; strncat(newpath, "/", MAX_PATH_LEN - strlen(newpath)); newpath[MAX_PATH_LEN]='\0'; } else { strncat(newpath, p->sname, MAX_PATH_LEN - strlen(newpath)); newpath[MAX_PATH_LEN]='\0'; strncat(newpath, "/", MAX_PATH_LEN - strlen(newpath)); newpath[MAX_PATH_LEN]='\0'; } if (sortClusterChain(fd, bs, c, newpath) == -1) { myerror("Failed to sort cluster chain!"); return -1; } } p=p->next; } freeDirEntryList(list); return 0; } int32_t sort_FAT16_rootdir(FILE *fd, struct sBootSector *bs) { /* sorts the root directory of a FAT16 file system */ assert(fd != NULL); assert(bs != NULL); off_t BSOffset; u_int32_t FATSz, i, ret; u_int32_t entries,count=0, c, value; u_int32_t direntries=0; char newpath[MAX_PATH_LEN+1]={0}; struct sDirEntryList *list = newDirEntryList(); struct sDirEntryList *p; if (bs->BS_FATSz16 != 0) { FATSz = SwapInt16(bs->BS_FATSz16); } else { FATSz = SwapInt32(bs->FATxx.FAT32.BS_FATSz32); } BSOffset = ((off_t)SwapInt16(bs->BS_RsvdSecCnt) + bs->BS_NumFATs * FATSz)* SwapInt16(bs->BS_BytesPerSec); fs_seek(fd, BSOffset, SEEK_SET); if (OPT_LIST) { printf("/\n"); } // read all entries and parse it to the list for (i=1;i<=SwapInt16(bs->BS_RootEntCnt);i++) { ret=parseDirEntry(fd, list, &entries); count+=entries; if (ret == 1) { break; } else if (ret == -1) { myerror("Failed to parse directory entries!"); return -1; } direntries++; // well, one entry read, but not matched if (entries == 0) count++; } if (!OPT_LIST) { // sort matching directories if (matchesDirPathLists(OPT_INCL_DIRS, OPT_INCL_DIRS_REC, OPT_EXCL_DIRS, OPT_EXCL_DIRS_REC, "/")) { if (OPT_RANDOM) randomizeDirEntryList(list, direntries); infomsg("Sorting directory /\n"); fs_seek(fd, BSOffset, SEEK_SET); // write the sorted entries back to the fs if (writeList(fd, list) == -1) { myerror("Failed to write FAT entries!"); return -1; } } } else { printf("\n"); } // sort sub directories p=list->next; while (p != NULL) { if ((p->sde->DIR_Atrr & ATTR_DIRECTORY) && (p->sde->DIR_Name[0] != DE_FREE) && !(p->sde->DIR_Atrr & ATTR_VOLUME_ID) && (strcmp(p->sname, ".")) && strcmp(p->sname, "..")) { c= (SwapInt16(p->sde->DIR_FstClusHI) * 65536 + SwapInt16(p->sde->DIR_FstClusLO)); if (getFATEntry(fd, bs, c, &value) == -1) { myerror("Failed to get FAT entry!"); return -1; } strncpy(newpath, "/", MAX_PATH_LEN - strlen(newpath)); newpath[MAX_PATH_LEN]='\0'; if ((p->lname != NULL) && (p->lname[0] != '\0')) { strncat(newpath, p->lname, MAX_PATH_LEN - strlen(newpath)); newpath[MAX_PATH_LEN]='\0'; strncat(newpath, "/", MAX_PATH_LEN - strlen(newpath)); newpath[MAX_PATH_LEN]='\0'; } else { strncat(newpath, p->sname, MAX_PATH_LEN - strlen(newpath)); newpath[MAX_PATH_LEN]='\0'; strncat(newpath, "/", MAX_PATH_LEN - strlen(newpath)); newpath[MAX_PATH_LEN]='\0'; } if (sortClusterChain(fd, bs, c, newpath) == -1) { myerror("Failed to sort cluster chain!"); return -1; } } p=p->next; } freeDirEntryList(list); return 0; } fatsort-0.9.15.245/src/entrylist.c0000664000076400007640000002031011626221353016106 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains/describes some ADOs which are used to represent the structures of FAT directory entries and entry lists. */ #include #include #include #include #include "entrylist.h" #include "options.h" #include "errors.h" #include "natstrcmp.h" #include "mallocv.h" #include "stringlist.h" // random number u_int32_t irand( u_int32_t b, u_int32_t e) { double r = e - b + 1; return b + (u_int32_t)(r * rand()/(RAND_MAX+1.0)); } // List functions struct sDirEntryList * newDirEntryList(void) { /* create new dir entry list */ struct sDirEntryList *tmp; if ((tmp=malloc(sizeof(struct sDirEntryList)))==NULL) { stderror(); return NULL; } memset(tmp, 0, sizeof(struct sDirEntryList)); return tmp; } struct sDirEntryList * newDirEntry(char *sname, char *lname, struct sShortDirEntry *sde, struct sLongDirEntryList *ldel, u_int32_t entries) { /* create a new directory entry holder */ assert(sname != NULL); assert(lname != NULL); assert(sde != NULL); struct sDirEntryList *tmp; if ((tmp=malloc(sizeof(struct sDirEntryList)))==NULL) { stderror(); return NULL; } if ((tmp->sname=malloc(strlen(sname)+1))==NULL) { stderror(); return NULL; } strcpy(tmp->sname, sname); if ((tmp->lname=malloc(strlen(lname)+1))==NULL) { stderror(); return NULL; } strcpy(tmp->lname, lname); if ((tmp->sde=malloc(sizeof(struct sShortDirEntry)))==NULL) { stderror(); return NULL; } memcpy(tmp->sde, sde, DIR_ENTRY_SIZE); tmp->ldel=ldel; tmp->entries=entries; tmp->next = NULL; return tmp; } struct sLongDirEntryList * insertLongDirEntryList(struct sLongDirEntry *lde, struct sLongDirEntryList *list) { /* insert a long directory entry to list */ assert(lde != NULL); struct sLongDirEntryList *tmp, *new; if ((new=malloc(sizeof(struct sLongDirEntryList)))==NULL) { stderror(); return NULL; } if ((new->lde=malloc(sizeof(struct sLongDirEntry)))==NULL) { stderror(); return NULL; } memcpy(new->lde, lde, DIR_ENTRY_SIZE); new->next=NULL; if (list != NULL) { tmp=list; while(tmp->next != NULL) { tmp=tmp->next; } tmp->next=new; return list; } else { return new; } } int32_t stripSpecialPrefixes(char *old, char *new) { /* strip special prefixes "a" and "the" */ assert(old != NULL); assert(new != NULL); struct sStringList *prefix=OPT_IGNORE_PREFIXES_LIST; int32_t len, len_old; len_old=strlen(old); while(prefix->next != NULL) { len=strlen(prefix->next->str); DEBUGMSG("prefix: %s", prefix->next->str); if (strncasecmp(old, prefix->next->str, len) == 0) { strncpy(new, old+len, len_old-len); new[len_old-len] = '\0'; return 1; } prefix=prefix->next; } return 0; } int32_t cmpEntries(struct sDirEntryList *de1, struct sDirEntryList *de2) { /* compare two directory entries */ assert(de1 != NULL); assert(de2 != NULL); char s1[MAX_PATH_LEN+1]; char s2[MAX_PATH_LEN+1]; // the volume label must always remain at the beginning of the (root) directory if ((de1->sde->DIR_Atrr & (ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID | ATTR_DIRECTORY)) == ATTR_VOLUME_ID) { return(-1); } else if ((de2->sde->DIR_Atrr & (ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID | ATTR_DIRECTORY)) == ATTR_VOLUME_ID) { return(1); // the special "." and ".." directories must always remain at the beginning of directories, in this order } else if (strcmp(de1->sname, ".") == 0) { return(-1); } else if (strcmp(de2->sname, ".") == 0) { return(1); } else if (strcmp(de1->sname, "..") == 0) { return(-1); } else if (strcmp(de2->sname, "..") == 0) { return(1); // deleted entries should be moved to the end of the directory } else if (de1->sname[0] == DE_FREE) { return(1); } else if (de2->sname[0] == DE_FREE) { return(-1); } char *ss1,*ss2; if ((de1->lname != NULL) && (de1->lname[0] != '\0')) { ss1=de1->lname; } else { ss1=de1->sname; } if ((de2->lname != NULL) && (de2->lname[0] != '\0')) { ss2=de2->lname; } else { ss2=de2->sname; } // it's not necessary to compare files for listing and randomization, // each entry will be put to the end of the list if (OPT_LIST || OPT_RANDOM) return 1; // directories will be put above normal files if (OPT_ORDER == 0) { if ((de1->sde->DIR_Atrr & ATTR_DIRECTORY) && !(de2->sde->DIR_Atrr & ATTR_DIRECTORY)) { return -1; } else if (!(de1->sde->DIR_Atrr & ATTR_DIRECTORY) && (de2->sde->DIR_Atrr & ATTR_DIRECTORY)) { return 1; } } else if (OPT_ORDER == 1) { if ((de1->sde->DIR_Atrr & ATTR_DIRECTORY) && !(de2->sde->DIR_Atrr & ATTR_DIRECTORY)) { return 1; } else if (!(de1->sde->DIR_Atrr & ATTR_DIRECTORY) && (de2->sde->DIR_Atrr & ATTR_DIRECTORY)) { return -1; } } // strip special prefixes if (OPT_IGNORE_PREFIXES_LIST->next != NULL) { if (stripSpecialPrefixes(ss1, s1)) { ss1=s1; } if (stripSpecialPrefixes(ss2, s2)) { ss2=s2; } } if (OPT_NATURAL_SORT) { if (OPT_IGNORE_CASE) { return natstrcasecmp(ss1, ss2) * OPT_REVERSE; } else { return natstrcmp(ss1, ss2) * OPT_REVERSE; } } else { if (OPT_IGNORE_CASE) { return strcasecmp(ss1, ss2) * OPT_REVERSE; } else { return strcmp(ss1, ss2) * OPT_REVERSE; } } } void insertDirEntryList(struct sDirEntryList *new, struct sDirEntryList *list) { /* insert a directory entry into list */ assert(new != NULL); assert(list != NULL); struct sDirEntryList *tmp, *dummy; tmp=list; while ((tmp->next != NULL) && (cmpEntries(new, tmp->next) >= 0)) { tmp=tmp->next; } dummy=tmp->next; tmp->next=new; new->next=dummy; } void freeDirEntryList(struct sDirEntryList *list) { /* free dir entry list */ /* char *sname, *lname; // short and long name strings struct sShortDirEntry *sde; // short dir entry struct sLongDirEntryList *ldel; // long name entries in a list int32_t entries; // number of entries struct sDirEntryList *next; // next dir entry */ assert(list != NULL); struct sDirEntryList *tmp; struct sLongDirEntryList *ldelist, *tmp2; while(list != NULL) { if (list->sname) free(list->sname); if (list->lname) free(list->lname); if (list->sde) free(list->sde); ldelist=list->ldel; while(ldelist != NULL) { free(ldelist->lde); tmp2=ldelist; ldelist = ldelist->next; free(tmp2); } tmp=list; list=list->next; free(tmp); } } void randomizeDirEntryList(struct sDirEntryList *list, u_int32_t entries) { /* randomize entry list */ assert(list != NULL); struct sDirEntryList *randlist, *tmp, *dummy1, *dummy2; u_int32_t i, j, pos; u_int32_t skip=0; randlist=list; // the volume label must always remain at the beginning of the (root) directory // the special "." and ".." directories must always remain at the beginning of directories, so skip them while (randlist->next && (((randlist->next->sde->DIR_Atrr & (ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID | ATTR_DIRECTORY)) == ATTR_VOLUME_ID) || (strcmp(randlist->next->sname, ".") == 0) || (strcmp(randlist->next->sname, "..") == 0))) { DEBUGMSG("skipping randomization for %s", randlist->next->sname) randlist=randlist->next; skip++; } for (i=skip; i < entries; i++) { pos=irand(0, entries - 1 - i); tmp=randlist; // after the loop tmp->next is the selected item for (j=0; jnext; } // put selected entry to top of list dummy1=tmp->next; tmp->next=dummy1->next; dummy2=randlist->next; randlist->next=dummy1; dummy1->next=dummy2; randlist=randlist->next; } } fatsort-0.9.15.245/src/signal.h0000664000076400007640000000243510703712006015336 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains/describes function for signal handling. */ #ifndef __signal_h__ #define __signal_h__ #ifdef __WIN32__ #define init_signal_handling() #define start_critical_section() #define end_critical_section() #else // initialize signal handling for critical sections void init_signal_handling(void); // blocks signals for critical section void start_critical_section(void); // unblocks signals after critical section void end_critical_section(void); #endif #endif // __signal_h__ fatsort-0.9.15.245/src/errors.c0000664000076400007640000000233311626174302015373 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains/describes functions for error handling and messaging. */ #include #include #include "errors.h" #include "mallocv.h" void errormsg(const char *func, const char *str, ...) { /* error messages with function name and argument list */ char msg[129]; va_list argptr; va_start(argptr,str); vsnprintf(msg, 128, str, argptr); fprintf(stderr, "%s: %s\n", func, msg); va_end(argptr); } fatsort-0.9.15.245/src/FAT_fs.c0000664000076400007640000001670711626174302015173 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains/describes functions that are used to read, write, check, and use FAT filesystems. */ #include "FAT_fs.h" #include #include "errors.h" #include "endianness.h" #include "fileio.h" #include "mallocv.h" // --- int32_t check_bootsector(struct sBootSector *bs) { /* lazy check if this is really a FAT bootsector */ assert(bs != NULL); if (!((bs->BS_JmpBoot[0] == 0xeb) && (bs->BS_JmpBoot[2] == 0x90)) && !(bs->BS_JmpBoot[0] == 0xe9)) { // boot sector does not begin with specific instruction myerror("Boot sector does not begin with jump instruction!"); return -1; } else if (SwapInt16(bs->BS_EndOfBS) != 0xaa55) { // end of bootsector marker is missing myerror("End of boot sector marker is missing!"); return -1; } else if (SwapInt16(bs->BS_BytesPerSec) == 0) { myerror("Sectors have a size of zero! Corrupt boot sector!"); return -1; } else if (SwapInt16(bs->BS_SecPerClus) == 0) { myerror("Clusters have a size of zero! Corrupt boot sector!"); return -1; } return 0; } int32_t read_bootsector(FILE *fd, struct sBootSector *bs) { /* reads bootsector */ assert(fd != NULL); assert(bs != NULL); if (fs_read(bs, sizeof(struct sBootSector), 1, fd) < 1) { if (feof(fd)) { myerror("Boot sector is too short!"); } else { myerror("Failed to read from file!"); } return -1; } // #ifdef __WIN32__ // // after having read the boot sector in, fix sector size // sector_size = SwapInt16(bs->BS_BytesPerSec); // #endif if (check_bootsector(bs)) { myerror("This is not a FAT bootsector!"); return -1; } return 0; } int32_t getCountOfClusters(struct sBootSector *bs) { /* calculates count of clusters */ assert(bs != NULL); u_int32_t RootDirSectors, FATSz, TotSec, DataSec; int32_t retvalue; RootDirSectors = ((SwapInt16(bs->BS_RootEntCnt) * DIR_ENTRY_SIZE) + (SwapInt16(bs->BS_BytesPerSec) - 1)); RootDirSectors = RootDirSectors / SwapInt16(bs->BS_BytesPerSec); if (bs->BS_FATSz16 != 0) { FATSz = SwapInt16(bs->BS_FATSz16); } else { FATSz = SwapInt32(bs->FATxx.FAT32.BS_FATSz32); } if (SwapInt16(bs->BS_TotSec16) != 0) { TotSec = SwapInt16(bs->BS_TotSec16); } else { TotSec = SwapInt32(bs->BS_TotSec32); } DataSec = TotSec - (SwapInt16(bs->BS_RsvdSecCnt) + (bs->BS_NumFATs * FATSz) + RootDirSectors); retvalue = DataSec / bs->BS_SecPerClus; if (retvalue <= 0) { myerror("Failed to calculate count of clusters!"); return -1; } return retvalue; } int32_t getFATType(struct sBootSector *bs) { /* retrieves FAT type from bootsector */ assert(bs != NULL); u_int32_t CountOfClusters; CountOfClusters=getCountOfClusters(bs); if (CountOfClusters == -1) { myerror("Failed to get count of clusters!"); return -1; } else if (CountOfClusters < 4096) { // FAT12! return FATTYPE_FAT12; } else if (CountOfClusters < 65525) { // FAT16! return FATTYPE_FAT16; } else { // FAT32! return FATTYPE_FAT32; } } int32_t getFATEntry(FILE *fd, struct sBootSector *bs, u_int32_t cluster, u_int32_t *data) { /* retrieves FAT entry for a cluster number */ assert(fd != NULL); assert(bs != NULL); assert(data != NULL); off_t FATOffset, BSOffset; int32_t FATType; *data=0; FATType = getFATType(bs); if (FATType == FATTYPE_FAT16) { FATOffset = (off_t)cluster * 2; BSOffset = (off_t)SwapInt16(bs->BS_RsvdSecCnt) * SwapInt16(bs->BS_BytesPerSec) + FATOffset; if (fs_seek(fd, BSOffset, SEEK_SET) == -1) { myerror("Seek error!"); return -1; } if (fs_read(data, 2, 1, fd)<1) { myerror("Failed to read from file!"); return -1; } *data=SwapInt32(*data); } else if (FATType == FATTYPE_FAT32) { FATOffset = (off_t)cluster * 4; BSOffset = (off_t)SwapInt16(bs->BS_RsvdSecCnt) * SwapInt16(bs->BS_BytesPerSec) + FATOffset; if (fs_seek(fd, BSOffset, SEEK_SET) == -1) { myerror("Seek error!"); return -1; } if (fs_read(data, 4, 1, fd) < 1) { myerror("Failed to read from file!"); return -1; } *data=SwapInt32(*data); *data = *data & 0x0fffffff; } else if (FATType == FATTYPE_FAT12) { myerror("FAT12 is not supported!"); return -1; } else { myerror("Failed to get FAT type!"); return -1; } return 0; } int32_t putFATEntry(FILE *fd, struct sBootSector *bs, u_int32_t cluster, u_int32_t data) { /* write a FAT entry */ assert(fd != NULL); assert(bs != NULL); off_t FATOffset, FATSz, BSOffset; u_int32_t value, i; int32_t FATType; if (bs->BS_FATSz16 != 0) { FATSz = SwapInt16(bs->BS_FATSz16); } else { FATSz = SwapInt32(bs->FATxx.FAT32.BS_FATSz32); } FATType = getFATType(bs); if (FATType == FATTYPE_FAT16) { FATOffset = (off_t)cluster * 2; BSOffset = (off_t)SwapInt16(bs->BS_RsvdSecCnt) * SwapInt16(bs->BS_BytesPerSec) + FATOffset; fs_seek(fd, BSOffset, SEEK_SET); data=SwapInt32(data); if (fs_write(&data, 2, 1, fd)<1) { myerror("Failed to write to file!"); return -1; } } else if (FATType == FATTYPE_FAT32) { FATOffset = (off_t)cluster * 4; BSOffset = (off_t)SwapInt16(bs->BS_RsvdSecCnt) * SwapInt16(bs->BS_BytesPerSec) + FATOffset; if (getFATEntry(fd, bs, cluster, &value)==-1) { myerror("Failed to get FAT entry!"); return -1; } value = (value & 0xf0000000) | (data & 0x0fffffff); for(i=0; iBS_NumFATs; i++) { fs_seek(fd, BSOffset+i*FATSz*bs->BS_BytesPerSec, SEEK_SET); value=SwapInt32(value); if (fs_write(&value, 4, 1, fd) < 1) { myerror("Failed to write to file!"); return -1; } } } else if (FATType == FATTYPE_FAT12) { myerror("FAT12 is not supported!"); return -1; } else { myerror("Failed to get FAT type!"); return -1; } return 0; } off_t getClusterOffset(struct sBootSector *bs, u_int32_t cluster) { /* returns the offset of a specific cluster in the data region of the file system */ assert(bs != NULL); assert(cluster > 1); u_int32_t FATSz, RootDirSectors, FirstDataSector; if (bs->BS_FATSz16 != 0) { FATSz = SwapInt16(bs->BS_FATSz16); } else { FATSz = SwapInt32(bs->FATxx.FAT32.BS_FATSz32); } RootDirSectors = ((SwapInt16(bs->BS_RootEntCnt) * DIR_ENTRY_SIZE) + (SwapInt16(bs->BS_BytesPerSec) - 1)) / SwapInt16(bs->BS_BytesPerSec); FirstDataSector = (SwapInt16(bs->BS_RsvdSecCnt) + (bs->BS_NumFATs * FATSz) + RootDirSectors); return (((off_t)(cluster - 2) * bs->BS_SecPerClus) + FirstDataSector) * SwapInt16(bs->BS_BytesPerSec); } int32_t parseEntry(FILE *fd, union sDirEntry *de) { /* parses one directory entry */ assert(fd != NULL); assert(de != NULL); if ((fs_read(de, DIR_ENTRY_SIZE, 1, fd)<1)) { myerror("Failed to read from file!"); return -1; } if (de->ShortDirEntry.DIR_Name[0] == DE_FOLLOWING_FREE ) return 0; // no more entries // long dir entry if ((de->LongDirEntry.LDIR_Attr & ATTR_LONG_NAME_MASK) == ATTR_LONG_NAME) return 2; return 1; // short dir entry } fatsort-0.9.15.245/src/stringlist.h0000664000076400007640000000356211626221353016272 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains/describes functions to manage string lists. */ #ifndef __stringlist_h__ #define __stringlist_h__ #include #include "platform.h" #include "FAT_fs.h" struct sStringList { char *str; struct sStringList *next; }; // defines return values for function matchesStringList #define RETURN_NO_MATCH 0 #define RETURN_EXACT_MATCH 1 #define RETURN_SUB_MATCH 2 // create a new string list struct sStringList *newStringList(); // insert new directory path into directory path list int32_t addStringToStringList(struct sStringList *stringList, char *str); // evaluates whether str is contained in strList int32_t matchesStringList(struct sStringList *stringList, char *str); // evaluate whether str matches the include an exclude dir path lists or not int32_t matchesStringLists(struct sStringList *includes, struct sStringList *includes_recursion, struct sStringList *excludes, struct sStringList *excludes_recursion, char str[MAX_PATH_LEN+1]); // free string list void freeStringList(struct sStringList *stringList); #endif //__stringlist_h__ fatsort-0.9.15.245/src/options.c0000664000076400007640000001401411626221353015550 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains/describes functions that parse command line options. */ #include "options.h" #include #include #include #include "errors.h" #include "stringlist.h" #include "mallocv.h" u_int32_t OPT_VERSION, OPT_HELP, OPT_INFO, OPT_QUIET, OPT_IGNORE_CASE, OPT_ORDER, OPT_LIST, OPT_REVERSE, OPT_FORCE, OPT_NATURAL_SORT, OPT_RECURSIVE, OPT_RANDOM; struct sStringList *OPT_INCL_DIRS, *OPT_EXCL_DIRS, *OPT_INCL_DIRS_REC, *OPT_EXCL_DIRS_REC, *OPT_IGNORE_PREFIXES_LIST; int32_t addDirPathToStringList(struct sStringList *stringList, char str[MAX_PATH_LEN+1]) { /* insert new string into string list */ assert(stringList != NULL); assert(stringList->str == NULL); assert(str != NULL); assert(strlen(str) <= MAX_PATH_LEN); char *newStr; int32_t ret, prefix=0, suffix=0, len; len=strlen(str); // determine whether we have to add slashes if (str[0] != '/') prefix=1; if (str[len-1] != '/') suffix=1; // allocate memory for string newStr=malloc(prefix+len+suffix+1); if (newStr == NULL) { stderror(); return -1; } // copy string to new structure including missing slashes newStr[0] = '\0'; strncat(newStr, "/", prefix); strncat(newStr, str, len); strncat(newStr, "/", suffix); if (prefix+len+suffix > MAX_PATH_LEN) { newStr[MAX_PATH_LEN] = '\0'; } else { newStr[prefix+len+suffix] = '\0'; } ret = addStringToStringList(stringList, newStr); free(newStr); return ret; } int32_t matchesDirPathLists(struct sStringList *includes, struct sStringList *includes_recursion, struct sStringList *excludes, struct sStringList *excludes_recursion, char str[MAX_PATH_LEN+1]) { /* evaluate whether str matches the include an exclude dir path lists or not */ int32_t incl, incl_rec, excl, excl_rec; incl=matchesStringList(includes, str); incl_rec=matchesStringList(includes_recursion, str); excl=matchesStringList(excludes, str); excl_rec=matchesStringList(excludes_recursion, str); // debug("str=%s,incl=%d,inclrec=%d,excl=%d,exclrec=%d", str, incl, incl_rec, excl, excl_rec); // if no options -d and -D are used if ((includes->next==NULL) && (includes_recursion->next==NULL)) { // match all directories except those are supplied via -x // and those and subdirs that are supplied via -X if ((excl != RETURN_EXACT_MATCH) && (excl_rec == RETURN_NO_MATCH)) { return 1; // match } // if options -d and -D are used } else { // match all dirs that are supplied via -d, and all dirs and subdirs that are supplied via -D, // except those that excplicitly excluded via -x, or those and their subdirs that are supplied via -X if (((incl == RETURN_EXACT_MATCH) || (incl_rec != RETURN_NO_MATCH)) && (excl != RETURN_EXACT_MATCH) && (excl_rec == RETURN_NO_MATCH)) { return 1; // match } } return 0; // no match } int32_t parse_options(int argc, char *argv[]) { /* parses command line options */ int8_t c; /* Default (1) is normal order, use -1 for reverse order. */ OPT_REVERSE = 1; // natural sort OPT_NATURAL_SORT = 0; // random sort order OPT_RANDOM = 0; // empty string lists for inclusion and exclusion of dirs OPT_INCL_DIRS=newStringList(); OPT_INCL_DIRS_REC=newStringList(); OPT_EXCL_DIRS=newStringList(); OPT_EXCL_DIRS_REC=newStringList(); // empty string list for to be ignored prefixes OPT_IGNORE_PREFIXES_LIST=newStringList(); opterr=0; while ((c=getopt(argc, argv, "ivhqcfo:lrRnd:D:x:X:I:")) != -1) { switch(c) { case 'c' : OPT_IGNORE_CASE = 1; break; case 'f' : OPT_FORCE = 1; break; case 'h' : OPT_HELP = 1; break; case 'i' : OPT_INFO = 1; break; case 'l' : OPT_LIST = 1; break; case 'o' : switch(optarg[0]) { case 'd': OPT_ORDER=0; break; case 'f': OPT_ORDER=1; break; case 'a': OPT_ORDER=2; break; default: myerror("Unknown flag '%c' for option 'o'.", optarg[0]); myerror("Use -h for more help."); return -1; } break; case 'd' : if (addDirPathToStringList(OPT_INCL_DIRS, optarg)) { myerror("Could not add directory path to dirPathList"); return -1; } break; case 'D' : if (addDirPathToStringList(OPT_INCL_DIRS_REC, optarg)) { myerror("Could not add directory path to string list"); return -1; } break; case 'x' : if (addDirPathToStringList(OPT_EXCL_DIRS, optarg)) { myerror("Could not add directory path to string list"); return -1; } break; case 'X' : if (addDirPathToStringList(OPT_EXCL_DIRS_REC, optarg)) { myerror("Could not add directory path to string list"); return -1; } break; case 'I' : if (addStringToStringList(OPT_IGNORE_PREFIXES_LIST, optarg)) { myerror("Could not add directory path to string list"); return -1; } break; case 'n' : OPT_NATURAL_SORT = 1; break; case 'q' : OPT_QUIET = 1; break; case 'r' : OPT_REVERSE = -1; break; case 'R' : OPT_RANDOM = 1; break; case 'v' : OPT_VERSION = 1; break; default : myerror("Unknown option '%c'.", optopt); myerror("Use -h for more help."); return -1; } } return 0; } void freeOptions() { freeStringList(OPT_INCL_DIRS); freeStringList(OPT_INCL_DIRS_REC); freeStringList(OPT_EXCL_DIRS); freeStringList(OPT_EXCL_DIRS_REC); freeStringList(OPT_IGNORE_PREFIXES_LIST); } fatsort-0.9.15.245/src/clusterchain.h0000664000076400007640000000307710703713332016553 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains/describes the cluster chain ADO with its structures and functions. Cluster chain ADOs hold a linked list of cluster numbers. Together all clusters in a cluster chain hold the date of a file or a directory in a FAT filesystem. */ #ifndef __clusterchain_h__ #define __clusterchain_h__ #include #include "platform.h" struct sClusterChain { /* this structure contains cluster chains */ u_int32_t cluster; struct sClusterChain *next; }; // create new cluster chain struct sClusterChain *newClusterChain(void); // allocate memory and insert cluster into cluster chain int32_t insertCluster(struct sClusterChain *chain, u_int32_t cluster); // free cluster chain void freeClusterChain(struct sClusterChain *chain); #endif // __clusterchain_h__ fatsort-0.9.15.245/src/platform.h0000664000076400007640000000314210710206344015702 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains platform dependend macros. */ #ifndef __platform_h__ #define __platform_h__ #ifndef __WIN32__ #if defined(linux) || defined(__linux) || defined(__linux__) #undef __LINUX__ #define __LINUX__ 1 #elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) #undef __BSD__ #define __BSD__ 1 #endif #endif #ifdef __WIN32__ #define off_t off64_t // types defined under Unix but not Windows typedef unsigned char u_char; typedef unsigned char u_int8_t; typedef signed char int8_t; typedef unsigned short u_int16_t; typedef unsigned int u_int32_t; typedef short int int16_t; typedef int int32_t; // extra header files needed under Windows // #include // #include // #include #endif #endif // __platform_h__ fatsort-0.9.15.245/src/natstrcmp.c0000664000076400007640000000544611626204732016103 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2008 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains/describes functions for natural order sorting. */ #include "natstrcmp.h" #include #include #include #include #include "mallocv.h" int32_t isDigit(const char c) { /* return true if c is a digit, otherwise false */ if ((c >= '0') && (c <= '9')) return 1; return 0; } u_int32_t parseNumber(char **s) { /* parse integer in string s */ u_int32_t value=0; if (!isDigit(**s)) return -1; while(isDigit(**s)) { value=value*10 + **s -'0'; (*s)++; } return value; } int32_t natstrcompare(const char *str1, const char *str2, const u_int32_t respectCase) { /* natural order string compare */ assert(str1 != NULL); assert(str2 != NULL); u_int32_t n1=0, n2=0; char *s1 = (char *) str1; char *s2 = (char *) str2; while(1) { // printf("Strings: %s %s\n", s1, s2); if ((*s1 == '\0') || (*s2 == '\0')) { return strcmp(s1, s2); } // compare characters until the first digit occurs while (1) { if (isDigit(*s1) || isDigit(*s2)) break; else if ((*s1 == '\0') && (*s1 == '\0')) return 0; else if ((*s2 == '\0') || (respectCase ? toupper(*s1) > toupper(*s2) : *s1 > *s2)) return 1; else if ((*s1 == '\0') || (respectCase ? toupper(*s1) < toupper(*s2) : *s1 < *s2)) return -1; s1++; s2++; } // at least one of the strings has a number in it n1=parseNumber(&s1); n2=parseNumber(&s2); // printf("Numbers: %d %d\n", n1, n2); // one of the strings had no number if ((n1 == -1) || (n2 == -1)) { if ((*s1 == '\0') && (n1 == -1)) return -1; else if ((*s1 == '\0') && (n2 == -1)) return '0' < *s2 ? -1 : 1; else if ((*s2 == '\0') && (n1 == -1)) return '0' < *s1 ? 1 : -1; else if ((*s2 == '\0') && (n2 == -1)) return 1; // both strings had numbers in it } else if (n1 != n2) return n1 > n2 ? 1 : -1; } } int32_t natstrcmp(const char *str1, const char *str2) { return natstrcompare(str1, str2, 0); } int32_t natstrcasecmp(const char *str1, const char *str2) { return natstrcompare(str1, str2, 1); } fatsort-0.9.15.245/src/clusterchain.c0000664000076400007640000000406111626174302016543 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains/describes the cluster chain ADO with its structures and functions. Cluster chain ADOs hold a linked list of cluster numbers. Together all clusters in a cluster chain hold the date of a file or a directory in a FAT filesystem. */ #include "clusterchain.h" #include #include #include #include "errors.h" #include "mallocv.h" // const struct sClusterChain __INITCLUSTERCHAIN__ = {0, NULL}; struct sClusterChain *newClusterChain(void) { /* create new cluster chain */ struct sClusterChain *tmp; if ((tmp=malloc(sizeof(struct sClusterChain)))==NULL) { stderror(); return NULL; } tmp->cluster=0; tmp->next=NULL; return tmp; } int32_t insertCluster(struct sClusterChain *chain, u_int32_t cluster) { /* allocate memory and insert cluster into cluster chain */ assert(chain != NULL); while (chain->next != NULL) chain=chain->next; if ((chain->next = malloc(sizeof(struct sClusterChain))) == NULL) { stderror(); return -1; } chain->next->cluster=cluster; chain->next->next=NULL; return 0; } void freeClusterChain(struct sClusterChain *chain) { /* free cluster chain */ assert(chain != NULL); struct sClusterChain *tmp; while(chain != NULL) { tmp=chain; chain=chain->next; free(tmp); } } fatsort-0.9.15.245/src/endianness.c0000664000076400007640000000300511626174302016203 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This functions are used to convert endianness of integers. */ #include "endianness.h" #include "mallocv.h" // Endian swap functions #ifdef __BIG_ENDIAN__ u_int16_t SwapInt16(u_int16_t value) { /* swaps endianness of a 16 bit integer */ union { u_int16_t ivalue; char cvalue[2]; } u; u.ivalue=value; char tmp; tmp=u.cvalue[0]; u.cvalue[0]=u.cvalue[1]; u.cvalue[1]=tmp; return u.ivalue; } u_int32_t SwapInt32(u_int32_t value) { /* swaps endianness of a 32 bit integer */ union { u_int32_t ivalue; char cvalue[4]; } u; u.ivalue=value; char tmp; tmp=u.cvalue[0]; u.cvalue[0]=u.cvalue[3]; u.cvalue[3]=tmp; tmp=u.cvalue[1]; u.cvalue[1]=u.cvalue[2]; u.cvalue[2]=tmp; return u.ivalue; } #endif fatsort-0.9.15.245/src/sort.h0000664000076400007640000000244710703712006015053 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains/describes functions for sorting of FAT filesystems. */ #ifndef __sort_h__ #define __sort_h__ #include #include #include "FAT_fs.h" // sorts FAT file system int32_t sort_fs(char *filename); // sorts the root directory of a FAT16 file system int32_t sort_FAT16_rootdir(FILE *fd, struct sBootSector *bs); // sorts directory entries in a cluster int32_t sortClusterChain(FILE *fd, struct sBootSector *bs, u_int32_t cluster, char *path); #endif // __sort_h__ fatsort-0.9.15.245/src/mallocv.h0000664000076400007640000000243711626147617015537 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains/describes debug versions for malloc and free */ #ifndef __mallocv_h__ #define __mallocv_h__ #include #if DEBUG >= 2 #define malloc(size) mallocv(__FILE__, __LINE__, size) #define free(ptr) freev(__FILE__, __LINE__, ptr) #define REPORT_MEMORY_LEAKS reportLeaks(); void *mallocv(char *filename, u_int32_t line, size_t size); void freev(char *filename, u_int32_t line, void *ptr); void reportLeaks(); #else #define REPORT_MEMORY_LEAKS #endif #endif // __mallocv_h__fatsort-0.9.15.245/src/natstrcmp.h0000664000076400007640000000222211116266775016106 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2008 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains/describes functions for natural order sorting. */ #ifndef __natstrcmp_h__ #define __natstrcmp_h__ #include // natural order comparison int32_t natstrcmp(const char *str1, const char *str2); // natural order comparison ignoring case int32_t natstrcasecmp(const char *str1, const char *str2); #endif // __natstrcmp_h__ fatsort-0.9.15.245/src/errors.h0000664000076400007640000000247011626204732015403 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains/describes functions for error handling and messaging. */ #ifndef __errors_h__ #define __errors_h__ #include #include // macros #if DEBUG >= 1 #define DEBUGMSG(msg...) errormsg("DEBUG", msg); #else #define DEBUGMSG(msg...) #endif #define myerror(msg...) errormsg(__func__, msg); #define stderror() errormsg(__func__, "%s!", strerror(errno)); // error messages with function name and argument list void errormsg(const char *func, const char *str, ...); #endif // __errors_h__ fatsort-0.9.15.245/src/entrylist.h0000664000076400007640000000456011314437547016134 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains/describes some ADOs which are used to represent the structures of FAT directory entries and entry lists. */ #ifndef __entrylist_h__ #define __entrylist_h__ #include #include "FAT_fs.h" struct sLongDirEntryList { /* list structures for directory entries list structure for a long name entry */ struct sLongDirEntry *lde; struct sLongDirEntryList *next; }; struct sDirEntryList { /* list structure for every file with short name entries and long name entries */ char *sname, *lname; // short and long name strings struct sShortDirEntry *sde; // short dir entry struct sLongDirEntryList *ldel; // long name entries in a list int32_t entries; // number of entries struct sDirEntryList *next; // next dir entry }; // create new dir entry list struct sDirEntryList * newDirEntryList(void); // randomize entry list void randomizeDirEntryList(struct sDirEntryList *list, u_int32_t entries); // create a new directory entry holder struct sDirEntryList * newDirEntry(char *sname, char *lname, struct sShortDirEntry *sde, struct sLongDirEntryList *ldel, u_int32_t entries); // insert a long directory entry to list struct sLongDirEntryList * insertLongDirEntryList(struct sLongDirEntry *lde, struct sLongDirEntryList *list); // compare two directory entries int32_t cmpEntries(struct sDirEntryList *de1, struct sDirEntryList *de2); // insert a directory entry into list void insertDirEntryList(struct sDirEntryList *new, struct sDirEntryList *list); // free dir entry list void freeDirEntryList(struct sDirEntryList *list); #endif // __entrylist_h__ fatsort-0.9.15.245/src/fileio.c0000664000076400007640000001344611626174302015335 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains file io functions for UNIX/Linux AND Win32 */ #include "fileio.h" #ifdef __WIN32__ /* Win32 implementation of file io */ // extra header files needed under Windows #include #include #include #include #include #include "mallocv.h" // fseek, fread and fwrite need to be wrapped as in drive devices you can only seek to the beginning of sectors and can only write whole sectors #define DEFAULT_SECSIZE 512 #define MAX_SECSIZE 1024 #define UNKNOWN_OFFSET -1 #define hi_dword(qword) ((long)((qword) >> 32)) #define lo_dword(qword) ((long)(qword)) int sector_size = DEFAULT_SECSIZE; off64_t seek_target = 0; off64_t current_off = 0; off64_t prev_sec_off = UNKNOWN_OFFSET; u_char sector_buffer[MAX_SECSIZE]; char prev_access = ' '; int fs_seek(FILE *stream, off64_t offset, int whence) { switch(whence) { case SEEK_SET: seek_target = offset; // DEBUG // printf("SEEK: %08lx%08lx\n", hi_dword(seek_target), lo_dword(seek_target)); return 0; default: return -1; } } void split_off(off64_t off, off64_t *_true_off, int *_off_sec) { int off_sec = off % sector_size; if (_true_off) *_true_off = off - off_sec; if (_off_sec) *_off_sec = off_sec; } int true_fseek_win32(FILE *stream, off64_t target, char access) { int off_sec; off64_t true_off; int seek_result; u_char dummy_buffer[MAX_SECSIZE]; // force seeking between interleaved reads/writes if (target != current_off || access != prev_access) { prev_access = access; split_off(target, &true_off, &off_sec); // DEBUG // printf("TRUESEEK: %08lx%08lx!=%08lx%08lx/%04x->%08lx%08lx+%04x\n", hi_dword(current_off), lo_dword(current_off), hi_dword(seek_target), lo_dword(seek_target), sector_size, hi_dword(true_off), lo_dword(true_off), off_sec); if ((seek_result = fseeko64(stream, true_off, SEEK_SET)) != 0) return seek_result; if (off_sec > 0 && access == 'R' && fread(dummy_buffer, 1, off_sec, stream) < off_sec) return -1; } return 0; } off_t fs_read(void *ptr, u_int32_t size, u_int32_t n, FILE *stream) { if (true_fseek_win32(stream, seek_target, 'R') != 0) return -1; off_t n_read = fread(ptr, size, n, stream); // DEBUG // printf("READ: %08lx%08lx->%02lx*%02lx@%02lx (%02x,%02x,%02x...)\n", hi_dword(seek_target), lo_dword(seek_target), lo_dword(size), lo_dword(n), lo_dword(n_read), ((u_char*)(ptr))[0], ((u_char*)(ptr))[1], ((u_char*)(ptr))[2]); seek_target += (size * n_read); if (n_read < n) current_off = UNKNOWN_OFFSET; else current_off = seek_target; return n_read; } int true_write_win32(FILE *stream) { if (prev_sec_off != UNKNOWN_OFFSET) { if (true_fseek_win32(stream, prev_sec_off, 'W') != 0) { current_off = UNKNOWN_OFFSET; return -1; } current_off = UNKNOWN_OFFSET; if (fwrite(sector_buffer, sector_size, 1, stream) < 1) return -1; // DEBUG // printf("TRUEWRITE: %08lx%08lx\n", hi_dword(prev_sec_off), lo_dword(prev_sec_off)); // {FILE *f; char fn[100]; sprintf(fn, "%08lx%08lx-w.dat", hi_dword(prev_sec_off), lo_dword(prev_sec_off)); f = fopen(fn, "wb"); fwrite(sector_buffer, sector_size, 1, f); fclose(f);} current_off = prev_sec_off + sector_size; } return 0; } off_t fs_write(const void *ptr, u_int32_t size, u_int32_t n, FILE *stream) { int off_sec; off64_t sec_true_off; split_off(seek_target, &sec_true_off, NULL); // if writing a new sector, flush the previous sector and read in the new one if (sec_true_off != prev_sec_off) { if (true_write_win32(stream) != 0) return -1; if (true_fseek_win32(stream, sec_true_off, 'R') != 0) return -1; if (fread(sector_buffer, sector_size, 1, stream) < 1) return -1; // DEBUG // {FILE *f; char fn[100]; sprintf(fn, "%08lx%08lx-r.dat", hi_dword(sec_true_off), lo_dword(sec_true_off)); f = fopen(fn, "rb"); if (f == NULL) {f = fopen(fn, "wb"); fwrite(sector_buffer, sector_size, 1, f);} fclose(f);} prev_sec_off = sec_true_off; current_off = sec_true_off + sector_size; } split_off(seek_target, NULL, &off_sec); memcpy(§or_buffer[off_sec], ptr, size * n); // DEBUG // printf("WRITE: %08lx%08lx->%02lx*%02lx@%02lx (%02x,%02x,%02x...)\n", hi_dword(seek_target), lo_dword(seek_target), lo_dword(size), lo_dword(n), lo_dword(n), ((u_char*)(ptr))[0], ((u_char*)(ptr))[1], ((u_char*)(ptr))[2]); seek_target += (size * n); return n; } int fs_close(FILE* file) { true_write_win32(file); return fclose(file); } #else /* Linux or UNIX */ #include #include int fs_seek(FILE *stream, off_t offset, int whence) { return fseeko(stream, offset, whence); } off_t fs_read(void *ptr, u_int32_t size, u_int32_t n, FILE *stream) { return fread(ptr, size, n, stream); } off_t fs_write(const void *ptr, u_int32_t size, u_int32_t n, FILE *stream) { return fwrite(ptr, size, n, stream); } int fs_close(FILE* file) { return fclose(file); } #define fs_seek(stream,offset,whence) fseeko(stream,offset,whence) // #define fs_read(ptr,size,n,stream) fread(ptr,size,n,stream) #define fs_write(ptr,size,n,stream) fwrite(ptr,size,n,stream) #define fs_close(file) fclose(file) #endif fatsort-0.9.15.245/src/options.h0000664000076400007640000000333211626221353015556 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains/describes functions that parse command line options. */ #ifndef __options_h__ #define __options_h__ #include #include "platform.h" #include "FAT_fs.h" #include "stringlist.h" extern u_int32_t OPT_VERSION, OPT_HELP, OPT_INFO, OPT_QUIET, OPT_IGNORE_CASE, OPT_ORDER, OPT_LIST, OPT_REVERSE, OPT_FORCE, OPT_NATURAL_SORT, OPT_RECURSIVE, OPT_RANDOM; extern struct sStringList *OPT_INCL_DIRS, *OPT_EXCL_DIRS, *OPT_INCL_DIRS_REC, *OPT_EXCL_DIRS_REC, *OPT_IGNORE_PREFIXES_LIST; // parses command line options int32_t parse_options(int argc, char *argv[]); // evaluate whether str matches the include an exclude dir path lists or not int32_t matchesDirPathLists(struct sStringList *includes, struct sStringList *includes_recursion, struct sStringList *excludes, struct sStringList *excludes_recursion, char str[MAX_PATH_LEN+1]); // free options void freeOptions(); #endif // __options_h__ fatsort-0.9.15.245/src/misc.c0000664000076400007640000000223311626174302015011 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains/describes miscellaneous functions. */ #include "misc.h" #include #include #include "options.h" #include "mallocv.h" void infomsg(char *str, ...) { /* info messages that can be muted with a command line option */ va_list argptr; if (!OPT_QUIET) { va_start(argptr,str); vprintf(str,argptr); va_end(argptr); } } fatsort-0.9.15.245/src/signal.c0000664000076400007640000000261311626174302015335 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains/describes function for signal handling. */ #ifndef __WIN32__ #include "signal.h" #include #include #include "mallocv.h" sigset_t blocked_signals_set; void init_signal_handling(void) { /* initialize signal handling for critical sections */ sigfillset(&blocked_signals_set); } void start_critical_section(void) { /* blocks signals for critical section */ sigprocmask(SIG_BLOCK, &blocked_signals_set, NULL); } void end_critical_section(void) { /* unblocks signals after critical section */ sigprocmask(SIG_UNBLOCK, &blocked_signals_set, NULL); } #endif fatsort-0.9.15.245/src/fileio.h0000664000076400007640000000271510703740630015335 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains/describes the cluster chain ADO with its structures and functions. Cluster chain ADOs hold a linked list of cluster numbers. Together all clusters in a cluster chain hold the date of a file or a directory in a FAT filesystem. */ #ifndef __FAT_fs_win32_h__ #define __FAT_fs_win32_h__ #include #include #include "platform.h" #ifdef __WIN32__ // #define off_t off64_t #endif int fs_seek(FILE *stream, off_t offset, int whence); off_t fs_read(void *ptr, u_int32_t size, u_int32_t n, FILE *stream); off_t fs_write(const void *ptr, u_int32_t size, u_int32_t n, FILE *stream); int fs_close(FILE* file); #endif // FAT_fs_win32 fatsort-0.9.15.245/src/endianness.h0000664000076400007640000000240311023777712016216 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This functions are used to convert endianness of integers. */ #ifndef __endianness_h__ #define __endianness_h__ /* supports different byte-orders */ #ifndef __BIG_ENDIAN__ #define SwapInt16(i) i #define SwapInt32(i) i #else #include #include "platform.h" // swaps endianness of a 16 bit integer u_int16_t SwapInt16(u_int16_t value); // swaps endianness of a 32 bit integer u_int32_t SwapInt32(u_int32_t value); #endif #endif //__ endianness_h__ fatsort-0.9.15.245/src/mallocv.c0000664000076400007640000000566211626147617015535 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains/describes debug versions for malloc and free */ #include #include #include #include "mallocv.h" #include "errors.h" #undef malloc #undef free int64_t mem_used=0; struct sList { void *ptr; size_t size; char*file; u_int32_t line; struct sList *next; }; struct sList list={0}; void add(struct sList *list, void *ptr, size_t size, char *filename, u_int32_t line) { assert(list != NULL); while(list->next != NULL) { list = list->next; } list->next = malloc(sizeof(struct sList)); if (list->next == NULL) { stderror(); exit(1); } list->next->ptr=ptr; list->next->size=size; list->next->file=malloc(strlen(filename)+1); if (list->next->file == NULL) { stderror(); exit(1); } strncpy(list->next->file, filename, strlen(filename)); list->next->line=line; list->next->next=NULL; } size_t del(struct sList *list, void *ptr) { assert(list != NULL); size_t size; struct sList *tmp; while(list->next != NULL) { if (list->next->ptr == ptr) { size=list->next->size; free(list->next->ptr); free(list->next->file); tmp=list->next->next; free(list->next); list->next=tmp; return size; } list=list->next; } return 0; } void *mallocv(char *filename, u_int32_t line, size_t size) { void* ptr = malloc(size); add(&list, ptr, size, filename, line); mem_used += size; #if DEBUG >= 3 myerror("%d bytes allocated in %s:%u, ptr=%x (total memory %d)!", size, filename, line, ptr, mem_used); #endif return ptr; } void freev(char *filename, u_int32_t line, void *ptr) { size_t size=del(&list, ptr); if (size) { mem_used-=size; #if DEBUG >= 3 myerror("%d bytes freed in %s:%u (total memory %d)!", size, filename, line, mem_used); #endif } else { #if DEBUG >= 4 myerror("No memory allocated for ptr %x freed at %s:%u!", ptr, filename, line); #endif } } void reportLeaks() { struct sList *tmp=&list; while(tmp->next != NULL) { myerror("%d bytes allocated for ptr %x at %s:%u were not freed!", tmp->next->size, tmp->next->ptr, tmp->next->file, tmp->next->line); tmp = tmp->next; } myerror("Total bytes not freed: %d", mem_used); } fatsort-0.9.15.245/src/FAT_fs.h0000664000076400007640000001370410703726347015201 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains/describes functions that are used to read, write, check, and use FAT filesystems. */ #ifndef __FAT_fs_h__ #define __FAT_fs_h__ // FAT types #define FATTYPE_FAT12 12 #define FATTYPE_FAT16 16 #define FATTYPE_FAT32 32 // file attributes #define ATTR_READ_ONLY 0x01 #define ATTR_HIDDEN 0x02 #define ATTR_SYSTEM 0x04 #define ATTR_VOLUME_ID 0x08 #define ATTR_DIRECTORY 0x10 #define ATTR_ARCHIVE 0x20 #define ATTR_LONG_NAME (ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID) #define ATTR_LONG_NAME_MASK (ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID | ATTR_DIRECTORY | ATTR_ARCHIVE) // constants for the LDIR structure #define DE_FREE (char) 0xe5 #define DE_FOLLOWING_FREE 0x00 #define LAST_LONG_ENTRY 0x40 #define DIR_ENTRY_SIZE 32 // maximum path len on FAT file systems (above specification) #define MAX_PATH_LEN 512 // maximum file len // (specification: file < 4GB which is // maximum clusters in chain * cluster size) #define MAX_FILE_LEN 0xFFFFFFFF #define MAX_CHAIN_LENGTH (MAX_FILE_LEN / 1024) #include #include #include "platform.h" // Directory entry structures // Structure for long directory names struct sLongDirEntry { u_char LDIR_Ord; // Order of entry in sequence char LDIR_Name1[10]; // Chars 1-5 of long name u_char LDIR_Attr; // Attributes (ATTR_LONG_NAME must be set) u_char LDIR_Type; // Type u_char LDIR_Checksum; // Short name checksum char LDIR_Name2[12]; // Chars 6-11 of long name u_int16_t LDIR_FstClusLO; // Zero char LDIR_Name3[4]; // Chars 12-13 of long name } __attribute__((packed)); // Structure for old short directory names struct sShortDirEntry { char DIR_Name[11]; // Short name u_char DIR_Atrr; // File attributes u_char DIR_NTRes; // Reserved for NT u_char DIR_CrtTimeTenth; // Time of creation in ms u_int16_t DIR_CrtTime; // Time of creation u_int16_t DIR_CrtDate; // Date of creation u_int16_t DIR_LstAccDate; // Last access date u_int16_t DIR_FstClusHI; // Hiword of first cluster u_int16_t DIR_WrtTime; // Time of last write u_int16_t DIR_WrtDate; // Date of last write u_int16_t DIR_FstClusLO; // Loword of first cluster u_int32_t DIR_FileSize; // file size in bytes } __attribute__((packed)); union sDirEntry { struct sShortDirEntry ShortDirEntry; struct sLongDirEntry LongDirEntry; } __attribute__((packed)); // Bootsector structures // FAT12 and FAT16 struct sFAT12_16 { u_char BS_DrvNum; // Physical drive number u_char BS_Reserved; // Current head u_char BS_BootSig; // Signature u_int32_t BS_VolID; // Volume ID char BS_VolLab[11]; // Volume Label char BS_FilSysType[8]; // FAT file system type (e.g. FAT, FAT12, FAT16, FAT32) u_char unused[448]; // unused space in bootsector } __attribute__((packed)); // FAT32 struct sFAT32 { u_int32_t BS_FATSz32; // Sectors per FAT u_int16_t BS_ExtFlags; // Flags u_int16_t BS_FSVer; // Version u_int32_t BS_RootClus; // Root Directory Cluster u_int16_t BS_FSInfo; // Sector of FSInfo structure u_int16_t BS_BkBootSec; // Sector number of the boot sector copy in reserved sectors char BS_Reserved[12]; // for future expansion char BS_DrvNum; // see fat12/16 char BS_Reserved1; // see fat12/16 char BS_BootSig; // ... u_int32_t BS_VolID; char BS_VolLab[11]; char BS_FilSysType[8]; u_char unused[420]; // unused space in bootsector } __attribute__((packed)); union sFATxx { struct sFAT12_16 FAT12_16; struct sFAT32 FAT32; } __attribute__((packed)); // First sector = boot sector struct sBootSector { u_char BS_JmpBoot[3]; // Jump instruction (to skip over header on boot) char BS_OEMName[8]; // OEM Name (padded with spaces) u_int16_t BS_BytesPerSec; // Bytes per sector u_char BS_SecPerClus; // Sectors per cluster u_int16_t BS_RsvdSecCnt; // Reserved sector count (including boot sector) u_char BS_NumFATs; // Number of file allocation tables u_int16_t BS_RootEntCnt; // Number of root directory entries u_int16_t BS_TotSec16; // Total sectors (bits 0-15) u_char BS_Media; // Media descriptor u_int16_t BS_FATSz16; // Sectors per file allocation table u_int16_t BS_SecPerTrk; // Sectors per track u_int16_t BS_NumHeads; // Number of heads u_int32_t BS_HiddSec; // Hidden sectors u_int32_t BS_TotSec32; // Total sectors (bits 16-47) union sFATxx FATxx; u_int16_t BS_EndOfBS; // marks end of bootsector } __attribute__((packed)); // functions // lazy check if this is really a FAT bootsector int32_t check_bootsector(struct sBootSector *bs); // reads bootsector int32_t read_bootsector(FILE *fd, struct sBootSector *bs); // calculates count of clusters int32_t getCountOfClusters(struct sBootSector *bs); // retrieves FAT type from bootsector int32_t getFATType(struct sBootSector *bs); // retrieves FAT entry for a cluster number int32_t getFATEntry(FILE *fd, struct sBootSector *bs, u_int32_t cluster, u_int32_t *data); // write a FAT entry int32_t putFATEntry(FILE *fd, struct sBootSector *bs, u_int32_t cluster, u_int32_t data); // returns the offset of a specific cluster in the data region of the file system off_t getClusterOffset(struct sBootSector *bs, u_int32_t cluster); // parses one directory entry int32_t parseEntry(FILE *fd, union sDirEntry *de); #endif // __FAT_fs_h__ fatsort-0.9.15.245/src/Makefile0000664000076400007640000000440411626221353015353 0ustar feanorfeanorCC=gcc LD=gcc ifdef DEBUG CFLAGS += -g -DDEBUG=$(DEBUG) DEBUG_OBJ=mallocv.o else LDFLAGS += -s endif CFLAGS += -Wall override CFLAGS+= -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 INSTALL_FLAGS=-m 0755 -p -D # Detect Mac OS X ($OSTYPE = darwin9.0 for Mac OS X 10.5 and darwin10.0 for Mac OS X 10.6) UNAME=$(shell uname -s) ifeq ($(UNAME),Darwin) NEED_ICONV_LIB = 1 # OS X's install does not support the '-D' flag. INSTALL_FLAGS=-m 0755 -p endif ifeq ($(OSTYPE),FreeBSD) override CFLAGS += -I/usr/local/include LDFLAGS += -L/usr/local/lib NEED_ICONV_LIB = 1 endif ifdef NEED_ICONV_LIB LDFLAGS += -liconv endif # Mac OS X does not have a "/usr/local/sbin" ifeq ($(UNAME),Darwin) SBINDIR=/usr/local/bin else SBINDIR=/usr/local/sbin endif OBJ=fatsort.o FAT_fs.o fileio.o endianness.o signal.o entrylist.o errors.o options.o clusterchain.o sort.o misc.o natstrcmp.o stringlist.o all: fatsort fatsort: $(OBJ) $(DEBUG_OBJ) Makefile ${LD} ${LDFLAGS} $(OBJ) $(DEBUG_OBJ) -o $@ fatsort.o: fatsort.c endianness.h signal.h FAT_fs.h options.h errors.h sort.h misc.h Makefile $(CC) ${CFLAGS} -c $< -o $@ FAT_fs.o: FAT_fs.c FAT_fs.h fileio.h endianness.h errors.h Makefile $(CC) ${CFLAGS} -c $< -o $@ fileio.o: fileio.c fileio.h Makefile $(CC) ${CFLAGS} -c $< -o $@ endianness.o: endianness.c endianness.h Makefile $(CC) ${CFLAGS} -c $< -o $@ signal.o: signal.c signal.h Makefile $(CC) ${CFLAGS} -c $< -o $@ entrylist.o: entrylist.c entrylist.h options.h errors.h FAT_fs.h natstrcmp.h Makefile $(CC) ${CFLAGS} -c $< -o $@ errors.o: errors.c errors.h Makefile $(CC) ${CFLAGS} -c $< -o $@ options.o: options.c options.h errors.h FAT_fs.h Makefile $(CC) ${CFLAGS} -c $< -o $@ clusterchain.o: clusterchain.c clusterchain.h errors.h Makefile $(CC) ${CFLAGS} -c $< -o $@ sort.o: sort.c sort.h options.h FAT_fs.h fileio.h entrylist.h errors.h endianness.h clusterchain.h signal.h misc.h platform.h Makefile $(CC) ${CFLAGS} -c $< -o $@ misc.o: misc.c misc.h options.h Makefile $(CC) ${CFLAGS} -c $< -o $@ natstrcmp.o: natstrcmp.c natstrcmp.h Makefile $(CC) ${CFLAGS} -c $< -o $@ stringlist.o: stringlist.c stringlist.h platform.h errors.h Makefile $(CC) ${CFLAGS} -c $< -o $@ install: install $(INSTALL_FLAGS) fatsort $(DESTDIR)$(SBINDIR)/fatsort clean: rm -f *.o fatsort .PHONY: all clean fatsort-0.9.15.245/src/fatsort.c0000664000076400007640000001501411626204732015542 0ustar feanorfeanor/* FATSort, utility for sorting FAT directory structures Copyright (C) 2004 Boris Leidner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains the main function of fatsort. */ #include #include #include #include #include #include #include #include #include #include // project includes #include "endianness.h" #include "signal.h" #include "FAT_fs.h" #include "options.h" #include "errors.h" #include "sort.h" #include "misc.h" #include "platform.h" #include "mallocv.h" #ifdef __WIN32__ #include #endif // program information #define INFO_PROGRAM "FATSort Utility" #define INFO_VERSION "0.9.15" #define INFO_AUTHOR "Boris Leidner " #define INFO_HEADER INFO_PROGRAM " " INFO_VERSION " by " INFO_AUTHOR #define INFO_LICENSE "License GPLv2: GNU GPL version 2 (see LICENSE.txt)\n" \ "This is free software: you are free to change and redistribute it.\n" \ "There is NO WARRANTY, to the extent permitted by law.\n" #define INFO_USAGE "\n" "Usage: fatsort [options] device\n" \ "\n" \ "Options:\n" \ "\t-c\t Ignore case of file names\n" \ "\t-f\t Force sorting even if filesystem is mounted\n" \ "\t-h\t Print some help\n" \ "\t-i\t Print file system information only\n" \ "\t-I\t Ignore prefixes \"a\" and \"the\"\n" \ "\t-l\t Print current order of files only\n" \ "\t-o flag\t Sort order of files where flag is one of\n" \ "\t\t\td : directories first (default)\n" \ "\t\t\tf : files first\n" \ "\t\t\ta : files and directories are not differentiated\n" \ "\t-n\t Natural order sorting\n" \ "\t-q\t Be quiet\n" \ "\t-r\t Sort in reverse order\n" \ "\t-R\t Sort in random order\n" \ "\t-v\t Print version information\n" \ "\n" \ "\tThe following options can be specified multiple times:\n" \ "\n" \ "\t-d dir\t Sort directory dir only\n" \ "\t-D dir\t Sort directory dir and all subdirectories\n" \ "\t-x dir\t Don't sort directory dir\n" \ "\t-X dir\t Don't sort directory dir and its subdirectories\n" \ "\n" \ "Device must be a FAT16 or FAT32 file system. FAT12 is not supported yet.\n" \ "\n" \ "Example: fatsort /dev/sda\n" \ "\n" \ "NOTE: THE FILESYSTEM MUST BE CONSISTENT, OTHERWISE YOU MAY DAMAGE IT!\n" \ "IF SOMEONE ELSE HAS ACCESS TO THE DEVICE HE MIGHT EXPLOIT FATSORT WITH\n" \ "A FORGED CORRUPT FILESYSTEM! USE THIS PROGRAM AT YOUR OWN RISK!\n" int32_t printFSInfo(char *filename) { /* print file system information */ assert(filename != NULL); u_int32_t FATSz, value; int32_t FATType, cluster; FILE *fd; struct sBootSector bs; printf("\t- File system information -\n"); if ((fd=fopen(filename, "rb")) == NULL) { stderror(); return -1; } // read boot sector if (read_bootsector(fd, &bs)) { myerror("Failed to read boot sector!"); return -1; } if (bs.BS_FATSz16 != 0) { FATSz = SwapInt16(bs.BS_FATSz16); } else { FATSz = SwapInt32(bs.FATxx.FAT32.BS_FATSz32); } FATType = getFATType(&bs); if (FATType == -1) { myerror("Failed to get FAT type!"); return -1; } cluster=getCountOfClusters(&bs); if (cluster == -1) { myerror("Failed to get count of cluster!"); return -1; } printf("Device:\t\t\t\t%s\n", filename); fflush(stdout); printf("Type:\t\t\t\tFAT%u\n", getFATType(&bs)); fflush(stdout); printf("Sector size:\t\t\t%u bytes\n", SwapInt16(bs.BS_BytesPerSec)); fflush(stdout); printf("FAT size:\t\t\t%u sectors (%u bytes)\n", FATSz, FATSz * SwapInt16(bs.BS_BytesPerSec)); printf("Cluster size:\t\t\t%u bytes\n", bs.BS_SecPerClus * SwapInt16(bs.BS_BytesPerSec)); printf("Cluster count:\t\t\t%u\n", cluster); printf("FS size:\t\t\t%.2f MiBytes\n", (float)cluster * bs.BS_SecPerClus * SwapInt16(bs.BS_BytesPerSec) / (1024.0*1024)); if (FATType == FATTYPE_FAT32) { if (getFATEntry(fd, &bs, SwapInt32(bs.FATxx.FAT32.BS_RootClus), &value) == -1) { myerror("Failed to get FAT enry!"); return -1; } printf("FAT32 root directory first cluster: 0x%x, Data offset: 0x%llx, FAT entry: 0x%x\n", SwapInt32(bs.FATxx.FAT32.BS_RootClus), (unsigned long long)getClusterOffset(&bs, SwapInt32(bs.FATxx.FAT32.BS_RootClus)), value); } fclose(fd); return 0; } #ifdef __WIN32__ int32_t win32_fix_filename(char *real_filename, char *filename) { char drive_letter = toupper(filename[0]); if (drive_letter >= 'A' && drive_letter <= 'Z') { strcpy(real_filename, "\\\\.\\?:"); real_filename[4] = drive_letter; return 0; } else { myerror("Invalid drive letter"); return -1; } } #endif int main(int argc, char *argv[]) { /* parse arguments and options and start sorting */ // initialize rng srand(time(0)); // use locale from environment if (setlocale(LC_ALL, "") == NULL) { myerror("Could not set locale!"); return -1; } // initialize blocked signals init_signal_handling(); char *filename; if (parse_options(argc, argv) == -1) { myerror("Faild to parse options!"); return -1; } if (OPT_HELP) { printf(INFO_HEADER "\n\n" INFO_LICENSE INFO_USAGE); return 0; } else if (OPT_VERSION) { printf(INFO_HEADER "\n\n" INFO_LICENSE); return 0; } else if (optind < argc -1) { myerror("Too many arguments!"); myerror("Use -h for more help."); return -1; } else if (optind == argc) { myerror("Device must be given!"); myerror("Use -h for more help."); return -1; } #ifdef __WIN32__ char win_filename[16]; win32_fix_filename(win_filename,argv[optind]); filename=win_filename; #else filename=argv[optind]; #endif if (OPT_INFO) { infomsg(INFO_HEADER "\n\n"); if (printFSInfo(filename) == -1) { myerror("Failed to print file system information"); return -1; } } else { infomsg(INFO_HEADER "\n\n"); if (sort_fs(filename) == -1) { myerror("Failed to sort file system!"); return -1; } } freeOptions(); // report mallocv debugging information REPORT_MEMORY_LEAKS return 0; } fatsort-0.9.15.245/CHANGES0000664000076400007640000000754111626222753014131 0ustar feanorfeanor08/15/2011 v0.9.15 * Multiple directories can now be included and excluded for sorting using options -d, -D, -x, and -X. Thanks to Renaud Métrich for the idea. * Added option -I which allows to ignore filename prefixes during sorting. Thanks to Matthew Altus for the idea. * Added support for memory leak detection in debug modes 2-4 * Fixed a bug in function randomizeDirEntryList. Thanks to Renaud Métrich for reporting the bug. * Updated Makefiles for better Max OS X support. Thanks to Tom Freiberger for the Makefiles. * Minor change to remove a compiler warning in FAT_fs.c. * Minor change to remove a redundant option check. 06/11/2010 v0.9.14.1 * Check for last directory entry in FAT_fs.c was fixed. thanks to Peter De Wachter for the hint. 14/05/2010 v0.9.14 * Included a patch for an iconv issue under Mac and FreeBSD. Thanks to Max Campos. 28/12/2009 v0.9.13.1 * Fixed a pointer initialization in insertLongDirEntryList 23/12/2009 v0.9.13 * Added random order sorting (option -R) * Updated manpage * manpage is now installed via make install 29/09/2009 v0.9.12 * locale is now set to locale of environment 27/09/2009 v0.9.11 * segmentation fault in parseClusterChain fixed * LFNs are now correctly converted from UTF-16 to UTF-8 12/05/2008 v0.9.10 * Options -d and -D added * natural order comparison algorithm reimplemented 12/02/2008 v0.9.9.1 * Small Makefile update 11/28/2008 v0.9.9 * Martin Pool's natural order comparison algorithm is now included into FATSort * Makefile patches 07/08/2008 v0.9.8.3 * bug in check_mounted fixed 06/11/2008 v0.9.8.2 * minor fixes in header files and make files * modified README 06/10/2008 v0.9.8.1 * some minor fixes. Thanks to Till Maas. 09/25/2007 v0.9.8 * splitted fatsort into several source files * implemented exclusive file lock (not mandatory) * signals are blocked while writing to file (implemented critial sections) * sorting of special directory entries (".", ".." and volume label) is now prevented * enhanced mount check feature * -f option to force sorting introduced * small updates * thanks to Joe Forster/STA for some fixes 04/30/2007 v0.9.7.1 * support for files >4GB * thanks to Sebastian Biallas for the patch 02/01/2007 v0.9.7 * fatsort now checks if device is mounted (only BSD and linux) * thanks to Sebastian Dröge for the patch 01/08/2006 v0.9.6.2 * added option for sorting in reverse order * fixed some memory leaks - thanks to Giorgio Moscardi for both patches 07/01/2006 v0.9.6.1 * removed unused variables, minor changes 06/26/2006 v0.9.6 * big-endian support added * getopt fix for PPC * cluster chains are dynamic structures now * small fixes * error handling in FSInfo 05/27/2006 v0.9.5 * fixed volume label bug * tidied up some code * added function assertions * added error handlings * changed error messages 09/09/2005 v0.9.4 * fixed integer issues, included stdlib.h 01/13/2005 v0.9.3 * fixed some data types because of bugs on opteron systems 01/13/2005 v0.9.2 * fixed some bugs 02/08/2004 * FATSort is now put under GPL 02/06/2004 v0.9.1 * major bug concerning FAT specification fixed fatsort-0.9.15.245/Makefile0000664000076400007640000000047211626405017014566 0ustar feanorfeanorMANDIR=/usr/local/share/man/man1 INSTALL_FLAGS=-m 0755 -p -D #detect Mac OS X UNAME=$(shell uname -s) ifeq ($(UNAME),Darwin) INSTALL_FLAGS=-m 0755 -p endif all: $(MAKE) -C src/ clean: $(MAKE) -C src/ clean install: install $(INSTALL_FLAGS) man/fatsort.1 $(DESTDIR)$(MANDIR)/fatsort.1 $(MAKE) -C src/ installfatsort-0.9.15.245/man/0000775000076400007640000000000011626405034013675 5ustar feanorfeanorfatsort-0.9.15.245/man/fatsort.10000664000076400007640000000507011626221353015443 0ustar feanorfeanor.TH "fatsort" "1" "2011" "FATSort 0.9.15" .SH NAME FATSort \- FAT filesystem sorting utility .SH SYNOPSIS .B fatsort [options] device .SH DESCRIPTION FATsort sorts directory structures of FAT filesystems. Many MP3 hardware players don't sort files automatically but play them in the order they were transmitted to the device. FATSort can help here. .SH OPTIONS .TP .B \-c This option causes FATSort to ignore the case of filenames (e.g. 'example.mp3' is equal to 'EXAMPLE.MP3'). .TP .B \-f Force sorting even if the device is mounted or if FATSort cannot determine if the device is mounted. .TP .B \-h Shows some help information. .TP .B \-i Prints some file system information of the specified device. .TP .B \-l FATSort will not sort directory structures, but just print the current order. .TP .BI \-o \ type This options specifies how FATSort will sort files and directories. .I type can be 'd' for directories before files (which is the default), 'f' for files before directories, or 'a' for no differentiation between files and directories. .TP .B \-n Uses natural order to sort directory structures instead of alphanumeric order. For example, an alphanumeric order would be .RS .RS file123.mp3 .RE .RS file21.mp3 .RE .RS file3.mp3 .RE and the corresponding natural order would be .RS .br file3.mp3 .RE .RS .br file21.mp3 .RE .RS .br file123.mp3. .RE .RE .TP .B \-q FATSort will work quietly without printing additional information messages. .TP .B \-r Sorts the directories in reverse order (Z-A). .TP .B \-R Sorts the directories in random order. .TP .B \-v Shows version information only. .TP The following options can be specified multiple times: .TP .BI \-d \ directory Sort .I directory only .TP .BI \-D \ directory Sort .I directory and all subdirectories .TP .BI \-x \ directory Don't sort .I directory .TP .BI \-X \ directory Don't sort .I directory and all subdirectories .TP .BI \-I \ prefix Ignore filename prefix .I prefix during sorting. For example, passing option -I "the " tells FATSort to sort 'The Beatles.mp3' like 'Beatles.mp3'. .SH EXAMPLES .TP Sort FAT filesystem on an USB stick: .B "fatsort /dev/sda1" .TP Sort FAT filesystem in a file: .B "fatsort /home/user/fat16_fs.img" .TP Sort directory /dir1 and all subdirectories except /dir1/dirA: .B "fatsort /dev/sda1 -D /dir1 -x /dir1/dirA" .TP Ignore prefixes 'a ' and 'the ' during sorting: .B "fatsort /dev/sda1 -I ""a "" -I ""the "" .SH AUTHOR Boris Leidner .SH "SEE ALSO" .BR mount (8) .BR fsck (8) .SH NOTES FAT12 is not supported yet. .SH "REPORT BUGS" Please report bugs to fatsort(at)formenos.de. Thanks. fatsort-0.9.15.245/TODO0000664000076400007640000000020011626241033013577 0ustar feanorfeanor* ENHANCEMENT: sort options: sorting by size, etc... * FIX: Understand iconv_close memory corruption in parseLongFilenamePart()