fsck_v7fs.c revision 1.1
11.1Such/*	$NetBSD: fsck_v7fs.c,v 1.1 2011/06/27 11:52:58 uch 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.1Such__RCSID("$NetBSD: fsck_v7fs.c,v 1.1 2011/06/27 11:52:58 uch Exp $");
351.1Such#endif /* not lint */
361.1Such
371.1Such#include <stdio.h>
381.1Such#include <stdlib.h>
391.1Such#include <string.h>
401.1Such#include <unistd.h>
411.1Such#include <fcntl.h>
421.1Such#include <err.h>
431.1Such#include <sys/ioctl.h>
441.1Such#include <sys/disklabel.h>
451.1Such
461.1Such#include <fs/v7fs/v7fs.h>
471.1Such#include "v7fs_impl.h"
481.1Such#include "fsck_v7fs.h"
491.1Such#include "progress.h"
501.1Such
511.1Suchstatic void usage(void) __dead;
521.1Suchstatic void catopt(char **, const char *);
531.1Such
541.1Suchenum fsck_operate fsck_operate;
551.1Suchbool verbose = true;
561.1Such#define	VPRINTF(fmt, args...)	{ if (verbose) printf(fmt, ##args); }
571.1Such
581.1Suchint
591.1Suchmain(int argc, char **argv)
601.1Such{
611.1Such	const char *device;
621.1Such	struct disklabel d;
631.1Such	struct partition *p;
641.1Such	struct stat st;
651.1Such	int Fflag = 0;
661.1Such	int part;
671.1Such	int fd, ch;
681.1Such	int endian = _BYTE_ORDER;
691.1Such	int openflags = O_RDWR;
701.1Such	size_t part_sectors;
711.1Such	int fsck_flags = 0;
721.1Such	char *options = 0;
731.1Such	bool progress_bar_enable = false;
741.1Such
751.1Such	fsck_operate = ASK;
761.1Such
771.1Such	if (argc < 2)
781.1Such		usage();
791.1Such
801.1Such	while ((ch = getopt(argc, argv, "pPqynfx:dFB:o:")) != -1) {
811.1Such		switch (ch) {
821.1Such			/*
831.1Such			 * generic fsck options
841.1Such			 */
851.1Such		case 'd':	/* Not supported */
861.1Such			break;
871.1Such		case 'f':	/* Always forced */
881.1Such			break;
891.1Such		case 'p':
901.1Such			fsck_operate = PREEN;
911.1Such			break;
921.1Such		case 'y':
931.1Such			fsck_operate = ALWAYS_YES;
941.1Such			break;
951.1Such		case 'n':
961.1Such			fsck_operate = ALWAYS_NO;
971.1Such			openflags = O_RDONLY;
981.1Such			break;
991.1Such		case 'P':
1001.1Such			progress_bar_enable = true;
1011.1Such			break;
1021.1Such		case 'q':	/* Not supported */
1031.1Such			break;
1041.1Such		case 'x':	/* Not supported */
1051.1Such			break;
1061.1Such			/*
1071.1Such			 * v7fs fsck options
1081.1Such			 */
1091.1Such		case 'F':
1101.1Such			Fflag = 1;
1111.1Such			break;
1121.1Such		case 'B':
1131.1Such			switch (optarg[0]) {
1141.1Such			case 'l':
1151.1Such				endian = _LITTLE_ENDIAN;
1161.1Such				break;
1171.1Such			case 'b':
1181.1Such				endian = _BIG_ENDIAN;
1191.1Such				break;
1201.1Such			case 'p':
1211.1Such				endian = _PDP_ENDIAN;
1221.1Such				break;
1231.1Such			}
1241.1Such			break;
1251.1Such		case 'o': /* datablock, freeblock duplication check */
1261.1Such			if (*optarg)
1271.1Such				catopt(&options, optarg);
1281.1Such			break;
1291.1Such		default:
1301.1Such			usage();
1311.1Such			/*NOTREACHED*/
1321.1Such		}
1331.1Such	}
1341.1Such
1351.1Such	argc -= optind;
1361.1Such	argv += optind;
1371.1Such
1381.1Such	if (argc != 1)
1391.1Such		usage();
1401.1Such	device = argv[0];
1411.1Such
1421.1Such	if (options) {
1431.1Such		if (strstr(options, "data"))
1441.1Such			fsck_flags |= V7FS_FSCK_DATABLOCK_DUP;
1451.1Such		if (strstr(options, "free"))
1461.1Such			fsck_flags |= V7FS_FSCK_FREEBLOCK_DUP;
1471.1Such	}
1481.1Such
1491.1Such	if (Fflag) {
1501.1Such		if ((fd = open(device, openflags)) == -1) {
1511.1Such			pfatal("%s", device);
1521.1Such		}
1531.1Such		if (fstat(fd, &st)) {
1541.1Such			pfatal("stat");
1551.1Such		}
1561.1Such		part_sectors = st.st_size >> V7FS_BSHIFT;
1571.1Such		setcdevname(device, fsck_operate == PREEN);
1581.1Such	} else {
1591.1Such		/* blockcheck sets 'hot' */
1601.1Such		device = blockcheck(device);
1611.1Such		setcdevname(device, fsck_operate == PREEN);
1621.1Such
1631.1Such		if ((fd = open(device, openflags)) == -1) {
1641.1Such			pfatal("%s", device);
1651.1Such		}
1661.1Such		part = DISKPART(st.st_rdev);
1671.1Such
1681.1Such		if (ioctl(fd, DIOCGDINFO, &d) == -1) {
1691.1Such			pfatal("DIOCGDINFO");
1701.1Such		}
1711.1Such		p = &d.d_partitions[part];
1721.1Such		part_sectors = p->p_size;
1731.1Such		VPRINTF("partition=%d size=%d offset=%d fstype=%d secsize=%d\n",
1741.1Such		    part, p->p_size, p->p_offset, p->p_fstype, d.d_secsize);
1751.1Such		if (p->p_fstype != FS_V7) {
1761.1Such			pfatal("not a Version 7 partition.");
1771.1Such		}
1781.1Such	}
1791.1Such
1801.1Such	progress_switch(progress_bar_enable);
1811.1Such	progress_init();
1821.1Such	progress(&(struct progress_arg){ .cdev = device });
1831.1Such
1841.1Such	struct v7fs_mount_device mount;
1851.1Such	mount.device.fd = fd;
1861.1Such	mount.endian = endian;
1871.1Such	mount.sectors = part_sectors;
1881.1Such	int error = v7fs_fsck(&mount, fsck_flags);
1891.1Such
1901.1Such	close(fd);
1911.1Such
1921.1Such	return error;
1931.1Such}
1941.1Such
1951.1Suchstatic void
1961.1Suchcatopt(char **sp, const char *o)
1971.1Such{
1981.1Such	char *s, *n;
1991.1Such
2001.1Such	s = *sp;
2011.1Such	if (s) {
2021.1Such		if (asprintf(&n, "%s,%s", s, o) < 0)
2031.1Such			err(1, "asprintf");
2041.1Such		free(s);
2051.1Such		s = n;
2061.1Such	} else
2071.1Such		s = strdup(o);
2081.1Such	*sp = s;
2091.1Such}
2101.1Such
2111.1Suchstatic void
2121.1Suchusage(void)
2131.1Such{
2141.1Such
2151.1Such	(void)fprintf(stderr, "usage: %s [-ynpP] [-o options] [-B endian] "
2161.1Such	    "special-device\n",
2171.1Such	    getprogname());
2181.1Such	(void)fprintf(stderr, "usage: %s -F [-ynpP] [-o options] [-B endian] "
2191.1Such	    "file\n",
2201.1Such	    getprogname());
2211.1Such
2221.1Such	exit(FSCK_EXIT_USAGE);
2231.1Such}
224