check.c revision 241806
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 241806 2012-10-21 12:01:11Z uqs $"; 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); 7179455Sobrien return 8; 7279455Sobrien } 7379455Sobrien 7479455Sobrien if (readboot(dosfs, &boot) != FSOK) { 7579455Sobrien close(dosfs); 7679455Sobrien printf("\n"); 7779455Sobrien return 8; 7879455Sobrien } 7979455Sobrien 80125486Sbde if (skipclean && preen && checkdirty(dosfs, &boot)) { 81125486Sbde printf("%s: ", fname); 82123873Strhodes printf("FILESYSTEM CLEAN; SKIPPING CHECKS\n"); 83123873Strhodes ret = 0; 84123873Strhodes goto out; 85123873Strhodes } 86123873Strhodes 8779455Sobrien if (!preen) { 8879455Sobrien if (boot.ValidFat < 0) 8979455Sobrien printf("** Phase 1 - Read and Compare FATs\n"); 9079455Sobrien else 9179455Sobrien printf("** Phase 1 - Read FAT\n"); 9279455Sobrien } 9379455Sobrien 9479455Sobrien mod |= readfat(dosfs, &boot, boot.ValidFat >= 0 ? boot.ValidFat : 0, &fat); 9579455Sobrien if (mod & FSFATAL) { 9679455Sobrien close(dosfs); 9779455Sobrien return 8; 9879455Sobrien } 9979455Sobrien 10079455Sobrien if (boot.ValidFat < 0) 101209364Sbrian for (i = 1; i < boot.bpbFATs; i++) { 10279455Sobrien struct fatEntry *currentFat; 10379455Sobrien 10479455Sobrien mod |= readfat(dosfs, &boot, i, ¤tFat); 10579455Sobrien 10679455Sobrien if (mod & FSFATAL) 10779455Sobrien goto out; 10879455Sobrien 10979455Sobrien mod |= comparefat(&boot, fat, currentFat, i); 11079455Sobrien free(currentFat); 11179455Sobrien if (mod & FSFATAL) 11279455Sobrien goto out; 11379455Sobrien } 11479455Sobrien 11579455Sobrien if (!preen) 11679455Sobrien printf("** Phase 2 - Check Cluster Chains\n"); 11779455Sobrien 11879455Sobrien mod |= checkfat(&boot, fat); 11979455Sobrien if (mod & FSFATAL) 12079455Sobrien goto out; 12179455Sobrien /* delay writing FATs */ 12279455Sobrien 12379455Sobrien if (!preen) 12479455Sobrien printf("** Phase 3 - Checking Directories\n"); 12579455Sobrien 12679455Sobrien mod |= resetDosDirSection(&boot, fat); 12779455Sobrien finish_dosdirsection = 1; 12879455Sobrien if (mod & FSFATAL) 12979455Sobrien goto out; 13079455Sobrien /* delay writing FATs */ 13179455Sobrien 13279455Sobrien mod |= handleDirTree(dosfs, &boot, fat); 13379455Sobrien if (mod & FSFATAL) 13479455Sobrien goto out; 13579455Sobrien 13679455Sobrien if (!preen) 13779455Sobrien printf("** Phase 4 - Checking for Lost Files\n"); 13879455Sobrien 13979455Sobrien mod |= checklost(dosfs, &boot, fat); 14079455Sobrien if (mod & FSFATAL) 14179455Sobrien goto out; 14279455Sobrien 14379455Sobrien /* now write the FATs */ 14479455Sobrien if (mod & FSFATMOD) { 14579455Sobrien if (ask(1, "Update FATs")) { 14679455Sobrien mod |= writefat(dosfs, &boot, fat, mod & FSFIXFAT); 14779455Sobrien if (mod & FSFATAL) 14879455Sobrien goto out; 14979455Sobrien } else 15079455Sobrien mod |= FSERROR; 15179455Sobrien } 15279455Sobrien 15379455Sobrien if (boot.NumBad) 15479455Sobrien pwarn("%d files, %d free (%d clusters), %d bad (%d clusters)\n", 15579455Sobrien boot.NumFiles, 15679455Sobrien boot.NumFree * boot.ClusterSize / 1024, boot.NumFree, 15779455Sobrien boot.NumBad * boot.ClusterSize / 1024, boot.NumBad); 15879455Sobrien else 15979455Sobrien pwarn("%d files, %d free (%d clusters)\n", 16079455Sobrien boot.NumFiles, 16179455Sobrien boot.NumFree * boot.ClusterSize / 1024, boot.NumFree); 16279455Sobrien 16379455Sobrien if (mod && (mod & FSERROR) == 0) { 16479455Sobrien if (mod & FSDIRTY) { 16579455Sobrien if (ask(1, "MARK FILE SYSTEM CLEAN") == 0) 16679455Sobrien mod &= ~FSDIRTY; 16779455Sobrien 16879455Sobrien if (mod & FSDIRTY) { 16979455Sobrien pwarn("MARKING FILE SYSTEM CLEAN\n"); 17079455Sobrien mod |= writefat(dosfs, &boot, fat, 1); 17179455Sobrien } else { 17279455Sobrien pwarn("\n***** FILE SYSTEM IS LEFT MARKED AS DIRTY *****\n"); 173102231Strhodes mod |= FSERROR; /* file system not clean */ 17479455Sobrien } 17579455Sobrien } 17679455Sobrien } 17779455Sobrien 17879455Sobrien if (mod & (FSFATAL | FSERROR)) 17979455Sobrien goto out; 18079455Sobrien 18179455Sobrien ret = 0; 18279455Sobrien 18379455Sobrien out: 18479455Sobrien if (finish_dosdirsection) 18579455Sobrien finishDosDirSection(); 18679455Sobrien free(fat); 18779455Sobrien close(dosfs); 18879455Sobrien 18979455Sobrien if (mod & (FSFATMOD|FSDIRMOD)) 19079455Sobrien pwarn("\n***** FILE SYSTEM WAS MODIFIED *****\n"); 19179455Sobrien 19279455Sobrien return ret; 19379455Sobrien} 194