fsck_v7fs.c revision 1.2
11.2Schristos/* $NetBSD: fsck_v7fs.c,v 1.2 2017/01/10 20:54:10 christos Exp $ */ 21.1Such 31.1Such/*- 41.1Such * Copyright (c) 2004, 2011 The NetBSD Foundation, Inc. 51.1Such * All rights reserved. 61.1Such * 71.1Such * This code is derived from software contributed to The NetBSD Foundation 81.1Such * by UCHIYAMA Yasushi. 91.1Such * 101.1Such * Redistribution and use in source and binary forms, with or without 111.1Such * modification, are permitted provided that the following conditions 121.1Such * are met: 131.1Such * 1. Redistributions of source code must retain the above copyright 141.1Such * notice, this list of conditions and the following disclaimer. 151.1Such * 2. Redistributions in binary form must reproduce the above copyright 161.1Such * notice, this list of conditions and the following disclaimer in the 171.1Such * documentation and/or other materials provided with the distribution. 181.1Such * 191.1Such * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 201.1Such * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 211.1Such * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 221.1Such * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 231.1Such * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 241.1Such * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 251.1Such * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 261.1Such * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 271.1Such * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 281.1Such * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 291.1Such * POSSIBILITY OF SUCH DAMAGE. 301.1Such */ 311.1Such 321.1Such#include <sys/cdefs.h> 331.1Such#ifndef lint 341.2Schristos__RCSID("$NetBSD: fsck_v7fs.c,v 1.2 2017/01/10 20:54:10 christos Exp $"); 351.1Such#endif /* not lint */ 361.1Such 371.2Schristos#include <sys/types.h> 381.2Schristos#include <sys/disklabel.h> 391.2Schristos#include <sys/ioctl.h> 401.2Schristos#include <sys/stat.h> 411.2Schristos 421.1Such#include <stdio.h> 431.1Such#include <stdlib.h> 441.1Such#include <string.h> 451.1Such#include <unistd.h> 461.1Such#include <fcntl.h> 471.1Such#include <err.h> 481.1Such 491.1Such#include <fs/v7fs/v7fs.h> 501.1Such#include "v7fs_impl.h" 511.1Such#include "fsck_v7fs.h" 521.1Such#include "progress.h" 531.1Such 541.1Suchstatic void usage(void) __dead; 551.1Suchstatic void catopt(char **, const char *); 561.1Such 571.1Suchenum fsck_operate fsck_operate; 581.1Suchbool verbose = true; 591.1Such#define VPRINTF(fmt, args...) { if (verbose) printf(fmt, ##args); } 601.1Such 611.1Suchint 621.1Suchmain(int argc, char **argv) 631.1Such{ 641.1Such const char *device; 651.1Such struct disklabel d; 661.1Such struct partition *p; 671.1Such struct stat st; 681.1Such int Fflag = 0; 691.1Such int part; 701.1Such int fd, ch; 711.1Such int endian = _BYTE_ORDER; 721.1Such int openflags = O_RDWR; 731.1Such size_t part_sectors; 741.1Such int fsck_flags = 0; 751.1Such char *options = 0; 761.1Such bool progress_bar_enable = false; 771.1Such 781.1Such fsck_operate = ASK; 791.1Such 801.1Such if (argc < 2) 811.1Such usage(); 821.1Such 831.1Such while ((ch = getopt(argc, argv, "pPqynfx:dFB:o:")) != -1) { 841.1Such switch (ch) { 851.1Such /* 861.1Such * generic fsck options 871.1Such */ 881.1Such case 'd': /* Not supported */ 891.1Such break; 901.1Such case 'f': /* Always forced */ 911.1Such break; 921.1Such case 'p': 931.1Such fsck_operate = PREEN; 941.1Such break; 951.1Such case 'y': 961.1Such fsck_operate = ALWAYS_YES; 971.1Such break; 981.1Such case 'n': 991.1Such fsck_operate = ALWAYS_NO; 1001.1Such openflags = O_RDONLY; 1011.1Such break; 1021.1Such case 'P': 1031.1Such progress_bar_enable = true; 1041.1Such break; 1051.1Such case 'q': /* Not supported */ 1061.1Such break; 1071.1Such case 'x': /* Not supported */ 1081.1Such break; 1091.1Such /* 1101.1Such * v7fs fsck options 1111.1Such */ 1121.1Such case 'F': 1131.1Such Fflag = 1; 1141.1Such break; 1151.1Such case 'B': 1161.1Such switch (optarg[0]) { 1171.1Such case 'l': 1181.1Such endian = _LITTLE_ENDIAN; 1191.1Such break; 1201.1Such case 'b': 1211.1Such endian = _BIG_ENDIAN; 1221.1Such break; 1231.1Such case 'p': 1241.1Such endian = _PDP_ENDIAN; 1251.1Such break; 1261.1Such } 1271.1Such break; 1281.1Such case 'o': /* datablock, freeblock duplication check */ 1291.1Such if (*optarg) 1301.1Such catopt(&options, optarg); 1311.1Such break; 1321.1Such default: 1331.1Such usage(); 1341.1Such /*NOTREACHED*/ 1351.1Such } 1361.1Such } 1371.1Such 1381.1Such argc -= optind; 1391.1Such argv += optind; 1401.1Such 1411.1Such if (argc != 1) 1421.1Such usage(); 1431.1Such device = argv[0]; 1441.1Such 1451.1Such if (options) { 1461.1Such if (strstr(options, "data")) 1471.1Such fsck_flags |= V7FS_FSCK_DATABLOCK_DUP; 1481.1Such if (strstr(options, "free")) 1491.1Such fsck_flags |= V7FS_FSCK_FREEBLOCK_DUP; 1501.1Such } 1511.1Such 1521.1Such if (Fflag) { 1531.1Such if ((fd = open(device, openflags)) == -1) { 1541.1Such pfatal("%s", device); 1551.1Such } 1561.1Such if (fstat(fd, &st)) { 1571.1Such pfatal("stat"); 1581.1Such } 1591.1Such part_sectors = st.st_size >> V7FS_BSHIFT; 1601.1Such setcdevname(device, fsck_operate == PREEN); 1611.1Such } else { 1621.1Such /* blockcheck sets 'hot' */ 1631.1Such device = blockcheck(device); 1641.1Such setcdevname(device, fsck_operate == PREEN); 1651.1Such 1661.1Such if ((fd = open(device, openflags)) == -1) { 1671.1Such pfatal("%s", device); 1681.1Such } 1691.1Such part = DISKPART(st.st_rdev); 1701.1Such 1711.1Such if (ioctl(fd, DIOCGDINFO, &d) == -1) { 1721.1Such pfatal("DIOCGDINFO"); 1731.1Such } 1741.1Such p = &d.d_partitions[part]; 1751.1Such part_sectors = p->p_size; 1761.1Such VPRINTF("partition=%d size=%d offset=%d fstype=%d secsize=%d\n", 1771.1Such part, p->p_size, p->p_offset, p->p_fstype, d.d_secsize); 1781.1Such if (p->p_fstype != FS_V7) { 1791.1Such pfatal("not a Version 7 partition."); 1801.1Such } 1811.1Such } 1821.1Such 1831.1Such progress_switch(progress_bar_enable); 1841.1Such progress_init(); 1851.1Such progress(&(struct progress_arg){ .cdev = device }); 1861.1Such 1871.1Such struct v7fs_mount_device mount; 1881.1Such mount.device.fd = fd; 1891.1Such mount.endian = endian; 1901.1Such mount.sectors = part_sectors; 1911.1Such int error = v7fs_fsck(&mount, fsck_flags); 1921.1Such 1931.1Such close(fd); 1941.1Such 1951.1Such return error; 1961.1Such} 1971.1Such 1981.1Suchstatic void 1991.1Suchcatopt(char **sp, const char *o) 2001.1Such{ 2011.1Such char *s, *n; 2021.1Such 2031.1Such s = *sp; 2041.1Such if (s) { 2051.1Such if (asprintf(&n, "%s,%s", s, o) < 0) 2061.1Such err(1, "asprintf"); 2071.1Such free(s); 2081.1Such s = n; 2091.1Such } else 2101.1Such s = strdup(o); 2111.1Such *sp = s; 2121.1Such} 2131.1Such 2141.1Suchstatic void 2151.1Suchusage(void) 2161.1Such{ 2171.1Such 2181.1Such (void)fprintf(stderr, "usage: %s [-ynpP] [-o options] [-B endian] " 2191.1Such "special-device\n", 2201.1Such getprogname()); 2211.1Such (void)fprintf(stderr, "usage: %s -F [-ynpP] [-o options] [-B endian] " 2221.1Such "file\n", 2231.1Such getprogname()); 2241.1Such 2251.1Such exit(FSCK_EXIT_USAGE); 2261.1Such} 227