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