home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Crawly Crypt Collection 2
/
crawlyvol2.bin
/
alt_os
/
mint
/
mfs6011
/
source
/
minit.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-12-30
|
20KB
|
820 lines
/* minit Minix INITializer . Freely distributable Minix filesys creator.
* Copyright S N Henson 1991,1992,1993.
* Use entirely at your own risk ! If it trashes your hard-drive then
* it isn't my fault !
*/
/* Version 0.27 */
#include <mintbind.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <alloc.h>
#include "minixfs/hdio.h"
#include "minixfs/xhdi.h"
#include "minixfs/pun.h"
#define MNAME_MAX 14
int shift,drive=-1,no_phys;
long numblocks,numinodes,incr=1;
/* various flags */
char protect,sonly,v2,lrecno,tst,no_size;
/* tosfs restore flags */
char restore_tosfs;
struct hdinfo hdinf,hdinf2;
unsigned char block_buf[1024];
/* Structures we will need */
typedef struct {
unsigned short s_ninodes; /* # usable inodes on the minor device */
unsigned short s_nzones; /* total device size, including bit maps etc */
unsigned short s_imap_blks; /* # of blocks used by inode bit map */
unsigned short s_zmap_blks; /* # of blocks used by zone bit map */
unsigned short s_firstdatazn; /* number of first data zone */
short int s_log_zsize; /* log2 of blocks/zone */
unsigned long s_max_size; /* maximum file size on this device */
short s_magic; /* magic number to recognize super-blocks */
short pad; /* padding */
long s_zones; /* equivalent to 's_nzones' for V2 */
} super_block;
super_block *sblk=(super_block *)block_buf;
/* This structure is used to restore the original TOS filesystem */
struct tfsav {
unsigned char bstart[64]; /* Start of bootsector */
#define SAV_MAGIC 0xcaba1372l
unsigned sav_datrec; /* First data record */
unsigned long sav_magic; /* Contains SAV_MAGIC if info valid */
} *sav_tosfs=(struct tfsav *)(block_buf+256),sav_tmp;
typedef struct { /* directory entry */
unsigned short d_inum; /* inode number */
char d_name[MNAME_MAX]; /* character string */
} dir_struct;
typedef struct { /* disk inode. */
unsigned short i_mode; /* file type, protection, etc. */
unsigned short i_uid; /* user id of the file's owner */
unsigned long i_size; /* current file size in bytes */
unsigned long i_mtime; /* when was file data last changed */
unsigned char i_gid; /* group number */
unsigned char i_nlinks; /* how many links to this file */
unsigned short i_zone[9]; /* block nums for direct, ind, and dbl ind */
} d_inode;
typedef struct {
unsigned short i_mode;
unsigned short i_nlinks;
unsigned short i_uid;
unsigned short i_gid;
unsigned long i_size;
unsigned long i_atime;
unsigned long i_mtime;
unsigned long i_ctime;
long i_zone[10];
} d_inode2;
_BPB *bpb;
/* prototypes */
#ifdef __STDC__
# define P(s) s
#else
# define P(s) ()
#endif
/* Useful macro: DIV, divide a by b rounded up to nearest integer */
#define DIV(a,b) ((a+b-1)/b)
void main P((int argc , char **argv ));
int nrwabs P((int rw , void *buf , unsigned count , long recno , int drive ));
void get_block P((long num ));
void put_block P((long num ));
void check_lrecno P((void ));
void warn P((void ));
void make_tosfs P((void ));
#undef P
void main(argc,argv)
int argc;
char **argv;
{
extern int optind,opterr;
extern char *optarg;
extern int __mint;
long hderr;
int c ;
static char err=0;
int i,j;
unsigned short ioff,zone1;
super_block csblk;
d_inode *rip=(d_inode *)block_buf;
d_inode2 *ripn=(d_inode2 *)block_buf;
dir_struct *dir=(dir_struct *)block_buf;
unsigned short *srt=(unsigned short *)block_buf;
long icount, zcount;
struct
{
long start;
long finish;
char shadow;
char scsiz;
} pp;
if(__mint==0)
{
fprintf(stderr,"Error: MiNT not active.\n");
exit(1);
}
/* Parse command-line options */
opterr=0;
while((c=getopt(argc,argv,"b:B:i:I:n:pPSZztVeRr"))!=EOF)
{
switch(c){
case 'B':
case 'b':
numblocks=atol(optarg);
break;
case 'n':
incr=atol(optarg);
break;
case 'i':
case 'I':
numinodes=atol(optarg);
break;
case 'P':
protect=1;
break;
case 'p':
protect=2;
break;
case 'S':
sonly=1;
break;
case 'Z':
protect=1;
break;
case 'z':
protect=2;
break;
case 'V':
v2=1;
break;
case 't':
tst=1;
break;
case 'e':
no_size=1;
break;
case 'R':
case 'r':
restore_tosfs=1;
break;
case '?':
err=1;
break;
}
}
if(argc-optind!=1 || err)
{
fprintf(stderr,"Minix-compatible filesystem initializer\n");
fprintf(stderr,"Copyright S N Henson 1991,1992,1993,1994\n");
fprintf(stderr,"Version 0.27\n");
fprintf(stderr,"Usage\t(auto)\t: minit drive\n");
fprintf(stderr,"\t(manual): minit -b blocks -i inodes drive\n");
fprintf(stderr,"Also :\t-S only write out super-block\n");
fprintf(stderr,"\t-P/-Z protect filesystem with null disk\n");
fprintf(stderr,"\t-p/-z make null disk of existing filestystem\n");
fprintf(stderr,"\t-V make a V2 filesystem\n");
fprintf(stderr,"\t-n dirincrement\n");
fprintf(stderr,"\t-t test mode (no writing)\n");
fprintf(stderr,"\t-e find size by reading past partition end\n");
fprintf(stderr,"\t-r restore a tos filesystem to partition\n");
exit(1);
}
drive=(argv[optind][0] & ~32)-'A' ;
bpb=Getbpb(drive);
if(restore_tosfs) make_tosfs();
if(tst)
{
if(bpb)
{
printf("Sector size %d\n",bpb->recsiz);
printf("Cluster size in sectors: %d\n",bpb->clsiz);
printf("Cluster size in bytes: %d\n",bpb->clsizb);
printf("Root dir length %d\n",bpb->rdlen);
printf("Fat size %d\n",bpb->fsiz);
printf("Second Fat start %d\n",bpb->fatrec);
printf("First data record %d\n",bpb->datrec);
printf("Flags %d\n",bpb->bflags);
printf("Total Clusters %d\n",bpb->numcl);
}
else printf("Invalid BPB\n");
}
/* Sanity checking time */
if((incr < 1) || (incr > 16) || ( (incr) & (incr-1) ) )
{
fprintf(stderr,"Dirincrement must be a power of two between\n");
fprintf(stderr,"1 and 16 (inclusive)\n");
exit(1);
}
if( (numinodes < 0) || (numinodes > 65535) )
{
fprintf(stderr,"Need at least 1 and no more than 65535 inodes\n");
exit(1);
}
if(protect==2 && bpb->recsiz!=512)
{
fprintf(stderr,"Sorry can't add protection to this filesytem.\n");
fprintf(stderr,"Sector size not 512 bytes.\n");
exit(1);
}
/* Test for physical partition */
if(!Dcntl(0x109,argv[optind],&pp) && pp.start!=-1)
{
long tstack;
hdinf.start=pp.start;
hdinf.size=pp.finish-hdinf.start+1;
hdinf.scsiz=pp.scsiz;
hdinf.major = pp.shadow;
hdinf.drive = drive;
tstack=Super(0l);
if(init_icd()==2)
{
Super(tstack);
fprintf(stderr,"Can't kludge ICD bug\n");
exit(1);
}
Super(tstack);
hdinf.rwmode = RW_PHYS;
if(hdinf.start > 0xfffe)
{
if(no_plrecno(hdinf.major))
fprintf(stderr,"Cannot access Drive %c:\n",drive+'A');
hdinf.rwmode |= RW_LRECNO;
}
}
else
{
pp.start=-1;
if( (hderr=get_hddinf(drive,&hdinf,0)) )
{
fprintf(stderr,"Cannot access Drive %c: %s\n",drive+'A',
hdd_err[hderr]);
exit(1);
}
}
if(tst)
{
unsigned int llrecno,xhret;
no_phys=0;
if(pp.start==-1)
{
llrecno=no_lrecno(drive);
if(llrecno && llrecno!=3)
fprintf(stderr,"Logical lrecno error\n");
else fprintf(stderr,"Logical lrecno OK\n");
}
else
{
fprintf(stderr,"Physical Partition\n");
hdinf2=hdinf;
}
if( (no_phys=get_hddinf(drive,&hdinf2,1) ) )
fprintf(stderr,"Can't get physical drive info: %s\n",hdd_err[no_phys]);
else if( (hdinf2.rwmode & RW_MODE) != RW_XHDI )
{
llrecno=no_plrecno(hdinf2.major);
if(llrecno && llrecno!=3)
fprintf(stderr,"Physical lrecno error\n");
else fprintf(stderr,"Physical lrecno OK\n");
}
if( (xhret=XHGetVersion()) ) fprintf(stderr,"XHDI supported"
" version %x.%02x\n", xhret>>8,xhret & 0xff);
else fprintf(stderr,"XHDI not supported\n");
if(!no_phys)
{
fprintf(stderr,"Partition start: %ld\n",hdinf2.start);
if(hdinf2.size)
fprintf(stderr,"Partition size: %ld\n",hdinf2.size);
if( (hdinf2.rwmode & RW_MODE) == RW_PHYS)
{
unsigned ddev;
char *sbus;
ddev=hdinf2.minor;
fprintf(stderr,"Unit number %d\n",ddev);
if( ddev & PUN_IDE) sbus="IDE";
else
{
if( ddev & PUN_SCSI) sbus="SCSI";
else sbus="ACSI";
}
fprintf(stderr,"%s bus: device %d.(",sbus,
ddev & PUN_UNIT);
if(ddev & PUN_REMOVABLE) fprintf(stderr,"Removable)\n");
else fprintf(stderr,"Non-removable)\n");
}
else fprintf(stderr,"Major number %d Minor number %d\n",
hdinf2.major,hdinf2.minor);
}
}
if(!numblocks) numblocks=hdinf.size>>hdinf.scsiz;
else if(hdinf.size && (numblocks > hdinf.size>>hdinf.scsiz))
{
fprintf(stderr,"Partition has only %ld blocks\n",
hdinf.size>>hdinf.scsiz);
exit(1);
}
if(!numblocks && no_size)
{
if( ( hderr=get_size(drive,&numblocks) ) )
fprintf(stderr,"get_size Warning: %s\n",size_err[hderr]);
}
/* read in boot sector */
get_block(0);
/* Fill in TOS save info */
bcopy(block_buf,sav_tmp.bstart,64l);
sav_tmp.sav_magic=SAV_MAGIC;
if(bpb) sav_tmp.sav_datrec=bpb->datrec;
else sav_tmp.sav_datrec=0;
/* If size of partition not known try BPB/boot sector */
if(!numblocks)
{
if(!bpb || (bpb->recsiz & 511))
{
fprintf(stderr,"Can't figure out partition size: "
"try the -b option\n");
exit(1);
}
numblocks=( (block_buf[19]+( ((long)block_buf[20])<<8))*
bpb->recsiz)>>10;
if(numblocks < 40 )
{
fprintf(stderr,"%ld blocks ? Is that bootsector OK ?\n",numblocks);
exit(1);
}
}
if(!v2 && (numblocks > 65535) )
{
fprintf(stderr,"V1 filesystems can be at most 65535 blocks\n");
exit(1);
}
if( (hderr=set_lrecno(&hdinf,numblocks)) )
{
fprintf(stderr,"Can't access partition: %s\n",hdd_err[hderr]);
exit(1);
}
if(tst)
{
fprintf(stderr,"\nHard disk access information:\nAccess mode: ");
switch(hdinf.rwmode & RW_MODE)
{
case RW_NORMAL:
fprintf(stderr,"Normal mode\n");
break;
case RW_XHDI:
fprintf(stderr,"XHDI mode\n");
break;
case RW_PHYS:
fprintf(stderr,"Physical mode\n");
break;
}
if(hdinf.rwmode & RW_LRECNO)
fprintf(stderr,"Lrecno access\n\n");
else fprintf(stderr,"Non lrecno access\n\n");
}
/* Special test to check PHYS mode is OK:
* read in block 0 with Rwabs and our routines. If they are
* different then signal error and halt.
*/
if( ( ( (hdinf.rwmode & RW_MODE) == RW_PHYS ) || ( tst && !no_phys ) )
&& bpb )
{
char *tmp1,*tmp2;
tmp1=malloc(1024);
tmp2=malloc(bpb->recsiz);
if(!tmp1 || !tmp2)
{
fprintf(stderr,"Memory allocation error\n");
exit(1);
}
if( Rwabs(2,tmp2,1,0,hdinf.drive) )
{
fprintf(stderr,"Rwabs failure\n");
exit(1);
}
if(tst) block_rwabs(2,tmp1,1,0,&hdinf2);
else block_rwabs(2,tmp1,1,0,&hdinf);
if( bcmp(tmp1,tmp2,512) )
{
fprintf(stderr,"Physical Comparison error!\n");
if(!tst) exit(1);
}
else if(tst) fprintf(stderr,"Physical Comparison OK\n");
free(tmp1);
free(tmp2);
}
if(numinodes==0)
{
numinodes = numblocks/3;
/* Round up inode number to nearest block */
if(v2) numinodes = (numinodes + 15) & ~15;
else numinodes=(numinodes + 31 ) & ~31;
}
if(numinodes > 65535) numinodes = 65535;
if(protect==2)
{
get_block(1);
if( sblk->s_magic!=0x137f && sblk->s_magic!=0x2468
&& sblk->s_magic!=0x138f)
{
fprintf(stderr,"Fatal: bad magic number\n");
exit(1);
}
}
if(!tst) warn();
/* OK lets work out some stuff */
if(protect==2) get_block(1);
else
{
bzero(block_buf,1024l);
/* Super block */
sblk->s_ninodes=numinodes;
if(v2) sblk->s_zones=numblocks;
else sblk->s_nzones=numblocks;
sblk->s_imap_blks=(numinodes+8192)/8192;
sblk->s_zmap_blks=(numblocks+8191)/8192;
sblk->s_firstdatazn=2+sblk->s_imap_blks+sblk->s_zmap_blks
+ ( v2 ? ((numinodes+15)/16) : ((numinodes+31)/32)) ;
sblk->s_log_zsize=0;
sblk->s_max_size= v2 ? 0x7fffffffl : 0x10081c00l;
if(v2) sblk->s_magic=0x2468;
else
{
if(incr==2) sblk->s_magic=0x138f;
else sblk->s_magic=0x137f;
}
}
/* If we have a valid sav_tosfs structure in the superblock leave
* it there. Otherwise copy our structure across.
*/
if(sav_tosfs->sav_magic!=SAV_MAGIC) *sav_tosfs=sav_tmp;
/* If sector size 512 bytes handle protection now */
if(protect)
{
unsigned pseudo_root,root_entries;
/* 512 bytes pseudo root after super block */
if(bpb->recsiz==512)
{
bzero(&block_buf[512],512);
for(i=512;i<1024;i+=32)
{
strncpy(block_buf+i,"MINIXFS ",11);
block_buf[i+11]=0x08;
}
put_block(1);
csblk=*sblk;
pseudo_root=3;
}
else
/* Not 512 bytes: insert pseudo root after inodes but
* before first data zone.
*/
{
unsigned secblocks; /* blocks per log. sector */
secblocks = bpb->recsiz/1024;
/* Round up first data zone to sector boundary + 1 */
sblk->s_firstdatazn += 2*secblocks - 1;
sblk->s_firstdatazn /= secblocks;
sblk->s_firstdatazn *= secblocks;
put_block(1);
pseudo_root = sblk->s_firstdatazn / secblocks - 1;
csblk=*sblk;
/* Pseudo root directory : whole block */
for(i=0;i<1024;i+=32)
{
strncpy((char *)(block_buf+i),"MINIXFS ",11);
block_buf[i+11]=0x8;
}
/* Write them all out */
for(i = - secblocks ; i < 0 ;i++)
put_block(csblk.s_firstdatazn+i);
}
/* Set up boot sector to point to pseudo root */
get_block(0);
strcpy((char *)(block_buf+2),"MINIX");
block_buf[16] = 2; /* 2 FAT's */
root_entries = bpb->recsiz/32; /* Root directory: 1 sector */
block_buf[17] = root_entries & 0xff;
block_buf[18] = root_entries >> 8;
block_buf[22] = 1; /* FAT = 1 sector */
block_buf[23] = 0;
pseudo_root-=2;
block_buf[14] = pseudo_root & 0xff;
block_buf[15] = pseudo_root >> 8;
put_block(0);
}
else
{
put_block(1);
csblk=*sblk;
}
if( sonly || protect==2 ) exit(0);
ioff=2+csblk.s_imap_blks+csblk.s_zmap_blks;
zone1=csblk.s_firstdatazn;
bzero(block_buf,1024l);
/* Inode bitmaps */
icount = numinodes + 1;
for(i=2;i<2+csblk.s_imap_blks;i++)
{
if(i==2)
{
srt[0]=3;
}
if(icount < 8192) /* Need to mark dead inodes as used */
{
if(icount & 15)
{
srt[icount/16] = 0xffff << (icount & 15);
icount+= 16 - (icount & 15);
}
for(j=icount/16;j<512;j++)srt[j]=0xffff;
}
put_block(i);
if(i==2)srt[0]=0;
icount-=8192;
}
bzero(block_buf,1024l);
/* Zone bitmaps */
zcount = numblocks + 1 - csblk.s_firstdatazn;
for(i=2+csblk.s_imap_blks;i<ioff;i++)
{
if(i==2+csblk.s_imap_blks)
{
srt[0]=3;
}
if (zcount < 8192) /* Need to mark dead zones as used */
{
if(zcount < 0) zcount=0;
if(zcount & 15)
{
srt[zcount/16] = 0xffff << (zcount & 15);
zcount+= 16 - (zcount & 15);
}
for(j=zcount/16;j<512;j++)srt[j]=0xffff;
}
put_block(i);
if(i==2+csblk.s_imap_blks)srt[0]=0;
zcount-=8192;
}
bzero(block_buf,1024l);
/* Initialise inodes */
for(i=ioff;i<ioff+
(v2 ? ((numinodes +15)/16) : ((numinodes+31)/32 )) ;i++)
{
if(i==ioff) /* Root inode , initialise it properly */
{
if(v2)
{
ripn->i_mode=040777; /* Directory */
ripn->i_size=32*incr;
ripn->i_mtime=time((time_t *)0);
ripn->i_ctime=ripn->i_mtime;
ripn->i_atime=ripn->i_mtime;
ripn->i_nlinks=2;
ripn->i_zone[0]=zone1;
}
else
{
rip->i_mode=040777; /* Directory */
rip->i_size=32*incr;
rip->i_mtime=time((time_t *)0);
rip->i_nlinks=2;
rip->i_zone[0]=zone1;
}
}
put_block(i);
if(i==ioff)bzero(block_buf,1024l);
}
bzero(block_buf,1024l);
/* And finally the root directory */
dir[0].d_inum=1;
strcpy(dir[0].d_name,".");
dir[incr].d_inum=1;
strcpy(dir[incr].d_name,"..");
put_block(zone1);
if(!tst) fprintf(stderr,"Initialised OK.\n");
fprintf(stderr,"%ld Blocks, %ld Inodes.\n",numblocks,numinodes);
/* Force media change on specified drive */
if(Dlock(1,drive))
fprintf(stderr,"Can't Lock Drive, Reboot to be sure\n");
exit(0);
}
void get_block(num)
long num;
{
long r;
if( (r = block_rwabs(2,block_buf,1,num,&hdinf)) )
{
fprintf(stderr,"Fatal Read Error %ld block %ld\n",r,num);
exit(2);
}
}
void put_block(num)
long num;
{
long r;
if(tst) return;
if( (r = block_rwabs(3,block_buf,1,num,&hdinf)) )
{
fprintf(stderr,"Fatal Write Error %ld block %ld\n",r,num);
exit(2);
}
}
void warn()
{
int ch;
fprintf(stderr,"WARNING ! THIS %s TOTALLY DESTROY ANY DATA ON ",
(sonly || protect==2 ) ? "MAY":"WILL");
fprintf(stderr,"DRIVE %c !\n",drive+'A');
fprintf(stderr,"Are you ABSOLUTELY SURE you want to do this (y/n)?\n");
ch=Crawcin() & 0xff ;
if((ch & ~32) !='Y')
{
fprintf(stderr,"Aborted\n");
exit(0);
}
}
/* Restore a tosfs filesystem. Using the tfsav structure.
*/
void make_tosfs()
{
int hderr,i;
long clear_blk; /* Number of blocks to clear */
char ch;
if( (hderr=get_hddinf(drive,&hdinf,0)) )
{
fprintf(stderr,"Cannot access Drive %c: %s\n",drive+'A',
hdd_err[hderr]);
exit(1);
}
get_block(1);
if(sblk->s_magic!=0x2468 && sblk->s_magic!=0x137f &&
sblk->s_magic!=0x138f )
{
fprintf(stderr,"Can't restore: not a Minixfs filesystem\n");
exit(1);
}
if( sav_tosfs->sav_magic!=SAV_MAGIC )
{
fprintf(stderr,"Can't recreate filesystem: perhaps you made the\
\nfilesystem with an older version of minit?\n");
exit(1);
}
fprintf(stderr,"WARNING: You are about to Restore a TOS filesystem\n");
fprintf(stderr,"on a Minixfs Filesystem. This will TOTALLY DESTROY\n");
fprintf(stderr,"the Minixfs files!\n");
fprintf(stderr,"ARE YOU ABSOLUTELY SURE YOU WANT TO DO THIS ? (y/n)\n");
ch=Crawcin() & 0xff;
if((ch & ~32) != 'Y') exit(0);
sav_tmp=*sav_tosfs;
get_block(0);
bcopy(sav_tmp.bstart,block_buf,64l);
if(sav_tmp.sav_datrec) clear_blk = (sav_tmp.sav_datrec*block_buf[12])/2;
else /* Work out datrec from other parameters */
{
int nphys; /* 512 byte sectors per logical sector */
long dirent; /* root dir logical sectors */
nphys = block_buf[12]/2;
clear_blk = nphys; /* Boot sector */
/* Add the FATs */
clear_blk += nphys*block_buf[16]*
(block_buf[22]+(block_buf[23]<<8));
/* Root dir 512 byte sectors (16 entries per sector) */
dirent = DIV(block_buf[17]+(block_buf[18]<<8),16);
/* Now round up to nearest physical sector */
dirent = DIV(dirent,nphys);
clear_blk += nphys*dirent;
}
/* convert clear_blk to blocks */
clear_blk = DIV(clear_blk,2);
bzero(block_buf+512,512);
put_block(0);
/* Now we zero 2 FATs and root directory */
bzero(block_buf,512);
for(i=1;i < 1+clear_blk; i++) put_block(i);
/* Force disk change */
(void)Dlock(1,drive);
fprintf(stderr,"TOS filesystem recreated: Reboot to be sure\n");
exit(0);
}