home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / filesy~1 / mfs609s.zoo / minixfs / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-25  |  8.9 KB  |  416 lines

  1. /* Minixfs version 0.60 , Copyright S.N. Henson 1991,1992,1993
  2.  * see the file 'copying' for more info.
  3.  */
  4.  
  5. /* Define all global variables */
  6. #define EXTERN /**/
  7.  
  8. #include "minixfs.h"
  9. #include "proto.h"
  10. #include "global.h"
  11. #include "xhdi.h"
  12. #include "pun.h"
  13. #include <basepage.h>
  14. #include <mintbind.h>
  15. #include <signal.h>
  16.  
  17. /* This rubbish ensures that str(XXX) gets expanded then stringifyed */
  18. #define str(x) _stringify(x)
  19. #define _stringify(x) #x
  20.  
  21. /* Initialisation routine called first by the kernel */
  22.  
  23. extern FILESYS minix_filesys;
  24.  
  25. typedef long (*lfptr)();
  26.  
  27. lfptr old_rwabs,old_getbpb,old_mediach;
  28.  
  29. unsigned long shadmap;
  30.  
  31. extern long kludge_rwabs(),kludge_getbpb(),kludge_mediach(),setstack();
  32.  
  33. FILESYS *
  34. minix_init(k)
  35.     struct kerinfo *k;
  36. {
  37.     extern int init_icd();
  38.     unsigned long p2,vdrvs;
  39.     int i;
  40.  
  41.     kernel = k;
  42.     CCONWS("Minix file system driver for MiNT. Version " 
  43.     str(MFS_MAJOR) "." str(MFS_MINOR) "\r\n"
  44.     "Copyright 1991,1992,1993 S.N.Henson\r\n");
  45. #ifdef MFS_PLEV
  46.     CCONWS("Patch Level " str(MFS_PLEV) "\r\n");
  47. #endif
  48.     CCONWS("Please read the file COPYING for conditions of use.\r\n");
  49.  
  50.     if( (k->maj_version > 0) || (k->min_version >= 94) ) lockok=1;
  51.     else CCONWS("File Locking not Installed , Use MiNT 0.94 or newer\r\n");
  52.  
  53.     if( (k->maj_version==0) && (k->min_version < 97) ) no_length=1;
  54.  
  55.     /* Allocate Cache */
  56.     if(init_cache()) return NULL; 
  57.  
  58.     /* See if there are any shadow drives */
  59.  
  60.     vdrvs=*((unsigned long *)0x4c2);
  61.  
  62.     for(i=0,p2=1;i<NUM_DRIVES;i++,p2<<=1)
  63.     {
  64.         if(ppart[i].start !=-1 )
  65.         {
  66.             if(vdrvs & p2)
  67.             ALERT("Minixfs: shadow drive %c: not installed: drive"
  68.                 " already exists!",i+'A');
  69.             else
  70.             {
  71.                 ALERT("Shadow Drive %c Installed",i+'A');
  72.                 ALERT("Start %ld Finish %ld Device %d",
  73.                 ppart[i].start,ppart[i].finish,ppart[i].shadow);
  74.                 shadmap |= p2;
  75.             }
  76.         }
  77.     }
  78.  
  79.     *((unsigned long *)0x4c2) = vdrvs | shadmap;
  80.  
  81.     /* Initialise icd kludge */
  82.     init_icd();
  83.  
  84.     if(shadmap) /* Any shadows installed ? */
  85.     {
  86.         /* Set new system vectors */
  87.  
  88.         old_mediach = *((lfptr *) 0x47e);
  89.         old_rwabs = *((lfptr *) 0x476);
  90.         old_getbpb = *((lfptr *) 0x472);
  91.  
  92.         *((lfptr *) 0x47e) = kludge_mediach;
  93.         *((lfptr *) 0x476) = kludge_rwabs;
  94.         *((lfptr *) 0x472) = kludge_getbpb;
  95.     }
  96.  
  97.     switch(cache_mode)
  98.     {
  99.         case ROBUST:
  100.         CCONWS("Robust mode\r\n");
  101.         break;
  102.  
  103.         case NORMAL:
  104.         CCONWS("Normal mode\r\n");
  105.         break;
  106.  
  107.         case TURBO:
  108.         CCONWS("TURBO mode\r\n");
  109.         break;
  110.     }
  111.  
  112. /* If we are in Turbo mode then run a backround updater.
  113.  * This is a variant of the code used in 'thread.c' in mintlib
  114.  */
  115.  
  116.     if(cache_mode==TURBO)
  117.     {
  118.         BASEPAGE *b;
  119.  
  120.         b = (BASEPAGE *)p_exec(5, 0L, "", 0L);    /* create a basepage */
  121.  
  122.         (void)m_shrink(0,b, 512l);        /* Basepage + stack */
  123.  
  124.         b->p_tbase = (char *)update;        /* text start = func to start */
  125.         b->p_hitpa = ((char *)b) + 512;
  126.  
  127.         update_pid = (short) p_exec(104, "update", b, 0L);
  128.         /* run in backround */
  129.  
  130.     }
  131.  
  132.     return &minix_filesys;
  133. }
  134.  
  135. /* Note: update is a user level process and must act accordingly i.e. use
  136.  * the syscalls not the dos/bios tables.
  137.  */
  138.  
  139. int update(bp)
  140. long bp;
  141. {
  142.     setstack(bp+512);
  143.  
  144.     /* Trap most signals */
  145.  
  146.     Psignal(SIGALRM,do_sync);
  147.     Psignal(SIGTERM,do_sync);
  148.     Psignal(SIGQUIT,do_sync);
  149.     Psignal(SIGHUP,do_sync);
  150.     Psignal(SIGTSTP,do_sync);
  151.     Psignal(SIGINT,do_sync);
  152.  
  153.     for(;;)
  154.     {
  155.         Talarm(sync_time);
  156.         Pause();
  157.     }
  158. }
  159.  
  160. char mfspath[]="A:";
  161.  
  162. void do_sync(signum)
  163. long signum;
  164. {
  165.     int i;
  166.     if(update_suspend) return;
  167.     for(i=0;i<NUM_DRIVES;i++)
  168.     {
  169.         if(super_ptr[i] && super_ptr[i]!=DFS)
  170.         {
  171.             mfspath[0]='A'+i;
  172.             Dcntl(MFS_SYNC,mfspath,0);
  173.             return;
  174.         }
  175.     }
  176. }
  177.  
  178.  
  179. /* Sanity checker, checks a filesystem is minix and then sets up all internal
  180.  * structures accordingly, e.g. superblock and directory increment. Returns
  181.  * '1' if the filesystem is minix, 0 otherwise. Uses get_hddinf to try all
  182.  * possible means to access the drive.
  183.  */
  184.  
  185. int
  186. minix_sanity(drv)
  187. int drv;
  188. {
  189.     int i;
  190.     d_inode rip;
  191.     struct hdinfo *dsk;
  192.     char is_phys;
  193.     long err;
  194.     unsigned long drv_mask;
  195.     super_info *psblk;
  196.  
  197.     drv_mask = 1l<<drv;
  198.  
  199.     if(!( *((unsigned long *)0x4c2) & drv_mask ))
  200.     {
  201.         DEBUG("Invalid drive %c:",drv+'A');
  202.         return 0;
  203.     }
  204.  
  205.     dsk=&disk[drv];
  206.     psblk=Kmalloc(sizeof(super_info));
  207.     if(!psblk)
  208.     {
  209.         ALERT("Minixfs: No memory for super_info structure");
  210.         return 0;
  211.     }
  212.  
  213.     psblk->dev=drv;
  214.  
  215.     if(ppart[drv].start!=-1) /* Is this a physical partition ? */
  216.     {
  217.         struct phys_part *pp;
  218.         pp=&ppart[drv];
  219.         dsk->start=pp->start;
  220.         dsk->size=pp->finish-dsk->start+1;
  221.         dsk->scsiz=pp->scsiz;
  222.         dsk->major = pp->shadow;
  223.         dsk->drive = drv;
  224.         (void)GETBPB(drv);     /* Satisfy disk changes */
  225.         dsk->rwmode = RW_PHYS;
  226.         if(dsk->start > 0xfff0)
  227.         {
  228.             if(no_plrecno(dsk->major))
  229.             {
  230.                 ALERT("Cannot access physical parition %c:",drv+'A');
  231.                 Kfree(psblk);
  232.                 return 0;
  233.             }
  234.             dsk->rwmode |= RW_LRECNO;
  235.         }
  236.         is_phys=1;
  237.     }
  238.     else
  239.     {
  240.         is_phys=0;
  241.         if( (err=get_hddinf(drv,dsk,0)) )
  242.         {
  243.         DEBUG("Cannot access partition %c: %s.",drv+'A',hdd_err[err]);
  244.         Kfree(psblk);
  245.         return 0;
  246.         }
  247.     }
  248.  
  249.     super_ptr[drv]=psblk;
  250.  
  251.     crwabs(2,&temp,1,SUPER_BLOCK,drv);
  252.  
  253.     psblk->sblk=*((super_block *)&temp);
  254.  
  255.     if(( (psblk->sblk.s_magic==SUPER_MAGIC) || 
  256.          (psblk->sblk.s_magic==SUPER_V2))
  257.         && psblk->sblk.s_ninodes) {
  258.         if(psblk->sblk.s_log_zsize) {
  259.         DEBUG("Cannot read Drive %c Zone-size > Block-size",drv+'A');
  260.             super_ptr[drv]=DFS;
  261.             Kfree(psblk);
  262.             return -1;
  263.         }
  264.         if(psblk->sblk.s_magic==SUPER_MAGIC)
  265.         {
  266.             TRACE("Drive %c V1 filesyetem",drv+'A');
  267.             psblk->version=0;
  268.             psblk->ipb=INODES_PER_BLOCK;
  269.             psblk->zpind=NR_INDIRECTS;
  270.             psblk->sblk.s_zones=psblk->sblk.s_nzones;
  271.             psblk->dzpi=NR_DZONE_NUM;
  272.             psblk->ndbl=NR_DBL;
  273.         }
  274.         else
  275.         {
  276.             TRACE("Drive %c V2 filesystem",drv+'A');
  277.             psblk->version=1;
  278.             psblk->ipb=INODES_PER_BLOCK2;
  279.             psblk->zpind=NR_INDIRECTS2;
  280.             psblk->dzpi=NR_DZONE_NUM2;
  281.             psblk->ndbl=NR_DBL2;
  282.  
  283.         }
  284.  
  285.         /* Check if lrecno needed/supported */
  286.  
  287.         if(set_lrecno(dsk,psblk->sblk.s_zones))
  288.         {
  289.             ALERT("No way to access large partition %c:",drv+'A');
  290.             Kfree(psblk);
  291.             super_ptr[drv]=DFS;
  292.             return -1;
  293.         }
  294.  
  295.         psblk->ioff = psblk->sblk.s_imap_blks + psblk->sblk.s_zmap_blks
  296.                                      + 2 ;
  297.         read_inode(ROOT_INODE,&rip,drv);
  298.         if(IS_DIR(rip)) {
  299.           void *p;
  300.           int dot=-1,dotdot=-1;
  301.           p=Kmalloc((unsigned) (BLOCK_SIZE*(psblk->sblk.s_imap_blks+
  302.             psblk->sblk.s_zmap_blks)));
  303.           if(!p) {
  304.             DEBUG("No room for bitmaps");
  305.             Kfree(psblk);
  306.             super_ptr[drv]=DFS;
  307.             return -1;
  308.           }
  309.           psblk->ibitmap=p;
  310.           psblk->zbitmap=p+BLOCK_SIZE*psblk->sblk.s_imap_blks;
  311.           crwabs(2,p,psblk->sblk.s_imap_blks+psblk->sblk.s_zmap_blks
  312.                                     ,2,drv);
  313.           psblk->idirty=0;
  314.           psblk->zdirty=0;
  315.           psblk->zlast=0;
  316.           psblk->ilast=0;
  317.  
  318.           /* Clear all mount flags */
  319.  
  320.           psblk->mnt_first=0;
  321.           psblk->mnt_next=0;
  322.           psblk->mnt_inode=0;
  323.           psblk->mnt_flags=0;
  324.           psblk->mnt_dev=0;
  325.  
  326. /* Final step , read in the root directory zone 1 and check the '.' and '..'
  327.  * spacing , The spacing between the '.' and '..' will be used as an indicator
  328.  * of the directory entry size. If in doubt assume a normal minix filesystem.
  329.  */
  330.  
  331.           read_zone(rip.i_zone[0],&temp,drv,&syscache);
  332.  
  333.           for(i=0;i<min(NR_DIR_ENTRIES,rip.i_size/DIR_ENTRY_SIZE);i++)
  334.           {
  335.             if(temp.bdir[i].d_inum)
  336.             {
  337.                 if(!strcmp(temp.bdir[i].d_name,"."))
  338.                 {
  339.                     if(dot==-1) dot=i;
  340.                     else
  341.                     {
  342.                         ALERT ("Drive %c multiple \".\" in root dir!!", drv + 'A');
  343.                         dot=-1;
  344.                         i=NR_DIR_ENTRIES;
  345.                     }
  346.                 }
  347.  
  348.                 if(!strcmp(temp.bdir[i].d_name,".."))
  349.                 {
  350.                     if(dotdot==-1) dotdot=i;
  351.                     else
  352.                     {
  353.                         ALERT ("Drive %c multiple \"..\" in root directory", drv + 'A');
  354.                         dotdot=-1;
  355.                         i=NR_DIR_ENTRIES;
  356.                     }
  357.                 }
  358.             }
  359.           }
  360.  
  361.           if( (dotdot==-1) || (dot==-1) )
  362.           {
  363.             ALERT("Drive %c no . or .. in root directory",drv+'A');
  364.             Kfree(psblk->ibitmap);
  365.             Kfree(psblk);
  366.             super_ptr[drv]=DFS;
  367.             return -1;
  368.           }
  369.           else psblk->increment=dotdot-dot;
  370.  
  371.           if( (psblk->increment < 1) || NPOW2(psblk->increment))
  372.           {
  373.             ALERT("Drive %c weird . .. positions",drv+'A');
  374.             Kfree(psblk->ibitmap);
  375.             Kfree(psblk);
  376.             super_ptr[drv]=DFS;
  377.             return -1;
  378.           }
  379.  
  380.            if(psblk->increment > MAX_INCREMENT)
  381.           {
  382.             ALERT("Drive %c Increment %d",drv+'A',psblk->increment);
  383.             ALERT("This minix.xfs binary can only handle %d",MAX_INCREMENT);
  384.             ALERT("Recompile with a higher MAX_INCREMENT");
  385.             Kfree(psblk->ibitmap);
  386.             Kfree(psblk);
  387.             super_ptr[drv]=DFS;
  388.             return -1;
  389.           }
  390.  
  391.           return 1;
  392.  
  393.         }
  394.         else {
  395.             ALERT("root inode on drive %c is not a directory??",
  396.                 drv+'A');
  397.             Kfree(psblk->ibitmap);
  398.             Kfree(psblk);
  399.             super_ptr[drv]=DFS;
  400.             return -1;
  401.         }
  402.     }
  403.  
  404.     Kfree(psblk);
  405.  
  406.     if(is_phys)
  407.     {
  408.         ALERT("Physical partition %c: not minix!!",drv+'A');
  409.         super_ptr[drv]=DFS;
  410.         return -1;
  411.     }
  412.  
  413.     super_ptr[drv]=0;
  414.     return 0;
  415. }
  416.