home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / alt_os / mint / mfs6011 / source / minit.c < prev    next >
C/C++ Source or Header  |  1994-12-30  |  20KB  |  820 lines

  1. /* minit Minix INITializer . Freely distributable Minix filesys creator.
  2.  * Copyright S N Henson 1991,1992,1993.
  3.  * Use entirely at your own risk ! If it trashes your hard-drive then
  4.  * it isn't my fault ! 
  5.  */
  6.  
  7. /* Version 0.27 */
  8.  
  9.  
  10. #include <mintbind.h>
  11. #include <stdio.h>
  12. #include <time.h>
  13. #include <string.h>
  14. #include <unistd.h>
  15. #include <stdlib.h>
  16. #include <alloc.h>
  17.  
  18. #include "minixfs/hdio.h"
  19. #include "minixfs/xhdi.h"
  20. #include "minixfs/pun.h"
  21.  
  22. #define MNAME_MAX 14
  23.  
  24. int shift,drive=-1,no_phys;
  25. long numblocks,numinodes,incr=1;
  26.  
  27. /* various flags */
  28. char protect,sonly,v2,lrecno,tst,no_size;
  29.  
  30. /* tosfs restore flags */
  31. char restore_tosfs;
  32.  
  33. struct hdinfo hdinf,hdinf2;
  34.  
  35. unsigned char block_buf[1024];
  36.  
  37. /* Structures we will need */
  38.  
  39. typedef struct  {
  40.   unsigned short  s_ninodes;    /* # usable inodes on the minor device */
  41.   unsigned short  s_nzones;    /* total device size, including bit maps etc */
  42.   unsigned short s_imap_blks;    /* # of blocks used by inode bit map */
  43.   unsigned short s_zmap_blks;    /* # of blocks used by zone bit map */
  44.   unsigned short s_firstdatazn;    /* number of first data zone */
  45.   short int s_log_zsize;    /* log2 of blocks/zone */
  46.   unsigned long s_max_size;    /* maximum file size on this device */
  47.   short s_magic;        /* magic number to recognize super-blocks */
  48.   short pad;            /* padding */
  49.   long s_zones;            /* equivalent to 's_nzones' for V2 */
  50. } super_block;
  51.  
  52. super_block *sblk=(super_block *)block_buf;
  53.  
  54. /* This structure is used to restore the original TOS filesystem */
  55.  
  56. struct tfsav {
  57.     unsigned char bstart[64]; /* Start of bootsector */
  58. #define SAV_MAGIC 0xcaba1372l
  59.     unsigned sav_datrec;      /* First data record */
  60.     unsigned long sav_magic;  /* Contains SAV_MAGIC if info valid */
  61. } *sav_tosfs=(struct tfsav *)(block_buf+256),sav_tmp;
  62.  
  63. typedef struct {        /* directory entry */
  64.   unsigned short d_inum;    /* inode number */
  65.   char d_name[MNAME_MAX];        /* character string */
  66. } dir_struct;
  67.  
  68. typedef struct {        /* disk inode. */
  69.   unsigned short i_mode;        /* file type, protection, etc. */
  70.   unsigned short i_uid;            /* user id of the file's owner */
  71.   unsigned long  i_size;        /* current file size in bytes */
  72.   unsigned long  i_mtime;        /* when was file data last changed */
  73.   unsigned char i_gid;            /* group number */
  74.   unsigned char i_nlinks;        /* how many links to this file */
  75.   unsigned short i_zone[9];    /* block nums for direct, ind, and dbl ind */
  76. } d_inode;
  77.  
  78. typedef struct {
  79. unsigned short i_mode;
  80. unsigned short i_nlinks;
  81. unsigned short i_uid;
  82. unsigned short i_gid;
  83. unsigned long i_size;
  84. unsigned long i_atime;
  85. unsigned long i_mtime;
  86. unsigned long i_ctime;
  87. long i_zone[10];
  88. } d_inode2;
  89.  
  90. _BPB *bpb;
  91.  
  92. /* prototypes */
  93.  
  94. #ifdef __STDC__
  95. # define    P(s) s
  96. #else
  97. # define P(s) ()
  98. #endif
  99.  
  100. /* Useful macro: DIV, divide a by b rounded up to nearest integer */
  101. #define DIV(a,b) ((a+b-1)/b)
  102.  
  103. void main P((int argc , char **argv ));
  104. int nrwabs P((int rw , void *buf , unsigned count , long recno , int drive ));
  105. void get_block P((long num ));
  106. void put_block P((long num ));
  107. void check_lrecno P((void ));
  108. void warn P((void ));
  109. void make_tosfs P((void ));
  110.  
  111. #undef P
  112.  
  113. void main(argc,argv)
  114. int argc;
  115. char **argv;
  116. {
  117.     extern int optind,opterr;
  118.     extern char *optarg;
  119.     extern int __mint;
  120.     long hderr;
  121.     int c ;
  122.     static char err=0;
  123.     int i,j;
  124.     unsigned short ioff,zone1;
  125.         super_block csblk;
  126.         d_inode *rip=(d_inode *)block_buf;
  127.     d_inode2 *ripn=(d_inode2 *)block_buf;
  128.         dir_struct *dir=(dir_struct *)block_buf;
  129.     unsigned short *srt=(unsigned short *)block_buf;
  130.     long icount, zcount;
  131.  
  132.     struct
  133.     {
  134.         long start;
  135.         long finish;
  136.         char shadow;
  137.         char scsiz;
  138.     } pp;
  139.  
  140.     if(__mint==0)
  141.     {
  142.         fprintf(stderr,"Error: MiNT not active.\n");
  143.         exit(1);
  144.     }
  145.  
  146.     /* Parse command-line options */
  147.     opterr=0;
  148.     while((c=getopt(argc,argv,"b:B:i:I:n:pPSZztVeRr"))!=EOF)
  149.     {
  150.             switch(c){
  151.  
  152.                 case 'B':
  153.             case 'b':
  154.             numblocks=atol(optarg);
  155.             break;
  156.  
  157.             case 'n':
  158.             incr=atol(optarg);
  159.             break;
  160.  
  161.             case 'i':
  162.             case 'I':
  163.             numinodes=atol(optarg);
  164.             break;
  165.  
  166.             case 'P':
  167.             protect=1;
  168.             break;
  169.  
  170.             case 'p':
  171.             protect=2;
  172.             break;
  173.  
  174.             case 'S':
  175.             sonly=1;
  176.             break;
  177.  
  178.             case 'Z':
  179.             protect=1;
  180.             break;
  181.  
  182.             case 'z':
  183.             protect=2;
  184.             break;
  185.  
  186.             case 'V':
  187.             v2=1;
  188.             break;
  189.  
  190.             case 't':
  191.             tst=1;
  192.             break;
  193.  
  194.             case 'e':
  195.             no_size=1;
  196.             break;            
  197.  
  198.             case 'R':
  199.             case 'r':
  200.             restore_tosfs=1;
  201.             break;
  202.  
  203.             case '?':
  204.             err=1;
  205.             break;
  206.         }
  207.     }
  208.  
  209.     if(argc-optind!=1 || err)
  210.     {
  211.         fprintf(stderr,"Minix-compatible filesystem initializer\n");
  212.         fprintf(stderr,"Copyright S N Henson 1991,1992,1993,1994\n");
  213.         fprintf(stderr,"Version 0.27\n");
  214.         fprintf(stderr,"Usage\t(auto)\t: minit drive\n");
  215.         fprintf(stderr,"\t(manual): minit -b blocks -i inodes drive\n");
  216.         fprintf(stderr,"Also :\t-S only write out super-block\n");
  217.         fprintf(stderr,"\t-P/-Z protect filesystem with null disk\n");
  218.         fprintf(stderr,"\t-p/-z make null disk of existing filestystem\n");
  219.         fprintf(stderr,"\t-V make a V2 filesystem\n");
  220.         fprintf(stderr,"\t-n dirincrement\n");
  221.         fprintf(stderr,"\t-t test mode (no writing)\n");
  222.         fprintf(stderr,"\t-e find size by reading past partition end\n");
  223.         fprintf(stderr,"\t-r restore a tos filesystem to partition\n");
  224.         exit(1);
  225.     }
  226.     drive=(argv[optind][0] & ~32)-'A' ;
  227.  
  228.     bpb=Getbpb(drive);
  229.  
  230.     if(restore_tosfs) make_tosfs();
  231.  
  232.     if(tst)
  233.     {
  234.         if(bpb)
  235.         {
  236.             printf("Sector size %d\n",bpb->recsiz);
  237.             printf("Cluster size in sectors: %d\n",bpb->clsiz);
  238.             printf("Cluster size in bytes: %d\n",bpb->clsizb);
  239.             printf("Root dir length %d\n",bpb->rdlen);
  240.             printf("Fat size %d\n",bpb->fsiz);
  241.             printf("Second Fat start %d\n",bpb->fatrec);
  242.             printf("First data record %d\n",bpb->datrec);
  243.             printf("Flags %d\n",bpb->bflags);
  244.             printf("Total Clusters %d\n",bpb->numcl);
  245.         }
  246.         else printf("Invalid BPB\n");
  247.     }
  248.  
  249.     /* Sanity checking time */
  250.  
  251.     if((incr < 1) || (incr > 16) || ( (incr) & (incr-1) ) )
  252.     {
  253.         fprintf(stderr,"Dirincrement must be a power of two between\n");
  254.         fprintf(stderr,"1 and 16 (inclusive)\n");
  255.         exit(1);
  256.     }
  257.  
  258.     if( (numinodes < 0) || (numinodes > 65535) )
  259.     {
  260.         fprintf(stderr,"Need at least 1 and no more than 65535 inodes\n");
  261.         exit(1);
  262.     }
  263.  
  264.     if(protect==2 && bpb->recsiz!=512)
  265.     {
  266.         fprintf(stderr,"Sorry can't add protection to this filesytem.\n");
  267.         fprintf(stderr,"Sector size not 512 bytes.\n");
  268.         exit(1);
  269.     }
  270.  
  271.     /* Test for physical partition */
  272.     if(!Dcntl(0x109,argv[optind],&pp) && pp.start!=-1) 
  273.     {
  274.         long tstack;
  275.         hdinf.start=pp.start;
  276.         hdinf.size=pp.finish-hdinf.start+1;
  277.         hdinf.scsiz=pp.scsiz;
  278.         hdinf.major = pp.shadow;
  279.         hdinf.drive = drive;
  280.         tstack=Super(0l);
  281.         if(init_icd()==2)
  282.         {
  283.             Super(tstack);
  284.             fprintf(stderr,"Can't kludge ICD bug\n");
  285.             exit(1);
  286.         }
  287.         Super(tstack);
  288.         hdinf.rwmode = RW_PHYS;
  289.         if(hdinf.start > 0xfffe)
  290.         {
  291.             if(no_plrecno(hdinf.major))
  292.             fprintf(stderr,"Cannot access Drive %c:\n",drive+'A');
  293.             hdinf.rwmode |= RW_LRECNO;
  294.         }
  295.     }
  296.     else 
  297.     {
  298.         pp.start=-1;
  299.         if( (hderr=get_hddinf(drive,&hdinf,0)) )
  300.         {
  301.             fprintf(stderr,"Cannot access Drive %c: %s\n",drive+'A',
  302.                                 hdd_err[hderr]);
  303.             exit(1);
  304.         }
  305.     }
  306.     if(tst)
  307.     {
  308.         unsigned int llrecno,xhret;
  309.         no_phys=0;
  310.         if(pp.start==-1)
  311.         {
  312.             llrecno=no_lrecno(drive);
  313.             if(llrecno && llrecno!=3)
  314.                 fprintf(stderr,"Logical lrecno error\n");
  315.             else fprintf(stderr,"Logical lrecno OK\n");
  316.         }
  317.         else
  318.         {
  319.             fprintf(stderr,"Physical Partition\n");
  320.             hdinf2=hdinf;
  321.         }
  322.         if( (no_phys=get_hddinf(drive,&hdinf2,1) ) )
  323.     fprintf(stderr,"Can't get physical drive info: %s\n",hdd_err[no_phys]);
  324.         else if( (hdinf2.rwmode & RW_MODE) != RW_XHDI )
  325.         {
  326.             llrecno=no_plrecno(hdinf2.major);
  327.             if(llrecno && llrecno!=3)
  328.                 fprintf(stderr,"Physical lrecno error\n");
  329.             else fprintf(stderr,"Physical lrecno OK\n");
  330.         }
  331.         if( (xhret=XHGetVersion()) ) fprintf(stderr,"XHDI supported"
  332.                    " version %x.%02x\n", xhret>>8,xhret & 0xff);
  333.  
  334.         else fprintf(stderr,"XHDI not supported\n");
  335.         if(!no_phys)
  336.         {
  337.           fprintf(stderr,"Partition start: %ld\n",hdinf2.start);
  338.           if(hdinf2.size)
  339.             fprintf(stderr,"Partition size: %ld\n",hdinf2.size);
  340.           if( (hdinf2.rwmode & RW_MODE) == RW_PHYS)
  341.           {
  342.             unsigned ddev;
  343.             char *sbus;
  344.             ddev=hdinf2.minor;
  345.             fprintf(stderr,"Unit number %d\n",ddev);
  346.             if( ddev & PUN_IDE) sbus="IDE";
  347.             else
  348.             {
  349.                 if( ddev & PUN_SCSI) sbus="SCSI";
  350.                 else sbus="ACSI";
  351.             }
  352.             fprintf(stderr,"%s bus: device %d.(",sbus,
  353.                                    ddev & PUN_UNIT);
  354.             if(ddev & PUN_REMOVABLE) fprintf(stderr,"Removable)\n");
  355.             else fprintf(stderr,"Non-removable)\n");
  356.           }
  357.           else fprintf(stderr,"Major number %d Minor number %d\n",
  358.                              hdinf2.major,hdinf2.minor);
  359.         }
  360.  
  361.     }
  362.  
  363.     if(!numblocks) numblocks=hdinf.size>>hdinf.scsiz;
  364.     else if(hdinf.size && (numblocks > hdinf.size>>hdinf.scsiz))
  365.     {
  366.         fprintf(stderr,"Partition has only %ld blocks\n",
  367.                                hdinf.size>>hdinf.scsiz);
  368.         exit(1);
  369.     }
  370.  
  371.     if(!numblocks && no_size)
  372.     {
  373.         if( ( hderr=get_size(drive,&numblocks) ) )
  374.             fprintf(stderr,"get_size Warning: %s\n",size_err[hderr]);
  375.     }
  376.  
  377.     /* read in boot sector */
  378.     get_block(0);
  379.  
  380.     /* Fill in TOS save info */
  381.     bcopy(block_buf,sav_tmp.bstart,64l);
  382.     sav_tmp.sav_magic=SAV_MAGIC;
  383.     if(bpb) sav_tmp.sav_datrec=bpb->datrec;
  384.     else sav_tmp.sav_datrec=0;
  385.  
  386.     /* If size of partition not known try BPB/boot sector */
  387.     if(!numblocks)
  388.     {
  389.         if(!bpb || (bpb->recsiz & 511))
  390.         {
  391.             fprintf(stderr,"Can't figure out partition size: "
  392.                              "try the -b option\n");
  393.             exit(1);
  394.         }
  395.  
  396.         numblocks=( (block_buf[19]+( ((long)block_buf[20])<<8))*
  397.                                    bpb->recsiz)>>10;
  398.         if(numblocks < 40 )
  399.         {
  400.                  fprintf(stderr,"%ld blocks ? Is that bootsector OK ?\n",numblocks);
  401.                  exit(1);
  402.         }
  403.     }
  404.  
  405.     if(!v2 && (numblocks > 65535) )
  406.     {
  407.         fprintf(stderr,"V1 filesystems can be at most 65535 blocks\n");
  408.         exit(1);
  409.     }
  410.  
  411.     if( (hderr=set_lrecno(&hdinf,numblocks)) )
  412.     {
  413.         fprintf(stderr,"Can't access partition: %s\n",hdd_err[hderr]);
  414.         exit(1);
  415.     }
  416.  
  417.     if(tst)
  418.     {
  419.         fprintf(stderr,"\nHard disk access information:\nAccess mode: ");
  420.         switch(hdinf.rwmode & RW_MODE)
  421.         {
  422.           case RW_NORMAL:
  423.           fprintf(stderr,"Normal mode\n");
  424.           break;
  425.  
  426.           case RW_XHDI:
  427.           fprintf(stderr,"XHDI mode\n");
  428.           break;
  429.  
  430.           case RW_PHYS:
  431.           fprintf(stderr,"Physical mode\n");
  432.           break;
  433.         }
  434.  
  435.         if(hdinf.rwmode & RW_LRECNO)
  436.                         fprintf(stderr,"Lrecno access\n\n");
  437.         else fprintf(stderr,"Non lrecno access\n\n");
  438.     }
  439.  
  440.     /* Special test to check PHYS mode is OK:
  441.      * read in block 0 with Rwabs and our routines. If they are
  442.      * different then signal error and halt.
  443.      */
  444.  
  445.     if( ( ( (hdinf.rwmode & RW_MODE) == RW_PHYS ) || ( tst && !no_phys ) )
  446.                                     && bpb )
  447.     {
  448.         char *tmp1,*tmp2;
  449.  
  450.         tmp1=malloc(1024);
  451.         tmp2=malloc(bpb->recsiz);
  452.         if(!tmp1 || !tmp2)
  453.         {
  454.             fprintf(stderr,"Memory allocation error\n");
  455.             exit(1);
  456.         }
  457.  
  458.         if( Rwabs(2,tmp2,1,0,hdinf.drive) )
  459.         {
  460.             fprintf(stderr,"Rwabs failure\n");
  461.             exit(1);
  462.         }
  463.  
  464.         if(tst) block_rwabs(2,tmp1,1,0,&hdinf2);
  465.         else block_rwabs(2,tmp1,1,0,&hdinf);
  466.         
  467.         if( bcmp(tmp1,tmp2,512) )
  468.         {
  469.             fprintf(stderr,"Physical Comparison error!\n");
  470.             if(!tst) exit(1);
  471.         }
  472.         else if(tst) fprintf(stderr,"Physical Comparison OK\n");
  473.         free(tmp1);
  474.         free(tmp2);
  475.     }
  476.  
  477.     if(numinodes==0)
  478.     {
  479.         numinodes = numblocks/3;
  480.     
  481.         /* Round up inode number to nearest block */
  482.  
  483.         if(v2) numinodes = (numinodes + 15) & ~15;
  484.  
  485.         else numinodes=(numinodes + 31 ) & ~31;
  486.     }
  487.  
  488.     if(numinodes > 65535) numinodes = 65535;
  489.  
  490.     if(protect==2)
  491.     {
  492.         get_block(1);
  493.         if( sblk->s_magic!=0x137f && sblk->s_magic!=0x2468 
  494.             && sblk->s_magic!=0x138f)
  495.  
  496.         {
  497.             fprintf(stderr,"Fatal: bad magic number\n");
  498.             exit(1);
  499.         }
  500.     }
  501.  
  502.     if(!tst) warn();
  503.  
  504.     /* OK lets work out some stuff */
  505.  
  506.     if(protect==2) get_block(1);
  507.     else
  508.     {
  509.         bzero(block_buf,1024l);
  510.         /* Super block */
  511.             sblk->s_ninodes=numinodes;
  512.             if(v2) sblk->s_zones=numblocks;
  513.         else sblk->s_nzones=numblocks;
  514.             sblk->s_imap_blks=(numinodes+8192)/8192;
  515.         sblk->s_zmap_blks=(numblocks+8191)/8192;
  516.         sblk->s_firstdatazn=2+sblk->s_imap_blks+sblk->s_zmap_blks
  517.             + ( v2 ? ((numinodes+15)/16) : ((numinodes+31)/32)) ;
  518.         sblk->s_log_zsize=0;
  519.         sblk->s_max_size= v2 ? 0x7fffffffl : 0x10081c00l;
  520.         if(v2) sblk->s_magic=0x2468;
  521.         else
  522.         {
  523.             if(incr==2) sblk->s_magic=0x138f;
  524.             else sblk->s_magic=0x137f;
  525.         }
  526.     }
  527.  
  528.     /* If we have a valid sav_tosfs structure in the superblock leave
  529.      * it there. Otherwise copy our structure across.
  530.      */
  531.     if(sav_tosfs->sav_magic!=SAV_MAGIC) *sav_tosfs=sav_tmp;
  532.  
  533.     /* If sector size 512 bytes handle protection now */
  534.     if(protect)
  535.     {
  536.         unsigned pseudo_root,root_entries;
  537.         /* 512 bytes pseudo root after super block */
  538.         if(bpb->recsiz==512)
  539.         {
  540.             bzero(&block_buf[512],512);
  541.             for(i=512;i<1024;i+=32)
  542.             {
  543.                 strncpy(block_buf+i,"MINIXFS    ",11);
  544.                 block_buf[i+11]=0x08;
  545.             }
  546.             put_block(1);
  547.             csblk=*sblk;
  548.             pseudo_root=3;
  549.         }
  550.         else
  551.         /* Not 512 bytes: insert pseudo root after inodes but 
  552.           * before first data zone.
  553.           */
  554.         {
  555.             unsigned secblocks;    /* blocks per log. sector */
  556.              secblocks = bpb->recsiz/1024;
  557.             /* Round up first data zone to sector boundary + 1 */
  558.             sblk->s_firstdatazn += 2*secblocks - 1;
  559.             sblk->s_firstdatazn /= secblocks;
  560.             sblk->s_firstdatazn *= secblocks;
  561.             put_block(1);
  562.             pseudo_root = sblk->s_firstdatazn / secblocks - 1;
  563.             csblk=*sblk;
  564.             /* Pseudo root directory : whole block */
  565.             for(i=0;i<1024;i+=32)
  566.             {
  567.                 strncpy((char *)(block_buf+i),"MINIXFS    ",11);
  568.                 block_buf[i+11]=0x8;
  569.             }
  570.             /* Write them all out */
  571.             for(i = - secblocks ; i < 0 ;i++)
  572.                          put_block(csblk.s_firstdatazn+i);
  573.         }
  574.         /* Set up boot sector to point to pseudo root */
  575.         get_block(0);
  576.         strcpy((char *)(block_buf+2),"MINIX");
  577.         block_buf[16] = 2;    /* 2 FAT's */
  578.         root_entries = bpb->recsiz/32; /* Root directory: 1 sector */
  579.         block_buf[17] = root_entries & 0xff;
  580.         block_buf[18] = root_entries >> 8;
  581.         block_buf[22] = 1;    /* FAT = 1 sector */
  582.         block_buf[23] = 0;
  583.         pseudo_root-=2;
  584.         block_buf[14] = pseudo_root & 0xff;
  585.         block_buf[15] = pseudo_root >> 8;
  586.         put_block(0);
  587.     }
  588.     else
  589.     {
  590.         put_block(1);
  591.         csblk=*sblk;
  592.     }
  593.  
  594.     if( sonly || protect==2 ) exit(0);
  595.  
  596.     ioff=2+csblk.s_imap_blks+csblk.s_zmap_blks;
  597.     zone1=csblk.s_firstdatazn;
  598.  
  599.     bzero(block_buf,1024l);
  600.  
  601.     /* Inode bitmaps */
  602.  
  603.     icount = numinodes + 1;
  604.     for(i=2;i<2+csblk.s_imap_blks;i++)
  605.     {
  606.         if(i==2)
  607.         {
  608.             srt[0]=3;
  609.         }
  610.         if(icount < 8192) /* Need to mark dead inodes as used */
  611.         {
  612.             if(icount & 15)
  613.             {
  614.                 srt[icount/16] = 0xffff << (icount & 15);
  615.                 icount+= 16 - (icount & 15);
  616.             }
  617.             for(j=icount/16;j<512;j++)srt[j]=0xffff;
  618.         }
  619.         put_block(i);
  620.         if(i==2)srt[0]=0;
  621.         icount-=8192;
  622.     }
  623.  
  624.     bzero(block_buf,1024l);
  625.  
  626.         /* Zone bitmaps */
  627.  
  628.     zcount = numblocks + 1 - csblk.s_firstdatazn;
  629.     for(i=2+csblk.s_imap_blks;i<ioff;i++)
  630.     {
  631.         if(i==2+csblk.s_imap_blks)
  632.         {
  633.             srt[0]=3;
  634.         }
  635.         if (zcount < 8192) /* Need to mark dead zones as used */
  636.         {
  637.             if(zcount < 0) zcount=0;
  638.             if(zcount & 15)
  639.             {
  640.                 srt[zcount/16] = 0xffff << (zcount & 15);
  641.                 zcount+= 16 - (zcount & 15);
  642.             }
  643.             for(j=zcount/16;j<512;j++)srt[j]=0xffff;
  644.         }
  645.         put_block(i);
  646.         if(i==2+csblk.s_imap_blks)srt[0]=0;
  647.         zcount-=8192;
  648.     }
  649.  
  650.     bzero(block_buf,1024l);
  651.  
  652.     /* Initialise inodes */
  653.     
  654.     for(i=ioff;i<ioff+
  655.             (v2 ? ((numinodes +15)/16) : ((numinodes+31)/32 )) ;i++)
  656.     {
  657.         if(i==ioff) /* Root inode , initialise it properly */
  658.         {
  659.             if(v2)
  660.             {
  661.                 ripn->i_mode=040777; /* Directory */
  662.                 ripn->i_size=32*incr;
  663.                 ripn->i_mtime=time((time_t *)0);
  664.                 ripn->i_ctime=ripn->i_mtime;
  665.                 ripn->i_atime=ripn->i_mtime;
  666.                 ripn->i_nlinks=2;
  667.                 ripn->i_zone[0]=zone1;
  668.             }
  669.             else
  670.             {
  671.                 rip->i_mode=040777; /* Directory */
  672.                 rip->i_size=32*incr;
  673.                 rip->i_mtime=time((time_t *)0);
  674.                 rip->i_nlinks=2;
  675.                 rip->i_zone[0]=zone1;
  676.             }
  677.         }    
  678.         put_block(i);
  679.         if(i==ioff)bzero(block_buf,1024l);
  680.     }
  681.  
  682.     bzero(block_buf,1024l);
  683.     /* And finally the root directory */
  684.     dir[0].d_inum=1;
  685.     strcpy(dir[0].d_name,".");
  686.     dir[incr].d_inum=1;
  687.     strcpy(dir[incr].d_name,"..");
  688.     put_block(zone1);
  689.     if(!tst) fprintf(stderr,"Initialised OK.\n");
  690.     fprintf(stderr,"%ld Blocks, %ld Inodes.\n",numblocks,numinodes);
  691.  
  692.     /* Force media change on specified drive */
  693.     if(Dlock(1,drive)) 
  694.         fprintf(stderr,"Can't Lock Drive, Reboot to be sure\n");
  695.  
  696.     exit(0);
  697. }
  698.  
  699. void get_block(num)
  700. long num;
  701. {
  702.     long r;
  703.  
  704.     if( (r = block_rwabs(2,block_buf,1,num,&hdinf)) )
  705.     {
  706.         fprintf(stderr,"Fatal Read Error %ld block %ld\n",r,num);
  707.         exit(2);
  708.     }
  709. }
  710.  
  711. void put_block(num)
  712. long num;
  713. {
  714.     long r;
  715.  
  716.     if(tst) return;
  717.  
  718.     if( (r = block_rwabs(3,block_buf,1,num,&hdinf)) )
  719.     {
  720.         fprintf(stderr,"Fatal Write Error %ld block %ld\n",r,num);
  721.         exit(2);
  722.     }
  723. }
  724.  
  725. void warn()
  726. {
  727.     int ch;
  728.     fprintf(stderr,"WARNING ! THIS %s TOTALLY DESTROY ANY DATA ON ",
  729.                   (sonly || protect==2 ) ? "MAY":"WILL");
  730.     fprintf(stderr,"DRIVE %c !\n",drive+'A');
  731.     fprintf(stderr,"Are you ABSOLUTELY SURE you want to do this (y/n)?\n");
  732.     ch=Crawcin() & 0xff ;
  733.     if((ch & ~32) !='Y')
  734.     {
  735.         fprintf(stderr,"Aborted\n");
  736.         exit(0);
  737.     }
  738. }
  739.  
  740. /* Restore a tosfs filesystem. Using the tfsav structure.
  741.  */
  742.  
  743. void make_tosfs()
  744. {
  745.     int hderr,i;
  746.     long clear_blk;        /* Number of blocks to clear */
  747.     char ch;
  748.  
  749.     if( (hderr=get_hddinf(drive,&hdinf,0)) )
  750.     {
  751.         fprintf(stderr,"Cannot access Drive %c: %s\n",drive+'A',
  752.                                 hdd_err[hderr]);
  753.         exit(1);
  754.     }
  755.  
  756.     get_block(1);
  757.     if(sblk->s_magic!=0x2468 && sblk->s_magic!=0x137f && 
  758.         sblk->s_magic!=0x138f )
  759.     {
  760.         fprintf(stderr,"Can't restore: not a Minixfs filesystem\n");    
  761.         exit(1);
  762.     }
  763.  
  764.     if( sav_tosfs->sav_magic!=SAV_MAGIC )
  765.     {
  766.         fprintf(stderr,"Can't recreate filesystem: perhaps you made the\
  767. \nfilesystem with an older version of minit?\n");
  768.         exit(1);
  769.     }
  770.  
  771.     fprintf(stderr,"WARNING: You are about to Restore a TOS filesystem\n");
  772.     fprintf(stderr,"on a Minixfs Filesystem. This will TOTALLY DESTROY\n");
  773.     fprintf(stderr,"the Minixfs files!\n");
  774.     fprintf(stderr,"ARE YOU ABSOLUTELY SURE YOU WANT TO DO THIS ? (y/n)\n");
  775.     ch=Crawcin() & 0xff;
  776.     if((ch & ~32) != 'Y') exit(0);
  777.  
  778.  
  779.     sav_tmp=*sav_tosfs;
  780.     get_block(0);
  781.     bcopy(sav_tmp.bstart,block_buf,64l);
  782.  
  783.     if(sav_tmp.sav_datrec) clear_blk = (sav_tmp.sav_datrec*block_buf[12])/2;
  784.     else /* Work out datrec from other parameters */
  785.     {
  786.         int nphys;    /* 512 byte sectors per logical sector */
  787.         long dirent;    /* root dir logical sectors */
  788.         nphys = block_buf[12]/2;
  789.         clear_blk = nphys;    /* Boot sector */
  790.  
  791.         /* Add the FATs */
  792.         clear_blk += nphys*block_buf[16]*
  793.                 (block_buf[22]+(block_buf[23]<<8));
  794.  
  795.         /* Root dir 512 byte sectors (16 entries per sector) */
  796.         dirent = DIV(block_buf[17]+(block_buf[18]<<8),16);        
  797.         /* Now round up to nearest physical sector */
  798.         dirent = DIV(dirent,nphys);
  799.         clear_blk += nphys*dirent;
  800.     }
  801.  
  802.     /* convert clear_blk to blocks */
  803.     clear_blk = DIV(clear_blk,2);
  804.  
  805.     bzero(block_buf+512,512);
  806.     put_block(0);
  807.  
  808.     /* Now we zero 2 FATs and root directory */
  809.     bzero(block_buf,512);
  810.  
  811.     for(i=1;i < 1+clear_blk; i++) put_block(i);
  812.  
  813.     /* Force disk change */
  814.     (void)Dlock(1,drive);
  815.  
  816.     fprintf(stderr,"TOS filesystem recreated: Reboot to be sure\n");
  817.     exit(0);
  818.  
  819. }
  820.