Import revision 4b0089abdf36a27fda364b25e95706a0abfe6c3a from FreeBSD.

Change-Id: Ib131afe8f995a1847f2f8090c62b288177f6c23b
diff --git a/dir.c b/dir.c
index 6bdc3b4..018250a 100644
--- a/dir.c
+++ b/dir.c
@@ -388,7 +388,8 @@
 checksize(struct fat_descriptor *fat, u_char *p, struct dosDirEntry *dir)
 {
 	int ret = FSOK;
-	size_t physicalSize;
+	size_t chainsize;
+	u_int64_t physicalSize;
 	struct bootblock *boot;
 
 	boot = fat_get_boot(fat);
@@ -401,9 +402,9 @@
 	} else {
 		if (!fat_is_valid_cl(fat, dir->head))
 			return FSERROR;
-		ret = checkchain(fat, dir->head, &physicalSize);
+		ret = checkchain(fat, dir->head, &chainsize);
 		/*
-		 * Upon return, physicalSize would hold the chain length
+		 * Upon return, chainsize would hold the chain length
 		 * that checkchain() was able to validate, but if the user
 		 * refused the proposed repair, it would be unsafe to
 		 * proceed with directory entry fix, so bail out in that
@@ -412,7 +413,13 @@
 		if (ret == FSERROR) {
 			return (FSERROR);
 		}
-		physicalSize *= boot->ClusterSize;
+		/*
+		 * The maximum file size on FAT32 is 4GiB - 1, which
+		 * will occupy a cluster chain of exactly 4GiB in
+		 * size.  On 32-bit platforms, since size_t is 32-bit,
+		 * it would wrap back to 0.
+		 */
+		physicalSize = (u_int64_t)chainsize * boot->ClusterSize;
 	}
 	if (physicalSize < dir->size) {
 		pwarn("size of %s is %u, should at most be %zu\n",