1 /* $OpenBSD: check.c,v 1.18 2015/10/14 16:58:55 deraadt 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 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/types.h> 30 #include <sys/ioctl.h> 31 #include <sys/dkio.h> 32 #include <sys/disklabel.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <ctype.h> 36 #include <stdio.h> 37 #include <unistd.h> 38 #include <limits.h> 39 #include <fcntl.h> 40 #include <util.h> 41 #include <err.h> 42 43 #include "ext.h" 44 45 struct disklabel lab; 46 47 int 48 checkfilesys(const char *fname) 49 { 50 int dosfs; 51 struct bootblock boot; 52 struct fatEntry *fat = NULL; 53 char *realdev; 54 int i; 55 int mod = 0; 56 57 rdonly = alwaysno; 58 59 dosfs = opendev(fname, rdonly ? O_RDONLY : O_RDWR, 0, &realdev); 60 if (dosfs < 0 && !rdonly) { 61 dosfs = opendev(fname, O_RDONLY, 0, &realdev); 62 rdonly = 1; 63 } 64 if (dosfs < 0) { 65 xperror("Can't open"); 66 return (8); 67 } 68 69 if (!preen) { 70 printf("** %s", realdev); 71 if (strncmp(fname, realdev, PATH_MAX) != 0) 72 printf(" (%s)", fname); 73 if (rdonly) 74 printf(" (NO WRITE)"); 75 printf("\n"); 76 } 77 78 if (ioctl(dosfs, DIOCGDINFO, (char *)&lab) < 0) 79 pfatal("can't read disk label for %s\n", fname); 80 81 if (pledge("stdio", NULL) == -1) 82 err(1, "pledge"); 83 84 if (readboot(dosfs, &boot) != FSOK) { 85 (void)close(dosfs); 86 return (8); 87 } 88 89 if (!preen) { 90 if (boot.ValidFat < 0) 91 printf("** Phase 1 - Read and Compare FATs\n"); 92 else 93 printf("** Phase 1 - Read FAT\n"); 94 } 95 96 mod |= readfat(dosfs, &boot, boot.ValidFat >= 0 ? boot.ValidFat : 0, &fat); 97 if (mod & FSFATAL) { 98 (void)close(dosfs); 99 return 8; 100 } 101 102 if (boot.ValidFat < 0) 103 for (i = 1; i < boot.FATs; i++) { 104 struct fatEntry *currentFat; 105 mod |= readfat(dosfs, &boot, i, ¤tFat); 106 107 if (mod & FSFATAL) { 108 free(fat); 109 (void)close(dosfs); 110 return 8; 111 } 112 113 mod |= comparefat(&boot, fat, currentFat, i); 114 free(currentFat); 115 if (mod & FSFATAL) { 116 free(fat); 117 (void)close(dosfs); 118 return (8); 119 } 120 } 121 122 if (!preen) 123 printf("** Phase 2 - Check Cluster Chains\n"); 124 125 mod |= checkfat(&boot, fat); 126 if (mod & FSFATAL) { 127 free(fat); 128 (void)close(dosfs); 129 return (8); 130 } 131 132 if (mod & FSFATMOD) 133 mod |= writefat(dosfs, &boot, fat); /* delay writing fats? XXX */ 134 if (mod & FSFATAL) { 135 free(fat); 136 (void)close(dosfs); 137 return (8); 138 } 139 140 if (!preen) 141 printf("** Phase 3 - Check Directories\n"); 142 143 mod |= resetDosDirSection(&boot, fat); 144 if (mod & FSFATAL) { 145 free(fat); 146 close(dosfs); 147 return 8; 148 } 149 150 if (mod & FSFATMOD) 151 mod |= writefat(dosfs, &boot, fat); /* delay writing fats? XXX */ 152 if (mod & FSFATAL) { 153 finishDosDirSection(); 154 free(fat); 155 (void)close(dosfs); 156 return (8); 157 } 158 159 mod |= handleDirTree(dosfs, &boot, fat); 160 if (mod & FSFATAL) { 161 finishDosDirSection(); 162 free(fat); 163 (void)close(dosfs); 164 return (8); 165 } 166 167 if (!preen) 168 printf("** Phase 4 - Check for Lost Files\n"); 169 170 mod |= checklost(dosfs, &boot, fat); 171 if (mod & FSFATAL) { 172 finishDosDirSection(); 173 free(fat); 174 (void)close(dosfs); 175 return 8; 176 } 177 178 if (mod & FSFATMOD) 179 mod |= writefat(dosfs, &boot, fat); /* delay writing fats? XXX */ 180 181 finishDosDirSection(); 182 free(fat); 183 (void)close(dosfs); 184 if (mod & FSFATAL) 185 return 8; 186 187 if (boot.NumBad) 188 pwarn("%d files, %d free (%d clusters), %d bad (%d clusters)\n", 189 boot.NumFiles, 190 boot.NumFree * boot.ClusterSize / 1024, boot.NumFree, 191 boot.NumBad * boot.ClusterSize / 1024, boot.NumBad); 192 else 193 pwarn("%d files, %d free (%d clusters)\n", 194 boot.NumFiles, 195 boot.NumFree * boot.ClusterSize / 1024, boot.NumFree); 196 197 if (mod & (FSFATAL | FSERROR)) 198 return (8); 199 if (mod) { 200 pwarn("\n***** FILE SYSTEM WAS MODIFIED *****\n"); 201 return (4); 202 } 203 return (0); 204 } 205