|
|
researchv10 Norman
#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);
}
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.