1 /* $OpenBSD: check.c,v 1.21 2021/07/12 15:09:18 beck 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 if (unveil("/dev", "rw") == -1) 58 err(1, "unveil /dev"); 59 60 rdonly = alwaysno; 61 62 dosfs = opendev(fname, rdonly ? O_RDONLY : O_RDWR, 0, &realdev); 63 if (dosfs == -1 && !rdonly) { 64 dosfs = opendev(fname, O_RDONLY, 0, &realdev); 65 rdonly = 1; 66 } 67 if (dosfs == -1) { 68 xperror("Can't open"); 69 return (8); 70 } 71 72 if (!preen) { 73 printf("** %s", realdev); 74 if (strncmp(fname, realdev, PATH_MAX) != 0) 75 printf(" (%s)", fname); 76 if (rdonly) 77 printf(" (NO WRITE)"); 78 printf("\n"); 79 } 80 81 if (ioctl(dosfs, DIOCGDINFO, (char *)&lab) == -1) 82 pfatal("can't read disk label for %s\n", fname); 83 84 if (pledge("stdio", NULL) == -1) 85 err(1, "pledge"); 86 87 if (readboot(dosfs, &boot) != FSOK) { 88 (void)close(dosfs); 89 return (8); 90 } 91 92 if (!preen) { 93 if (boot.ValidFat < 0) 94 printf("** Phase 1 - Read and Compare FATs\n"); 95 else 96 printf("** Phase 1 - Read FAT\n"); 97 } 98 99 mod |= readfat(dosfs, &boot, boot.ValidFat >= 0 ? boot.ValidFat : 0, &fat); 100 if (mod & FSFATAL) { 101 (void)close(dosfs); 102 return 8; 103 } 104 105 if (boot.ValidFat < 0) 106 for (i = 1; i < boot.FATs; i++) { 107 struct fatEntry *currentFat; 108 mod |= readfat(dosfs, &boot, i, ¤tFat); 109 110 if (mod & FSFATAL) { 111 free(fat); 112 (void)close(dosfs); 113 return 8; 114 } 115 116 mod |= comparefat(&boot, fat, currentFat, i); 117 free(currentFat); 118 if (mod & FSFATAL) { 119 free(fat); 120 (void)close(dosfs); 121 return (8); 122 } 123 } 124 125 if (!preen) 126 printf("** Phase 2 - Check Cluster Chains\n"); 127 128 mod |= checkfat(&boot, fat); 129 if (mod & FSFATAL) { 130 free(fat); 131 (void)close(dosfs); 132 return (8); 133 } 134 135 if (mod & FSFATMOD) 136 mod |= writefat(dosfs, &boot, fat); /* delay writing fats? XXX */ 137 if (mod & FSFATAL) { 138 free(fat); 139 (void)close(dosfs); 140 return (8); 141 } 142 143 if (!preen) 144 printf("** Phase 3 - Check Directories\n"); 145 146 mod |= resetDosDirSection(&boot, fat); 147 if (mod & FSFATAL) { 148 free(fat); 149 close(dosfs); 150 return 8; 151 } 152 153 if (mod & FSFATMOD) 154 mod |= writefat(dosfs, &boot, fat); /* delay writing fats? XXX */ 155 if (mod & FSFATAL) { 156 finishDosDirSection(); 157 free(fat); 158 (void)close(dosfs); 159 return (8); 160 } 161 162 mod |= handleDirTree(dosfs, &boot, fat); 163 if (mod & FSFATAL) { 164 finishDosDirSection(); 165 free(fat); 166 (void)close(dosfs); 167 return (8); 168 } 169 170 if (!preen) 171 printf("** Phase 4 - Check for Lost Files\n"); 172 173 mod |= checklost(dosfs, &boot, fat); 174 if (mod & FSFATAL) { 175 finishDosDirSection(); 176 free(fat); 177 (void)close(dosfs); 178 return 8; 179 } 180 181 if (mod & FSFATMOD) 182 mod |= writefat(dosfs, &boot, fat); /* delay writing fats? XXX */ 183 184 finishDosDirSection(); 185 free(fat); 186 (void)close(dosfs); 187 if (mod & FSFATAL) 188 return 8; 189 190 if (boot.NumBad) 191 pwarn("%d files, %d free (%d clusters), %d bad (%d clusters)\n", 192 boot.NumFiles, 193 boot.NumFree * boot.ClusterSize / 1024, boot.NumFree, 194 boot.NumBad * boot.ClusterSize / 1024, boot.NumBad); 195 else 196 pwarn("%d files, %d free (%d clusters)\n", 197 boot.NumFiles, 198 boot.NumFree * boot.ClusterSize / 1024, boot.NumFree); 199 200 if (mod & (FSFATAL | FSERROR)) 201 return (8); 202 if (mod) { 203 pwarn("\n***** FILE SYSTEM WAS MODIFIED *****\n"); 204 return (4); 205 } 206 return (0); 207 } 208