V10/cmd/worm/wmkfs.c

Compare this file to the similar file:
Show the results in this format:

#include	<libc.h>
#include	"worm.h"
#include	<sys/types.h>
#include	<sys/udaioc.h>

usage()
{
	fprint(2, "Usage: worm mkfs [-fdevice] [-ccomments] [-bblksize] [-nnblks] [-vnewvol_id] vol_id\n");
	fprint(2, "e.g. worm mkfs -f1 -c\"512x512x24 movies\" tdmovies1a\n");
	exit(1);
}

main(argc, argv)
	char **argv;
{
	Superblock s, os;
	char *b;
	long sb;
	int c;
	char *volid;
	char *dev = "/dev/worm0";
	char *nblks = 0;
	char *bsize = 0;
	char *nvolid = 0;
	char *comments = 0;
	char *e;
	int virgin;
	extern optind;
	extern char *optarg;

	while((c = getopt(argc, argv, "f:n:b:c:v:")) != -1)
		switch(c)
		{
		case 'b':	bsize = optarg; break;
		case 'c':	comments = optarg; break;
		case 'f':	dev = optarg; break;
		case 'n':	nblks = optarg; break;
		case 'v':	nvolid = optarg; break;
		case '?':	usage();
		}
	if(optind != argc-1)
		usage();
	volid = argv[optind];
	if(strlen(volid) > sizeof(s.vol_id)-1)
		volid[sizeof(s.vol_id)-1] = 0;
	c = volid[strlen(volid)-1];
	if((c != 'a') && (c != 'b')){
		if(nvolid == 0){
			fprint(2, "worm mkfs: vol_id '%s' must end in 'a' or 'b'\n", volid);
			exit(1);
		}
		fprint(2, "worm mkfs: warning: vol_id '%s' should end in 'a' or 'b'\n", volid);
	}
	if(nvolid){
		if(strlen(nvolid) > sizeof(s.vol_id)-1)
			nvolid[sizeof(s.vol_id)-1] = 0;
		c = nvolid[strlen(nvolid)-1];
		if((c != 'a') && (c != 'b')){
			fprint(2, "worm mkfs: vol_id '%s' must end in 'a' or 'b'\n", nvolid);
			exit(1);
		}
	}
	dev = mapdev(dev);
	if((s.fd = open(dev, 2)) < 0){
		perror(dev);
		exit(1);
	}
	/*
		now, do we read the current superblock or make one up?
		this is hard to answer in general, push the answer off to virginal()
	*/
	virgin = virginal(&s);
	if(virgin){
		setdefaults(&s, nblks);
		if((s.blocksize < 512) || (s.blocksize%512)){
			fprint(2, "worm mkfs: bad blocksize '%s'\n", bsize);
			exit(1);
		}
		strcpy(s.vol_id, volid);
	} else {
		if(strcmp(volid, s.vol_id)){
			fprint(2, "worm mkfs: volid mismatch; expected %s, got %s\n",
				volid, s.vol_id);
			exit(1);
		}
	}
	/* set any new parameters */
	if(nvolid)
		strcpy(s.vol_id, nvolid);
	if(bsize)
		s.blocksize = atoi(bsize);
	if(s.blocksize < 512){
		fprint(2, "wormmkfs: bad nblocks = '%s'\n", nblks);
		exit(1);
	}
	if(s.blocksize % sizeof(Inode)){
		fprint(2, "worm mkfs: sizeof(Inode)=%d does not divide blocksize %d\n",
			sizeof(Inode), s.blocksize);
		exit(1);
	}
	if(comments){
		if(strlen(comments) > sizeof(s.comment)-1)
			comments[sizeof(s.comment)-1] = 0;
		strcpy(s.comment, comments);
	}
	/* only check if we are changing it */
	if(nblks && !virgin){
		s.nblocks = atoi(nblks);
		s.nfree = s.nblocks - s.nextffree;
		if(s.nfree <= 1){
			fprint(2, "worm mkfs: new nblocks(%d) is too small\n", s.nblocks);
			exit(1);
		}
	}
	/* now allocate the new superblock */
	sb = s.nextsb;
	s.myblock = sb;
	s.nextsb = sb+1;
	s.nextffree = sb+2;
	s.nfree -= 1;
	s.ninodes = 0;
	s.ninochars = 0;
	s.binodes = 0;
	time(&s.ctime);
	/* write it */
	if((b = malloc(s.blocksize)) == 0){
		fprint(2, "worm mkfs: cannot malloc buffer %d bytes\n", s.blocksize);
		exit(1);
	}
	memset(b, 0, s.blocksize);
	memcpy(b, (char *)&s, sizeof(s));
	Seek(&s, sb);
	if(Write(&s, b, 1L))
		exit(1);
	ioctl(s.fd, UIOSPDW);
	exit(0);
}

setdefaults(s, nblks)
	Superblock *s;
	char *nblks;
{
	struct ud_unit sz;
	char buf[1024];

	s->magic = SMAGIC;
	s->blocksize = 1024;
	s->version = VLINK;
	if(nblks){
		s->nblocks = atoi(nblks);
		if(s->nblocks <= 2){
			fprint(2, "worm mkfs: nblocks(%d) too small\n", s->nblocks);
			exit(1);
		}
	} else {
		read(s->fd, buf, sizeof buf);	/* ignore error */
		if(ioctl(s->fd, UIOCHAR, &sz) >= 0){
			switch(sz.radsize)
			{		/* note below figures/2 used in scsi/volid.c */
			case 3275999:		/* sony 12in clv single density */
				s->nblocks = 1600000;
				break;
			case 6551999:		/* sony 12in clv double density */
				s->nblocks = 3250000;
				break;
			default:
				fprint(2, "worm mkfs: unknown size %d\n", sz.radsize);
				exit(1);
			}
		} else
			s->nblocks = 1600000;
		fprint(2, "worm mkfs: using disk size %d\n", s->nblocks);
	}
	s->zero = 0;
	s->nfree = s->nblocks-1;
	s->nextffree = 0;
	s->nextsb = 1;
	s->vol_id[0] = 0;
	s->comment[0] = 0;
	s->myblock = 0;
	s->ctime = 0;
}

virginal(s)
	Superblock *s;
{
	char buf[1024];
	static char zeros[1024];
	long sb;
	char *e;
	extern char *getenv();

	if(e = getenv("WORMZERO"))
		sb = atoi(e);
	else
		sb = 1;
	bigseek(s->fd, sb, 1024, 0);
	errno = 0;
	if(read(s->fd, buf, 1024) == 1024)
		goto valid;
	if((errno != ENXIO) && (errno != 0) && memcmp(buf, zeros, 1024))
		goto invalid;
	errno = 0;
	if(read(s->fd, buf, 1024) == 1024){	/* try next block */
valid:
		if(e = openinode(s, SPIN_DOWN)){
			fprint(2, "worm mkfs: %s\n", e);
			exit(1);
		}
		return(0);
	} else {
		if((errno == ENXIO) || (errno == 0) || (memcmp(buf, zeros, 1024) == 0))
			return(1);
invalid:
		perror("worm mkfs: I/O errors probing for superblock");
		exit(1);
	}
}