check.c revision 242511
179455Sobrien/* 279455Sobrien * Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank 379455Sobrien * Copyright (c) 1995 Martin Husemann 479455Sobrien * 579455Sobrien * Redistribution and use in source and binary forms, with or without 679455Sobrien * modification, are permitted provided that the following conditions 779455Sobrien * are met: 879455Sobrien * 1. Redistributions of source code must retain the above copyright 979455Sobrien * notice, this list of conditions and the following disclaimer. 1079455Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1179455Sobrien * notice, this list of conditions and the following disclaimer in the 1279455Sobrien * documentation and/or other materials provided with the distribution. 1379455Sobrien * 1479455Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 1579455Sobrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1679455Sobrien * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1779455Sobrien * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 1879455Sobrien * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1979455Sobrien * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2079455Sobrien * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2179455Sobrien * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2279455Sobrien * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2379455Sobrien * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2479455Sobrien */ 2579455Sobrien 2679455Sobrien 2779455Sobrien#include <sys/cdefs.h> 2879455Sobrien#ifndef lint 29241806Suqs__RCSID("$NetBSD: check.c,v 1.14 2006/06/05 16:51:18 christos Exp $"); 3079455Sobrienstatic const char rcsid[] = 3179455Sobrien "$FreeBSD: head/sbin/fsck_msdosfs/check.c 242511 2012-11-03 09:18:37Z jh $"; 3279455Sobrien#endif /* not lint */ 3379455Sobrien 3479455Sobrien#include <stdlib.h> 3579455Sobrien#include <string.h> 3679455Sobrien#include <stdio.h> 3779455Sobrien#include <unistd.h> 3879455Sobrien#include <fcntl.h> 3979455Sobrien 4079455Sobrien#include "ext.h" 4179455Sobrien#include "fsutil.h" 4279455Sobrien 4379455Sobrienint 44121726Strhodescheckfilesys(const char *fname) 4579455Sobrien{ 4679455Sobrien int dosfs; 4779455Sobrien struct bootblock boot; 4879455Sobrien struct fatEntry *fat = NULL; 49203872Skib int finish_dosdirsection=0; 50203872Skib u_int i; 5179455Sobrien int mod = 0; 5279455Sobrien int ret = 8; 5379455Sobrien 5479455Sobrien rdonly = alwaysno; 5579455Sobrien if (!preen) 5679455Sobrien printf("** %s", fname); 5779455Sobrien 5879455Sobrien dosfs = open(fname, rdonly ? O_RDONLY : O_RDWR, 0); 5979455Sobrien if (dosfs < 0 && !rdonly) { 6079455Sobrien dosfs = open(fname, O_RDONLY, 0); 6179455Sobrien if (dosfs >= 0) 6279455Sobrien pwarn(" (NO WRITE)\n"); 6379455Sobrien else if (!preen) 6479455Sobrien printf("\n"); 6579455Sobrien rdonly = 1; 6679455Sobrien } else if (!preen) 6779455Sobrien printf("\n"); 6879455Sobrien 6979455Sobrien if (dosfs < 0) { 70241806Suqs perr("Can't open `%s'", fname); 71242511Sjh printf("\n"); 7279455Sobrien return 8; 7379455Sobrien } 7479455Sobrien 7579455Sobrien if (readboot(dosfs, &boot) != FSOK) { 7679455Sobrien close(dosfs); 7779455Sobrien printf("\n"); 7879455Sobrien return 8; 7979455Sobrien } 8079455Sobrien 81125486Sbde if (skipclean && preen && checkdirty(dosfs, &boot)) { 82125486Sbde printf("%s: ", fname); 83123873Strhodes printf("FILESYSTEM CLEAN; SKIPPING CHECKS\n"); 84123873Strhodes ret = 0; 85123873Strhodes goto out; 86123873Strhodes } 87123873Strhodes 8879455Sobrien if (!preen) { 8979455Sobrien if (boot.ValidFat < 0) 9079455Sobrien printf("** Phase 1 - Read and Compare FATs\n"); 9179455Sobrien else 9279455Sobrien printf("** Phase 1 - Read FAT\n"); 9379455Sobrien } 9479455Sobrien 9579455Sobrien mod |= readfat(dosfs, &boot, boot.ValidFat >= 0 ? boot.ValidFat : 0, &fat); 9679455Sobrien if (mod & FSFATAL) { 9779455Sobrien close(dosfs); 9879455Sobrien return 8; 9979455Sobrien } 10079455Sobrien 10179455Sobrien if (boot.ValidFat < 0) 102209364Sbrian for (i = 1; i < boot.bpbFATs; i++) { 10379455Sobrien struct fatEntry *currentFat; 10479455Sobrien 10579455Sobrien mod |= readfat(dosfs, &boot, i, ¤tFat); 10679455Sobrien 10779455Sobrien if (mod & FSFATAL) 10879455Sobrien goto out; 10979455Sobrien 11079455Sobrien mod |= comparefat(&boot, fat, currentFat, i); 11179455Sobrien free(currentFat); 11279455Sobrien if (mod & FSFATAL) 11379455Sobrien goto out; 11479455Sobrien } 11579455Sobrien 11679455Sobrien if (!preen) 11779455Sobrien printf("** Phase 2 - Check Cluster Chains\n"); 11879455Sobrien 11979455Sobrien mod |= checkfat(&boot, fat); 12079455Sobrien if (mod & FSFATAL) 12179455Sobrien goto out; 12279455Sobrien /* delay writing FATs */ 12379455Sobrien 12479455Sobrien if (!preen) 12579455Sobrien printf("** Phase 3 - Checking Directories\n"); 12679455Sobrien 12779455Sobrien mod |= resetDosDirSection(&boot, fat); 12879455Sobrien finish_dosdirsection = 1; 12979455Sobrien if (mod & FSFATAL) 13079455Sobrien goto out; 13179455Sobrien /* delay writing FATs */ 13279455Sobrien 13379455Sobrien mod |= handleDirTree(dosfs, &boot, fat); 13479455Sobrien if (mod & FSFATAL) 13579455Sobrien goto out; 13679455Sobrien 13779455Sobrien if (!preen) 13879455Sobrien printf("** Phase 4 - Checking for Lost Files\n"); 13979455Sobrien 14079455Sobrien mod |= checklost(dosfs, &boot, fat); 14179455Sobrien if (mod & FSFATAL) 14279455Sobrien goto out; 14379455Sobrien 14479455Sobrien /* now write the FATs */ 14579455Sobrien if (mod & FSFATMOD) { 14679455Sobrien if (ask(1, "Update FATs")) { 14779455Sobrien mod |= writefat(dosfs, &boot, fat, mod & FSFIXFAT); 14879455Sobrien if (mod & FSFATAL) 14979455Sobrien goto out; 15079455Sobrien } else 15179455Sobrien mod |= FSERROR; 15279455Sobrien } 15379455Sobrien 15479455Sobrien if (boot.NumBad) 15579455Sobrien pwarn("%d files, %d free (%d clusters), %d bad (%d clusters)\n", 15679455Sobrien boot.NumFiles, 15779455Sobrien boot.NumFree * boot.ClusterSize / 1024, boot.NumFree, 15879455Sobrien boot.NumBad * boot.ClusterSize / 1024, boot.NumBad); 15979455Sobrien else 16079455Sobrien pwarn("%d files, %d free (%d clusters)\n", 16179455Sobrien boot.NumFiles, 16279455Sobrien boot.NumFree * boot.ClusterSize / 1024, boot.NumFree); 16379455Sobrien 16479455Sobrien if (mod && (mod & FSERROR) == 0) { 16579455Sobrien if (mod & FSDIRTY) { 16679455Sobrien if (ask(1, "MARK FILE SYSTEM CLEAN") == 0) 16779455Sobrien mod &= ~FSDIRTY; 16879455Sobrien 16979455Sobrien if (mod & FSDIRTY) { 17079455Sobrien pwarn("MARKING FILE SYSTEM CLEAN\n"); 17179455Sobrien mod |= writefat(dosfs, &boot, fat, 1); 17279455Sobrien } else { 17379455Sobrien pwarn("\n***** FILE SYSTEM IS LEFT MARKED AS DIRTY *****\n"); 174102231Strhodes mod |= FSERROR; /* file system not clean */ 17579455Sobrien } 17679455Sobrien } 17779455Sobrien } 17879455Sobrien 17979455Sobrien if (mod & (FSFATAL | FSERROR)) 18079455Sobrien goto out; 18179455Sobrien 18279455Sobrien ret = 0; 18379455Sobrien 18479455Sobrien out: 18579455Sobrien if (finish_dosdirsection) 18679455Sobrien finishDosDirSection(); 18779455Sobrien free(fat); 18879455Sobrien close(dosfs); 18979455Sobrien 19079455Sobrien if (mod & (FSFATMOD|FSDIRMOD)) 19179455Sobrien pwarn("\n***** FILE SYSTEM WAS MODIFIED *****\n"); 19279455Sobrien 19379455Sobrien return ret; 19479455Sobrien} 195