home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / alt_os / mint / mfs6011 / source / minixfs / main.c < prev    next >
C/C++ Source or Header  |  1995-01-01  |  11KB  |  471 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,1995 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. #ifdef SYSUPDATE
  127.         if ((kernel->maj_version) && (kernel->min_version >= 12) &&
  128.             (kernel->dos_tab[0x150] != NULL) )
  129.         {
  130.             /* Do not start the update daemon, or use the root timeout
  131.              * method, as the system already has a Sync() system call,
  132.              * and hopefully a running update daemon.
  133.              */
  134.         }
  135.         else
  136. #endif
  137.         if(Addroottimeout) Addroottimeout(sync_time*1000l,t_sync,0);
  138.         else
  139.         {
  140.           b = (BASEPAGE *)p_exec(5, 0L, "", 0L);    /* create a basepage */
  141.  
  142.           (void)m_shrink(0,b, 256 + _stksize);    /* Basepage + stack */
  143.  
  144.           b->p_tbase = (char *)update;        /* text start = func to start */
  145.           b->p_hitpa = ((char *)b) + 256 + _stksize;
  146.  
  147.           update_pid = (short) p_exec(104, "update", b, 0L);
  148.  
  149.           /* run in backround */
  150.         }
  151.     }
  152.  
  153.     return &minix_filesys;
  154. }
  155.  
  156. /* Note: update is a user level process and must act accordingly i.e. use
  157.  * the syscalls not the dos/bios tables.
  158.  */
  159.  
  160. int update(bp)
  161. long bp;
  162. {
  163. #if 1
  164. #define _base ((BASEPAGE *)(&init_addr)-1)
  165.     extern long init_addr;
  166.     ((BASEPAGE *)bp)->p_tbase = _base->p_tbase;
  167.     ((BASEPAGE *)bp)->p_tlen = _base->p_tlen;
  168.     ((BASEPAGE *)bp)->p_dbase = _base->p_dbase;
  169.     ((BASEPAGE *)bp)->p_dlen = _base->p_dlen;
  170.     ((BASEPAGE *)bp)->p_bbase = _base->p_bbase;
  171.     ((BASEPAGE *)bp)->p_blen = _base->p_blen;
  172. #endif
  173.  
  174.     setstack(bp+256+_stksize);
  175.  
  176.     /* Trap most signals */
  177.  
  178.     Psignal(SIGALRM,do_sync);
  179.     Psignal(SIGTERM,do_sync);
  180.     Psignal(SIGQUIT,do_sync);
  181.     Psignal(SIGHUP,do_sync);
  182.     Psignal(SIGTSTP,do_sync);
  183.     Psignal(SIGINT,do_sync);
  184.  
  185.     for(;;)
  186.     {
  187.         int tsync;
  188.         tsync=sync_time;
  189.         while(tsync > 32 )
  190.         {
  191.             (void) Fselect(32000,0l,0l,0l);
  192.             tsync-=32;
  193.         }
  194.         if(tsync > 0) (void) Fselect(tsync*1000l,0l,0l,0l);
  195.         do_sync(0);
  196.     }
  197. }
  198.  
  199. char mfspath[]="A:";
  200.  
  201. void do_sync(signum)
  202. long signum;
  203. {
  204.     int i;
  205.     if(update_suspend) return;
  206.     for(i=0;i<NUM_DRIVES;i++)
  207.     {
  208.         if(super_ptr[i] && super_ptr[i]!=DFS)
  209.         {
  210.             mfspath[0]='A'+i;
  211.             Dcntl(MFS_SYNC,mfspath,0);
  212.             return;
  213.         }
  214.     }
  215. }
  216.  
  217. /* Much cleaner method using addroottimeout(), this is now at kernel
  218.  * level and so can call l_sync() safely, it also schedules the next
  219.  * sync()
  220.  */
  221.  
  222. void t_sync()
  223. {
  224.     TRACE("Minixfs: doing t_sync()");
  225.     if(!update_suspend) l_sync();
  226.     Addroottimeout(1000l*sync_time,t_sync,0);
  227. }
  228.  
  229. /* Sanity checker, checks a filesystem is minix and then sets up all internal
  230.  * structures accordingly, e.g. superblock and directory increment. Returns
  231.  * '1' if the filesystem is minix, 0 otherwise. Uses get_hddinf to try all
  232.  * possible means to access the drive.
  233.  */
  234.  
  235. int
  236. minix_sanity(drv)
  237. int drv;
  238. {
  239.     int i;
  240.     d_inode rip;
  241.     struct hdinfo *dsk;
  242.     char is_phys;
  243.     long err;
  244.     unsigned long drv_mask;
  245.     super_info *psblk;
  246.  
  247.     drv_mask = 1l<<drv;
  248.  
  249.     if(!( *((unsigned long *)0x4c2) & drv_mask ))
  250.     {
  251.         DEBUG("Invalid drive %c:",drv+'A');
  252.         return 0;
  253.     }
  254.  
  255.     dsk=&disk[drv];
  256.     psblk=Kmalloc(sizeof(super_info));
  257.     if(!psblk)
  258.     {
  259.         ALERT("Minixfs: No memory for super_info structure");
  260.         return 0;
  261.     }
  262.  
  263.     psblk->dev=drv;
  264.  
  265.     if(ppart[drv].start!=-1) /* Is this a physical partition ? */
  266.     {
  267.         struct phys_part *pp;
  268.         pp=&ppart[drv];
  269.         dsk->start=pp->start;
  270.         dsk->size=pp->finish-dsk->start+1;
  271.         dsk->scsiz=pp->scsiz;
  272.         dsk->major = pp->shadow;
  273.         dsk->drive = drv;
  274.         (void)GETBPB(drv);     /* Satisfy disk changes */
  275.         dsk->rwmode = RW_PHYS;
  276.         if(dsk->start > 0xfff0)
  277.         {
  278.             if(no_plrecno(dsk->major))
  279.             {
  280.                 ALERT("Cannot access physical parition %c:",drv+'A');
  281.                 Kfree(psblk);
  282.                 return 0;
  283.             }
  284.             dsk->rwmode |= RW_LRECNO;
  285.         }
  286.         is_phys=1;
  287.     }
  288.     else
  289.     {
  290.         is_phys=0;
  291.         if( (err=get_hddinf(drv,dsk,0)) )
  292.         {
  293.         DEBUG("Cannot access partition %c: %s.",drv+'A',hdd_err[err]);
  294.         Kfree(psblk);
  295.         return 0;
  296.         }
  297.     }
  298.  
  299.     super_ptr[drv]=psblk;
  300.  
  301.     crwabs(2,&temp,1,SUPER_BLOCK,drv);
  302.  
  303.     psblk->sblk=*((super_block *)&temp);
  304.  
  305.     if(( (psblk->sblk.s_magic==SUPER_MAGIC) || 
  306.          (psblk->sblk.s_magic==SUPER_V2) ||
  307.          (psblk->sblk.s_magic==SUPER_V1_30)    )
  308.         && psblk->sblk.s_ninodes) {
  309.         if(psblk->sblk.s_log_zsize) {
  310.         DEBUG("Cannot read Drive %c Zone-size > Block-size",drv+'A');
  311.             super_ptr[drv]=DFS;
  312.             Kfree(psblk);
  313.             return -1;
  314.         }
  315.         if(psblk->sblk.s_magic==SUPER_V2)
  316.         {
  317.             TRACE("Drive %c V2 filesystem",drv+'A');
  318.             psblk->version=1;
  319.             psblk->ipb=INODES_PER_BLOCK2;
  320.             psblk->zpind=NR_INDIRECTS2;
  321.             psblk->dzpi=NR_DZONE_NUM2;
  322.             psblk->ndbl=NR_DBL2;
  323.  
  324.             /* Check if lrecno needed/supported */
  325.  
  326.             if(set_lrecno(dsk,psblk->sblk.s_zones))
  327.             {
  328.                 ALERT("No way to access large partition %c:",drv+'A');
  329.                 Kfree(psblk);
  330.                 super_ptr[drv]=DFS;
  331.                 return -1;
  332.             }
  333.         }
  334.         else
  335.         {
  336.             TRACE("Drive %c V1 filesyetem",drv+'A');
  337.             psblk->version=0;
  338.             psblk->ipb=INODES_PER_BLOCK;
  339.             psblk->zpind=NR_INDIRECTS;
  340.             psblk->sblk.s_zones=psblk->sblk.s_nzones;
  341.             psblk->dzpi=NR_DZONE_NUM;
  342.             psblk->ndbl=NR_DBL;
  343.         }
  344.  
  345.         psblk->ioff = psblk->sblk.s_imap_blks + psblk->sblk.s_zmap_blks
  346.                                      + 2 ;
  347.         read_inode(ROOT_INODE,&rip,drv);
  348.         if(IS_DIR(rip)) {
  349.           void *p;
  350.           int dot=-1,dotdot=-1;
  351. #if 1
  352.           p=Kmalloc((unsigned long) (BLOCK_SIZE*((unsigned long) psblk->sblk.s_imap_blks+
  353.             psblk->sblk.s_zmap_blks)));
  354. #else
  355.           p=Kmalloc((unsigned) (BLOCK_SIZE*(psblk->sblk.s_imap_blks+
  356.             psblk->sblk.s_zmap_blks)));
  357. #endif
  358.           if(!p) {
  359.             DEBUG("No room for bitmaps");
  360.             Kfree(psblk);
  361.             super_ptr[drv]=DFS;
  362.             return -1;
  363.           }
  364.           psblk->ibitmap=p;
  365.           psblk->zbitmap=p+BLOCK_SIZE*psblk->sblk.s_imap_blks;
  366.           crwabs(2,p,psblk->sblk.s_imap_blks+psblk->sblk.s_zmap_blks
  367.                                     ,2,drv);
  368.           psblk->idirty=0;
  369.           psblk->zdirty=0;
  370.           psblk->zlast=0;
  371.           psblk->ilast=0;
  372.  
  373.           /* Clear all mount flags */
  374.  
  375.           psblk->mnt_first=0;
  376.           psblk->mnt_next=0;
  377.           psblk->mnt_inode=0;
  378.           psblk->mnt_flags=0;
  379.           psblk->mnt_dev=0;
  380.  
  381. /* Final step , read in the root directory zone 1 and check the '.' and '..'
  382.  * spacing , The spacing between the '.' and '..' will be used as an indicator
  383.  * of the directory entry size. If in doubt assume a normal minix filesystem.
  384.  */
  385.  
  386.           read_zone(rip.i_zone[0],&temp,drv,&syscache);
  387.  
  388.           for(i=0;i<min(NR_DIR_ENTRIES,rip.i_size/DIR_ENTRY_SIZE);i++)
  389.           {
  390.             if(temp.bdir[i].d_inum)
  391.             {
  392.                 if(!strcmp(temp.bdir[i].d_name,"."))
  393.                 {
  394.                     if(dot==-1) dot=i;
  395.                     else
  396.                     {
  397.                         ALERT ("Drive %c multiple \".\" in root dir!!", drv + 'A');
  398.                         dot=-1;
  399.                         i=NR_DIR_ENTRIES;
  400.                     }
  401.                 }
  402.  
  403.                 if(!strcmp(temp.bdir[i].d_name,".."))
  404.                 {
  405.                     if(dotdot==-1) dotdot=i;
  406.                     else
  407.                     {
  408.                         ALERT ("Drive %c multiple \"..\" in root directory", drv + 'A');
  409.                         dotdot=-1;
  410.                         i=NR_DIR_ENTRIES;
  411.                     }
  412.                 }
  413.             }
  414.           }
  415.  
  416.           if( (dotdot==-1) || (dot==-1) )
  417.           {
  418.             ALERT("Drive %c no . or .. in root directory",drv+'A');
  419.             Kfree(psblk->ibitmap);
  420.             Kfree(psblk);
  421.             super_ptr[drv]=DFS;
  422.             return -1;
  423.           }
  424.           else psblk->increment=dotdot-dot;
  425.  
  426.           if( (psblk->increment < 1) || NPOW2(psblk->increment))
  427.           {
  428.             ALERT("Drive %c weird . .. positions",drv+'A');
  429.             Kfree(psblk->ibitmap);
  430.             Kfree(psblk);
  431.             super_ptr[drv]=DFS;
  432.             return -1;
  433.           }
  434.  
  435.            if(psblk->increment > MAX_INCREMENT)
  436.           {
  437.             ALERT("Drive %c Increment %d",drv+'A',psblk->increment);
  438.             ALERT("This minix.xfs binary can only handle %d",MAX_INCREMENT);
  439.             ALERT("Recompile with a higher MAX_INCREMENT");
  440.             Kfree(psblk->ibitmap);
  441.             Kfree(psblk);
  442.             super_ptr[drv]=DFS;
  443.             return -1;
  444.           }
  445.  
  446.           return 1;
  447.  
  448.         }
  449.         else {
  450.             ALERT("root inode on drive %c is not a directory??",
  451.                 drv+'A');
  452.             Kfree(psblk->ibitmap);
  453.             Kfree(psblk);
  454.             super_ptr[drv]=DFS;
  455.             return -1;
  456.         }
  457.     }
  458.  
  459.     Kfree(psblk);
  460.  
  461.     if(is_phys)
  462.     {
  463.         ALERT("Physical partition %c: not minix!!",drv+'A');
  464.         super_ptr[drv]=DFS;
  465.         return -1;
  466.     }
  467.  
  468.     super_ptr[drv]=0;
  469.     return 0;
  470. }
  471.