diff options
author | Xiaogang Cui <xiaogang@codeaurora.org> | 2013-10-28 16:47:46 +0800 |
---|---|---|
committer | Adnan Begovic <adnan@cyngn.com> | 2015-10-07 17:39:54 -0700 |
commit | 4678ebd56997c5bba2a34a1c021c906cd769de45 (patch) | |
tree | e1e7cc412a814baec44b5e37303836c353ef27ca | |
parent | 45a5a8bd40065bb0989541252bcca1119e1edb6f (diff) | |
download | android_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.c | 35 |
1 files changed, 25 insertions, 10 deletions
@@ -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; |