diff options
author | Xin Li <delphij@google.com> | 2019-04-10 13:38:23 -0700 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2019-04-10 13:38:23 -0700 |
commit | 1e1dad6992abea357715fdae4f747ae2051025a0 (patch) | |
tree | 1032d98650dc82331ccdcba50ae36e98c507ad84 /check.c | |
download | fsck_msdos-1e1dad6992abea357715fdae4f747ae2051025a0.tar.gz |
Import revision 9131ba637f003fb5894e3f6343a27d6322205f18 from FreeBSD.
Change-Id: I8ee418314ea407ca679bcd1bed85bd4cff435c22
Diffstat (limited to 'check.c')
-rw-r--r-- | check.c | 196 |
1 files changed, 196 insertions, 0 deletions
@@ -0,0 +1,196 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank + * Copyright (c) 1995 Martin Husemann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: check.c,v 1.14 2006/06/05 16:51:18 christos Exp $"); +static const char rcsid[] = + "$FreeBSD$"; +#endif /* not lint */ + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> + +#include "ext.h" +#include "fsutil.h" + +int +checkfilesys(const char *fname) +{ + int dosfs; + struct bootblock boot; + struct fatEntry *fat = NULL; + int finish_dosdirsection=0; + u_int i; + int mod = 0; + int ret = 8; + + rdonly = alwaysno; + if (!preen) + printf("** %s", fname); + + dosfs = open(fname, rdonly ? O_RDONLY : O_RDWR, 0); + if (dosfs < 0 && !rdonly) { + dosfs = open(fname, O_RDONLY, 0); + if (dosfs >= 0) + pwarn(" (NO WRITE)\n"); + else if (!preen) + printf("\n"); + rdonly = 1; + } else if (!preen) + printf("\n"); + + if (dosfs < 0) { + perr("Can't open `%s'", fname); + printf("\n"); + return 8; + } + + if (readboot(dosfs, &boot) == FSFATAL) { + close(dosfs); + printf("\n"); + return 8; + } + + if (skipclean && preen && checkdirty(dosfs, &boot)) { + printf("%s: ", fname); + printf("FILESYSTEM CLEAN; SKIPPING CHECKS\n"); + ret = 0; + goto out; + } + + if (!preen) { + if (boot.ValidFat < 0) + printf("** Phase 1 - Read and Compare FATs\n"); + else + printf("** Phase 1 - Read FAT\n"); + } + + mod |= readfat(dosfs, &boot, boot.ValidFat >= 0 ? boot.ValidFat : 0, &fat); + if (mod & FSFATAL) { + close(dosfs); + return 8; + } + + if (boot.ValidFat < 0) + for (i = 1; i < boot.bpbFATs; i++) { + struct fatEntry *currentFat; + + mod |= readfat(dosfs, &boot, i, ¤tFat); + + if (mod & FSFATAL) + goto out; + + mod |= comparefat(&boot, fat, currentFat, i); + free(currentFat); + if (mod & FSFATAL) + goto out; + } + + if (!preen) + printf("** Phase 2 - Check Cluster Chains\n"); + + mod |= checkfat(&boot, fat); + if (mod & FSFATAL) + goto out; + /* delay writing FATs */ + + if (!preen) + printf("** Phase 3 - Checking Directories\n"); + + mod |= resetDosDirSection(&boot, fat); + finish_dosdirsection = 1; + if (mod & FSFATAL) + goto out; + /* delay writing FATs */ + + mod |= handleDirTree(dosfs, &boot, fat); + if (mod & FSFATAL) + goto out; + + if (!preen) + printf("** Phase 4 - Checking for Lost Files\n"); + + mod |= checklost(dosfs, &boot, fat); + if (mod & FSFATAL) + goto out; + + /* now write the FATs */ + if (mod & (FSFATMOD|FSFIXFAT)) { + if (ask(1, "Update FATs")) { + mod |= writefat(dosfs, &boot, fat, mod & FSFIXFAT); + if (mod & FSFATAL) + goto out; + } else + mod |= FSERROR; + } + + if (boot.NumBad) + pwarn("%d files, %d free (%d clusters), %d 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", + boot.NumFiles, + boot.NumFree * boot.ClusterSize / 1024, boot.NumFree); + + if (mod && (mod & FSERROR) == 0) { + if (mod & FSDIRTY) { + if (ask(1, "MARK FILE SYSTEM CLEAN") == 0) + mod &= ~FSDIRTY; + + if (mod & FSDIRTY) { + pwarn("MARKING FILE SYSTEM CLEAN\n"); + mod |= writefat(dosfs, &boot, fat, 1); + } else { + pwarn("\n***** FILE SYSTEM IS LEFT MARKED AS DIRTY *****\n"); + mod |= FSERROR; /* file system not clean */ + } + } + } + + if (mod & (FSFATAL | FSERROR)) + goto out; + + ret = 0; + + out: + if (finish_dosdirsection) + finishDosDirSection(); + free(fat); + close(dosfs); + + if (mod & (FSFATMOD|FSDIRMOD)) + pwarn("\n***** FILE SYSTEM WAS MODIFIED *****\n"); + + return ret; +} |