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