check.c revision 330449
1234449Sobrien/*- 268349Sobrien * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3234449Sobrien * 468349Sobrien * Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank 568349Sobrien * Copyright (c) 1995 Martin Husemann 668349Sobrien * 768349Sobrien * Redistribution and use in source and binary forms, with or without 868349Sobrien * modification, are permitted provided that the following conditions 968349Sobrien * are met: 1068349Sobrien * 1. Redistributions of source code must retain the above copyright 1168349Sobrien * notice, this list of conditions and the following disclaimer. 12133359Sobrien * 2. Redistributions in binary form must reproduce the above copyright 13186691Sobrien * notice, this list of conditions and the following disclaimer in the 1468349Sobrien * documentation and/or other materials provided with the distribution. 15186691Sobrien * 1668349Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 17186691Sobrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1868349Sobrien * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19186691Sobrien * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2068349Sobrien * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21186691Sobrien * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2268349Sobrien * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23186691Sobrien * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2468349Sobrien * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25186691Sobrien * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26133359Sobrien */ 27133359Sobrien 28133359Sobrien 29133359Sobrien#include <sys/cdefs.h> 30133359Sobrien#ifndef lint 31133359Sobrien__RCSID("$NetBSD: check.c,v 1.14 2006/06/05 16:51:18 christos Exp $"); 32133359Sobrienstatic const char rcsid[] = 33133359Sobrien "$FreeBSD: stable/11/sbin/fsck_msdosfs/check.c 330449 2018-03-05 07:26:05Z eadler $"; 34133359Sobrien#endif /* not lint */ 35133359Sobrien 36169942Sobrien#include <stdlib.h> 37186691Sobrien#include <string.h> 38133359Sobrien#include <stdio.h> 39133359Sobrien#include <unistd.h> 40133359Sobrien#include <fcntl.h> 41133359Sobrien 4268349Sobrien#include "ext.h" 4368349Sobrien#include "fsutil.h" 4468349Sobrien 4568349Sobrienint 4668349Sobriencheckfilesys(const char *fname) 4768349Sobrien{ 4868349Sobrien int dosfs; 4968349Sobrien struct bootblock boot; 50133359Sobrien struct fatEntry *fat = NULL; 51186691Sobrien int finish_dosdirsection=0; 5268349Sobrien u_int i; 53186691Sobrien int mod = 0; 5468349Sobrien int ret = 8; 55186691Sobrien 5668349Sobrien rdonly = alwaysno; 57186691Sobrien if (!preen) 5868349Sobrien printf("** %s", fname); 59186691Sobrien 6068349Sobrien dosfs = open(fname, rdonly ? O_RDONLY : O_RDWR, 0); 61186691Sobrien if (dosfs < 0 && !rdonly) { 6268349Sobrien dosfs = open(fname, O_RDONLY, 0); 63186691Sobrien if (dosfs >= 0) 64133359Sobrien pwarn(" (NO WRITE)\n"); 65133359Sobrien else if (!preen) 66133359Sobrien printf("\n"); 67133359Sobrien rdonly = 1; 68133359Sobrien } else if (!preen) 69133359Sobrien printf("\n"); 70133359Sobrien 71133359Sobrien if (dosfs < 0) { 72133359Sobrien perr("Can't open `%s'", fname); 73133359Sobrien printf("\n"); 74169942Sobrien return 8; 75186691Sobrien } 76133359Sobrien 77133359Sobrien if (readboot(dosfs, &boot) != FSOK) { 78133359Sobrien close(dosfs); 79133359Sobrien printf("\n"); 8068349Sobrien return 8; 8168349Sobrien } 8268349Sobrien 8368349Sobrien if (skipclean && preen && checkdirty(dosfs, &boot)) { 8468349Sobrien printf("%s: ", fname); 8568349Sobrien printf("FILESYSTEM CLEAN; SKIPPING CHECKS\n"); 8668349Sobrien ret = 0; 87186691Sobrien goto out; 88133359Sobrien } 89133359Sobrien 90133359Sobrien if (!preen) { 91133359Sobrien if (boot.ValidFat < 0) 92133359Sobrien printf("** Phase 1 - Read and Compare FATs\n"); 93133359Sobrien else 9468349Sobrien printf("** Phase 1 - Read FAT\n"); 95186691Sobrien } 9668349Sobrien 97186691Sobrien mod |= readfat(dosfs, &boot, boot.ValidFat >= 0 ? boot.ValidFat : 0, &fat); 9868349Sobrien if (mod & FSFATAL) { 99186691Sobrien close(dosfs); 10068349Sobrien return 8; 10168349Sobrien } 10268349Sobrien 10368349Sobrien if (boot.ValidFat < 0) 10468349Sobrien for (i = 1; i < boot.bpbFATs; i++) { 10568349Sobrien struct fatEntry *currentFat; 10668349Sobrien 10768349Sobrien mod |= readfat(dosfs, &boot, i, ¤tFat); 10868349Sobrien 10968349Sobrien if (mod & FSFATAL) 11068349Sobrien goto out; 11168349Sobrien 11268349Sobrien mod |= comparefat(&boot, fat, currentFat, i); 11368349Sobrien free(currentFat); 11468349Sobrien if (mod & FSFATAL) 11568349Sobrien goto out; 11668349Sobrien } 11768349Sobrien 11868349Sobrien if (!preen) 11968349Sobrien printf("** Phase 2 - Check Cluster Chains\n"); 120186691Sobrien 121234449Sobrien mod |= checkfat(&boot, fat); 122186691Sobrien if (mod & FSFATAL) 123186691Sobrien goto out; 124186691Sobrien /* delay writing FATs */ 125186691Sobrien 126186691Sobrien if (!preen) 12768349Sobrien printf("** Phase 3 - Checking Directories\n"); 12868349Sobrien 12968349Sobrien mod |= resetDosDirSection(&boot, fat); 130133359Sobrien finish_dosdirsection = 1; 131133359Sobrien if (mod & FSFATAL) 132133359Sobrien goto out; 13368349Sobrien /* delay writing FATs */ 134133359Sobrien 13568349Sobrien mod |= handleDirTree(dosfs, &boot, fat); 136133359Sobrien if (mod & FSFATAL) 137133359Sobrien goto out; 138133359Sobrien 139133359Sobrien if (!preen) 14068349Sobrien printf("** Phase 4 - Checking for Lost Files\n"); 141133359Sobrien 14268349Sobrien mod |= checklost(dosfs, &boot, fat); 14368349Sobrien if (mod & FSFATAL) 14468349Sobrien goto out; 14568349Sobrien 14668349Sobrien /* now write the FATs */ 14768349Sobrien if (mod & (FSFATMOD|FSFIXFAT)) { 14868349Sobrien if (ask(1, "Update FATs")) { 149186691Sobrien mod |= writefat(dosfs, &boot, fat, mod & FSFIXFAT); 150186691Sobrien if (mod & FSFATAL) 151186691Sobrien goto out; 152186691Sobrien } else 153186691Sobrien mod |= FSERROR; 154186691Sobrien } 155186691Sobrien 156186691Sobrien if (boot.NumBad) 157186691Sobrien pwarn("%d files, %d free (%d clusters), %d bad (%d clusters)\n", 158186691Sobrien boot.NumFiles, 15968349Sobrien boot.NumFree * boot.ClusterSize / 1024, boot.NumFree, 16068349Sobrien boot.NumBad * boot.ClusterSize / 1024, boot.NumBad); 16168349Sobrien else 162133359Sobrien pwarn("%d files, %d free (%d clusters)\n", 16368349Sobrien boot.NumFiles, 16468349Sobrien boot.NumFree * boot.ClusterSize / 1024, boot.NumFree); 165186691Sobrien 166186691Sobrien if (mod && (mod & FSERROR) == 0) { 167133359Sobrien if (mod & FSDIRTY) { 16868349Sobrien if (ask(1, "MARK FILE SYSTEM CLEAN") == 0) 169133359Sobrien mod &= ~FSDIRTY; 17068349Sobrien 171186691Sobrien if (mod & FSDIRTY) { 172186691Sobrien pwarn("MARKING FILE SYSTEM CLEAN\n"); 173133359Sobrien mod |= writefat(dosfs, &boot, fat, 1); 174133359Sobrien } else { 175159764Sobrien pwarn("\n***** FILE SYSTEM IS LEFT MARKED AS DIRTY *****\n"); 176186691Sobrien mod |= FSERROR; /* file system not clean */ 177186691Sobrien } 178133359Sobrien } 179186691Sobrien } 180186691Sobrien 18168349Sobrien if (mod & (FSFATAL | FSERROR)) 182186691Sobrien goto out; 183186691Sobrien 184133359Sobrien ret = 0; 18568349Sobrien 186186691Sobrien out: 187186691Sobrien if (finish_dosdirsection) 188133359Sobrien finishDosDirSection(); 18968349Sobrien free(fat); 190186691Sobrien close(dosfs); 191186691Sobrien 192133359Sobrien if (mod & (FSFATMOD|FSDIRMOD)) 193133359Sobrien pwarn("\n***** FILE SYSTEM WAS MODIFIED *****\n"); 194186691Sobrien 195186691Sobrien return ret; 196133359Sobrien} 19768349Sobrien