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