newfs.c revision 126254
11558Srgrimes/*
298542Smckusick * Copyright (c) 2002 Networks Associates Technology, Inc.
398542Smckusick * All rights reserved.
498542Smckusick *
598542Smckusick * This software was developed for the FreeBSD Project by Marshall
698542Smckusick * Kirk McKusick and Network Associates Laboratories, the Security
798542Smckusick * Research Division of Network Associates, Inc. under DARPA/SPAWAR
898542Smckusick * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
9110884Smckusick * research program.
1098542Smckusick *
111558Srgrimes * Copyright (c) 1983, 1989, 1993, 1994
121558Srgrimes *	The Regents of the University of California.  All rights reserved.
131558Srgrimes *
141558Srgrimes * Redistribution and use in source and binary forms, with or without
151558Srgrimes * modification, are permitted provided that the following conditions
161558Srgrimes * are met:
171558Srgrimes * 1. Redistributions of source code must retain the above copyright
181558Srgrimes *    notice, this list of conditions and the following disclaimer.
191558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
201558Srgrimes *    notice, this list of conditions and the following disclaimer in the
211558Srgrimes *    documentation and/or other materials provided with the distribution.
221558Srgrimes * 3. All advertising materials mentioning features or use of this software
231558Srgrimes *    must display the following acknowledgement:
241558Srgrimes *	This product includes software developed by the University of
251558Srgrimes *	California, Berkeley and its contributors.
261558Srgrimes * 4. Neither the name of the University nor the names of its contributors
271558Srgrimes *    may be used to endorse or promote products derived from this software
281558Srgrimes *    without specific prior written permission.
291558Srgrimes *
301558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
311558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
321558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
331558Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
341558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
351558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
361558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
371558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
381558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
391558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
401558Srgrimes * SUCH DAMAGE.
411558Srgrimes */
421558Srgrimes
43114589Sobrien#if 0
441558Srgrimes#ifndef lint
4537664Scharnierstatic const char copyright[] =
4637664Scharnier"@(#) Copyright (c) 1983, 1989, 1993, 1994\n\
4737664Scharnier	The Regents of the University of California.  All rights reserved.\n";
481558Srgrimes#endif /* not lint */
491558Srgrimes
501558Srgrimes#ifndef lint
5137664Scharnierstatic char sccsid[] = "@(#)newfs.c	8.13 (Berkeley) 5/1/95";
52114589Sobrien#endif /* not lint */
5337664Scharnier#endif
54114589Sobrien#include <sys/cdefs.h>
55114589Sobrien__FBSDID("$FreeBSD: head/sbin/newfs/newfs.c 126254 2004-02-26 01:14:27Z rwatson $");
561558Srgrimes
571558Srgrimes/*
581558Srgrimes * newfs: friendly front end to mkfs
591558Srgrimes */
601558Srgrimes#include <sys/param.h>
611558Srgrimes#include <sys/stat.h>
6295357Sphk#include <sys/disk.h>
631558Srgrimes#include <sys/disklabel.h>
641558Srgrimes#include <sys/file.h>
651558Srgrimes#include <sys/mount.h>
661558Srgrimes
6737707Scharnier#include <ufs/ufs/dir.h>
6837707Scharnier#include <ufs/ufs/dinode.h>
691558Srgrimes#include <ufs/ffs/fs.h>
7023682Speter#include <ufs/ufs/ufsmount.h>
711558Srgrimes
721558Srgrimes#include <ctype.h>
7337664Scharnier#include <err.h>
741558Srgrimes#include <errno.h>
751558Srgrimes#include <paths.h>
7693777Sbde#include <stdarg.h>
771558Srgrimes#include <stdio.h>
781558Srgrimes#include <stdlib.h>
791558Srgrimes#include <string.h>
801558Srgrimes#include <syslog.h>
811558Srgrimes#include <unistd.h>
821558Srgrimes
8392717Sphk#include "newfs.h"
841558Srgrimes
851558Srgrimes/*
861558Srgrimes * The following two constants set the default block and fragment sizes.
871558Srgrimes * Both constants must be a power of 2 and meet the following constraints:
881558Srgrimes *	MINBSIZE <= DESBLKSIZE <= MAXBSIZE
891558Srgrimes *	sectorsize <= DESFRAGSIZE <= DESBLKSIZE
901558Srgrimes *	DESBLKSIZE / DESFRAGSIZE <= 8
911558Srgrimes */
9287661Ssheldonh#define	DFL_FRAGSIZE	2048
9387661Ssheldonh#define	DFL_BLKSIZE	16384
941558Srgrimes
951558Srgrimes/*
9698542Smckusick * Cylinder groups may have up to MAXBLKSPERCG blocks. The actual
971558Srgrimes * number used depends upon how much information can be stored
98102231Strhodes * in a cylinder group map which must fit in a single file system
9998542Smckusick * block. The default is to use as many as possible blocks per group.
1001558Srgrimes */
10198542Smckusick#define	MAXBLKSPERCG	0x7fffffff	/* desired fs_fpg ("infinity") */
1021558Srgrimes
1031558Srgrimes/*
1041558Srgrimes * MAXBLKPG determines the maximum number of data blocks which are
1051558Srgrimes * placed in a single cylinder group. The default is one indirect
1061558Srgrimes * block worth of data blocks.
1071558Srgrimes */
10898542Smckusick#define MAXBLKPG(bsize)	((bsize) / sizeof(ufs2_daddr_t))
1091558Srgrimes
1101558Srgrimes/*
111102231Strhodes * Each file system has a number of inodes statically allocated.
1121558Srgrimes * We allocate one inode slot per NFPI fragments, expecting this
1131558Srgrimes * to be far more than we will ever need.
1141558Srgrimes */
1151558Srgrimes#define	NFPI		4
1161558Srgrimes
117110174Sgordonint	Lflag;			/* add a volume label */
118102231Strhodesint	Nflag;			/* run without writing file system */
119113751Srwatsonint	Oflag = 2;		/* file system format (1 => UFS1, 2 => UFS2) */
12092722Sphkint	Rflag;			/* regression test */
121102231Strhodesint	Uflag;			/* enable soft updates for file system */
122122785Swesint	Eflag = 0;		/* exit in middle of newfs for testing */
123126254Srwatsonint	lflag;			/* enable multilabel for file system */
12498542Smckusickquad_t	fssize;			/* file system size */
12598542Smckusickint	sectorsize;		/* bytes/sector */
1261558Srgrimesint	realsectorsize;		/* bytes/sector in hardware */
1271558Srgrimesint	fsize = 0;		/* fragment size */
1281558Srgrimesint	bsize = 0;		/* block size */
12998542Smckusickint	maxbsize = 0;		/* maximum clustering */
13098542Smckusickint	maxblkspercg = MAXBLKSPERCG; /* maximum blocks per cylinder group */
1311558Srgrimesint	minfree = MINFREE;	/* free space threshold */
1321558Srgrimesint	opt = DEFAULTOPT;	/* optimization preference (space or time) */
1331558Srgrimesint	density;		/* number of bytes per inode */
1341558Srgrimesint	maxcontig = 0;		/* max contiguous blocks to allocate */
1351558Srgrimesint	maxbpg;			/* maximum blocks per file in a cyl group */
13675377Smckusickint	avgfilesize = AVFILESIZ;/* expected average file size */
13775377Smckusickint	avgfilesperdir = AFPDIR;/* expected number of files per directory */
138110174Sgordonu_char	*volumelabel = NULL;	/* volume label for filesystem */
139110671Sjmallettstruct uufsd disk;		/* libufs disk structure */
1401558Srgrimes
14192763Sphkstatic char	device[MAXPATHLEN];
14293777Sbdestatic char	*disktype;
14393777Sbdestatic int	unlabeled;
1441558Srgrimes
14595357Sphkstatic struct disklabel *getdisklabel(char *s);
14695357Sphkstatic void rewritelabel(char *s, struct disklabel *lp);
14793777Sbdestatic void usage(void);
14837664Scharnier
1491558Srgrimesint
15092711Siedowsemain(int argc, char *argv[])
1511558Srgrimes{
15292483Sphk	struct partition *pp;
15392483Sphk	struct disklabel *lp;
1541558Srgrimes	struct partition oldpartition;
1551558Srgrimes	struct stat st;
15695357Sphk	char *cp, *special;
157110174Sgordon	int ch, i;
15895357Sphk	off_t mediasize;
1591558Srgrimes
16092717Sphk	while ((ch = getopt(argc, argv,
161126254Srwatson	    "EL:NO:RS:T:Ua:b:c:d:e:f:g:h:i:lm:o:s:")) != -1)
1621558Srgrimes		switch (ch) {
163122785Swes		case 'E':
164122785Swes			Eflag++;
165122785Swes			break;
166110174Sgordon		case 'L':
167110174Sgordon			volumelabel = optarg;
168110174Sgordon			i = -1;
169110174Sgordon			while (isalnum(volumelabel[++i]));
170110174Sgordon			if (volumelabel[i] != '\0') {
171110174Sgordon				errx(1, "bad volume label. Valid characters are alphanumerics.");
172110174Sgordon			}
173110174Sgordon			if (strlen(volumelabel) >= MAXVOLLEN) {
174110174Sgordon				errx(1, "bad volume label. Length is longer than %d.",
175110174Sgordon				    MAXVOLLEN);
176110174Sgordon			}
177110174Sgordon			Lflag = 1;
178110174Sgordon			break;
1791558Srgrimes		case 'N':
1801558Srgrimes			Nflag = 1;
1811558Srgrimes			break;
18298542Smckusick		case 'O':
18398542Smckusick			if ((Oflag = atoi(optarg)) < 1 || Oflag > 2)
184102231Strhodes				errx(1, "%s: bad file system format value",
18598542Smckusick				    optarg);
18698542Smckusick			break;
18792722Sphk		case 'R':
18892722Sphk			Rflag = 1;
18992722Sphk			break;
1901558Srgrimes		case 'S':
1911558Srgrimes			if ((sectorsize = atoi(optarg)) <= 0)
19295357Sphk				errx(1, "%s: bad sector size", optarg);
1931558Srgrimes			break;
1941558Srgrimes		case 'T':
1951558Srgrimes			disktype = optarg;
1961558Srgrimes			break;
19775078Sobrien		case 'U':
19875078Sobrien			Uflag = 1;
19975078Sobrien			break;
2001558Srgrimes		case 'a':
2011558Srgrimes			if ((maxcontig = atoi(optarg)) <= 0)
20295357Sphk				errx(1, "%s: bad maximum contiguous blocks",
2031558Srgrimes				    optarg);
2041558Srgrimes			break;
2051558Srgrimes		case 'b':
2061558Srgrimes			if ((bsize = atoi(optarg)) < MINBSIZE)
207107412Smckusick				errx(1, "%s: block size too small, min is %d",
208107412Smckusick				    optarg, MINBSIZE);
209107412Smckusick			if (bsize > MAXBSIZE)
210107412Smckusick				errx(1, "%s: block size too large, max is %d",
211107412Smckusick				    optarg, MAXBSIZE);
2121558Srgrimes			break;
2131558Srgrimes		case 'c':
21498542Smckusick			if ((maxblkspercg = atoi(optarg)) <= 0)
21598542Smckusick				errx(1, "%s: bad blocks per cylinder group",
21698542Smckusick				    optarg);
2171558Srgrimes			break;
21898542Smckusick		case 'd':
21998542Smckusick			if ((maxbsize = atoi(optarg)) < MINBSIZE)
22098542Smckusick				errx(1, "%s: bad extent block size", optarg);
22198542Smckusick			break;
2221558Srgrimes		case 'e':
2231558Srgrimes			if ((maxbpg = atoi(optarg)) <= 0)
22498542Smckusick			  errx(1, "%s: bad blocks per file in a cylinder group",
2251558Srgrimes				    optarg);
2261558Srgrimes			break;
2271558Srgrimes		case 'f':
2281558Srgrimes			if ((fsize = atoi(optarg)) <= 0)
22995357Sphk				errx(1, "%s: bad fragment size", optarg);
2301558Srgrimes			break;
23175377Smckusick		case 'g':
23275377Smckusick			if ((avgfilesize = atoi(optarg)) <= 0)
23395357Sphk				errx(1, "%s: bad average file size", optarg);
23475377Smckusick			break;
23575377Smckusick		case 'h':
23675377Smckusick			if ((avgfilesperdir = atoi(optarg)) <= 0)
23798542Smckusick			       errx(1, "%s: bad average files per dir", optarg);
23875377Smckusick			break;
2391558Srgrimes		case 'i':
2401558Srgrimes			if ((density = atoi(optarg)) <= 0)
24195357Sphk				errx(1, "%s: bad bytes per inode", optarg);
2421558Srgrimes			break;
243126254Srwatson		case 'l':
244126254Srwatson			lflag = 1;
245126254Srwatson			break;
2461558Srgrimes		case 'm':
2471558Srgrimes			if ((minfree = atoi(optarg)) < 0 || minfree > 99)
24895357Sphk				errx(1, "%s: bad free space %%", optarg);
2491558Srgrimes			break;
2501558Srgrimes		case 'o':
25177420Sphk			if (strcmp(optarg, "space") == 0)
25277420Sphk				opt = FS_OPTSPACE;
25377420Sphk			else if (strcmp(optarg, "time") == 0)
25477420Sphk				opt = FS_OPTTIME;
25577420Sphk			else
25695357Sphk				errx(1,
25792533Sbde		"%s: unknown optimization preference: use `space' or `time'",
25892533Sbde				    optarg);
2591558Srgrimes			break;
2601558Srgrimes		case 's':
2611558Srgrimes			if ((fssize = atoi(optarg)) <= 0)
262102231Strhodes				errx(1, "%s: bad file system size", optarg);
2631558Srgrimes			break;
2641558Srgrimes		case '?':
2651558Srgrimes		default:
2661558Srgrimes			usage();
2671558Srgrimes		}
2681558Srgrimes	argc -= optind;
2691558Srgrimes	argv += optind;
2701558Srgrimes
27195357Sphk	if (argc != 1)
2721558Srgrimes		usage();
2731558Srgrimes
2741558Srgrimes	special = argv[0];
27523682Speter	cp = strrchr(special, '/');
2761558Srgrimes	if (cp == 0) {
2771558Srgrimes		/*
27892533Sbde		 * No path prefix; try prefixing _PATH_DEV.
2791558Srgrimes		 */
28092533Sbde		snprintf(device, sizeof(device), "%s%s", _PATH_DEV, special);
2811558Srgrimes		special = device;
2821558Srgrimes	}
2831558Srgrimes
284110671Sjmallett	if (ufs_disk_fillout_blank(&disk, special) == -1 ||
285110671Sjmallett	    (!Nflag && ufs_disk_write(&disk) == -1)) {
286110671Sjmallett		if (disk.d_error != NULL)
287110671Sjmallett			errx(1, "%s: %s", special, disk.d_error);
288110671Sjmallett		else
289110671Sjmallett			err(1, "%s", special);
290110671Sjmallett	}
291110671Sjmallett	if (fstat(disk.d_fd, &st) < 0)
29295357Sphk		err(1, "%s", special);
29395357Sphk	if ((st.st_mode & S_IFMT) != S_IFCHR)
29495357Sphk		errx(1, "%s: not a character-special device", special);
2951558Srgrimes
296110671Sjmallett	if (sectorsize == 0)
297110671Sjmallett		ioctl(disk.d_fd, DIOCGSECTORSIZE, &sectorsize);
298110671Sjmallett	if (sectorsize && !ioctl(disk.d_fd, DIOCGMEDIASIZE, &mediasize)) {
29995357Sphk		if (fssize == 0)
30095357Sphk			fssize = mediasize / sectorsize;
30195357Sphk		else if (fssize > mediasize / sectorsize)
302102231Strhodes			errx(1, "%s: maximum file system size is %u",
30395357Sphk			    special, (u_int)(mediasize / sectorsize));
3041558Srgrimes	}
30595357Sphk	pp = NULL;
30695357Sphk	lp = getdisklabel(special);
30795357Sphk	if (lp != NULL) {
30895357Sphk		cp = strchr(special, '\0');
30995357Sphk		cp--;
31095360Sphk		if ((*cp < 'a' || *cp > 'h') && !isdigit(*cp))
311102231Strhodes			errx(1, "%s: can't figure out file system partition",
31295357Sphk			    special);
31395360Sphk		if (isdigit(*cp))
31495360Sphk			pp = &lp->d_partitions[RAW_PART];
31595357Sphk		else
31695357Sphk			pp = &lp->d_partitions[*cp - 'a'];
31795357Sphk		oldpartition = *pp;
31895357Sphk		if (pp->p_size == 0)
31995357Sphk			errx(1, "%s: `%c' partition is unavailable",
32095357Sphk			    special, *cp);
32195357Sphk		if (pp->p_fstype == FS_BOOT)
32295357Sphk			errx(1, "%s: `%c' partition overlaps boot program",
32395357Sphk			    special, *cp);
32495357Sphk		if (fssize == 0)
32595357Sphk			fssize = pp->p_size;
32695357Sphk		if (fssize > pp->p_size)
32795357Sphk			errx(1,
328102231Strhodes		    "%s: maximum file system size %d", special, pp->p_size);
32995357Sphk		if (sectorsize == 0)
33095357Sphk			sectorsize = lp->d_secsize;
33195357Sphk		if (fsize == 0)
33295357Sphk			fsize = pp->p_fsize;
33395357Sphk		if (bsize == 0)
33495357Sphk			bsize = pp->p_frag * pp->p_fsize;
3351558Srgrimes	}
33695357Sphk	if (sectorsize <= 0)
33795357Sphk		errx(1, "%s: no default sector size", special);
33895357Sphk	if (fsize <= 0)
33995357Sphk		fsize = MAX(DFL_FRAGSIZE, sectorsize);
34095357Sphk	if (bsize <= 0)
34195357Sphk		bsize = MIN(DFL_BLKSIZE, 8 * fsize);
34298542Smckusick	if (maxbsize == 0)
34398542Smckusick		maxbsize = bsize;
3441558Srgrimes	/*
3451558Srgrimes	 * Maxcontig sets the default for the maximum number of blocks
346102231Strhodes	 * that may be allocated sequentially. With file system clustering
3471558Srgrimes	 * it is possible to allocate contiguous blocks up to the maximum
3481558Srgrimes	 * transfer size permitted by the controller or buffering.
3491558Srgrimes	 */
3501558Srgrimes	if (maxcontig == 0)
35198542Smckusick		maxcontig = MAX(1, MAXPHYS / bsize);
3521558Srgrimes	if (density == 0)
3531558Srgrimes		density = NFPI * fsize;
3541558Srgrimes	if (minfree < MINFREE && opt != FS_OPTSPACE) {
3551558Srgrimes		fprintf(stderr, "Warning: changing optimization to space ");
3561558Srgrimes		fprintf(stderr, "because minfree is less than %d%%\n", MINFREE);
3571558Srgrimes		opt = FS_OPTSPACE;
3581558Srgrimes	}
3591558Srgrimes	if (maxbpg == 0)
3601558Srgrimes		maxbpg = MAXBLKPG(bsize);
3611558Srgrimes	realsectorsize = sectorsize;
3621558Srgrimes	if (sectorsize != DEV_BSIZE) {		/* XXX */
36320061Ssos		int secperblk = sectorsize / DEV_BSIZE;
36420061Ssos
36520061Ssos		sectorsize = DEV_BSIZE;
36620061Ssos		fssize *= secperblk;
367104308Sphk		if (pp != NULL)
36895357Sphk			pp->p_size *= secperblk;
36920061Ssos	}
37095357Sphk	mkfs(pp, special);
37195357Sphk	if (!unlabeled) {
37295357Sphk		if (realsectorsize != DEV_BSIZE)
37398542Smckusick			pp->p_size /= realsectorsize / DEV_BSIZE;
37495357Sphk		if (!Nflag && bcmp(pp, &oldpartition, sizeof(oldpartition)))
37595357Sphk			rewritelabel(special, lp);
37695357Sphk	}
377110671Sjmallett	ufs_disk_close(&disk);
3781558Srgrimes	exit(0);
3791558Srgrimes}
3801558Srgrimes
3811558Srgrimesstruct disklabel *
38295357Sphkgetdisklabel(char *s)
3831558Srgrimes{
3841558Srgrimes	static struct disklabel lab;
38595357Sphk	struct disklabel *lp;
3861558Srgrimes
387110671Sjmallett	if (!ioctl(disk.d_fd, DIOCGDINFO, (char *)&lab))
38895357Sphk		return (&lab);
38995357Sphk	unlabeled++;
39095357Sphk	if (disktype) {
39195357Sphk		lp = getdiskbyname(disktype);
39295357Sphk		if (lp != NULL)
3931558Srgrimes			return (lp);
3941558Srgrimes	}
39595357Sphk	return (NULL);
3961558Srgrimes}
3971558Srgrimes
39877420Sphkvoid
39995357Sphkrewritelabel(char *s, struct disklabel *lp)
40037775Sbde{
40137775Sbde	if (unlabeled)
40237775Sbde		return;
40337775Sbde	lp->d_checksum = 0;
40437775Sbde	lp->d_checksum = dkcksum(lp);
405110671Sjmallett	if (ioctl(disk.d_fd, DIOCWDINFO, (char *)lp) < 0)
406103797Sphk		warn("ioctl (WDINFO): %s: can't rewrite disk label", s);
40737775Sbde}
40837775Sbde
40937664Scharnierstatic void
410110065Sjmallettusage()
4111558Srgrimes{
41277420Sphk	fprintf(stderr,
41377420Sphk	    "usage: %s [ -fsoptions ] special-device%s\n",
41495357Sphk	    getprogname(),
41577420Sphk	    " [device-type]");
4161558Srgrimes	fprintf(stderr, "where fsoptions are:\n");
417110174Sgordon	fprintf(stderr, "\t-L volume label to add to superblock\n");
4181558Srgrimes	fprintf(stderr,
419102231Strhodes	    "\t-N do not create file system, just print out parameters\n");
420102231Strhodes	fprintf(stderr, "\t-O file system format: 1 => UFS1, 2 => UFS2\n");
42192722Sphk	fprintf(stderr, "\t-R regression test, supress random factors\n");
4221558Srgrimes	fprintf(stderr, "\t-S sector size\n");
4231558Srgrimes	fprintf(stderr, "\t-T disktype\n");
42475078Sobrien	fprintf(stderr, "\t-U enable soft updates\n");
4251558Srgrimes	fprintf(stderr, "\t-a maximum contiguous blocks\n");
4261558Srgrimes	fprintf(stderr, "\t-b block size\n");
42798542Smckusick	fprintf(stderr, "\t-c blocks per cylinders group\n");
42898542Smckusick	fprintf(stderr, "\t-d maximum extent size\n");
4291558Srgrimes	fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n");
4301558Srgrimes	fprintf(stderr, "\t-f frag size\n");
43175377Smckusick	fprintf(stderr, "\t-g average file size\n");
43275377Smckusick	fprintf(stderr, "\t-h average files per directory\n");
4331558Srgrimes	fprintf(stderr, "\t-i number of bytes per inode\n");
4341558Srgrimes	fprintf(stderr, "\t-m minimum free space %%\n");
4351558Srgrimes	fprintf(stderr, "\t-o optimization preference (`space' or `time')\n");
43698542Smckusick	fprintf(stderr, "\t-s file systemsize (sectors)\n");
4371558Srgrimes	exit(1);
4381558Srgrimes}
439