未验证 提交 401f6e68 编写于 作者: O openharmony_ci 提交者: Gitee

!56 Add sbin/fsck_msdos and sbin/newfs_msdos

Merge pull request !56 from xlfeng/master
# Copyright (c) 2022 Huawei Device Co., Ltd.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import("//build/ohos.gni")
config("vfat-defaults") {
cflags = [
"-O2",
"-g",
"-Wall",
"-Werror",
"-D_BSD_SOURCE",
"-D_LARGEFILE_SOURCE",
"-D_FILE_OFFSET_BITS=64",
"-DELFTC_NEED_BYTEORDER_EXTENSIONS",
"-Wno-unused-variable",
"-Wno-unused-const-variable",
"-Wno-format",
"-Wno-sign-compare",
"-Wno-implicit-function-declaration",
"-Wno-return-type",
"-Wno-implicit-int",
]
include_dirs = []
}
###################################################
##Build fsck_msdos
ohos_executable("fsck_msdos") {
configs = [ ":vfat-defaults" ]
sources = [
"boot.c",
"check.c",
"dir.c",
"fat.c",
"main.c",
]
include_dirs = [
".",
"//third_party/FreeBSD/sys",
]
deps = []
install_enable = true
subsystem_name = "filemanagement"
part_name = "storage_service"
install_images = [ "system" ]
}
# $NetBSD: Makefile,v 1.6 1997/05/08 21:11:11 gwr Exp $
# $FreeBSD$
FSCK= ${.CURDIR:H}/fsck
.PATH: ${FSCK}
PACKAGE=runtime
PROG= fsck_msdosfs
MAN= fsck_msdosfs.8
SRCS= main.c check.c boot.c fat.c dir.c fsutil.c
CFLAGS+= -I${FSCK} -DHAVE_LIBUTIL_H
LIBADD= util
.include <bsd.prog.mk>
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (C) 1995, 1997 Wolfgang Solfrank
* Copyright (c) 1995 Martin Husemann
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: boot.c,v 1.22 2020/01/11 16:29:07 christos Exp $");
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include <sys/param.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include "ext.h"
#include "fsutil.h"
int
readboot(int dosfs, struct bootblock *boot)
{
u_char block[DOSBOOTBLOCKSIZE];
u_char fsinfo[2 * DOSBOOTBLOCKSIZE];
int ret = FSOK;
if ((size_t)read(dosfs, block, sizeof block) != sizeof block) {
perr("could not read boot block");
return FSFATAL;
}
if (block[510] != 0x55 || block[511] != 0xaa) {
pfatal("Invalid signature in boot block: %02x%02x",
block[511], block[510]);
return FSFATAL;
}
memset(boot, 0, sizeof *boot);
boot->ValidFat = -1;
/* Decode BIOS Parameter Block */
/* Bytes per sector: can only be 512, 1024, 2048 and 4096. */
boot->bpbBytesPerSec = block[11] + (block[12] << 8);
if (boot->bpbBytesPerSec < DOSBOOTBLOCKSIZE_REAL ||
boot->bpbBytesPerSec > DOSBOOTBLOCKSIZE ||
!powerof2(boot->bpbBytesPerSec)) {
pfatal("Invalid sector size: %u", boot->bpbBytesPerSec);
return FSFATAL;
}
/* Sectors per cluster: can only be: 1, 2, 4, 8, 16, 32, 64, 128. */
boot->bpbSecPerClust = block[13];
if (boot->bpbSecPerClust == 0 || !powerof2(boot->bpbSecPerClust)) {
pfatal("Invalid cluster size: %u", boot->bpbSecPerClust);
return FSFATAL;
}
/* Reserved sectors: must be non-zero */
boot->bpbResSectors = block[14] + (block[15] << 8);
if (boot->bpbResSectors < 1) {
pfatal("Invalid reserved sectors: %u",
boot->bpbResSectors);
return FSFATAL;
}
/* Number of FATs */
boot->bpbFATs = block[16];
if (boot->bpbFATs == 0) {
pfatal("Invalid number of FATs: %u", boot->bpbFATs);
return FSFATAL;
}
/* Root directory entries for FAT12 and FAT16 */
boot->bpbRootDirEnts = block[17] + (block[18] << 8);
if (!boot->bpbRootDirEnts) {
/* bpbRootDirEnts = 0 suggests that we are FAT32 */
boot->flags |= FAT32;
}
/* Total sectors (16 bits) */
boot->bpbSectors = block[19] + (block[20] << 8);
if (boot->bpbSectors != 0 && (boot->flags & FAT32)) {
pfatal("Invalid 16-bit total sector count on FAT32: %u",
boot->bpbSectors);
return FSFATAL;
}
/* Media type: ignored */
boot->bpbMedia = block[21];
/* FAT12/FAT16: 16-bit count of sectors per FAT */
boot->bpbFATsmall = block[22] + (block[23] << 8);
if (boot->bpbFATsmall != 0 && (boot->flags & FAT32)) {
pfatal("Invalid 16-bit FAT sector count on FAT32: %u",
boot->bpbFATsmall);
return FSFATAL;
}
/* Legacy CHS geometry numbers: ignored */
boot->SecPerTrack = block[24] + (block[25] << 8);
boot->bpbHeads = block[26] + (block[27] << 8);
/* Hidden sectors: ignored */
boot->bpbHiddenSecs = block[28] + (block[29] << 8) +
(block[30] << 16) + (block[31] << 24);
/* Total sectors (32 bits) */
boot->bpbHugeSectors = block[32] + (block[33] << 8) +
(block[34] << 16) + (block[35] << 24);
if (boot->bpbHugeSectors == 0) {
if (boot->flags & FAT32) {
pfatal("FAT32 with sector count of zero");
return FSFATAL;
} else if (boot->bpbSectors == 0) {
pfatal("FAT with sector count of zero");
return FSFATAL;
}
boot->NumSectors = boot->bpbSectors;
} else {
if (boot->bpbSectors != 0) {
pfatal("Invalid FAT sector count");
return FSFATAL;
}
boot->NumSectors = boot->bpbHugeSectors;
}
if (boot->flags & FAT32) {
/* If the OEM Name field is EXFAT, it's not FAT32, so bail */
if (!memcmp(&block[3], "EXFAT ", 8)) {
pfatal("exFAT filesystem is not supported.");
return FSFATAL;
}
/* 32-bit count of sectors per FAT */
boot->FATsecs = block[36] + (block[37] << 8)
+ (block[38] << 16) + (block[39] << 24);
if (block[40] & 0x80)
boot->ValidFat = block[40] & 0x0f;
/* FAT32 version, bail out if not 0.0 */
if (block[42] || block[43]) {
pfatal("Unknown file system version: %x.%x",
block[43], block[42]);
return FSFATAL;
}
/*
* Cluster number of the first cluster of root directory.
*
* Should be 2 but do not require it.
*/
boot->bpbRootClust = block[44] + (block[45] << 8)
+ (block[46] << 16) + (block[47] << 24);
/* Sector number of the FSInfo structure, usually 1 */
boot->bpbFSInfo = block[48] + (block[49] << 8);
/* Sector number of the backup boot block, ignored */
boot->bpbBackup = block[50] + (block[51] << 8);
/* Check basic parameters */
if (boot->bpbFSInfo == 0) {
/*
* Either the BIOS Parameter Block has been corrupted,
* or this is not a FAT32 filesystem, most likely an
* exFAT filesystem.
*/
pfatal("Invalid FAT32 Extended BIOS Parameter Block");
return FSFATAL;
}
/* Read in and verify the FSInfo block */
if (lseek(dosfs, boot->bpbFSInfo * boot->bpbBytesPerSec,
SEEK_SET) != boot->bpbFSInfo * boot->bpbBytesPerSec
|| read(dosfs, fsinfo, sizeof fsinfo) != sizeof fsinfo) {
perr("could not read fsinfo block");
return FSFATAL;
}
if (memcmp(fsinfo, "RRaA", 4)
|| memcmp(fsinfo + 0x1e4, "rrAa", 4)
|| fsinfo[0x1fc]
|| fsinfo[0x1fd]
|| fsinfo[0x1fe] != 0x55
|| fsinfo[0x1ff] != 0xaa
|| fsinfo[0x3fc]
|| fsinfo[0x3fd]
|| fsinfo[0x3fe] != 0x55
|| fsinfo[0x3ff] != 0xaa) {
pwarn("Invalid signature in fsinfo block\n");
if (ask(0, "Fix")) {
memcpy(fsinfo, "RRaA", 4);
memcpy(fsinfo + 0x1e4, "rrAa", 4);
fsinfo[0x1fc] = fsinfo[0x1fd] = 0;
fsinfo[0x1fe] = 0x55;
fsinfo[0x1ff] = 0xaa;
fsinfo[0x3fc] = fsinfo[0x3fd] = 0;
fsinfo[0x3fe] = 0x55;
fsinfo[0x3ff] = 0xaa;
if (lseek(dosfs, boot->bpbFSInfo *
boot->bpbBytesPerSec, SEEK_SET)
!= boot->bpbFSInfo * boot->bpbBytesPerSec
|| write(dosfs, fsinfo, sizeof fsinfo)
!= sizeof fsinfo) {
perr("Unable to write bpbFSInfo");
return FSFATAL;
}
ret = FSBOOTMOD;
} else
boot->bpbFSInfo = 0;
} else {
/* We appear to have a valid FSInfo block, decode */
boot->FSFree = fsinfo[0x1e8] + (fsinfo[0x1e9] << 8)
+ (fsinfo[0x1ea] << 16)
+ (fsinfo[0x1eb] << 24);
boot->FSNext = fsinfo[0x1ec] + (fsinfo[0x1ed] << 8)
+ (fsinfo[0x1ee] << 16)
+ (fsinfo[0x1ef] << 24);
}
} else {
/* !FAT32: FAT12/FAT16 */
boot->FATsecs = boot->bpbFATsmall;
}
if (boot->FATsecs < 1 || boot->FATsecs > UINT32_MAX / boot->bpbFATs) {
pfatal("Invalid FATs(%u) with FATsecs(%zu)",
boot->bpbFATs, (size_t)boot->FATsecs);
return FSFATAL;
}
boot->FirstCluster = (boot->bpbRootDirEnts * 32 +
boot->bpbBytesPerSec - 1) / boot->bpbBytesPerSec +
boot->bpbResSectors + boot->bpbFATs * boot->FATsecs;
if (boot->FirstCluster + boot->bpbSecPerClust > boot->NumSectors) {
pfatal("Cluster offset too large (%u clusters)\n",
boot->FirstCluster);
return FSFATAL;
}
/*
* The number of clusters is derived from available data sectors,
* divided by sectors per cluster.
*/
boot->NumClusters =
(boot->NumSectors - boot->FirstCluster) / boot->bpbSecPerClust;
if (boot->flags & FAT32) {
if (boot->NumClusters > (CLUST_RSRVD & CLUST32_MASK)) {
pfatal("Filesystem too big (%u clusters) for FAT32 partition",
boot->NumClusters);
return FSFATAL;
}
if (boot->NumClusters < (CLUST_RSRVD & CLUST16_MASK)) {
pfatal("Filesystem too small (%u clusters) for FAT32 partition",
boot->NumClusters);
return FSFATAL;
}
boot->ClustMask = CLUST32_MASK;
if (boot->bpbRootClust < CLUST_FIRST ||
boot->bpbRootClust >= boot->NumClusters) {
pfatal("Root directory starts with cluster out of range(%u)",
boot->bpbRootClust);
return FSFATAL;
}
} else if (boot->NumClusters < (CLUST_RSRVD&CLUST12_MASK)) {
boot->ClustMask = CLUST12_MASK;
} else if (boot->NumClusters < (CLUST_RSRVD&CLUST16_MASK)) {
boot->ClustMask = CLUST16_MASK;
} else {
pfatal("Filesystem too big (%u clusters) for non-FAT32 partition",
boot->NumClusters);
return FSFATAL;
}
switch (boot->ClustMask) {
case CLUST32_MASK:
boot->NumFatEntries = (boot->FATsecs * boot->bpbBytesPerSec) / 4;
break;
case CLUST16_MASK:
boot->NumFatEntries = (boot->FATsecs * boot->bpbBytesPerSec) / 2;
break;
default:
boot->NumFatEntries = (boot->FATsecs * boot->bpbBytesPerSec * 2) / 3;
break;
}
if (boot->NumFatEntries < boot->NumClusters) {
pfatal("FAT size too small, %u entries won't fit into %u sectors\n",
boot->NumClusters, boot->FATsecs);
return FSFATAL;
}
/*
* There are two reserved clusters. To avoid adding CLUST_FIRST every
* time we perform boundary checks, we increment the NumClusters by 2,
* which is CLUST_FIRST to denote the first out-of-range cluster number.
*/
boot->NumClusters += CLUST_FIRST;
boot->ClusterSize = boot->bpbBytesPerSec * boot->bpbSecPerClust;
boot->NumFiles = 1;
boot->NumFree = 0;
return ret;
}
int
writefsinfo(int dosfs, struct bootblock *boot)
{
u_char fsinfo[2 * DOSBOOTBLOCKSIZE];
if (lseek(dosfs, boot->bpbFSInfo * boot->bpbBytesPerSec, SEEK_SET)
!= boot->bpbFSInfo * boot->bpbBytesPerSec
|| read(dosfs, fsinfo, sizeof fsinfo) != sizeof fsinfo) {
perr("could not read fsinfo block");
return FSFATAL;
}
fsinfo[0x1e8] = (u_char)boot->FSFree;
fsinfo[0x1e9] = (u_char)(boot->FSFree >> 8);
fsinfo[0x1ea] = (u_char)(boot->FSFree >> 16);
fsinfo[0x1eb] = (u_char)(boot->FSFree >> 24);
fsinfo[0x1ec] = (u_char)boot->FSNext;
fsinfo[0x1ed] = (u_char)(boot->FSNext >> 8);
fsinfo[0x1ee] = (u_char)(boot->FSNext >> 16);
fsinfo[0x1ef] = (u_char)(boot->FSNext >> 24);
if (lseek(dosfs, boot->bpbFSInfo * boot->bpbBytesPerSec, SEEK_SET)
!= boot->bpbFSInfo * boot->bpbBytesPerSec
|| write(dosfs, fsinfo, sizeof fsinfo)
!= sizeof fsinfo) {
perr("Unable to write bpbFSInfo");
return FSFATAL;
}
/*
* Technically, we should return FSBOOTMOD here.
*
* However, since Win95 OSR2 (the first M$ OS that has
* support for FAT32) doesn't maintain the FSINFO block
* correctly, it has to be fixed pretty often.
*
* Therefore, we handle the FSINFO block only informally,
* fixing it if necessary, but otherwise ignoring the
* fact that it was incorrect.
*/
return 0;
}
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank
* Copyright (c) 1995 Martin Husemann
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: check.c,v 1.14 2006/06/05 16:51:18 christos Exp $");
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#ifdef HAVE_LIBUTIL_H
#include <libutil.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include "ext.h"
#include "fsutil.h"
int
checkfilesys(const char *fname)
{
int dosfs;
struct bootblock boot;
struct fat_descriptor *fat = NULL;
int finish_dosdirsection=0;
int mod = 0;
int ret = 8;
int64_t freebytes;
int64_t badbytes;
rdonly = alwaysno;
if (!preen)
printf("** %s", fname);
dosfs = open(fname, rdonly ? O_RDONLY : O_RDWR, 0);
if (dosfs < 0 && !rdonly) {
dosfs = open(fname, O_RDONLY, 0);
if (dosfs >= 0)
pwarn(" (NO WRITE)\n");
else if (!preen)
printf("\n");
rdonly = 1;
} else if (!preen)
printf("\n");
if (dosfs < 0) {
perr("Can't open `%s'", fname);
printf("\n");
return 8;
}
if (readboot(dosfs, &boot) == FSFATAL) {
close(dosfs);
printf("\n");
return 8;
}
if (skipclean && preen && checkdirty(dosfs, &boot)) {
printf("%s: ", fname);
printf("FILESYSTEM CLEAN; SKIPPING CHECKS\n");
ret = 0;
goto out;
}
if (!preen) {
printf("** Phase 1 - Read FAT and checking connectivity\n");
}
mod |= readfat(dosfs, &boot, &fat);
if (mod & FSFATAL) {
close(dosfs);
return 8;
}
if (!preen)
printf("** Phase 2 - Checking Directories\n");
mod |= resetDosDirSection(fat);
finish_dosdirsection = 1;
if (mod & FSFATAL)
goto out;
/* delay writing FATs */
mod |= handleDirTree(fat);
if (mod & FSFATAL)
goto out;
if (!preen)
printf("** Phase 3 - Checking for Lost Files\n");
mod |= checklost(fat);
if (mod & FSFATAL)
goto out;
/* now write the FATs */
if (mod & FSFATMOD) {
if (ask(1, "Update FATs")) {
mod |= writefat(fat);
if (mod & FSFATAL)
goto out;
} else
mod |= FSERROR;
}
freebytes = (int64_t)boot.NumFree * boot.ClusterSize;
badbytes = (int64_t)boot.NumBad * boot.ClusterSize;
#ifdef HAVE_LIBUTIL_H
char freestr[7], badstr[7];
humanize_number(freestr, sizeof(freestr), freebytes, "",
HN_AUTOSCALE, HN_DECIMAL | HN_IEC_PREFIXES);
if (boot.NumBad) {
humanize_number(badstr, sizeof(badstr), badbytes, "",
HN_AUTOSCALE, HN_B | HN_DECIMAL | HN_IEC_PREFIXES);
pwarn("%d files, %sB free (%d clusters), %sB bad (%d clusters)\n",
boot.NumFiles, freestr, boot.NumFree,
badstr, boot.NumBad);
} else {
pwarn("%d files, %sB free (%d clusters)\n",
boot.NumFiles, freestr, boot.NumFree);
}
#else
if (boot.NumBad)
pwarn("%d files, %jd KiB free (%d clusters), %jd KiB bad (%d clusters)\n",
boot.NumFiles, (intmax_t)freebytes / 1024, boot.NumFree,
(intmax_t)badbytes / 1024, boot.NumBad);
else
pwarn("%d files, %jd KiB free (%d clusters)\n",
boot.NumFiles, (intmax_t)freebytes / 1024, boot.NumFree);
#endif
if (mod && (mod & FSERROR) == 0) {
if (mod & FSDIRTY) {
if (ask(1, "MARK FILE SYSTEM CLEAN") == 0)
mod &= ~FSDIRTY;
if (mod & FSDIRTY) {
pwarn("MARKING FILE SYSTEM CLEAN\n");
mod |= cleardirty(fat);
} else {
pwarn("\n***** FILE SYSTEM IS LEFT MARKED AS DIRTY *****\n");
mod |= FSERROR; /* file system not clean */
}
}
}
if (mod & (FSFATAL | FSERROR))
goto out;
ret = 0;
out:
if (finish_dosdirsection)
finishDosDirSection();
free(fat);
close(dosfs);
if (mod & (FSFATMOD|FSDIRMOD))
pwarn("\n***** FILE SYSTEM WAS MODIFIED *****\n");
return ret;
}
此差异已折叠。
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank
* Copyright (c) 1995 Martin Husemann
* Some structure declaration borrowed from Paul Popelka
* (paulp@uts.amdahl.com), see /sys/msdosfs/ for reference.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* $NetBSD: dosfs.h,v 1.4 1997/01/03 14:32:48 ws Exp $
* $FreeBSD$
*/
#ifndef DOSFS_H
#define DOSFS_H
/* support 4Kn disk reads */
#define DOSBOOTBLOCKSIZE_REAL 512
#define DOSBOOTBLOCKSIZE 4096
typedef u_int32_t cl_t; /* type holding a cluster number */
/*
* architecture independent description of all the info stored in a
* FAT boot block.
*/
struct bootblock {
u_int bpbBytesPerSec; /* bytes per sector */
u_int bpbSecPerClust; /* sectors per cluster */
u_int bpbResSectors; /* number of reserved sectors */
u_int bpbFATs; /* number of bpbFATs */
u_int bpbRootDirEnts; /* number of root directory entries */
u_int32_t bpbSectors; /* total number of sectors */
u_int bpbMedia; /* media descriptor */
u_int bpbFATsmall; /* number of sectors per FAT */
u_int SecPerTrack; /* sectors per track */
u_int bpbHeads; /* number of heads */
u_int32_t bpbHiddenSecs; /* # of hidden sectors */
u_int32_t bpbHugeSectors; /* # of sectors if bpbbpbSectors == 0 */
cl_t bpbRootClust; /* Start of Root Directory */
u_int bpbFSInfo; /* FSInfo sector */
u_int bpbBackup; /* Backup of Bootblocks */
cl_t FSFree; /* Number of free clusters acc. FSInfo */
cl_t FSNext; /* Next free cluster acc. FSInfo */
/* and some more calculated values */
u_int flags; /* some flags: */
#define FAT32 1 /* this is a FAT32 file system */
/*
* Maybe, we should separate out
* various parts of FAT32? XXX
*/
int ValidFat; /* valid fat if FAT32 non-mirrored */
cl_t ClustMask; /* mask for entries in FAT */
cl_t NumClusters; /* # of entries in a FAT */
u_int32_t NumSectors; /* how many sectors are there */
u_int32_t FATsecs; /* how many sectors are in FAT */
u_int32_t NumFatEntries; /* how many entries really are there */
u_int FirstCluster; /* at what sector is Cluster CLUST_FIRST */
u_int ClusterSize; /* Cluster size in bytes */
/* Now some statistics: */
u_int NumFiles; /* # of plain files */
u_int NumFree; /* # of free clusters */
u_int NumBad; /* # of bad clusters */
};
#define CLUST_FREE 0 /* 0 means cluster is free */
#define CLUST_FIRST 2 /* 2 is the minimum valid cluster number */
#define CLUST_RSRVD 0xfffffff6 /* start of reserved clusters */
#define CLUST_BAD 0xfffffff7 /* a cluster with a defect */
#define CLUST_EOFS 0xfffffff8 /* start of EOF indicators */
#define CLUST_EOF 0xffffffff /* standard value for last cluster */
#define CLUST_DEAD 0xfdeadc0d /* error encountered */
/*
* Masks for cluster values
*/
#define CLUST12_MASK 0xfff
#define CLUST16_MASK 0xffff
#define CLUST32_MASK 0xfffffff
#define DOSLONGNAMELEN 256 /* long name maximal length */
#define LRFIRST 0x40 /* first long name record */
#define LRNOMASK 0x1f /* mask to extract long record
* sequence number */
/*
* Architecture independent description of a directory entry
*/
struct dosDirEntry {
struct dosDirEntry
*parent, /* previous tree level */
*next, /* next brother */
*child; /* if this is a directory */
char name[8+1+3+1]; /* alias name first part */
char lname[DOSLONGNAMELEN]; /* real name */
uint flags; /* attributes */
cl_t head; /* cluster no */
u_int32_t size; /* filesize in bytes */
uint fsckflags; /* flags during fsck */
};
/* Flags in fsckflags: */
#define DIREMPTY 1
#define DIREMPWARN 2
/*
* TODO-list of unread directories
*/
struct dirTodoNode {
struct dosDirEntry *dir;
struct dirTodoNode *next;
};
#endif
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank
* Copyright (c) 1995 Martin Husemann
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* $NetBSD: ext.h,v 1.6 2000/04/25 23:02:51 jdolecek Exp $
* $FreeBSD$
*/
#ifndef EXT_H
#define EXT_H
#include <sys/types.h>
#include <stdbool.h>
#include "dosfs.h"
#define LOSTDIR "LOST.DIR"
/*
* Options:
*/
extern int alwaysno; /* assume "no" for all questions */
extern int alwaysyes; /* assume "yes" for all questions */
extern int preen; /* we are preening */
extern int rdonly; /* device is opened read only (supersedes above) */
extern int skipclean; /* skip clean file systems if preening */
extern int allow_mmap; /* allow the use of mmap() */
/*
* function declarations
*/
int ask(int, const char *, ...) __printflike(2, 3);
/*
* Check the dirty flag. If the file system is clean, then return 1.
* Otherwise, return 0 (this includes the case of FAT12 file systems --
* they have no dirty flag, so they must be assumed to be unclean).
*/
int checkdirty(int, struct bootblock *);
/*
* Check file system given as arg
*/
int checkfilesys(const char *);
/*
* Return values of various functions
*/
#define FSOK 0 /* Check was OK */
#define FSBOOTMOD 1 /* Boot block was modified */
#define FSDIRMOD 2 /* Some directory was modified */
#define FSFATMOD 4 /* The FAT was modified */
#define FSERROR 8 /* Some unrecovered error remains */
#define FSFATAL 16 /* Some unrecoverable error occurred */
#define FSDIRTY 32 /* File system is dirty */
/*
* read a boot block in a machine independent fashion and translate
* it into our struct bootblock.
*/
int readboot(int, struct bootblock *);
/*
* Correct the FSInfo block.
*/
int writefsinfo(int, struct bootblock *);
/* Opaque type */
struct fat_descriptor;
int cleardirty(struct fat_descriptor *);
void fat_clear_cl_head(struct fat_descriptor *, cl_t);
bool fat_is_cl_head(struct fat_descriptor *, cl_t);
cl_t fat_get_cl_next(struct fat_descriptor *, cl_t);
int fat_set_cl_next(struct fat_descriptor *, cl_t, cl_t);
cl_t fat_allocate_cluster(struct fat_descriptor *fat);
struct bootblock* fat_get_boot(struct fat_descriptor *);
int fat_get_fd(struct fat_descriptor *);
bool fat_is_valid_cl(struct fat_descriptor *, cl_t);
/*
* Read the FAT 0 and return a pointer to the newly allocated
* descriptor of it.
*/
int readfat(int, struct bootblock *, struct fat_descriptor **);
/*
* Write back FAT entries
*/
int writefat(struct fat_descriptor *);
/*
* Read a directory
*/
int resetDosDirSection(struct fat_descriptor *);
void finishDosDirSection(void);
int handleDirTree(struct fat_descriptor *);
/*
* Cross-check routines run after everything is completely in memory
*/
int checkchain(struct fat_descriptor *, cl_t, size_t *);
/*
* Check for lost cluster chains
*/
int checklost(struct fat_descriptor *);
/*
* Try to reconnect a lost cluster chain
*/
int reconnect(struct fat_descriptor *, cl_t, size_t);
void finishlf(void);
/*
* Small helper functions
*/
/*
* Return the type of a reserved cluster as text
*/
const char *rsrvdcltype(cl_t);
/*
* Clear a cluster chain in a FAT
*/
void clearchain(struct fat_descriptor *, cl_t);
#endif
此差异已折叠。
.\" $NetBSD: fsck_msdos.8,v 1.9 1997/10/17 11:19:58 ws Exp $
.\"
.\" Copyright (C) 1995 Wolfgang Solfrank
.\" Copyright (c) 1995 Martin Husemann
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd January 6, 2020
.Dt FSCK_MSDOSFS 8
.Os
.Sh NAME
.Nm fsck_msdosfs
.Nd DOS/Windows (FAT) file system consistency checker
.Sh SYNOPSIS
.Nm
.Fl p
.Op Fl Cf
.Ar filesystem ...
.Nm
.Op Fl CMny
.Ar filesystem ...
.Sh DESCRIPTION
The
.Nm
utility verifies and repairs
.Tn FAT
file systems (more commonly known
as
.Tn DOS
file systems).
.Pp
The first form of
.Nm
preens the specified file systems.
It is normally started by
.Xr fsck 8
run from
.Pa /etc/rc
during automatic reboot, when a FAT file system is detected.
When preening file systems,
.Nm
will fix common inconsistencies non-interactively.
If more serious problems are found,
.Nm
does not try to fix them, indicates that it was not
successful, and exits.
.Pp
The second form of
.Nm
checks the specified file systems and tries to repair all
detected inconsistencies, requesting confirmation before
making any changes.
.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl C
Compatibility with the corresponding
.Xr fsck 8
option (skip check if clean), defined to no-op.
.It Fl F
Compatibility with the wrapper
.Xr fsck 8
which seeks to determine whether the file system needs to be cleaned
immediately in foreground, or if its cleaning can be deferred to background.
FAT (MS-DOS) file systems must always be cleaned in the foreground.
A non-zero exit code is always returned for this option.
.It Fl M
Causes
.Nm
to not use
.Xr mmap 2
when checking a FAT32 file system.
This option is mainly for debugging purposes and is not normally necessary.
The
.Nm
utility will automatically fall back to use a simple LRU cache of 4 MiB
when it failed to perform
.Xr mmap 2 ,
or when
.Fl M
is specified.
.It Fl f
Force
.Nm
to check
.Dq clean
file systems when preening.
.It Fl n
Causes
.Nm
to assume
.Dq Li no
as the answer to all operator
questions, except
.Dq Li CONTINUE? .
.It Fl p
Preen the specified file systems.
.It Fl y
Causes
.Nm
to assume
.Dq Li yes
as the answer to all operator questions.
.El
.Sh SEE ALSO
.Xr fsck 8 ,
.Xr fsck_ffs 8 ,
.Xr mount_msdosfs 8
.Sh HISTORY
The
.Nm
utility appeared in
.Nx 1.2 .
.Nm
first appeared in
.Fx 4.4 .
.Sh BUGS
The
.Nm
utility is
.Ud
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FS_UTIL_H
#define _FS_UTIL_H
#include <stdint.h>
#define pwarn printf
#define pfatal printf
#define perr printf
/*
* le16dec(),le32dec(),le16enc(),le32enc()
* Link: https://github.com/freebsd/freebsd-src/
* Path: freebsd-src/contrib/elftoolchain/libpe/_libpe.h
*/
/* Encode/Decode macros */
#if defined(ELFTC_NEED_BYTEORDER_EXTENSIONS)
static __inline uint16_t
le16dec(const void *pp)
{
unsigned char const *p = (unsigned char const *)pp;
return ((p[1] << 8) | p[0]);
}
static __inline uint32_t
le32dec(const void *pp)
{
unsigned char const *p = (unsigned char const *)pp;
return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]);
}
static __inline void
le16enc(void *pp, uint16_t u)
{
unsigned char *p = (unsigned char *)pp;
p[0] = u & 0xff;
p[1] = (u >> 8) & 0xff;
}
static __inline void
le32enc(void *pp, uint32_t u)
{
unsigned char *p = (unsigned char *)pp;
p[0] = u & 0xff;
p[1] = (u >> 8) & 0xff;
p[2] = (u >> 16) & 0xff;
p[3] = (u >> 24) & 0xff;
}
#endif /* ELFTC_NEED_BYTEORDER_EXTENSIONS */
/*
* roundup2
* Link: https://github.com/freebsd/freebsd-src/
* Path: freebsd-src/tools/build/cross-build/include/common/sys/cdefs.h
*/
#ifndef roundup2
#define roundup2(x, y) \
(((x) + ((y)-1)) & (~((y)-1))) /* if y is powers of two */
#endif
#endif // _FS_UTIL_H
\ No newline at end of file
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 1995 Wolfgang Solfrank
* Copyright (c) 1995 Martin Husemann
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: main.c,v 1.10 1997/10/01 02:18:14 enami Exp $");
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdarg.h>
#include "fsutil.h"
#include "ext.h"
int alwaysno; /* assume "no" for all questions */
int alwaysyes; /* assume "yes" for all questions */
int preen; /* set when preening */
int rdonly; /* device is opened read only (supersedes above) */
int skipclean; /* skip clean file systems if preening */
int allow_mmap; /* Allow the use of mmap(), if possible */
static void usage(void) __dead2;
static void
usage(void)
{
fprintf(stderr, "%s\n%s\n",
"usage: fsck_msdosfs -p [-f] filesystem ...",
" fsck_msdosfs [-ny] filesystem ...");
exit(1);
}
int
main(int argc, char **argv)
{
int ret = 0, erg;
int ch;
skipclean = 1;
allow_mmap = 1;
while ((ch = getopt(argc, argv, "CfFnpyM")) != -1) {
switch (ch) {
case 'C': /* for fsck_ffs compatibility */
break;
case 'f':
skipclean = 0;
break;
case 'F':
/*
* We can never run in the background. We must exit
* silently with a nonzero exit code so that fsck(8)
* can probe our support for -F. The exit code
* doesn't really matter, but we use an unusual one
* in case someone tries -F directly. The -F flag
* is intentionally left out of the usage message.
*/
exit(5);
case 'n':
alwaysno = 1;
alwaysyes = 0;
break;
case 'y':
alwaysyes = 1;
alwaysno = 0;
break;
case 'p':
preen = 1;
break;
case 'M':
allow_mmap = 0;
break;
default:
usage();
break;
}
}
argc -= optind;
argv += optind;
if (!argc)
usage();
while (--argc >= 0) {
// setcdevname(*argv, preen);
erg = checkfilesys(*argv++);
if (erg > ret)
ret = erg;
}
return ret;
}
/*VARARGS*/
int
ask(int def, const char *fmt, ...)
{
va_list ap;
char prompt[256];
int c;
if (alwaysyes || alwaysno || rdonly)
def = (alwaysyes && !rdonly && !alwaysno);
if (preen) {
if (def)
printf("FIXED\n");
return def;
}
va_start(ap, fmt);
vsnprintf(prompt, sizeof(prompt), fmt, ap);
va_end(ap);
if (alwaysyes || alwaysno || rdonly) {
printf("%s? %s\n", prompt, def ? "yes" : "no");
return def;
}
do {
printf("%s? [yn] ", prompt);
fflush(stdout);
c = getchar();
while (c != '\n' && getchar() != '\n')
if (feof(stdin))
return 0;
} while (c != 'y' && c != 'Y' && c != 'n' && c != 'N');
return c == 'y' || c == 'Y';
}
# Copyright (c) 2022 Huawei Device Co., Ltd.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import("//build/ohos.gni")
config("vfat-defaults") {
cflags = [
"-Wall",
"-Werror",
"-Wno-unused-function",
"-Wno-unused-parameter",
"-Wno-unused-variable",
"-D_FILE_OFFSET_BITS=64",
"-D_GNU_SOURCE",
"-DSIGINFO=SIGUSR2",
"-Dnitems(x)=(sizeof((x))/sizeof((x)[0]))",
"-Wno-implicit-function-declaration",
"-DMAKEFS",
"-D_MACHINE_IOCTL_FD_H_",
]
include_dirs = [ "//third_party/FreeBSD/sys" ]
}
###################################################
##Build newfs_msdos
ohos_executable("newfs_msdos") {
configs = [ ":vfat-defaults" ]
sources = [
"mkfs_msdos.c",
"newfs_msdos.c",
]
include_dirs = []
install_enable = true
deps = []
subsystem_name = "filemanagement"
part_name = "storage_service"
install_images = [ "system" ]
}
# $FreeBSD$
PACKAGE=runtime
PROG= newfs_msdos
MAN= newfs_msdos.8
SRCS= newfs_msdos.c mkfs_msdos.c
# XXX - this is verboten
.if ${MACHINE_CPUARCH} == "arm"
WARNS?= 3
.endif
CSTD= c11
.include <bsd.prog.mk>
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MKFS_DEFINE_H
#define MKFS_DEFINE_H
#include <stdint.h>
/*
* BSD_NPARTS_MIN,BSD_NDRIVEDATA,BSD_NSPARE
* Link: https://github.com/freebsd/freebsd-src/
* Path: freebsd-src/sys/sys/disk/bsd.h
*/
#define BSD_NPARTS_MIN 8
/* Drive-type specific data size (in number of 32-bit inegrals) */
#define BSD_NDRIVEDATA 5
/* Number of spare 32-bit integrals following drive-type data */
#define BSD_NSPARE 5
/*
* MAXPHYS
* Link: https://github.com/freebsd/freebsd-src/
* Path: freebsd-src/sys/sys/param.h
*/
#ifdef __ILP32__
#define MAXPHYS (128 * 1024)
#else
#define MAXPHYS (1024 * 1024)
#endif
/*
* DIOCGMEDIASIZE,DIOCGFWSECTORS,DIOCGSECTORSIZE,DIOCGFWHEADS
* Link: https://github.com/freebsd/freebsd-src/
* Path: freebsd-src/sys/sys/disk.h
*/
#define DIOCGMEDIASIZE _IOR('d', 129, off_t) /* Get media size in bytes */
/*
* Get the size of the entire device in bytes. This should be a
* multiple of the sector size.
*/
#define DIOCGFWSECTORS _IOR('d', 130, u_int) /* Get firmware's sectorcount */
/*
* Get the firmware's notion of number of sectors per track. This
* value is mostly used for compatibility with various ill designed
* disk label formats. Don't use it unless you have to.
*/
#define DIOCGSECTORSIZE _IOR('d', 128, u_int)
/*
* Get the sector size of the device in bytes. The sector size is the
* smallest unit of data which can be transferred from this device.
* Usually this is a power of 2 but it might not be (i.e. CDROM audio).
*/
#define DIOCGFWHEADS _IOR('d', 131, u_int) /* Get firmware's headcount */
/*
* Get the firmwares notion of number of heads per cylinder. This
* value is mostly used for compatibility with various ill designed
* disk label formats. Don't use it unless you have to.
*/
/*
* FD_GTYPE
* Link: https://github.com/freebsd/freebsd-src/
* Path: freebsd-src/sys/sys/fdcio.h
*/
#ifndef _MACHINE_IOCTL_FD_H_
#define FD_GTYPE _IOR('F', 62, struct fd_type) /* get drive type */
#endif
/*
* disklabel
* Link: https://github.com/freebsd/freebsd-src/
* Path: freebsd-src/sys/sys/disk/bsd.h
*/
struct disklabel {
uint32_t d_magic; /* the magic number */
uint16_t d_type; /* drive type */
uint16_t d_subtype; /* controller/d_type specific */
char d_typename[16]; /* type name, e.g. "eagle" */
char d_packname[16]; /* pack identifier */
/* disk geometry: */
uint32_t d_secsize; /* # of bytes per sector */
uint32_t d_nsectors; /* # of data sectors per track */
uint32_t d_ntracks; /* # of tracks per cylinder */
uint32_t d_ncylinders; /* # of data cylinders per unit */
uint32_t d_secpercyl; /* # of data sectors per cylinder */
uint32_t d_secperunit; /* # of data sectors per unit */
/*
* Spares (bad sector replacements) below are not counted in
* d_nsectors or d_secpercyl. Spare sectors are assumed to
* be physical sectors which occupy space at the end of each
* track and/or cylinder.
*/
uint16_t d_sparespertrack; /* # of spare sectors per track */
uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
/*
* Alternate cylinders include maintenance, replacement, configuration
* description areas, etc.
*/
uint32_t d_acylinders; /* # of alt. cylinders per unit */
/* hardware characteristics: */
/*
* d_interleave, d_trackskew and d_cylskew describe perturbations
* in the media format used to compensate for a slow controller.
* Interleave is physical sector interleave, set up by the
* formatter or controller when formatting. When interleaving is
* in use, logically adjacent sectors are not physically
* contiguous, but instead are separated by some number of
* sectors. It is specified as the ratio of physical sectors
* traversed per logical sector. Thus an interleave of 1:1
* implies contiguous layout, while 2:1 implies that logical
* sector 0 is separated by one sector from logical sector 1.
* d_trackskew is the offset of sector 0 on track N relative to
* sector 0 on track N-1 on the same cylinder. Finally, d_cylskew
* is the offset of sector 0 on cylinder N relative to sector 0
* on cylinder N-1.
*/
uint16_t d_rpm; /* rotational speed */
uint16_t d_interleave; /* hardware sector interleave */
uint16_t d_trackskew; /* sector 0 skew, per track */
uint16_t d_cylskew; /* sector 0 skew, per cylinder */
uint32_t d_headswitch; /* head switch time, usec */
uint32_t d_trkseek; /* track-to-track seek, usec */
uint32_t d_flags; /* generic flags */
uint32_t d_drivedata[BSD_NDRIVEDATA]; /* drive-type specific data */
uint32_t d_spare[BSD_NSPARE]; /* reserved for future use */
uint32_t d_magic2; /* the magic number (again) */
uint16_t d_checksum; /* xor of data incl. partitions */
/* filesystem and partition information: */
uint16_t d_npartitions; /* number of partitions in following */
uint32_t d_bbsize; /* size of boot area at sn0, bytes */
uint32_t d_sbsize; /* max size of fs superblock, bytes */
struct partition { /* the partition table */
uint32_t p_size; /* number of sectors in partition */
uint32_t p_offset; /* starting sector */
uint32_t p_fsize; /* filesystem basic fragment size */
uint8_t p_fstype; /* filesystem type, see below */
uint8_t p_frag; /* filesystem fragments per block */
uint16_t p_cpg; /* filesystem cylinders per group */
} d_partitions[BSD_NPARTS_MIN]; /* actually may be more */
};
/*
* fd_type
* Link: https://github.com/freebsd/freebsd-src/
* Path: freebsd-src/sys/sys/fdcio.h
*/
struct fd_type {
int sectrac; /* sectors per track */
int secsize; /* size code for sectors */
int datalen; /* data len when secsize = 0 */
int gap; /* gap len between sectors */
int tracks; /* total number of cylinders */
int size; /* size of disk in sectors */
int trans; /* transfer speed code */
int heads; /* number of heads */
int f_gap; /* format gap len */
int f_inter; /* format interleave factor */
int offset_side2; /* offset of sectors on side2 */
int flags; /* misc. features */
#define FL_MFM 0x0001 /* MFM recording */
#define FL_2STEP 0x0002 /* 2 steps between cylinders */
#define FL_PERPND 0x0004 /* perpendicular recording */
#define FL_AUTO 0x0008 /* autodetect format */
};
#endif //MKFS_DEFINE_H
\ No newline at end of file
此差异已折叠。
/* $FreeBSD$ */
/* $NetBSD: mkfs_msdos.h,v 1.3 2015/10/16 17:38:17 christos Exp $ */
/*-
* Copyright (c) 2013 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Christos Zoulas.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
#include <stdbool.h>
#include "mkfs_define.h"
#define ALLOPTS \
AOPT('@', off_t, offset, 0, "Offset in device") \
AOPT('A', bool, align, -2, "Attempt to cluster align root directory") \
AOPT('B', const char *, bootstrap, -1, "Bootstrap file") \
AOPT('C', off_t, create_size, 0, "Create file") \
AOPT('F', uint8_t, fat_type, 12, "FAT type (12, 16, or 32)") \
AOPT('I', uint32_t, volume_id, 0, "Volume ID") \
AOPT('L', const char *, volume_label, -1, "Volume Label") \
AOPT('N', bool, no_create, -2, "Don't create filesystem, print params only") \
AOPT('O', const char *, OEM_string, -1, "OEM string") \
AOPT('S', uint16_t, bytes_per_sector, 1, "Bytes per sector") \
AOPT('T', time_t, timestamp, 0, "Timestamp") \
AOPT('a', uint32_t, sectors_per_fat, 1, "Sectors per FAT") \
AOPT('b', uint32_t, block_size, 1, "Block size") \
AOPT('c', uint8_t, sectors_per_cluster, 1, "Sectors per cluster") \
AOPT('e', uint16_t, directory_entries, 1, "Directory entries") \
AOPT('f', const char *, floppy, -1, "Standard format floppies (160,180,320,360,640,720,1200,1232,1440,2880)") \
AOPT('h', uint16_t, drive_heads, 1, "Drive heads") \
AOPT('i', uint16_t, info_sector, 1, "Info sector") \
AOPT('k', uint16_t, backup_sector, 1, "Backup sector") \
AOPT('m', uint8_t, media_descriptor, 0, "Media descriptor") \
AOPT('n', uint8_t, num_FAT, 1, "Number of FATs") \
AOPT('o', uint32_t, hidden_sectors, 0, "Hidden sectors") \
AOPT('r', uint16_t, reserved_sectors, 1, "Reserved sectors") \
AOPT('s', uint32_t, size, 1, "File System size") \
AOPT('u', uint16_t, sectors_per_track, 1, "Sectors per track")
struct msdos_options {
#define AOPT(_opt, _type, _name, _min, _desc) _type _name;
ALLOPTS
#undef AOPT
uint32_t timestamp_set:1;
uint32_t volume_id_set:1;
uint32_t media_descriptor_set:1;
uint32_t hidden_sectors_set:1;
};
int mkfs_msdos(const char *, const char *, const struct msdos_options *);
.\" Copyright (c) 1998 Robert Nordier
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in
.\" the documentation and/or other materials provided with the
.\" distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd June 14, 2018
.Dt NEWFS_MSDOS 8
.Os
.Sh NAME
.Nm newfs_msdos
.Nd construct a new MS-DOS (FAT) file system
.Sh SYNOPSIS
.Nm
.Op Fl N
.Op Fl @ Ar offset
.Op Fl A
.Op Fl B Ar boot
.Op Fl C Ar create-size
.Op Fl F Ar FAT-type
.Op Fl I Ar VolumeID
.Op Fl L Ar label
.Op Fl O Ar OEM
.Op Fl S Ar sector-size
.Op Fl T Ar timestamp
.Op Fl a Ar FAT-size
.Op Fl b Ar block-size
.Op Fl c Ar cluster-size
.Op Fl e Ar DirEnts
.Op Fl f Ar format
.Op Fl h Ar heads
.Op Fl i Ar info
.Op Fl k Ar backup
.Op Fl m Ar media
.Op Fl n Ar FATs
.Op Fl o Ar hidden
.Op Fl r Ar reserved
.Op Fl s Ar total
.Op Fl u Ar track-size
.Ar special
.Op Ar disktype
.Sh DESCRIPTION
The
.Nm
utility creates a FAT12, FAT16, or FAT32 file system on device or file named
.Ar special ,
using
.Xr disktab 5
entry
.Ar disktype
to determine geometry, if required.
.Pp
If
.Ar special
does not contain a
.Ar /
and
.Fl C
is not used, it is assumed to be a device name and
.Ar /dev/
is prepended to the name to construct the actual device name.
To work a file in the current directory use
.Ar ./filename
.Pp
The options are as follow:
.Bl -tag -width indent
.It Fl N
Do not create a file system: just print out parameters.
.It Fl @ Ar offset
Build the filesystem at the specified offset in bytes in the device or file.
A suffix s, k, m, g (lower or upper case)
appended to the offset specifies that the
number is in sectors, kilobytes, megabytes or gigabytes, respectively.
.It Fl A
Attempt to cluster align root directory, useful for SD card.
.It Fl B Ar boot
Get bootstrap from file.
.It Fl C Ar create-size
Create the image file with the specified size.
A suffix character appended to the size is interpreted as for the
.Fl @
option.
The file is created by truncating any existing file with the same name and
resizing it to the requested size.
If the file system supports sparse files, the space occupied on disk may be
smaller than the size specified as parameter.
.It Fl F Ar FAT-type
FAT type (one of 12, 16, or 32).
.It Fl I Ar VolumeID
Volume ID, a 32 bit number in decimal or hexadecimal (0x...) format.
.It Fl L Ar label
Volume label (up to 11 characters).
The label should consist of
only those characters permitted in regular DOS (8+3) filenames.
.It Fl O Ar OEM
OEM string (up to 8 characters).
The default is
.Qq Li "BSD4.4 " .
.It Fl S Ar sector-size
Number of bytes per sector.
Acceptable values are powers of 2
in the range 512 through 32768, inclusive.
.It Fl T Ar timestamp
Create the filesystem as though the current time is
.Ar timestamp .
The default filesystem volume ID is derived from the time.
.Ar timestamp
can be a pathname (where the timestamp is derived from
that file) or an integer value interpreted
as the number of seconds since the Epoch.
.It Fl a Ar FAT-size
Number of sectors per FAT.
.It Fl b Ar block-size
File system block size (bytes per cluster).
This should resolve to an
acceptable number of sectors per cluster (see below).
.It Fl c Ar cluster-size
Sectors per cluster.
Acceptable values are powers of 2 in the range
1 through 128.
If the block or cluster size are not specified, the code
uses a cluster between 512 bytes and 32K depending on
the filesystem size.
.It Fl e Ar DirEnts
Number of root directory entries (FAT12 and FAT16 only).
.It Fl f Ar format
Specify a standard (floppy disk) format.
The standard formats
are (capacities in kilobytes): 160, 180, 320, 360, 640, 720, 1200,
1232, 1440, 2880.
.It Fl h Ar heads
Number of drive heads.
.It Fl i Ar info
Location of the file system info sector (FAT32 only).
A value of 0xffff signifies no info sector.
.It Fl k Ar backup
Location of the backup boot sector (FAT32 only).
A value
of 0xffff signifies no backup sector.
.It Fl m Ar media
Media descriptor (acceptable range 0xf0 to 0xff).
.It Fl n Ar FATs
Number of FATs.
Acceptable values are 1 to 16 inclusive.
The default
is 2.
.It Fl o Ar hidden
Number of hidden sectors.
.It Fl r Ar reserved
Number of reserved sectors.
.It Fl s Ar total
File system size.
.It Fl u Ar track-size
Number of sectors per track.
.El
.Sh NOTES
If some parameters (e.g., size, number of sectors, etc.) are not specified
through options or disktype, the program tries to generate them automatically.
In particular, the size is determined as the device or file size minus the
offset specified with the
.Fl @
option.
When the geometry is not available, it is assumed to be 63 sectors, 255 heads.
The size is then rounded to become a multiple of the track size and avoid
complaints by some filesystem code.
.Pp
FAT file system parameters occupy a "Boot Sector BPB (BIOS Parameter
Block)" in the first of the "reserved" sectors which precede the actual
file system.
For reference purposes, this structure is presented
below.
.Bd -literal
struct bsbpb {
uint16_t bpbBytesPerSec; /* [-S] bytes per sector */
uint8_t bpbSecPerClust; /* [-c] sectors per cluster */
uint16_t bpbResSectors; /* [-r] reserved sectors */
uint8_t bpbFATs; /* [-n] number of FATs */
uint16_t bpbRootDirEnts; /* [-e] root directory entries */
uint16_t bpbSectors; /* [-s] total sectors */
uint8_t bpbMedia; /* [-m] media descriptor */
uint16_t bpbFATsecs; /* [-a] sectors per FAT */
uint16_t bpbSecPerTrack; /* [-u] sectors per track */
uint16_t bpbHeads; /* [-h] drive heads */
uint32_t bpbHiddenSecs; /* [-o] hidden sectors */
uint32_t bpbHugeSectors; /* [-s] big total sectors */
};
/* FAT32 extensions */
struct bsxbpb {
uint32_t bpbBigFATsecs; /* [-a] big sectors per FAT */
uint16_t bpbExtFlags; /* control flags */
uint16_t bpbFSVers; /* file system version */
uint32_t bpbRootClust; /* root directory start cluster */
uint16_t bpbFSInfo; /* [-i] file system info sector */
uint16_t bpbBackup; /* [-k] backup boot sector */
};
.Ed
.Sh LIMITATION
The maximum file size is 4GB, even if the file system itself is bigger.
.Sh EXIT STATUS
Exit status is 0 on success and 1 on error.
.Sh EXAMPLES
Create a file system, using default parameters, on
.Pa /dev/ada0s1 :
.Bd -literal -offset indent
newfs_msdos /dev/ada0s1
.Ed
.Pp
Create a standard 1.44M file system, with volume label
.Ar foo ,
on
.Pa /dev/fd0 :
.Bd -literal -offset indent
newfs_msdos -f 1440 -L foo fd0
.Ed
.Pp
Create a 30MB image file, with the FAT partition starting
63 sectors within the image file:
.Bd -literal -offset indent
newfs_msdos -C 30M -@63s ./somefile
.Ed
.Sh SEE ALSO
.Xr gpart 8 ,
.Xr newfs 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Fx 3.0 .
.Sh AUTHORS
.An Robert Nordier Aq Mt rnordier@FreeBSD.org
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 1998 Robert Nordier
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef lint
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <err.h>
#include <errno.h>
#include <paths.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "mkfs_msdos.h"
#define argto1(arg, lo, msg) argtou(arg, lo, 0xff, msg)
#define argto2(arg, lo, msg) argtou(arg, lo, 0xffff, msg)
#define argto4(arg, lo, msg) argtou(arg, lo, 0xffffffff, msg)
#define argtox(arg, lo, msg) argtou(arg, lo, UINT_MAX, msg)
static u_int argtou(const char *, u_int, u_int, const char *);
static off_t argtooff(const char *, const char *);
static void usage(void);
static time_t
get_tstamp(const char *b)
{
struct stat st;
char *eb;
long long l;
if (stat(b, &st) != -1)
return (time_t)st.st_mtime;
errno = 0;
l = strtoll(b, &eb, 0);
if (b == eb || *eb || errno)
errx(EXIT_FAILURE, "Can't parse timestamp '%s'", b);
return (time_t)l;
}
/*
* Construct a FAT12, FAT16, or FAT32 file system.
*/
int
main(int argc, char *argv[])
{
static const char opts[] = "@:NAB:C:F:I:L:O:S:a:b:c:e:f:h:i:k:m:n:o:r:s:T:u:";
struct msdos_options o;
const char *fname, *dtype;
char buf[MAXPATHLEN];
int ch;
memset(&o, 0, sizeof(o));
while ((ch = getopt(argc, argv, opts)) != -1)
switch (ch) {
case '@':
o.offset = argtooff(optarg, "offset");
break;
case 'N':
o.no_create = 1;
break;
case 'A':
o.align = true;
break;
case 'B':
o.bootstrap = optarg;
break;
case 'C':
o.create_size = argtooff(optarg, "create size");
break;
case 'F':
if (strcmp(optarg, "12") &&
strcmp(optarg, "16") &&
strcmp(optarg, "32"))
errx(1, "%s: bad FAT type", optarg);
o.fat_type = atoi(optarg);
break;
case 'I':
o.volume_id = argto4(optarg, 0, "volume ID");
o.volume_id_set = 1;
break;
case 'L':
o.volume_label = optarg;
break;
case 'O':
o.OEM_string = optarg;
break;
case 'S':
o.bytes_per_sector = argto2(optarg, 1, "bytes/sector");
break;
case 'a':
o.sectors_per_fat = argto4(optarg, 1, "sectors/FAT");
break;
case 'b':
o.block_size = argtox(optarg, 1, "block size");
o.sectors_per_cluster = 0;
break;
case 'c':
o.sectors_per_cluster = argto1(optarg, 1, "sectors/cluster");
o.block_size = 0;
break;
case 'e':
o.directory_entries = argto2(optarg, 1, "directory entries");
break;
case 'f':
o.floppy = optarg;
break;
case 'h':
o.drive_heads = argto2(optarg, 1, "drive heads");
break;
case 'i':
o.info_sector = argto2(optarg, 1, "info sector");
break;
case 'k':
o.backup_sector = argto2(optarg, 1, "backup sector");
break;
case 'm':
o.media_descriptor = argto1(optarg, 0, "media descriptor");
o.media_descriptor_set = 1;
break;
case 'n':
o.num_FAT = argto1(optarg, 1, "number of FATs");
break;
case 'o':
o.hidden_sectors = argto4(optarg, 0, "hidden sectors");
o.hidden_sectors_set = 1;
break;
case 'r':
o.reserved_sectors = argto2(optarg, 1, "reserved sectors");
break;
case 's':
o.size = argto4(optarg, 1, "file system size");
break;
case 'T':
o.timestamp_set = 1;
o.timestamp = get_tstamp(optarg);
break;
case 'u':
o.sectors_per_track = argto2(optarg, 1, "sectors/track");
break;
default:
usage();
}
argc -= optind;
argv += optind;
if (argc < 1 || argc > 2)
usage();
if (o.align) {
if (o.reserved_sectors)
errx(1, "align (-A) is incompatible with -r");
}
fname = *argv++;
if (!o.create_size && !strchr(fname, '/')) {
snprintf(buf, sizeof(buf), "%s%s", _PATH_DEV, fname);
fname = buf;
}
dtype = *argv;
exit(!!mkfs_msdos(fname, dtype, &o));
}
/*
* Convert and check a numeric option argument.
*/
static u_int
argtou(const char *arg, u_int lo, u_int hi, const char *msg)
{
char *s;
u_long x;
errno = 0;
x = strtoul(arg, &s, 0);
if (errno || !*arg || *s || x < lo || x > hi)
errx(1, "%s: bad %s", arg, msg);
return x;
}
/*
* Same for off_t, with optional skmgpP suffix
*/
static off_t
argtooff(const char *arg, const char *msg)
{
char *s;
off_t x;
errno = 0;
x = strtoll(arg, &s, 0);
/* allow at most one extra char */
if (errno || x < 0 || (s[0] && s[1]) )
errx(1, "%s: bad %s", arg, msg);
if (*s) { /* the extra char is the multiplier */
switch (*s) {
default:
errx(1, "%s: bad %s", arg, msg);
/* notreached */
case 's': /* sector */
case 'S':
x <<= 9; /* times 512 */
break;
case 'k': /* kilobyte */
case 'K':
x <<= 10; /* times 1024 */
break;
case 'm': /* megabyte */
case 'M':
x <<= 20; /* times 1024*1024 */
break;
case 'g': /* gigabyte */
case 'G':
x <<= 30; /* times 1024*1024*1024 */
break;
case 'p': /* partition start */
case 'P':
case 'l': /* partition length */
case 'L':
errx(1, "%s: not supported yet %s", arg, msg);
/* notreached */
}
}
return x;
}
/*
* Print usage message.
*/
static void
usage(void)
{
fprintf(stderr,
"usage: [ -options ] special [disktype]\n");
fprintf(stderr, "where the options are:\n");
static struct {
char o;
const char *h;
} opts[] = {
#define AOPT(_opt, _type, _name, _min, _desc) { _opt, _desc },
ALLOPTS
#undef AOPT
};
for (size_t i = 0; i < nitems(opts); i++)
fprintf(stderr, "\t-%c %s\n", opts[i].o, opts[i].h);
exit(1);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册