1 /* 2 * Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank 3 * Copyright (c) 1995 Martin Husemann 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Martin Husemann 16 * and Wolfgang Solfrank. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 34 #include <sys/cdefs.h> 35 #ifndef lint 36 __RCSID("$NetBSD: check.c,v 1.10 2000/04/25 23:02:51 jdolecek Exp $"); 37 static const char rcsid[] = 38 "$FreeBSD$"; 39 #endif /* not lint */ 40 41 #include <stdlib.h> 42 #include <string.h> 43 #include <ctype.h> 44 #include <stdio.h> 45 #include <unistd.h> 46 #include <fcntl.h> 47 48 #include "ext.h" 49 #include "fsutil.h" 50 51 int 52 checkfilesys(const char *fname) 53 { 54 int dosfs; 55 struct bootblock boot; 56 struct fatEntry *fat = NULL; 57 int i, finish_dosdirsection=0; 58 int mod = 0; 59 int ret = 8; 60 61 rdonly = alwaysno; 62 if (!preen) 63 printf("** %s", fname); 64 65 dosfs = open(fname, rdonly ? O_RDONLY : O_RDWR, 0); 66 if (dosfs < 0 && !rdonly) { 67 dosfs = open(fname, O_RDONLY, 0); 68 if (dosfs >= 0) 69 pwarn(" (NO WRITE)\n"); 70 else if (!preen) 71 printf("\n"); 72 rdonly = 1; 73 } else if (!preen) 74 printf("\n"); 75 76 if (dosfs < 0) { 77 perror("Can't open"); 78 return 8; 79 } 80 81 if (readboot(dosfs, &boot) != FSOK) { 82 close(dosfs); 83 printf("\n"); 84 return 8; 85 } 86 87 if (skipclean && preen && checkdirty(dosfs, &boot)) { 88 printf("%s: ", fname); 89 printf("FILESYSTEM CLEAN; SKIPPING CHECKS\n"); 90 ret = 0; 91 goto out; 92 } 93 94 if (!preen) { 95 if (boot.ValidFat < 0) 96 printf("** Phase 1 - Read and Compare FATs\n"); 97 else 98 printf("** Phase 1 - Read FAT\n"); 99 } 100 101 mod |= readfat(dosfs, &boot, boot.ValidFat >= 0 ? boot.ValidFat : 0, &fat); 102 if (mod & FSFATAL) { 103 close(dosfs); 104 return 8; 105 } 106 107 if (boot.ValidFat < 0) 108 for (i = 1; i < (int)boot.FATs; i++) { 109 struct fatEntry *currentFat; 110 111 mod |= readfat(dosfs, &boot, i, ¤tFat); 112 113 if (mod & FSFATAL) 114 goto out; 115 116 mod |= comparefat(&boot, fat, currentFat, i); 117 free(currentFat); 118 if (mod & FSFATAL) 119 goto out; 120 } 121 122 if (!preen) 123 printf("** Phase 2 - Check Cluster Chains\n"); 124 125 mod |= checkfat(&boot, fat); 126 if (mod & FSFATAL) 127 goto out; 128 /* delay writing FATs */ 129 130 if (!preen) 131 printf("** Phase 3 - Checking Directories\n"); 132 133 mod |= resetDosDirSection(&boot, fat); 134 finish_dosdirsection = 1; 135 if (mod & FSFATAL) 136 goto out; 137 /* delay writing FATs */ 138 139 mod |= handleDirTree(dosfs, &boot, fat); 140 if (mod & FSFATAL) 141 goto out; 142 143 if (!preen) 144 printf("** Phase 4 - Checking for Lost Files\n"); 145 146 mod |= checklost(dosfs, &boot, fat); 147 if (mod & FSFATAL) 148 goto out; 149 150 /* now write the FATs */ 151 if (mod & FSFATMOD) { 152 if (ask(1, "Update FATs")) { 153 mod |= writefat(dosfs, &boot, fat, mod & FSFIXFAT); 154 if (mod & FSFATAL) 155 goto out; 156 } else 157 mod |= FSERROR; 158 } 159 160 if (boot.NumBad) 161 pwarn("%d files, %d free (%d clusters), %d bad (%d clusters)\n", 162 boot.NumFiles, 163 boot.NumFree * boot.ClusterSize / 1024, boot.NumFree, 164 boot.NumBad * boot.ClusterSize / 1024, boot.NumBad); 165 else 166 pwarn("%d files, %d free (%d clusters)\n", 167 boot.NumFiles, 168 boot.NumFree * boot.ClusterSize / 1024, boot.NumFree); 169 170 if (mod && (mod & FSERROR) == 0) { 171 if (mod & FSDIRTY) { 172 if (ask(1, "MARK FILE SYSTEM CLEAN") == 0) 173 mod &= ~FSDIRTY; 174 175 if (mod & FSDIRTY) { 176 pwarn("MARKING FILE SYSTEM CLEAN\n"); 177 mod |= writefat(dosfs, &boot, fat, 1); 178 } else { 179 pwarn("\n***** FILE SYSTEM IS LEFT MARKED AS DIRTY *****\n"); 180 mod |= FSERROR; /* file system not clean */ 181 } 182 } 183 } 184 185 if (mod & (FSFATAL | FSERROR)) 186 goto out; 187 188 ret = 0; 189 190 out: 191 if (finish_dosdirsection) 192 finishDosDirSection(); 193 free(fat); 194 close(dosfs); 195 196 if (mod & (FSFATMOD|FSDIRMOD)) 197 pwarn("\n***** FILE SYSTEM WAS MODIFIED *****\n"); 198 199 return ret; 200 } 201