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 * $NetBSD: check.c,v 1.10 2000/04/25 23:02:51 jdolecek Exp $ 33 * $FreeBSD: src/sbin/fsck_msdosfs/check.c,v 1.1.2.1 2001/08/01 05:47:55 obrien Exp $ 34 * $DragonFly: src/sbin/fsck_msdosfs/check.c,v 1.3 2003/09/28 14:39:17 hmp Exp $ 35 */ 36 37 38 #include <sys/cdefs.h> 39 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 47 #include "ext.h" 48 #include "fsutil.h" 49 50 int 51 checkfilesys(const char *fname) 52 { 53 int dosfs; 54 struct bootblock boot; 55 struct fatEntry *fat = NULL; 56 int i, finish_dosdirsection=0; 57 int mod = 0; 58 int ret = 8; 59 60 rdonly = alwaysno; 61 if (!preen) 62 printf("** %s", fname); 63 64 dosfs = open(fname, rdonly ? O_RDONLY : O_RDWR, 0); 65 if (dosfs < 0 && !rdonly) { 66 dosfs = open(fname, O_RDONLY, 0); 67 if (dosfs >= 0) 68 pwarn(" (NO WRITE)\n"); 69 else if (!preen) 70 printf("\n"); 71 rdonly = 1; 72 } else if (!preen) 73 printf("\n"); 74 75 if (dosfs < 0) { 76 perror("Can't open"); 77 return 8; 78 } 79 80 if (readboot(dosfs, &boot) != FSOK) { 81 close(dosfs); 82 printf("\n"); 83 return 8; 84 } 85 86 if (!preen) { 87 if (boot.ValidFat < 0) 88 printf("** Phase 1 - Read and Compare FATs\n"); 89 else 90 printf("** Phase 1 - Read FAT\n"); 91 } 92 93 mod |= readfat(dosfs, &boot, boot.ValidFat >= 0 ? boot.ValidFat : 0, &fat); 94 if (mod & FSFATAL) { 95 close(dosfs); 96 return 8; 97 } 98 99 if (boot.ValidFat < 0) 100 for (i = 1; i < boot.FATs; i++) { 101 struct fatEntry *currentFat; 102 103 mod |= readfat(dosfs, &boot, i, ¤tFat); 104 105 if (mod & FSFATAL) 106 goto out; 107 108 mod |= comparefat(&boot, fat, currentFat, i); 109 free(currentFat); 110 if (mod & FSFATAL) 111 goto out; 112 } 113 114 if (!preen) 115 printf("** Phase 2 - Check Cluster Chains\n"); 116 117 mod |= checkfat(&boot, fat); 118 if (mod & FSFATAL) 119 goto out; 120 /* delay writing FATs */ 121 122 if (!preen) 123 printf("** Phase 3 - Checking Directories\n"); 124 125 mod |= resetDosDirSection(&boot, fat); 126 finish_dosdirsection = 1; 127 if (mod & FSFATAL) 128 goto out; 129 /* delay writing FATs */ 130 131 mod |= handleDirTree(dosfs, &boot, fat); 132 if (mod & FSFATAL) 133 goto out; 134 135 if (!preen) 136 printf("** Phase 4 - Checking for Lost Files\n"); 137 138 mod |= checklost(dosfs, &boot, fat); 139 if (mod & FSFATAL) 140 goto out; 141 142 /* now write the FATs */ 143 if (mod & FSFATMOD) { 144 if (ask(1, "Update FATs")) { 145 mod |= writefat(dosfs, &boot, fat, mod & FSFIXFAT); 146 if (mod & FSFATAL) 147 goto out; 148 } else 149 mod |= FSERROR; 150 } 151 152 if (boot.NumBad) 153 pwarn("%d files, %d free (%d clusters), %d bad (%d clusters)\n", 154 boot.NumFiles, 155 boot.NumFree * boot.ClusterSize / 1024, boot.NumFree, 156 boot.NumBad * boot.ClusterSize / 1024, boot.NumBad); 157 else 158 pwarn("%d files, %d free (%d clusters)\n", 159 boot.NumFiles, 160 boot.NumFree * boot.ClusterSize / 1024, boot.NumFree); 161 162 if (mod && (mod & FSERROR) == 0) { 163 if (mod & FSDIRTY) { 164 if (ask(1, "MARK FILE SYSTEM CLEAN") == 0) 165 mod &= ~FSDIRTY; 166 167 if (mod & FSDIRTY) { 168 pwarn("MARKING FILE SYSTEM CLEAN\n"); 169 mod |= writefat(dosfs, &boot, fat, 1); 170 } else { 171 pwarn("\n***** FILE SYSTEM IS LEFT MARKED AS DIRTY *****\n"); 172 mod |= FSERROR; /* file system not clean */ 173 } 174 } 175 } 176 177 if (mod & (FSFATAL | FSERROR)) 178 goto out; 179 180 ret = 0; 181 182 out: 183 if (finish_dosdirsection) 184 finishDosDirSection(); 185 free(fat); 186 close(dosfs); 187 188 if (mod & (FSFATMOD|FSDIRMOD)) 189 pwarn("\n***** FILE SYSTEM WAS MODIFIED *****\n"); 190 191 return ret; 192 } 193