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 360490 2020-04-30 06:34:34Z delphij $"; 3479455Sobrien#endif /* not lint */ 3579455Sobrien 36360490Sdelphij#ifdef HAVE_LIBUTIL_H 37360490Sdelphij#include <libutil.h> 38360490Sdelphij#endif 3979455Sobrien#include <stdlib.h> 4079455Sobrien#include <string.h> 4179455Sobrien#include <stdio.h> 4279455Sobrien#include <unistd.h> 4379455Sobrien#include <fcntl.h> 4479455Sobrien 4579455Sobrien#include "ext.h" 4679455Sobrien#include "fsutil.h" 4779455Sobrien 4879455Sobrienint 49121726Strhodescheckfilesys(const char *fname) 5079455Sobrien{ 5179455Sobrien int dosfs; 5279455Sobrien struct bootblock boot; 53360490Sdelphij struct fat_descriptor *fat = NULL; 54203872Skib int finish_dosdirsection=0; 5579455Sobrien int mod = 0; 5679455Sobrien int ret = 8; 57360490Sdelphij int64_t freebytes; 58360490Sdelphij int64_t badbytes; 5979455Sobrien 6079455Sobrien rdonly = alwaysno; 6179455Sobrien if (!preen) 6279455Sobrien printf("** %s", fname); 6379455Sobrien 6479455Sobrien dosfs = open(fname, rdonly ? O_RDONLY : O_RDWR, 0); 6579455Sobrien if (dosfs < 0 && !rdonly) { 6679455Sobrien dosfs = open(fname, O_RDONLY, 0); 6779455Sobrien if (dosfs >= 0) 6879455Sobrien pwarn(" (NO WRITE)\n"); 6979455Sobrien else if (!preen) 7079455Sobrien printf("\n"); 7179455Sobrien rdonly = 1; 7279455Sobrien } else if (!preen) 7379455Sobrien printf("\n"); 7479455Sobrien 7579455Sobrien if (dosfs < 0) { 76241806Suqs perr("Can't open `%s'", fname); 77242511Sjh printf("\n"); 7879455Sobrien return 8; 7979455Sobrien } 8079455Sobrien 81334605Sdelphij if (readboot(dosfs, &boot) == FSFATAL) { 8279455Sobrien close(dosfs); 8379455Sobrien printf("\n"); 8479455Sobrien return 8; 8579455Sobrien } 8679455Sobrien 87125486Sbde if (skipclean && preen && checkdirty(dosfs, &boot)) { 88125486Sbde printf("%s: ", fname); 89123873Strhodes printf("FILESYSTEM CLEAN; SKIPPING CHECKS\n"); 90123873Strhodes ret = 0; 91123873Strhodes goto out; 92123873Strhodes } 93123873Strhodes 9479455Sobrien if (!preen) { 95360490Sdelphij printf("** Phase 1 - Read FAT and checking connectivity\n"); 9679455Sobrien } 9779455Sobrien 98360490Sdelphij mod |= readfat(dosfs, &boot, &fat); 9979455Sobrien if (mod & FSFATAL) { 10079455Sobrien close(dosfs); 10179455Sobrien return 8; 10279455Sobrien } 10379455Sobrien 10479455Sobrien if (!preen) 105360490Sdelphij printf("** Phase 2 - Checking Directories\n"); 10679455Sobrien 107360490Sdelphij mod |= resetDosDirSection(fat); 10879455Sobrien finish_dosdirsection = 1; 10979455Sobrien if (mod & FSFATAL) 11079455Sobrien goto out; 11179455Sobrien /* delay writing FATs */ 11279455Sobrien 113360490Sdelphij mod |= handleDirTree(fat); 11479455Sobrien if (mod & FSFATAL) 11579455Sobrien goto out; 11679455Sobrien 11779455Sobrien if (!preen) 118360490Sdelphij printf("** Phase 3 - Checking for Lost Files\n"); 11979455Sobrien 120360490Sdelphij mod |= checklost(fat); 12179455Sobrien if (mod & FSFATAL) 12279455Sobrien goto out; 12379455Sobrien 12479455Sobrien /* now write the FATs */ 125360490Sdelphij if (mod & FSFATMOD) { 12679455Sobrien if (ask(1, "Update FATs")) { 127360490Sdelphij mod |= writefat(fat); 12879455Sobrien if (mod & FSFATAL) 12979455Sobrien goto out; 13079455Sobrien } else 13179455Sobrien mod |= FSERROR; 13279455Sobrien } 13379455Sobrien 134360490Sdelphij freebytes = (int64_t)boot.NumFree * boot.ClusterSize; 135360490Sdelphij badbytes = (int64_t)boot.NumBad * boot.ClusterSize; 136360490Sdelphij 137360490Sdelphij#ifdef HAVE_LIBUTIL_H 138360490Sdelphij char freestr[7], badstr[7]; 139360490Sdelphij 140360490Sdelphij humanize_number(freestr, sizeof(freestr), freebytes, "", 141360490Sdelphij HN_AUTOSCALE, HN_DECIMAL | HN_IEC_PREFIXES); 142360490Sdelphij if (boot.NumBad) { 143360490Sdelphij humanize_number(badstr, sizeof(badstr), badbytes, "", 144360490Sdelphij HN_AUTOSCALE, HN_B | HN_DECIMAL | HN_IEC_PREFIXES); 145360490Sdelphij 146360490Sdelphij pwarn("%d files, %sB free (%d clusters), %sB bad (%d clusters)\n", 147360490Sdelphij boot.NumFiles, freestr, boot.NumFree, 148360490Sdelphij badstr, boot.NumBad); 149360490Sdelphij } else { 150360490Sdelphij pwarn("%d files, %sB free (%d clusters)\n", 151360490Sdelphij boot.NumFiles, freestr, boot.NumFree); 152360490Sdelphij } 153360490Sdelphij#else 15479455Sobrien if (boot.NumBad) 155360490Sdelphij pwarn("%d files, %jd KiB free (%d clusters), %jd KiB bad (%d clusters)\n", 156360490Sdelphij boot.NumFiles, (intmax_t)freebytes / 1024, boot.NumFree, 157360490Sdelphij (intmax_t)badbytes / 1024, boot.NumBad); 15879455Sobrien else 159360490Sdelphij pwarn("%d files, %jd KiB free (%d clusters)\n", 160360490Sdelphij boot.NumFiles, (intmax_t)freebytes / 1024, boot.NumFree); 161360490Sdelphij#endif 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"); 170360490Sdelphij mod |= cleardirty(fat); 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