Update dosfstools

* Version 3.0.28
* Update filenames in source
* Remove unnecessary symlink to fsck
* Commit "Recode short filenames from DOS codepage (default 437)." has
  been reverted since we do not have access to iconv
* Commits cherry-picked on top of 3.0.28:
    - mkfs.fat: fix incorrect int type
    - Prevent out of bound array read in date_dos2unix()

Change-Id: I50310235c62ec2e6bc90afcd10f2814d3afb5113
diff --git a/dosfstools/src/fat.c b/dosfstools/src/fat.c
index 5a0dfb0..5a92f56 100644
--- a/dosfstools/src/fat.c
+++ b/dosfstools/src/fat.c
@@ -2,6 +2,7 @@
 
    Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
    Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
+   Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -16,7 +17,7 @@
    You should have received a copy of the GNU General Public License
    along with this program. If not, see <http://www.gnu.org/licenses/>.
 
-   On Debian systems, the complete text of the GNU General Public License
+   The complete text of the GNU General Public License
    can be found in /usr/share/common-licenses/GPL-3 file.
 */
 
@@ -29,7 +30,7 @@
 #include <unistd.h>
 
 #include "common.h"
-#include "dosfsck.h"
+#include "fsck.fat.h"
 #include "io.h"
 #include "check.h"
 #include "fat.h"
@@ -42,7 +43,7 @@
  * @param[in]	cluster     Cluster of interest
  * @param[in]	fs          Information from the FAT boot sectors (bits per FAT entry)
  */
-void get_fat(FAT_ENTRY * entry, void *fat, unsigned long cluster, DOS_FS * fs)
+void get_fat(FAT_ENTRY * entry, void *fat, uint32_t cluster, DOS_FS * fs)
 {
     unsigned char *ptr;
 
@@ -53,13 +54,13 @@
 				(ptr[0] | ptr[1] << 8));
 	break;
     case 16:
-	entry->value = CF_LE_W(((unsigned short *)fat)[cluster]);
+	entry->value = le16toh(((unsigned short *)fat)[cluster]);
 	break;
     case 32:
 	/* According to M$, the high 4 bits of a FAT32 entry are reserved and
 	 * are not part of the cluster number. So we cut them off. */
 	{
-	    unsigned long e = CF_LE_L(((unsigned int *)fat)[cluster]);
+	    uint32_t e = le32toh(((unsigned int *)fat)[cluster]);
 	    entry->value = e & 0xfffffff;
 	    entry->reserved = e >> 28;
 	}
@@ -79,24 +80,34 @@
  */
 void read_fat(DOS_FS * fs)
 {
-    int eff_size;
-    unsigned long i;
+    int eff_size, alloc_size;
+    uint32_t i;
     void *first, *second = NULL;
     int first_ok, second_ok;
-    unsigned long total_num_clusters;
+    uint32_t total_num_clusters;
 
     /* Clean up from previous pass */
-    free(fs->fat);
-    free(fs->cluster_owner);
+    if (fs->fat)
+	free(fs->fat);
+    if (fs->cluster_owner)
+	free(fs->cluster_owner);
     fs->fat = NULL;
     fs->cluster_owner = NULL;
 
     total_num_clusters = fs->clusters + 2UL;
     eff_size = (total_num_clusters * fs->fat_bits + 7) / 8ULL;
-    first = alloc(eff_size);
+
+    if (fs->fat_bits != 12)
+	    alloc_size = eff_size;
+    else
+	    /* round up to an even number of FAT entries to avoid special
+	     * casing the last entry in get_fat() */
+	    alloc_size = (total_num_clusters * 12 + 23) / 24 * 3;
+
+    first = alloc(alloc_size);
     fs_read(fs->fat_start, eff_size, first);
     if (fs->nfats > 1) {
-	second = alloc(eff_size);
+	second = alloc(alloc_size);
 	fs_read(fs->fat_start + fs->fat_size, eff_size, second);
     }
     if (second && memcmp(first, second, eff_size) != 0) {
@@ -148,13 +159,13 @@
 	FAT_ENTRY curEntry;
 	get_fat(&curEntry, fs->fat, i, fs);
 	if (curEntry.value == 1) {
-	    printf("Cluster %ld out of range (1). Setting to EOF.\n", i - 2);
+	    printf("Cluster %ld out of range (1). Setting to EOF.\n", (long)(i - 2));
 	    set_fat(fs, i, -1);
 	}
 	if (curEntry.value >= fs->clusters + 2 &&
 	    (curEntry.value < FAT_MIN_BAD(fs))) {
 	    printf("Cluster %ld out of range (%ld > %ld). Setting to EOF.\n",
-		   i - 2, curEntry.value, fs->clusters + 2 - 1);
+		   (long)(i - 2), (long)curEntry.value, (long)(fs->clusters + 2 - 1));
 	    set_fat(fs, i, -1);
 	}
     }
