diff options
author | Marc Espie <espie@cvs.openbsd.org> | 1999-09-06 12:39:59 +0000 |
---|---|---|
committer | Marc Espie <espie@cvs.openbsd.org> | 1999-09-06 12:39:59 +0000 |
commit | f3ee7cdaaa27287692a9c2b5e22d91ab57590820 (patch) | |
tree | d2cde3f54092d8d1509419b074ee3b2c5df92088 /sbin/fsck_msdos/fat.c | |
parent | 74f5d046347e1049df2145211ba94429ecb51575 (diff) |
Leech newer fat checking code from NetBSD.
Diffstat (limited to 'sbin/fsck_msdos/fat.c')
-rw-r--r-- | sbin/fsck_msdos/fat.c | 88 |
1 files changed, 45 insertions, 43 deletions
diff --git a/sbin/fsck_msdos/fat.c b/sbin/fsck_msdos/fat.c index d4091087e3e..36b0c8d08c3 100644 --- a/sbin/fsck_msdos/fat.c +++ b/sbin/fsck_msdos/fat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fat.c,v 1.7 1998/01/11 20:40:33 provos Exp $ */ +/* $OpenBSD: fat.c,v 1.8 1999/09/06 12:39:58 espie Exp $ */ /* $NetBSD: fat.c,v 1.8 1997/10/17 11:19:53 ws Exp $ */ /* @@ -35,7 +35,7 @@ #ifndef lint -static char rcsid[] = "$OpenBSD: fat.c,v 1.7 1998/01/11 20:40:33 provos Exp $"; +static char rcsid[] = "$OpenBSD: fat.c,v 1.8 1999/09/06 12:39:58 espie Exp $"; #endif /* not lint */ #include <stdlib.h> @@ -48,6 +48,7 @@ static char rcsid[] = "$OpenBSD: fat.c,v 1.7 1998/01/11 20:40:33 provos Exp $"; static int checkclnum __P((struct bootblock *, int, cl_t, cl_t *)); static int clustdiffer __P((cl_t, cl_t *, cl_t *, int)); +static int tryclear __P((struct bootblock *, struct fatEntry *, cl_t, cl_t *)); /* * Check a cluster number for valid value @@ -209,6 +210,8 @@ char * rsrvdcltype(cl) cl_t cl; { + if (cl == CLUST_FREE) + return ("free"); if (cl < CLUST_BAD) return ("reserved"); if (cl > CLUST_BAD) @@ -223,9 +226,10 @@ clustdiffer(cl, cp1, cp2, fatnum) cl_t *cp2; int fatnum; { - if (*cp1 >= CLUST_RSRVD) { - if (*cp2 >= CLUST_RSRVD) { - if ((*cp1 < CLUST_BAD && *cp2 < CLUST_BAD) + if (*cp1 == CLUST_FREE || *cp1 >= CLUST_RSRVD) { + if (*cp2 == CLUST_FREE || *cp2 >= CLUST_RSRVD) { + if ((*cp1 != CLUST_FREE && *cp1 < CLUST_BAD + && *cp2 != CLUST_FREE && *cp2 < CLUST_BAD) || (*cp1 > CLUST_BAD && *cp2 > CLUST_BAD)) { pwarn("Cluster %u is marked %s with different indicators, ", cl, rsrvdcltype(*cp1)); @@ -259,8 +263,8 @@ clustdiffer(cl, cp1, cp2, fatnum) } return (FSFATAL); } - if (*cp2 >= CLUST_RSRVD) { - pwarn("Cluster %u continues with cluster %u in FAT 1, but is marked %s in FAT %d\n", + if (*cp2 == CLUST_FREE || *cp2 >= CLUST_RSRVD) { + pwarn("Cluster %u continues with cluster %u in FAT 0, but is marked %s in FAT %d\n", cl, *cp1, rsrvdcltype(*cp2), fatnum); if (ask(0, "Use continuation from FAT 0")) { *cp2 = *cp1; @@ -322,6 +326,23 @@ clearchain(boot, fat, head) } } +int +tryclear(boot, fat, head, trunc) + struct bootblock *boot; + struct fatEntry *fat; + cl_t head; + cl_t *trunc; +{ + if (ask(0, "Clear chain starting at %u", head)) { + clearchain(boot, fat, head); + return FSFATMOD; + } else if (ask(0, "Truncate")) { + *trunc = CLUST_EOF; + return FSFATMOD; + } else + return FSERROR; +} + /* * Check a complete FAT in-memory for crosslinks */ @@ -330,7 +351,7 @@ checkfat(boot, fat) struct bootblock *boot; struct fatEntry *fat; { - cl_t head, p, h; + cl_t head, p, h, n; u_int len; int ret = 0; int conf; @@ -369,54 +390,35 @@ checkfat(boot, fat) /* follow the chain to its end (hopefully) */ for (p = head; - fat[p].next >= CLUST_FIRST && fat[p].next < boot->NumClusters; - p = fat[p].next) - if (fat[fat[p].next].head != head) + (n = fat[p].next) >= CLUST_FIRST && n < boot->NumClusters; + p = n) + if (fat[n].head != head) break; - if (fat[p].next >= CLUST_EOFS) + if (n >= CLUST_EOFS) continue; - if (fat[p].next == 0) { - pwarn("Cluster chain starting at %u ends with free cluster\n", head); - if (ask(0, "Clear chain starting at %u", head)) { - clearchain(boot, fat, head); - ret |= FSFATMOD; - } else - ret |= FSERROR; - continue; - } - if (fat[p].next >= CLUST_RSRVD) { + if (n == CLUST_FREE || n >= CLUST_RSRVD) { pwarn("Cluster chain starting at %u ends with cluster marked %s\n", - head, rsrvdcltype(fat[p].next)); - if (ask(0, "Clear chain starting at %u", head)) { - clearchain(boot, fat, head); - ret |= FSFATMOD; - } else - ret |= FSERROR; + head, rsrvdcltype(n)); + ret |= tryclear(boot, fat, head, &fat[p].next); continue; } - if (fat[p].next < CLUST_FIRST || fat[p].next >= boot->NumClusters) { + if (n < CLUST_FIRST || n >= boot->NumClusters) { pwarn("Cluster chain starting at %u ends with cluster out of range (%u)\n", - head, fat[p].next); - if (ask(0, "Clear chain starting at %u", head)) { - clearchain(boot, fat, head); - ret |= FSFATMOD; - } else - ret |= FSERROR; + head, n); + ret |= tryclear(boot, fat, head, &fat[p].next); + continue; } pwarn("Cluster chains starting at %u and %u are linked at cluster %u\n", - head, fat[p].head, p); - conf = FSERROR; - if (ask(0, "Clear chain starting at %u", head)) { - clearchain(boot, fat, head); - conf = FSFATMOD; - } - if (ask(0, "Clear chain starting at %u", h = fat[p].head)) { + head, fat[n].head, n); + conf = tryclear(boot, fat, head, &fat[p].next); + if (ask(0, "Clear chain starting at %u", h = fat[n].head)) { if (conf == FSERROR) { /* * Transfer the common chain to the one not cleared above. */ - for (; p >= CLUST_FIRST && p < boot->NumClusters; + for (p = n; + p >= CLUST_FIRST && p < boot->NumClusters; p = fat[p].next) { if (h != fat[p].head) { /* |