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