home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Crawly Crypt Collection 2
/
crawlyvol2.bin
/
alt_os
/
mint
/
mfs6011
/
source
/
minixfs
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-01-01
|
11KB
|
471 lines
/* Minixfs version 0.60 , Copyright S.N. Henson 1991,1992,1993
* see the file 'copying' for more info.
*/
/* Define all global variables */
#define EXTERN /**/
#include "minixfs.h"
#include "proto.h"
#include "global.h"
#include "xhdi.h"
#include "pun.h"
#include <basepage.h>
#include <mintbind.h>
#include <signal.h>
/* This rubbish ensures that str(XXX) gets expanded then stringifyed */
#define str(x) _stringify(x)
#define _stringify(x) #x
/* Initialisation routine called first by the kernel */
extern FILESYS minix_filesys;
typedef long (*lfptr)();
lfptr old_rwabs,old_getbpb,old_mediach;
unsigned long shadmap;
extern long kludge_rwabs(),kludge_getbpb(),kludge_mediach(),setstack();
long _stksize=1024l; /* Update stacksize */
FILESYS *
minix_init(k)
struct kerinfo *k;
{
extern int init_icd();
unsigned long p2,vdrvs;
int i;
kernel = k;
CCONWS("Minix file system driver for MiNT. Version "
str(MFS_MAJOR) "." str(MFS_MINOR) "\r\n"
"Copyright 1991,1992,1993,1994,1995 S.N.Henson\r\n");
#ifdef MFS_PLEV
CCONWS("Patch Level " str(MFS_PLEV) "\r\n");
#endif
#ifdef PRE_RELEASE
CCONWS("Pre-Release Test Version\r\n");
#endif
CCONWS("Please read the file COPYING for conditions of use.\r\n");
if( (k->maj_version > 0) || (k->min_version >= 94) ) lockok=1;
else CCONWS("File Locking not Installed , Use MiNT 0.94 or newer\r\n");
if( (k->maj_version==0) && (k->min_version < 97) ) no_length=1;
/* Allocate Cache */
if(init_cache()) return NULL;
/* See if there are any shadow drives */
vdrvs=*((unsigned long *)0x4c2);
for(i=0,p2=1;i<NUM_DRIVES;i++,p2<<=1)
{
if(ppart[i].start !=-1 )
{
if(vdrvs & p2)
ALERT("Minixfs: shadow drive %c: not installed: drive"
" already exists!",i+'A');
else
{
ALERT("Shadow Drive %c Installed",i+'A');
ALERT("Start %ld Finish %ld Device %d",
ppart[i].start,ppart[i].finish,ppart[i].shadow);
shadmap |= p2;
}
}
}
*((unsigned long *)0x4c2) = vdrvs | shadmap;
/* Initialise icd kludge */
init_icd();
if(shadmap) /* Any shadows installed ? */
{
/* Set new system vectors */
old_mediach = *((lfptr *) 0x47e);
old_rwabs = *((lfptr *) 0x476);
old_getbpb = *((lfptr *) 0x472);
*((lfptr *) 0x47e) = kludge_mediach;
*((lfptr *) 0x476) = kludge_rwabs;
*((lfptr *) 0x472) = kludge_getbpb;
}
switch(cache_mode)
{
case ROBUST:
CCONWS("Robust mode\r\n");
break;
case NORMAL:
CCONWS("Normal mode\r\n");
break;
case TURBO:
CCONWS("TURBO mode\r\n");
break;
}
/* If we are in Turbo mode then run a backround updater.
* This is a variant of the code used in 'thread.c' in mintlib
* If we have Addroottimeout, use that.
*/
if(cache_mode==TURBO)
{
BASEPAGE *b;
#ifdef SYSUPDATE
if ((kernel->maj_version) && (kernel->min_version >= 12) &&
(kernel->dos_tab[0x150] != NULL) )
{
/* Do not start the update daemon, or use the root timeout
* method, as the system already has a Sync() system call,
* and hopefully a running update daemon.
*/
}
else
#endif
if(Addroottimeout) Addroottimeout(sync_time*1000l,t_sync,0);
else
{
b = (BASEPAGE *)p_exec(5, 0L, "", 0L); /* create a basepage */
(void)m_shrink(0,b, 256 + _stksize); /* Basepage + stack */
b->p_tbase = (char *)update; /* text start = func to start */
b->p_hitpa = ((char *)b) + 256 + _stksize;
update_pid = (short) p_exec(104, "update", b, 0L);
/* run in backround */
}
}
return &minix_filesys;
}
/* Note: update is a user level process and must act accordingly i.e. use
* the syscalls not the dos/bios tables.
*/
int update(bp)
long bp;
{
#if 1
#define _base ((BASEPAGE *)(&init_addr)-1)
extern long init_addr;
((BASEPAGE *)bp)->p_tbase = _base->p_tbase;
((BASEPAGE *)bp)->p_tlen = _base->p_tlen;
((BASEPAGE *)bp)->p_dbase = _base->p_dbase;
((BASEPAGE *)bp)->p_dlen = _base->p_dlen;
((BASEPAGE *)bp)->p_bbase = _base->p_bbase;
((BASEPAGE *)bp)->p_blen = _base->p_blen;
#endif
setstack(bp+256+_stksize);
/* Trap most signals */
Psignal(SIGALRM,do_sync);
Psignal(SIGTERM,do_sync);
Psignal(SIGQUIT,do_sync);
Psignal(SIGHUP,do_sync);
Psignal(SIGTSTP,do_sync);
Psignal(SIGINT,do_sync);
for(;;)
{
int tsync;
tsync=sync_time;
while(tsync > 32 )
{
(void) Fselect(32000,0l,0l,0l);
tsync-=32;
}
if(tsync > 0) (void) Fselect(tsync*1000l,0l,0l,0l);
do_sync(0);
}
}
char mfspath[]="A:";
void do_sync(signum)
long signum;
{
int i;
if(update_suspend) return;
for(i=0;i<NUM_DRIVES;i++)
{
if(super_ptr[i] && super_ptr[i]!=DFS)
{
mfspath[0]='A'+i;
Dcntl(MFS_SYNC,mfspath,0);
return;
}
}
}
/* Much cleaner method using addroottimeout(), this is now at kernel
* level and so can call l_sync() safely, it also schedules the next
* sync()
*/
void t_sync()
{
TRACE("Minixfs: doing t_sync()");
if(!update_suspend) l_sync();
Addroottimeout(1000l*sync_time,t_sync,0);
}
/* Sanity checker, checks a filesystem is minix and then sets up all internal
* structures accordingly, e.g. superblock and directory increment. Returns
* '1' if the filesystem is minix, 0 otherwise. Uses get_hddinf to try all
* possible means to access the drive.
*/
int
minix_sanity(drv)
int drv;
{
int i;
d_inode rip;
struct hdinfo *dsk;
char is_phys;
long err;
unsigned long drv_mask;
super_info *psblk;
drv_mask = 1l<<drv;
if(!( *((unsigned long *)0x4c2) & drv_mask ))
{
DEBUG("Invalid drive %c:",drv+'A');
return 0;
}
dsk=&disk[drv];
psblk=Kmalloc(sizeof(super_info));
if(!psblk)
{
ALERT("Minixfs: No memory for super_info structure");
return 0;
}
psblk->dev=drv;
if(ppart[drv].start!=-1) /* Is this a physical partition ? */
{
struct phys_part *pp;
pp=&ppart[drv];
dsk->start=pp->start;
dsk->size=pp->finish-dsk->start+1;
dsk->scsiz=pp->scsiz;
dsk->major = pp->shadow;
dsk->drive = drv;
(void)GETBPB(drv); /* Satisfy disk changes */
dsk->rwmode = RW_PHYS;
if(dsk->start > 0xfff0)
{
if(no_plrecno(dsk->major))
{
ALERT("Cannot access physical parition %c:",drv+'A');
Kfree(psblk);
return 0;
}
dsk->rwmode |= RW_LRECNO;
}
is_phys=1;
}
else
{
is_phys=0;
if( (err=get_hddinf(drv,dsk,0)) )
{
DEBUG("Cannot access partition %c: %s.",drv+'A',hdd_err[err]);
Kfree(psblk);
return 0;
}
}
super_ptr[drv]=psblk;
crwabs(2,&temp,1,SUPER_BLOCK,drv);
psblk->sblk=*((super_block *)&temp);
if(( (psblk->sblk.s_magic==SUPER_MAGIC) ||
(psblk->sblk.s_magic==SUPER_V2) ||
(psblk->sblk.s_magic==SUPER_V1_30) )
&& psblk->sblk.s_ninodes) {
if(psblk->sblk.s_log_zsize) {
DEBUG("Cannot read Drive %c Zone-size > Block-size",drv+'A');
super_ptr[drv]=DFS;
Kfree(psblk);
return -1;
}
if(psblk->sblk.s_magic==SUPER_V2)
{
TRACE("Drive %c V2 filesystem",drv+'A');
psblk->version=1;
psblk->ipb=INODES_PER_BLOCK2;
psblk->zpind=NR_INDIRECTS2;
psblk->dzpi=NR_DZONE_NUM2;
psblk->ndbl=NR_DBL2;
/* Check if lrecno needed/supported */
if(set_lrecno(dsk,psblk->sblk.s_zones))
{
ALERT("No way to access large partition %c:",drv+'A');
Kfree(psblk);
super_ptr[drv]=DFS;
return -1;
}
}
else
{
TRACE("Drive %c V1 filesyetem",drv+'A');
psblk->version=0;
psblk->ipb=INODES_PER_BLOCK;
psblk->zpind=NR_INDIRECTS;
psblk->sblk.s_zones=psblk->sblk.s_nzones;
psblk->dzpi=NR_DZONE_NUM;
psblk->ndbl=NR_DBL;
}
psblk->ioff = psblk->sblk.s_imap_blks + psblk->sblk.s_zmap_blks
+ 2 ;
read_inode(ROOT_INODE,&rip,drv);
if(IS_DIR(rip)) {
void *p;
int dot=-1,dotdot=-1;
#if 1
p=Kmalloc((unsigned long) (BLOCK_SIZE*((unsigned long) psblk->sblk.s_imap_blks+
psblk->sblk.s_zmap_blks)));
#else
p=Kmalloc((unsigned) (BLOCK_SIZE*(psblk->sblk.s_imap_blks+
psblk->sblk.s_zmap_blks)));
#endif
if(!p) {
DEBUG("No room for bitmaps");
Kfree(psblk);
super_ptr[drv]=DFS;
return -1;
}
psblk->ibitmap=p;
psblk->zbitmap=p+BLOCK_SIZE*psblk->sblk.s_imap_blks;
crwabs(2,p,psblk->sblk.s_imap_blks+psblk->sblk.s_zmap_blks
,2,drv);
psblk->idirty=0;
psblk->zdirty=0;
psblk->zlast=0;
psblk->ilast=0;
/* Clear all mount flags */
psblk->mnt_first=0;
psblk->mnt_next=0;
psblk->mnt_inode=0;
psblk->mnt_flags=0;
psblk->mnt_dev=0;
/* Final step , read in the root directory zone 1 and check the '.' and '..'
* spacing , The spacing between the '.' and '..' will be used as an indicator
* of the directory entry size. If in doubt assume a normal minix filesystem.
*/
read_zone(rip.i_zone[0],&temp,drv,&syscache);
for(i=0;i<min(NR_DIR_ENTRIES,rip.i_size/DIR_ENTRY_SIZE);i++)
{
if(temp.bdir[i].d_inum)
{
if(!strcmp(temp.bdir[i].d_name,"."))
{
if(dot==-1) dot=i;
else
{
ALERT ("Drive %c multiple \".\" in root dir!!", drv + 'A');
dot=-1;
i=NR_DIR_ENTRIES;
}
}
if(!strcmp(temp.bdir[i].d_name,".."))
{
if(dotdot==-1) dotdot=i;
else
{
ALERT ("Drive %c multiple \"..\" in root directory", drv + 'A');
dotdot=-1;
i=NR_DIR_ENTRIES;
}
}
}
}
if( (dotdot==-1) || (dot==-1) )
{
ALERT("Drive %c no . or .. in root directory",drv+'A');
Kfree(psblk->ibitmap);
Kfree(psblk);
super_ptr[drv]=DFS;
return -1;
}
else psblk->increment=dotdot-dot;
if( (psblk->increment < 1) || NPOW2(psblk->increment))
{
ALERT("Drive %c weird . .. positions",drv+'A');
Kfree(psblk->ibitmap);
Kfree(psblk);
super_ptr[drv]=DFS;
return -1;
}
if(psblk->increment > MAX_INCREMENT)
{
ALERT("Drive %c Increment %d",drv+'A',psblk->increment);
ALERT("This minix.xfs binary can only handle %d",MAX_INCREMENT);
ALERT("Recompile with a higher MAX_INCREMENT");
Kfree(psblk->ibitmap);
Kfree(psblk);
super_ptr[drv]=DFS;
return -1;
}
return 1;
}
else {
ALERT("root inode on drive %c is not a directory??",
drv+'A');
Kfree(psblk->ibitmap);
Kfree(psblk);
super_ptr[drv]=DFS;
return -1;
}
}
Kfree(psblk);
if(is_phys)
{
ALERT("Physical partition %c: not minix!!",drv+'A');
super_ptr[drv]=DFS;
return -1;
}
super_ptr[drv]=0;
return 0;
}