/* minit Minix INITializer . Freely distributable Minix filesys creator. * Copyright S N Henson Nov 1991 . * Use entirely at your own risk ! If it trashes your hard-drive then * it isn't my fault ! */ /* Version 0.211 */ /* Compile with gcc -O -o minit.ttp minit.c -liio */ #include #include #include #include #include #include /* New extended Rwabs function , same as Rwabs except sectors can * be specified as longs , this will be needed for large V2 filesystems. * you will need to change this for other compilers .... */ #define _XRwabs(a,b,c,d,e,f) \ trap_13_wwlwwwl((short)(0x04),(short)(a),(long)(b),(short)(c),(short)(d)\ ,(short)(e),(long)(f) ) #define trap_13_wwlwwwl(n, a, b, c, d, e, f) \ ({ \ register long retvalue __asm__("d0"); \ volatile short _a = (volatile short)(a); \ volatile long _b = (volatile long) (b); \ volatile short _c = (volatile short)(c); \ volatile short _d = (volatile short)(d); \ volatile short _e = (volatile short)(e); \ volatile long _f = (volatile long) (f); \ \ __asm__ volatile \ ("\ movl %5,sp@-; \ movw %4,sp@-; \ movw %3,sp@-; \ movw %2,sp@-; \ movl %1,sp@-; \ movw %0,sp@- " \ : /* outputs */ \ : "g"(_a), "g"(_b), "g"(_c), "g"(_d), "g"(_e), "g"(_f) /* inputs */ \ ); \ \ __asm__ volatile \ ("\ movw %1,sp@-; \ trap #13; \ addw #18,sp " \ : "=r"(retvalue) /* outputs */ \ : "g"(n) /* inputs */ \ : "d0", "d1", "d2", "a0", "a1", "a2" /* clobbered regs */ \ ); \ retvalue; \ }) /* Change this if needed , but only if you know what you are doing */ /* You shouldn't need to with the -n option though */ #define MNAME_MAX 14 int shift,drive=-1; long numblocks,numinodes,incr=1; /* various flags */ char protect,sonly,zbpb,v2,lrecno,tst; 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; 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; /* prototypes */ #ifdef __STDC__ # define P(s) s #else # define P(s) () #endif int 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 )); int warn P((void )); #undef P main(argc,argv) int argc; char **argv; { extern int optind,opterr; extern char *optarg; int c ; static char err=0; int i,j; unsigned short *bpb; unsigned short ioff,zone1; super_block *sblk=(super_block *)block_buf,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; /* Parse command-line options */ opterr=0; while((c=getopt(argc,argv,"b:B:i:I:n:pPSZtV"))!=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': zbpb=1; break; case 'V': v2=1; break; case 't': tst=1; break; case '?': err=1; break; } } if(argc-optind!=1 || err || (zbpb && protect) ) { fprintf(stderr,"Minix-compatible filesystem initializer\n"); fprintf(stderr,"Copyright S N Henson Nov 1991\n"); fprintf(stderr,"Version 0.211\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 protect filesystem with null disk\n"); fprintf(stderr,"\t-p make null disk of existing filestystem\n"); fprintf(stderr,"\t-Z protect with zero BPB\n"); fprintf(stderr,"\t-V make a V2 filesystem\n"); fprintf(stderr,"\t-n dirincrement\n"); fprintf(stderr,"\t-t test for lrecno in driver software\n"); exit(1); } drive=(argv[optind][0] & ~32)-'A' ; /* 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(!(bpb=Getbpb(drive))) { fprintf(stderr,"Drive %c : Bad or illegal BPB\n",drive+'A'); exit(1); } if(bpb[0]!=512 && bpb[0]!=1024) { fprintf(stderr,"Sorry unsupported sector size: %d\n",bpb[0]); exit(1); } if(bpb[0]==512)shift=1; else if(protect) { fprintf(stderr,"Null disk requires 512 byte sectors\n"); exit(1); } if(drive > 1 ) check_lrecno(); if(tst) { if(lrecno) fprintf(stderr,"Lrecno supported by this setup\n"); else fprintf(stderr,"Lrecno not supported by this setup\n"); exit(0); } /* Work out parameters */ get_block(0); /* Read in boot sector */ /* Get filesys size from bootsector if not given */ if(numblocks==0) { numblocks=(block_buf[19]+( ((long)block_buf[20])<<8))>>shift; 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( !lrecno && (numblocks > 65535) ) { fprintf(stderr,"Filesystems bigger than 64MEG require lrecno\n"); exit(1); } if( !lrecno && shift && (numblocks > 32767) ) { fprintf(stderr,"Filesytems bigger than 32MEG require 1K sectors\n"); exit(1); } get_block(numblocks-1); /* Try to read last block */ 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) ) { fprintf(stderr,"Fatal: bad magic number\n"); exit(1); } } warn(); /* Set up boot sector */ if(!sonly && (protect || zbpb) ) { get_block(0); if(protect) { /* Make GEMDOS think we have a tiny partition */ /* With root directory immediately after super-block */ block_buf[16]=2; block_buf[17]=16; block_buf[18]=0; block_buf[22]=1; block_buf[23]=0; } else if(zbpb) { block_buf[16]=block_buf[17]=block_buf[18]=0; block_buf[22]=block_buf[23]=0; } strcpy((char *)(&block_buf[2]),"MINIX"); put_block(0); } /* 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 ? 0x4041c00l : 0x10081c00l; sblk->s_magic= v2 ? 0x2468 : 0x137f; } /* If protecting fill up the pseudo root directory with vol names */ if(protect) { bzero(&block_buf[512],512); for(i=512;i<1024;i+=32) { strncpy((char*)&block_buf[i],"MINIXFS ",11); block_buf[i+11]=0x08; } } put_block(1); if( sonly || protect==2 ) exit(0); csblk=*sblk; ioff=2+sblk->s_imap_blks+sblk->s_zmap_blks; zone1=sblk->s_firstdatazn; bzero(block_buf,1024l); /* Inode bitmaps */ for(i=2;i<2+csblk.s_imap_blks;i++) { long icount=numinodes+1; 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 */ for(i=2+csblk.s_imap_blks;ii_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); fprintf(stderr,"Initialised OK.\n"); fprintf(stderr,"%ld Blocks , %ld Inodes.\n",numblocks,numinodes); exit(0); } int nrwabs(rw,buf,count,recno,dev) int rw; void *buf; unsigned count; long recno; int dev; { if(lrecno && (dev > 1) ) return (_XRwabs(rw,buf,count,-1,dev,recno) ); else return (Rwabs(rw,buf,count,(unsigned)(recno),dev) ); } void get_block(num) long num; { if(nrwabs(2,block_buf,1<