summaryrefslogtreecommitdiff
path: root/sbin/fsck_msdos/fat.c
diff options
context:
space:
mode:
authorMarc Espie <espie@cvs.openbsd.org>1999-09-06 12:39:59 +0000
committerMarc Espie <espie@cvs.openbsd.org>1999-09-06 12:39:59 +0000
commitf3ee7cdaaa27287692a9c2b5e22d91ab57590820 (patch)
treed2cde3f54092d8d1509419b074ee3b2c5df92088 /sbin/fsck_msdos/fat.c
parent74f5d046347e1049df2145211ba94429ecb51575 (diff)
Leech newer fat checking code from NetBSD.
Diffstat (limited to 'sbin/fsck_msdos/fat.c')
-rw-r--r--sbin/fsck_msdos/fat.c88
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) {
/*