@@ -173,13 +184,13 @@
  *				  -1 == end-of-chain
  *				  -2 == bad cluster
  */
-void set_fat(DOS_FS * fs, unsigned long cluster, unsigned long new)
+void set_fat(DOS_FS * fs, uint32_t cluster, int32_t new)
 {
     unsigned char *data = NULL;
     int size;
     loff_t offs;
 
-    if ((long)new == -1)
+    if (new == -1)
 	new = FAT_EOF(fs);
     else if ((long)new == -2)
 	new = FAT_BAD(fs);
@@ -204,7 +215,7 @@
     case 16:
 	data = fs->fat + cluster * 2;
 	offs = fs->fat_start + cluster * 2;
-	*(unsigned short *)data = CT_LE_W(new);
+	*(unsigned short *)data = htole16(new);
 	size = 2;
 	break;
     case 32:
@@ -216,7 +227,7 @@
 	    offs = fs->fat_start + cluster * 4;
 	    /* According to M$, the high 4 bits of a FAT32 entry are reserved and
 	     * are not part of the cluster number. So we never touch them. */
-	    *(unsigned long *)data = CT_LE_L((new & 0xfffffff) |
+	    *(uint32_t *)data = htole32((new & 0xfffffff) |
 					     (curEntry.reserved << 28));
 	    size = 4;
 	}
@@ -230,7 +241,7 @@
     }
 }
 
-int bad_cluster(DOS_FS * fs, unsigned long cluster)
+int bad_cluster(DOS_FS * fs, uint32_t cluster)
 {
     FAT_ENTRY curEntry;
     get_fat(&curEntry, fs->fat, cluster, fs);
@@ -248,9 +259,9 @@
  * @return  -1              'cluster' is at the end of the chain
  * @return  Other values    Next cluster in this chain
  */
-unsigned long next_cluster(DOS_FS * fs, unsigned long cluster)
+uint32_t next_cluster(DOS_FS * fs, uint32_t cluster)
 {
-    unsigned long value;
+    uint32_t value;
     FAT_ENTRY curEntry;
 
     get_fat(&curEntry, fs->fat, cluster, fs);
@@ -261,10 +272,10 @@
     return FAT_IS_EOF(fs, value) ? -1 : value;
 }
 
-loff_t cluster_start(DOS_FS * fs, unsigned long cluster)
+loff_t cluster_start(DOS_FS * fs, uint32_t cluster)
 {
     return fs->data_start + ((loff_t) cluster -
-			     2) * (unsigned long long)fs->cluster_size;
+			     2) * (uint64_t)fs->cluster_size;
 }
 
 /**
@@ -276,7 +287,7 @@
  * @param[in]	    owner       Information on dentry that owns this cluster
  *                              (may be NULL)
  */
-void set_owner(DOS_FS * fs, unsigned long cluster, DOS_FILE * owner)
+void set_owner(DOS_FS * fs, uint32_t cluster, DOS_FILE * owner)
 {
     if (fs->cluster_owner == NULL)
 	die("Internal error: attempt to set owner in non-existent table");
@@ -287,7 +298,7 @@
     fs->cluster_owner[cluster] = owner;
 }
 
-DOS_FILE *get_owner(DOS_FS * fs, unsigned long cluster)
+DOS_FILE *get_owner(DOS_FS * fs, uint32_t cluster)
 {
     if (fs->cluster_owner == NULL)
 	return NULL;
@@ -297,7 +308,7 @@
 
 void fix_bad(DOS_FS * fs)
 {
-    unsigned long i;
+    uint32_t i;
 
     if (verbose)
 	printf("Checking for bad clusters.\n");
@@ -307,7 +318,7 @@
 
 	if (!get_owner(fs, i) && !FAT_IS_BAD(fs, curEntry.value))
 	    if (!fs_test(cluster_start(fs, i), fs->cluster_size)) {
-		printf("Cluster %lu is unreadable.\n", i);
+		printf("Cluster %lu is unreadable.\n", (unsigned long)i);
 		set_fat(fs, i, -2);
 	    }
     }
@@ -316,7 +327,7 @@
 void reclaim_free(DOS_FS * fs)
 {
     int reclaimed;
-    unsigned long i;
+    uint32_t i;
 
     if (verbose)
 	printf("Checking for unused clusters.\n");
@@ -332,7 +343,7 @@
 	}
     }
     if (reclaimed)
