From 05ca3f4d04b0e9bb673d1d59b764005cddbe98ce Mon Sep 17 00:00:00 2001 From: Xin Li Date: Mon, 27 Apr 2020 09:01:09 -0700 Subject: Sync with upstream ffa3961 (svn revision 360359): ffa3961: Fix a bug with dirty file system handling. r356313 broke handling of dirty file system because we have restricted the correction of "odd" byte sequences to checkfat(), and as a result the dirty bit is never cleared. The old fsck_msdosfs code would write FAT twice to fix the dirty bit, which is also not ideal. Fix this by introducing a new rountine, cleardirty() which will perform the set of clean bit only, and use it in checkfilesys() if we thought the file system was dirty. 996c6ae: Use humanize_number to format available and bad space sizes. (Visible change is the addition of KiB suffix in fsck_msdos summary on Android as we don't currently have humanize_number which supports larger numbers) 28bbeac: Diff reduction against NetBSD, no functional change. Bug: 155081558 Test: build Change-Id: I352ad474215fd340399697c0606d69687c8189d1 --- boot.c | 13 +++++++------ check.c | 32 +++++++++++++++++++++++++++++--- ext.h | 2 ++ fat.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 85 insertions(+), 10 deletions(-) diff --git a/boot.c b/boot.c index 86528ce..887312e 100644 --- a/boot.c +++ b/boot.c @@ -28,7 +28,7 @@ #include #ifndef lint -__RCSID("$NetBSD: boot.c,v 1.21 2018/02/08 09:05:17 dholland Exp $"); +__RCSID("$NetBSD: boot.c,v 1.22 2020/01/11 16:29:07 christos Exp $"); static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ @@ -267,10 +267,11 @@ readboot(int dosfs, struct bootblock *boot) } /* - * The number of clusters is derived from available data sectors, divided - * by sectors per cluster. + * The number of clusters is derived from available data sectors, + * divided by sectors per cluster. */ - boot->NumClusters = (boot->NumSectors - boot->FirstCluster) / boot->bpbSecPerClust; + boot->NumClusters = + (boot->NumSectors - boot->FirstCluster) / boot->bpbSecPerClust; if (boot->flags & FAT32) { if (boot->NumClusters > (CLUST_RSRVD & CLUST32_MASK)) { @@ -320,8 +321,8 @@ readboot(int dosfs, struct bootblock *boot) } /* - * There are two reserved clusters. To avoid adding CLUST_FIRST every time - * when we perform boundary checks, we increment the NumClusters by 2, + * There are two reserved clusters. To avoid adding CLUST_FIRST every + * time we perform boundary checks, we increment the NumClusters by 2, * which is CLUST_FIRST to denote the first out-of-range cluster number. */ boot->NumClusters += CLUST_FIRST; diff --git a/check.c b/check.c index 2c38662..f2e896b 100644 --- a/check.c +++ b/check.c @@ -33,6 +33,9 @@ static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ +#ifdef HAVE_LIBUTIL_H +#include +#endif #include #include #include @@ -126,15 +129,38 @@ checkfilesys(const char *fname) mod |= FSERROR; } +#ifdef HAVE_LIBUTIL_H + char freestr[7], badstr[7]; + + int64_t freebytes = boot.NumFree * boot.ClusterSize; + humanize_number(freestr, sizeof(freestr), freebytes, "", + HN_AUTOSCALE, HN_DECIMAL | HN_IEC_PREFIXES); + if (boot.NumBad) { + int64_t badbytes = boot.NumBad * boot.ClusterSize; + + humanize_number(badstr, sizeof(badstr), badbytes, "", + HN_AUTOSCALE, HN_B | HN_DECIMAL | HN_IEC_PREFIXES); + + pwarn("%d files, %sB free (%d clusters), %sB bad (%d clusters)\n", + boot.NumFiles, + freestr, boot.NumFree, + badstr, boot.NumBad); + } else { + pwarn("%d files, %sB free (%d clusters)\n", + boot.NumFiles, + freestr, boot.NumFree); + } +#else if (boot.NumBad) - pwarn("%d files, %d free (%d clusters), %d bad (%d clusters)\n", + pwarn("%d files, %d KiB free (%d clusters), %d KiB bad (%d clusters)\n", boot.NumFiles, boot.NumFree * boot.ClusterSize / 1024, boot.NumFree, boot.NumBad * boot.ClusterSize / 1024, boot.NumBad); else - pwarn("%d files, %d free (%d clusters)\n", + pwarn("%d files, %d KiB free (%d clusters)\n", boot.NumFiles, boot.NumFree * boot.ClusterSize / 1024, boot.NumFree); +#endif if (mod && (mod & FSERROR) == 0) { if (mod & FSDIRTY) { @@ -143,7 +169,7 @@ checkfilesys(const char *fname) if (mod & FSDIRTY) { pwarn("MARKING FILE SYSTEM CLEAN\n"); - mod |= writefat(fat); + mod |= cleardirty(fat); } else { pwarn("\n***** FILE SYSTEM IS LEFT MARKED AS DIRTY *****\n"); mod |= FSERROR; /* file system not clean */ diff --git a/ext.h b/ext.h index 6e9ba7f..532e840 100644 --- a/ext.h +++ b/ext.h @@ -90,6 +90,8 @@ int writefsinfo(int, struct bootblock *); /* Opaque type */ struct fat_descriptor; +int cleardirty(struct fat_descriptor *); + void fat_clear_cl_head(struct fat_descriptor *, cl_t); bool fat_is_cl_head(struct fat_descriptor *, cl_t); diff --git a/fat.c b/fat.c index cb92010..e35e2f2 100644 --- a/fat.c +++ b/fat.c @@ -578,7 +578,6 @@ valid_cl(struct fat_descriptor *fat, cl_t cl) * h = hard error flag (1 = ok; 0 = I/O error) * x = any value ok */ - int checkdirty(int fs, struct bootblock *boot) { @@ -642,6 +641,53 @@ err: return ret; } +int +cleardirty(struct fat_descriptor *fat) +{ + int fd, ret = FSERROR; + struct bootblock *boot; + u_char *buffer; + size_t len; + off_t off; + + boot = boot_of_(fat); + fd = fd_of_(fat); + + if (boot->ClustMask != CLUST16_MASK && boot->ClustMask != CLUST32_MASK) + return 0; + + off = boot->bpbResSectors; + off *= boot->bpbBytesPerSec; + + buffer = malloc(len = boot->bpbBytesPerSec); + if (buffer == NULL) { + perr("No memory for FAT sectors (%zu)", len); + return 1; + } + + if ((size_t)pread(fd, buffer, len, off) != len) { + perr("Unable to read FAT"); + goto err; + } + + if (boot->ClustMask == CLUST16_MASK) { + buffer[3] |= 0x80; + } else { + buffer[7] |= 0x08; + } + + if ((size_t)pwrite(fd, buffer, len, off) != len) { + perr("Unable to write FAT"); + goto err; + } + + ret = FSOK; + +err: + free(buffer); + return ret; +} + /* * Read a FAT from disk. Returns 1 if successful, 0 otherwise. */ -- cgit v1.2.3 From 4f36a18db8d324e8495f2a237e4824c03182e4ab Mon Sep 17 00:00:00 2001 From: Xin Li Date: Tue, 28 Apr 2020 09:03:01 -0700 Subject: Sync with upstream 2ccadef (svn revision 360428): Do not overflow when calculating file system size. Test: build Bug: 155183047 Change-Id: I05a8f1b3ef10ec6a765a78adf122f274dcda12cd --- check.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/check.c b/check.c index f2e896b..9519315 100644 --- a/check.c +++ b/check.c @@ -54,6 +54,8 @@ checkfilesys(const char *fname) int finish_dosdirsection=0; int mod = 0; int ret = 8; + int64_t freebytes; + int64_t badbytes; rdonly = alwaysno; if (!preen) @@ -129,37 +131,33 @@ checkfilesys(const char *fname) mod |= FSERROR; } + freebytes = (int64_t)boot.NumFree * boot.ClusterSize; + badbytes = (int64_t)boot.NumBad * boot.ClusterSize; + #ifdef HAVE_LIBUTIL_H char freestr[7], badstr[7]; - int64_t freebytes = boot.NumFree * boot.ClusterSize; humanize_number(freestr, sizeof(freestr), freebytes, "", HN_AUTOSCALE, HN_DECIMAL | HN_IEC_PREFIXES); if (boot.NumBad) { - int64_t badbytes = boot.NumBad * boot.ClusterSize; - humanize_number(badstr, sizeof(badstr), badbytes, "", HN_AUTOSCALE, HN_B | HN_DECIMAL | HN_IEC_PREFIXES); pwarn("%d files, %sB free (%d clusters), %sB bad (%d clusters)\n", - boot.NumFiles, - freestr, boot.NumFree, + boot.NumFiles, freestr, boot.NumFree, badstr, boot.NumBad); } else { pwarn("%d files, %sB free (%d clusters)\n", - boot.NumFiles, - freestr, boot.NumFree); + boot.NumFiles, freestr, boot.NumFree); } #else if (boot.NumBad) - pwarn("%d files, %d KiB free (%d clusters), %d KiB bad (%d clusters)\n", - boot.NumFiles, - boot.NumFree * boot.ClusterSize / 1024, boot.NumFree, - boot.NumBad * boot.ClusterSize / 1024, boot.NumBad); + pwarn("%d files, %jd KiB free (%d clusters), %jd KiB bad (%d clusters)\n", + boot.NumFiles, (intmax_t)freebytes / 1024, boot.NumFree, + (intmax_t)badbytes / 1024, boot.NumBad); else - pwarn("%d files, %d KiB free (%d clusters)\n", - boot.NumFiles, - boot.NumFree * boot.ClusterSize / 1024, boot.NumFree); + pwarn("%d files, %jd KiB free (%d clusters)\n", + boot.NumFiles, (intmax_t)freebytes / 1024, boot.NumFree); #endif if (mod && (mod & FSERROR) == 0) { -- cgit v1.2.3