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/lfn.c b/dosfstools/src/lfn.c
index 736491c..2601172 100644
--- a/dosfstools/src/lfn.c
+++ b/dosfstools/src/lfn.c
@@ -1,6 +1,7 @@
 /* lfn.c - Functions for handling VFAT long filenames
 
    Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
+   Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -15,11 +16,12 @@
    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.
 */
 
 #include <stdio.h>
+#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 #include <limits.h>
@@ -27,19 +29,19 @@
 
 #include "common.h"
 #include "io.h"
-#include "dosfsck.h"
+#include "fsck.fat.h"
 #include "lfn.h"
 #include "file.h"
 
 typedef struct {
-    __u8 id;			/* sequence number for slot */
-    __u8 name0_4[10];		/* first 5 characters in name */
-    __u8 attr;			/* attribute byte */
-    __u8 reserved;		/* always 0 */
-    __u8 alias_checksum;	/* checksum for 8.3 alias */
-    __u8 name5_10[12];		/* 6 more characters in name */
-    __u16 start;		/* starting cluster number, 0 in long slots */
-    __u8 name11_12[4];		/* last 2 characters in name */
+    uint8_t id;			/* sequence number for slot */
+    uint8_t name0_4[10];	/* first 5 characters in name */
+    uint8_t attr;		/* attribute byte */
+    uint8_t reserved;		/* always 0 */
+    uint8_t alias_checksum;	/* checksum for 8.3 alias */
+    uint8_t name5_10[12];	/* 6 more characters in name */
+    uint16_t start;		/* starting cluster number, 0 in long slots */
+    uint8_t name11_12[4];	/* last 2 characters in name */
 } LFN_ENT;
 
 #define LFN_ID_START	0x40
@@ -85,6 +87,22 @@
 	(cnv_unicode( lfn_unicode+(lfn_slot*CHARS_PER_LFN*2),	\
 		      lfn_parts*CHARS_PER_LFN, 0 ))
 
+#define BYTES_TO_WCHAR(cl,ch) ((wchar_t)((unsigned)(cl) + ((unsigned)(ch) << 8)))
+static size_t mbslen(wchar_t x)
+{
+    wchar_t wstr[] = { x, 0 };
+    return wcstombs(NULL, wstr, 0);
+}
+
+static size_t wctombs(char *dest, wchar_t x)
+{
+    wchar_t wstr[] = { x, 0 };
+    size_t size = wcstombs(NULL, wstr, 0);
+    if (size != (size_t) - 1)
+	size = wcstombs(dest, wstr, size + 1);
+    return size;
+}
+
 /* This function converts an unicode string to a normal ASCII string, assuming
  * ISO-8859-1 charset. Characters not in 8859-1 are converted to the same
  * escape notation as used by the kernel, i.e. the uuencode-like ":xxx" */
@@ -93,10 +111,13 @@
     const unsigned char *up;
     unsigned char *out, *cp;
     int len, val;
+    size_t x;
 
     for (len = 0, up = uni; (up - uni) / 2 < maxlen && (up[0] || up[1]);
 	 up += 2) {
-	if (UNICODE_CONVERTABLE(up[0], up[1]))
+	if ((x = mbslen(BYTES_TO_WCHAR(up[0], up[1]))) != (size_t) - 1)
+	    len += x;
+	else if (UNICODE_CONVERTABLE(up[0], up[1]))
 	    ++len;
 	else
 	    len += 4;
@@ -104,7 +125,10 @@
     cp = out = use_q ? qalloc(&mem_queue, len + 1) : alloc(len + 1);
 
     for (up = uni; (up - uni) / 2 < maxlen && (up[0] || up[1]); up += 2) {
-	if (UNICODE_CONVERTABLE(up[0], up[1]))
+	if ((x =
+	     wctombs((char *)cp, BYTES_TO_WCHAR(up[0], up[1]))) != (size_t) - 1)
+	    cp += x;
+	else if (UNICODE_CONVERTABLE(up[0], up[1]))
 	    *cp++ = up[0];
 	else {
 	    /* here the same escape notation is used as in the Linux kernel */
@@ -150,7 +174,7 @@
 void lfn_fix_checksum(loff_t from, loff_t to, const char *short_name)
 {
     int i;
-    __u8 sum;
+    uint8_t sum;
     for (sum = 0, i = 0; i < 11; i++)
 	sum = (((sum & 1) << 7) | ((sum & 0xfe) >> 1)) + short_name[i];
 
@@ -366,7 +390,7 @@
 		     sizeof(lfn->reserved), &lfn->reserved);
 	}
     }
-    if (lfn->start != CT_LE_W(0)) {
+    if (lfn->start != htole16(0)) {
 	printf("Start cluster field in VFAT long filename slot is not 0 "
 	       "(but 0x%04x).\n", lfn->start);
 	if (interactive)
@@ -374,7 +398,7 @@
 	else
 	    printf("Auto-setting to 0.\n");
 	if (!interactive || get_key("12", "?") == '1') {
-	    lfn->start = CT_LE_W(0);
+	    lfn->start = htole16(0);
 	    fs_write(dir_offset + offsetof(LFN_ENT, start),
 		     sizeof(lfn->start), &lfn->start);
 	}
@@ -386,7 +410,7 @@
 char *lfn_get(DIR_ENT * de, loff_t * lfn_offset)
 {
     char *lfn;
-    __u8 sum;
+    uint8_t sum;
     int i;
 
     *lfn_offset = 0;
@@ -430,7 +454,7 @@
 	    return NULL;
 	case '3':
 	    for (i = 0; i < lfn_parts; ++i) {
-		__u8 id = (lfn_parts - i) | (i == 0 ? LFN_ID_START : 0);
+		uint8_t id = (lfn_parts - i) | (i == 0 ? LFN_ID_START : 0);
 		fs_write(lfn_offsets[i] + offsetof(LFN_ENT, id),
 			 sizeof(id), &id);
 	    }
@@ -440,8 +464,10 @@
 	}
     }
 
-    for (sum = 0, i = 0; i < 11; i++)
+    for (sum = 0, i = 0; i < 8; i++)
 	sum = (((sum & 1) << 7) | ((sum & 0xfe) >> 1)) + de->name[i];
+    for (i = 0; i < 3; i++)
+	sum = (((sum & 1) << 7) | ((sum & 0xfe) >> 1)) + de->ext[i];
     if (sum != lfn_checksum) {
 	/* checksum doesn't match, long name doesn't apply to this alias */
 	/* Causes: 1) alias renamed */