summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXiaogang Cui <xiaogang@codeaurora.org>2013-10-28 16:47:46 +0800
committerAdnan Begovic <adnan@cyngn.com>2015-10-07 17:39:54 -0700
commit4678ebd56997c5bba2a34a1c021c906cd769de45 (patch)
treee1e7cc412a814baec44b5e37303836c353ef27ca
parent45a5a8bd40065bb0989541252bcca1119e1edb6f (diff)
downloadandroid_external_fsck_msdos-4678ebd56997c5bba2a34a1c021c906cd769de45.tar.gz
android_external_fsck_msdos-4678ebd56997c5bba2a34a1c021c906cd769de45.tar.bz2
android_external_fsck_msdos-4678ebd56997c5bba2a34a1c021c906cd769de45.zip
Fix removing file which use last cluster of 4GBytes
The FAT file system limit the file size to 4GBytes. Physical size is how much space in storage the file use, sometimes, we create a file which size is 10 Bytes. But it use 4KB space in disk. fsck_msdos use "int" type to calculate physical size of a file. If a file use last cluster of 4GBytes, 4GB - 1 etc. Then the physical size will overflow, and fsck_msdos treate the size as 0 byte. Change-Id: Ie76f2b8e0cbb510fa9d33c6a8543e6cded6bd347
-rw-r--r--dir.c35
1 files changed, 25 insertions, 10 deletions
diff --git a/dir.c b/dir.c
index 0b26fd4..681859b 100644
--- a/dir.c
+++ b/dir.c
@@ -427,7 +427,8 @@ checksize(struct bootblock *boot, u_char *p,
*/
struct cluster_chain_descriptor *fat,tofind;
struct fatcache *cache;
- int32_t physicalSize;
+ u_int64_t physicalSize;
+ const u_int64_t max_physical_size = 0x100000000;
if (dir->head == CLUST_FREE)
physicalSize = 0;
@@ -440,12 +441,29 @@ checksize(struct bootblock *boot, u_char *p,
pwarn("Can't find the cluster chain with head(%u) \n",dir->head);
return FSERROR;
}
- physicalSize = fat->length * boot->ClusterSize;
+ physicalSize = ((u_int64_t)fat->length) * ((u_int64_t)boot->ClusterSize);
}
- if (physicalSize < dir->size) {
+ /*
+ *The file size means how much useful data the file contains
+ *FAT use 4 bytes to describe the file size, so the max file size is (4GBytes - 1).
+ *The physical size means how much space the file use in disk. The max physical
+ *size is 4GBytes.
+ *
+ *For example, we create a new file in WINDOWS,which size is 100Bytes, but i
+ *use 4KB in disk. Here 100B is file size ,and 4KB is physical size.
+ *
+ *Physical size = (file size + boot->ClusterSize - 1) & (boot->ClusterSize - 1)
+ */
+ if (physicalSize > max_physical_size) {
+ fsck_err("file %s physical size exceed 4 GBytes. %llu\n",
+ fullpath(dir), physicalSize);
+ return FSERROR;
+ }
+
+ if (physicalSize < (u_int64_t)dir->size) {
pwarn("size of %s is %u, should at most be %u\n",
fullpath(dir), dir->size, physicalSize);
- fsck_debug("physicalSize:%d ,dir->size = %d ,dir->head:0x%x\n",physicalSize,dir->size,dir->head);
+ fsck_debug("physicalSize:%llu ,dir->size = %d ,dir->head:0x%x\n",physicalSize,dir->size,dir->head);
if (ask(1, "Truncate")) {
dir->size = physicalSize;
p[28] = (u_char)physicalSize;
@@ -455,10 +473,10 @@ checksize(struct bootblock *boot, u_char *p,
return FSDIRMOD;
} else
return FSERROR;
- } else if (physicalSize - dir->size >= boot->ClusterSize) {
+ } else if (physicalSize - (u_int64_t)dir->size >= (u_int64_t)boot->ClusterSize) {
pwarn("%s has too many clusters allocated\n",
fullpath(dir));
- fsck_debug("physicalSize:%d ,dir->size = %d ,dir->head:0x%x\n",physicalSize,dir->size,dir->head);
+ fsck_debug("physicalSize:%llu ,dir->size = %d ,dir->head:0x%x\n",physicalSize,dir->size,dir->head);
if (ask(1, "Drop superfluous clusters")) {
cl_t cl;
u_int32_t sz = 0;
@@ -470,12 +488,9 @@ checksize(struct bootblock *boot, u_char *p,
if(cl == CLUST_EOF)
break;
}
- //cache = Find_nextclus(fat,cl,&cl);
if(!cache && !cl)
return FSERROR;
- //TODO: i don't no why exec clearchain here.when cl != fat.head,clear do nothing
- //clearchain(boot, fat,cl);
- //if trunc it ,when next fsck ,the rest will locate in LOST.DIR
+
Trunc(boot,fat,cl);
fsck_debug("after truncate ,fat->length = %d \n",fat->length);
return FSFATMOD;