-	printf("Reclaimed %d unused cluster%s (%llu bytes).\n", reclaimed,
+	printf("Reclaimed %d unused cluster%s (%llu bytes).\n", (int)reclaimed,
 	       reclaimed == 1 ? "" : "s",
 	       (unsigned long long)reclaimed * fs->cluster_size);
 }
@@ -347,11 +358,11 @@
  *				   clusters link to it.
  * @param[in]	    start_cluster  Where to start scanning for orphans
  */
-static void tag_free(DOS_FS * fs, DOS_FILE * owner, unsigned long *num_refs,
-		     unsigned long start_cluster)
+static void tag_free(DOS_FS * fs, DOS_FILE * owner, uint32_t *num_refs,
+		     uint32_t start_cluster)
 {
     int prev;
-    unsigned long i, walk;
+    uint32_t i, walk;
 
     if (start_cluster == 0)
 	start_cluster = 2;
@@ -400,16 +411,16 @@
     DOS_FILE orphan;
     int reclaimed, files;
     int changed = 0;
-    unsigned long i, next, walk;
-    unsigned long *num_refs = NULL;	/* Only for orphaned clusters */
-    unsigned long total_num_clusters;
+    uint32_t i, next, walk;
+    uint32_t *num_refs = NULL;	/* Only for orphaned clusters */
+    uint32_t total_num_clusters;
 
     if (verbose)
 	printf("Reclaiming unconnected clusters.\n");
 
     total_num_clusters = fs->clusters + 2UL;
-    num_refs = alloc(total_num_clusters * sizeof(unsigned long));
-    memset(num_refs, 0, (total_num_clusters * sizeof(unsigned long)));
+    num_refs = alloc(total_num_clusters * sizeof(uint32_t));
+    memset(num_refs, 0, (total_num_clusters * sizeof(uint32_t)));
 
     /* Guarantee that all orphan chains (except cycles) end cleanly
      * with an end-of-chain mark.
@@ -454,7 +465,7 @@
 		    die("Internal error: num_refs going below zero");
 		set_fat(fs, i, -1);
 		changed = curEntry.value;
-		printf("Broke cycle at cluster %lu in free chain.\n", i);
+		printf("Broke cycle at cluster %lu in free chain.\n", (unsigned long)i);
 
 		/* If we've created a new chain head,
 		 * tag_free() can claim it
@@ -474,13 +485,13 @@
 	    DIR_ENT de;
 	    loff_t offset;
 	    files++;
-	    offset = alloc_rootdir_entry(fs, &de, "FSCK%04d");
-	    de.start = CT_LE_W(i & 0xffff);
+	    offset = alloc_rootdir_entry(fs, &de, "FSCK%04dREC");
+	    de.start = htole16(i & 0xffff);
 	    if (fs->fat_bits == 32)
-		de.starthi = CT_LE_W(i >> 16);
+		de.starthi = htole16(i >> 16);
 	    for (walk = i; walk > 0 && walk != -1;
 		 walk = next_cluster(fs, walk)) {
-		de.size = CT_LE_L(CF_LE_L(de.size) + fs->cluster_size);
+		de.size = htole32(le32toh(de.size) + fs->cluster_size);
 		reclaimed++;
 	    }
 	    fs_write(offset, sizeof(DIR_ENT), &de);
@@ -494,10 +505,10 @@
     free(num_refs);
 }
 
-unsigned long update_free(DOS_FS * fs)
+uint32_t update_free(DOS_FS * fs)
 {
-    unsigned long i;
-    unsigned long free = 0;
+    uint32_t i;
+    uint32_t free = 0;
     int do_set = 0;
 
     for (i = 2; i < fs->clusters + 2; i++) {
@@ -516,7 +527,7 @@
     if (fs->free_clusters != 0xFFFFFFFF) {
 	if (free != fs->free_clusters) {
 	    printf("Free cluster summary wrong (%ld vs. really %ld)\n",
-		   fs->free_clusters, free);
+		   (long)fs->free_clusters, (long)free);
 	    if (interactive)
 		printf("1) Correct\n2) Don't correct\n");
 	    else
@@ -525,7 +536,7 @@
 		do_set = 1;
 	}
     } else {
-	printf("Free cluster summary uninitialized (should be %ld)\n", free);
+	printf("Free cluster summary uninitialized (should be %ld)\n", (long)free);
 	if (rw) {
 	    if (interactive)
 		printf("1) Set it\n2) Leave it uninitialized\n");
@@ -537,7 +548,7 @@
     }
 
     if (do_set) {
-	unsigned long le_free = CT_LE_L(free);
+	uint32_t le_free = htole32(free);
 	fs->free_clusters = free;
 	fs_write(fs->fsinfo_start + offsetof(struct info_sector, free_clusters),
 		 sizeof(le_free), &le_free);