Annotation of dmsdos/src/dblspace_interface.c, revision 1.1

1.1     ! root        1: /*
        !             2: dblspace_interface.c
        !             3: 
        !             4: DMSDOS CVF-FAT module: high-level interface functions.
        !             5: 
        !             6: ******************************************************************************
        !             7: DMSDOS (compressed MSDOS filesystem support) for Linux
        !             8: written 1995-1998 by Frank Gockel and Pavel Pisa
        !             9: 
        !            10:     (C) Copyright 1995-1998 by Frank Gockel
        !            11:     (C) Copyright 1996-1998 by Pavel Pisa
        !            12: 
        !            13: Some code of dmsdos has been copied from the msdos filesystem
        !            14: so there are the following additional copyrights:
        !            15: 
        !            16:     (C) Copyright 1992,1993 by Werner Almesberger (msdos filesystem)
        !            17:     (C) Copyright 1994,1995 by Jacques Gelinas (mmap code)
        !            18:     (C) Copyright 1992-1995 by Linus Torvalds
        !            19: 
        !            20: DMSDOS was inspired by the THS filesystem (a simple doublespace
        !            21: DS-0-2 compressed read-only filesystem) written 1994 by Thomas Scheuermann.
        !            22: 
        !            23: The DMSDOS code is distributed under the Gnu General Public Licence.
        !            24: See file COPYING for details.
        !            25: ******************************************************************************
        !            26: 
        !            27: */
        !            28: 
        !            29: #ifdef __KERNEL__
        !            30: # include <linux/fs.h>
        !            31: # include <linux/blkdev.h>
        !            32: # include <linux/msdos_fs.h>
        !            33: # include <linux/msdos_fs_sb.h>
        !            34: # include <linux/fat_cvf.h>
        !            35: # include <linux/string.h>
        !            36: # include <linux/malloc.h>
        !            37: # include <asm/semaphore.h>
        !            38: # include <linux/module.h>
        !            39: #endif
        !            40: 
        !            41: #include"dmsdos.h"
        !            42: 
        !            43: #ifdef __DMSDOS_LIB__
        !            44: /* some interface hacks */
        !            45: # include"lib_interface.h"
        !            46: # include<string.h>
        !            47: # include<malloc.h>
        !            48: # define MAJOR(x) 0
        !            49: # define MINOR(x) 0
        !            50:   extern long int blk_size[0][0];
        !            51: #endif
        !            52: 
        !            53: extern Acache mdfat[];
        !            54: extern Acache dfat[];
        !            55: extern Acache bitfat[];
        !            56: 
        !            57: unsigned long loglevel=DEFAULT_LOGLEVEL;
        !            58: unsigned long dmsdos_speedup=DEFAULT_SPEEDUP;
        !            59: 
        !            60: /* evaluate numbers from options */
        !            61: char* read_number(char*p, unsigned long* n, int*error)
        !            62: { *n=0;
        !            63:   *error=-1;
        !            64:   if(*p=='b'||*p=='B'||*p=='%')
        !            65:   { /*binary*/
        !            66:     ++p;
        !            67:     while(*p=='0'||*p=='1')
        !            68:     { (*n)*=2;
        !            69:       if(*p=='1')++(*n);
        !            70:       ++p;
        !            71:       *error=0;
        !            72:     }
        !            73:   }
        !            74:   else if(*p=='0'&&(*(p+1)=='x'||*(p+1)=='X'))
        !            75:   { /*hexadecimal*/
        !            76:     p+=2;
        !            77:     while((*p>='0'&&*p<='9')||(*p>='a'&&*p<='f')||(*p>='A'&&*p<='F'))
        !            78:     { (*n)*=16;
        !            79:       (*n)+=((*p<='9')?(*p):(*p)-'a'+10)&0xf;
        !            80:       ++p;
        !            81:       *error=0;
        !            82:     }
        !            83:   }
        !            84:   else if(*p=='0'||*p=='O'||*p=='o')
        !            85:   { /*octal*/
        !            86:     ++p;
        !            87:     while(*p>='0'&&*p<='8')
        !            88:     { (*n)*=8;
        !            89:       (*n)+=(*p)-'0';
        !            90:       ++p;
        !            91:       *error=0;
        !            92:     }
        !            93:   }
        !            94:   else
        !            95:   { /*decimal*/
        !            96:     while(*p>='0'&&*p<='9')
        !            97:     { (*n)*=10;
        !            98:       (*n)+=(*p)-'0';
        !            99:       ++p;
        !           100:       *error=0;
        !           101:     }
        !           102:   }
        !           103:   LOG_REST("DMSDOS: read_number: n=%lu=0x%lx error=%d\n",*n,*n,*error);
        !           104:   return p;
        !           105: }
        !           106: 
        !           107: /* evaluates a single option (needn't be '\0' terminated) */
        !           108: int evaluate_option(char*option,Dblsb*dblsb,int*repair)
        !           109: {  int ret=0;
        !           110: 
        !           111:    LOG_REST("DMSDOS: evaluate option: %s\n",option); 
        !           112:    if(strncmp(option,"comp=",5)==0||strncmp(option,"comp:",5)==0)
        !           113:    {  if(strncmp(option+5,"no",2)==0)dblsb->s_comp=UNCOMPRESSED;
        !           114:       /*else if(strncmp(option+5,"ro",2)==0)*comp=READ_ONLY;*/
        !           115:       else if(strncmp(option+5,"ds00",4)==0)dblsb->s_comp=DS_0_0;
        !           116:       else if(strncmp(option+5,"ds01",4)==0)dblsb->s_comp=DS_0_1;
        !           117:       else if(strncmp(option+5,"ds02",4)==0)dblsb->s_comp=DS_0_2;
        !           118:       else if(strncmp(option+5,"jm00",4)==0)dblsb->s_comp=JM_0_0;
        !           119:       else if(strncmp(option+5,"jm01",4)==0)dblsb->s_comp=JM_0_1;
        !           120:       else if(strncmp(option+5,"sq00",4)==0)dblsb->s_comp=SQ_0_0;
        !           121:       else if(strncmp(option+5,"sd3",3)==0)dblsb->s_comp=SD_3;
        !           122:       else if(strncmp(option+5,"sd4",3)==0)dblsb->s_comp=SD_4;
        !           123:       else if(strncmp(option+5,"guess",5)==0)dblsb->s_comp=GUESS;
        !           124:       else ret=-1;
        !           125:    }
        !           126:    else if(strncmp(option,"cf=",3)==0||strncmp(option,"cf:",3)==0)
        !           127:    {  if(option[3]=='1'&&option[4]>='0'&&option[4]<='2')
        !           128:         dblsb->s_cfaktor=option[4]-'0'+9;
        !           129:       else if(option[3]>='1'&&option[3]<='9')
        !           130:         dblsb->s_cfaktor=option[3]-'0'-1;
        !           131:       else ret=-1;
        !           132:    }
        !           133:    else if(strncmp(option,"loglevel=",9)==0||strncmp(option,"loglevel:",9)==0)
        !           134:    { /* must be decimal or hexadecimal (0x preceeded) number */
        !           135:      read_number(option+9,&loglevel,&ret);
        !           136:      if(ret>=0)
        !           137:        LOG_REST("DMSDOS: evaluate_option: loglevel set to 0x%lx.\n",loglevel);
        !           138:    }
        !           139:    else if(strncmp(option,"speedup=",8)==0||strncmp(option,"speedup:",8)==0)
        !           140:    { /* must be decimal or hexadecimal (0x preceeded) number */
        !           141:      read_number(option+8,&dmsdos_speedup,&ret);
        !           142:      if(ret>=0)
        !           143:        LOG_REST("DMSDOS: evaluate_option: speedup set to 0x%lx.\n",dmsdos_speedup);
        !           144:    }
        !           145:    else if(strncmp(option,"bitfaterrs=",11)==0||strncmp(option,"bitfaterrs:",11)==0)
        !           146:    {  if(strncmp(option+11,"repair",6)==0)*repair=1;
        !           147:       else if(strncmp(option+11,"ignore",6)==0)*repair=2;
        !           148:       else if(strncmp(option+11,"setro",5)==0)*repair=0;
        !           149:       else if(strncmp(option+11,"nocheck",7)==0)*repair=-1;
        !           150:       else ret=-1;
        !           151:    }
        !           152:    else
        !           153:    {  printk(KERN_ERR "DMSDOS: unknown option %s, rejected\n",option);
        !           154:       ret=-1;
        !           155:    }
        !           156:    return ret;
        !           157: }
        !           158: 
        !           159: int parse_dmsdos_options(char*options,Dblsb*dblsb,int*repair)
        !           160: { if(options==NULL)return 0;
        !           161:   
        !           162:   while(*options)
        !           163:   { if(evaluate_option(options,dblsb,repair)<0)return -1;
        !           164:     while(*options!='\0'&&*options!='.'&&*options!='+')++options;
        !           165:     while(*options=='.'||*options=='+')++options;
        !           166:   }
        !           167:   return 0;
        !           168: }
        !           169: 
        !           170: int ilog2(int arg)
        !           171: { /* integer log2 */
        !           172:   int i=0;
        !           173:     
        !           174:   if(arg<=0)return -1;
        !           175: 
        !           176:   while(arg>>=1)++i;
        !           177:   return i;
        !           178: }
        !           179: 
        !           180: #ifndef __DMSDOS_LIB__
        !           181: void do_spc_init(void)
        !           182: { /* first call of DMSDOS filesystem, initialising variables */
        !           183:   int i;
        !           184: 
        !           185:   printk(KERN_NOTICE "DMSDOS CVF-FAT extension version %d.%d.%d" DMSDOS_VLT
        !           186:          " compiled " __DATE__ " " __TIME__ " with options:"
        !           187: #ifndef DBL_WRITEACCESS
        !           188:          " read-only"
        !           189: #else
        !           190:          " read-write"
        !           191: #endif
        !           192: #ifdef   USE_XMALLOC
        !           193:          ", xmalloc"
        !           194: #else
        !           195: #ifdef   USE_VMALLOC
        !           196:          ", vmalloc"
        !           197: #else
        !           198:          ", kmalloc"
        !           199: #endif
        !           200: #endif
        !           201: #ifdef DMSDOS_USE_READPAGE
        !           202:          ", readpage"
        !           203: #endif
        !           204: #ifdef   USE_READA_LIST
        !           205:          ", reada list"
        !           206: #endif
        !           207: #ifdef INTERNAL_DAEMON
        !           208:          ", internal daemon"
        !           209: #endif
        !           210: #ifdef DMSDOS_CONFIG_DBLSP_DRVSP
        !           211:          ", doublespace/drivespace(<3)"
        !           212: #endif
        !           213: #ifdef DMSDOS_CONFIG_DRVSP3
        !           214:          ", drivespace 3"
        !           215: #endif
        !           216: #ifdef DMSDOS_CONFIG_STAC3
        !           217:          ", stacker 3"
        !           218: #endif
        !           219: #ifdef DMSDOS_CONFIG_STAC4
        !           220:          ", stacker 4"
        !           221: #endif
        !           222:          "\n",
        !           223:          DMSDOS_MAJOR,DMSDOS_MINOR,DMSDOS_ACT_REL);
        !           224: 
        !           225:   /* init cluster cache */
        !           226:   ccache_init();
        !           227:   
        !           228: /* no this is done by mount ... and removed by unmount 
        !           229:    otherwise the module cannot be unloaded again if the
        !           230:    internal daemon is running  
        !           231:   init_daemon(); 
        !           232: */
        !           233:   
        !           234: #ifdef USE_READA_LIST
        !           235:   init_reada_list();
        !           236: #endif
        !           237: 
        !           238:   for(i=0;i<MDFATCACHESIZE;++i)
        !           239:   {  mdfat[i].a_time=0;
        !           240:      mdfat[i].a_acc=0;
        !           241:      mdfat[i].a_buffer=NULL;
        !           242:   }
        !           243:   for(i=0;i<DFATCACHESIZE;++i)
        !           244:   {  dfat[i].a_time=0;
        !           245:      dfat[i].a_acc=0;
        !           246:      dfat[i].a_buffer=NULL;
        !           247:   }
        !           248:   for(i=0;i<BITFATCACHESIZE;++i)
        !           249:   {  bitfat[i].a_time=0;
        !           250:      bitfat[i].a_acc=0;
        !           251:      bitfat[i].a_buffer=NULL;
        !           252:   }
        !           253: }
        !           254: 
        !           255: void do_spc_exit(void)
        !           256: { 
        !           257:   force_exit_daemon();
        !           258: }
        !           259: #endif
        !           260: 
        !           261: #ifdef DMSDOS_CONFIG_DBL
        !           262: int detect_dblspace(struct super_block*sb)
        !           263: { struct buffer_head*bh;
        !           264: 
        !           265:   MOD_INC_USE_COUNT;
        !           266:   bh=raw_bread(sb,0);
        !           267:   if(bh==NULL)
        !           268:   { printk(KERN_ERR "DMSDOS: unable to read super block\n");
        !           269:     MOD_DEC_USE_COUNT;
        !           270:     return 0;
        !           271:   }
        !           272:   if(strncmp(bh->b_data+3,"MSDBL6.0",8)==0
        !           273:      ||strncmp(bh->b_data+3,"MSDSP6.0",8)==0)
        !           274:   { raw_brelse(sb,bh);
        !           275:     MOD_DEC_USE_COUNT;
        !           276:     return 1;
        !           277:   }
        !           278:   raw_brelse(sb,bh);
        !           279:   MOD_DEC_USE_COUNT;
        !           280:   return 0;
        !           281: }
        !           282: 
        !           283: int mount_dblspace(struct super_block*sb,char*options)
        !           284: { struct buffer_head*bh;
        !           285:   struct buffer_head*bh2;
        !           286:   int i,mdfatb,fatb;
        !           287:   unsigned int version_flag;
        !           288:   unsigned char * pp;
        !           289:   Dblsb* dblsb;
        !           290:   int repair=0;
        !           291:   int mdrc,m_sector=0;
        !           292:   
        !           293:   MOD_INC_USE_COUNT;
        !           294:   LOG_REST("DMSDOS: dblspace/drvspace module mounting...\n");
        !           295:   bh=raw_bread(sb,0);
        !           296:   if(bh==NULL)
        !           297:   { printk(KERN_ERR "DMSDOS: unable to read super block\n");
        !           298:     MOD_DEC_USE_COUNT;
        !           299:     return -1;
        !           300:   }
        !           301:   if(strncmp(bh->b_data+3,"MSDBL6.0",8)&&strncmp(bh->b_data+3,"MSDSP6.0",8))
        !           302:   { printk(KERN_ERR "DMSDOS: MSDBL/MSDSP signature not found, CVF skipped\n");
        !           303:     raw_brelse(sb,bh);
        !           304:     MOD_DEC_USE_COUNT;
        !           305:     return -1;
        !           306:   }
        !           307:   dblsb=kmalloc(sizeof(Dblsb),GFP_KERNEL);
        !           308:   if(dblsb==NULL)
        !           309:   { printk(KERN_ERR "DMSDOS: mount_dblspace: out of memory\n");
        !           310:     raw_brelse(sb,bh);
        !           311:     MOD_DEC_USE_COUNT;
        !           312:     return -1;
        !           313:   }
        !           314:   MSDOS_SB(sb)->private_data=dblsb;
        !           315:   /*dblsb->mdfat_alloc_sem=MUTEX;*/
        !           316:   
        !           317: #ifdef __KERNEL__
        !           318:   { struct semaphore* sem;
        !           319: 
        !           320:     sem=kmalloc(sizeof(struct semaphore),GFP_KERNEL);
        !           321:     if(sem==NULL)
        !           322:     { printk(KERN_ERR "DMSDOS: mount_dblspace: out of memory\n");
        !           323:       raw_brelse(sb,bh);
        !           324:       MOD_DEC_USE_COUNT;
        !           325:       return -1;
        !           326:     }  
        !           327:     *sem=MUTEX;
        !           328:     dblsb->mdfat_alloc_semp=sem;
        !           329:   }
        !           330: #endif
        !           331:   
        !           332:   /* find out size */
        !           333:   dblsb->s_dataend=blk_size[MAJOR(sb->s_dev)][MINOR(sb->s_dev)]*2;
        !           334:     
        !           335:   dblsb->s_comp=GUESS;
        !           336:   dblsb->s_cfaktor=DEFAULT_CF;
        !           337: 
        !           338:   if(parse_dmsdos_options(options,dblsb,&repair))
        !           339:   {
        !           340:     raw_brelse(sb,bh);
        !           341:     MOD_DEC_USE_COUNT;
        !           342:     return -1;
        !           343:   }
        !           344:   
        !           345:     
        !           346:   if(sb->s_flags & MS_RDONLY)dblsb->s_comp=READ_ONLY;
        !           347:   printk(KERN_INFO "DMSDOS: mounting CVF on device 0x%x %s...\n",
        !           348:            sb->s_dev,
        !           349:            dblsb->s_comp==READ_ONLY?"read-only":"read-write");
        !           350:   
        !           351:   /* dblspace correction was relocated. Pavel */
        !           352:   dblsb->s_dataend-=1;
        !           353:   
        !           354:   pp=&(bh->b_data[45]);
        !           355:   dblsb->s_dcluster=CHS(pp);
        !           356:   if(dblsb->s_dcluster&0x8000)dblsb->s_dcluster|=0xffff0000;
        !           357:   pp=&(bh->b_data[36]);
        !           358:   dblsb->s_mdfatstart=CHS(pp)+1;
        !           359:   pp=&(bh->b_data[17]);
        !           360:   dblsb->s_rootdirentries=CHS(pp);
        !           361:   dblsb->s_sectperclust=((unsigned long)(bh->b_data[13]));
        !           362:   dblsb->s_spc_bits=ilog2(dblsb->s_sectperclust);
        !           363:   pp=&(bh->b_data[39]);i=CHS(pp);/*i=res0*/
        !           364:   dblsb->s_bootblock=i;
        !           365:   pp=&(bh->b_data[14]);
        !           366:   dblsb->s_fatstart=i+CHS(pp);
        !           367:   pp=&(bh->b_data[41]);
        !           368:   dblsb->s_rootdir=i+CHS(pp);
        !           369:   pp=&(bh->b_data[43]);
        !           370:   dblsb->s_datastart=i+CHS(pp)+2;
        !           371:   dblsb->s_2nd_fat_offset=0; /* dblsp doesn't have a second fat */
        !           372:   dblsb->s_cvf_version=DBLSP;
        !           373:   version_flag=bh->b_data[51];
        !           374:   if(version_flag==2)dblsb->s_cvf_version=DRVSP;
        !           375:   if(version_flag==3||dblsb->s_sectperclust>16)dblsb->s_cvf_version=DRVSP3;
        !           376:   if(version_flag>3)printk(KERN_WARNING "DMSDOS: strange version flag %d, assuming 0.\n",
        !           377:                            version_flag);
        !           378:                            
        !           379: #ifndef DMSDOS_CONFIG_DBLSP_DRVSP
        !           380:   if(dblsb->s_cvf_version<=DRVSP)
        !           381:   { printk(KERN_ERR "DMSDOS: support for doublespace/drivespace(<3) not compiled in.\n");
        !           382:     raw_brelse(sb,bh);
        !           383:     MOD_DEC_USE_COUNT;
        !           384:     return -1;
        !           385:   }
        !           386: #endif
        !           387: #ifndef DMSDOS_CONFIG_DRVSP3
        !           388:   if(dblsb->s_cvf_version==DRVSP3)
        !           389:   { printk(KERN_ERR "DMSDOS: support for drivespace 3 not compiled in.\n");
        !           390:     raw_brelse(sb,bh);
        !           391:     MOD_DEC_USE_COUNT;
        !           392:     return -1;
        !           393:   }
        !           394: #endif
        !           395:   
        !           396:   bh2=raw_bread(sb,dblsb->s_bootblock);
        !           397:   if(bh2==NULL)
        !           398:   { printk(KERN_ERR "DMSDOS: unable to read emulated boot block\n");
        !           399:     raw_brelse(sb,bh);
        !           400:     MOD_DEC_USE_COUNT;
        !           401:     return -1;
        !           402:   }
        !           403:   pp=&(bh2->b_data[57]);
        !           404:   if(CHL(pp)==0x20203631)dblsb->s_16bitfat=1;
        !           405:   else if(CHL(pp)==0x20203231)dblsb->s_16bitfat=0;
        !           406:   else if(CHL(pp)==0x20203233)
        !           407:   { printk(KERN_ERR "DMSDOS: CVF has FAT32 signature, not mounted. Please report this.\n");
        !           408:     raw_brelse(sb,bh2);
        !           409:     raw_brelse(sb,bh);
        !           410:     MOD_DEC_USE_COUNT;
        !           411:     return -1;
        !           412:   }
        !           413:   else
        !           414:   { pp=&(bh->b_data[62]);
        !           415:     dblsb->s_16bitfat=(CHS(pp)>32) ? 1 : 0;
        !           416:     printk(KERN_WARNING "DMSDOS: FAT bit size not recognized, guessed %d bit\n",
        !           417:            CHS(pp)>32 ? 16 : 12 );
        !           418:   }
        !           419:   raw_brelse(sb,bh2); 
        !           420:    
        !           421:   /* try to verify correct end of CVF */
        !           422:   mdrc=0;
        !           423:   for(i=-1;i<=1;++i)
        !           424:   { bh2=raw_bread(sb,dblsb->s_dataend+i);
        !           425:     if(bh2==NULL)
        !           426:     { LOG_REST("DMSDOS: MDR test breaks at i=%d\n",i);
        !           427:       break;
        !           428:     }
        !           429:     if(strcmp(bh2->b_data,"MDR")==0)
        !           430:     { ++mdrc;
        !           431:       m_sector=dblsb->s_dataend+i;
        !           432:       LOG_REST("DMSDOS: MDR signature found at sector %d\n",m_sector);
        !           433:     }
        !           434:     raw_brelse(sb,bh2);
        !           435:   }
        !           436:   if(mdrc!=1)
        !           437:     printk(KERN_WARNING "DMSDOS: could not find MDR signature or found more than one, mdrc=%d (ignored)\n",
        !           438:            mdrc);
        !           439:   else
        !           440:   { if(dblsb->s_dataend!=m_sector-1)
        !           441:     { LOG_REST("DMSDOS: dataend corrected due to MDR signature old=%d new=%d\n",
        !           442:              dblsb->s_dataend,m_sector-1);
        !           443:       dblsb->s_dataend=m_sector-1;
        !           444:     }
        !           445:   }
        !           446:   
        !           447:   dblsb->s_full=0;
        !           448:     
        !           449:   /* calculate maximum cluster nr (fixes lost cluster messages) */
        !           450:   mdfatb=(dblsb->s_bootblock-dblsb->s_mdfatstart);
        !           451:   mdfatb*=((dblsb->s_sectperclust>16)?102:128);
        !           452:   mdfatb-=dblsb->s_dcluster;
        !           453:   fatb=512*(dblsb->s_rootdir-dblsb->s_fatstart);
        !           454:   if(dblsb->s_16bitfat)fatb/=2; else fatb=(2*fatb)/3;
        !           455:   dblsb->s_max_cluster=((mdfatb<fatb)?mdfatb:fatb)-1;
        !           456:   if(dblsb->s_16bitfat)
        !           457:   { if(dblsb->s_max_cluster>0xFFF6)dblsb->s_max_cluster=0xFFF6;
        !           458:   }
        !           459:   else
        !           460:   { if(dblsb->s_max_cluster>0xFF6)dblsb->s_max_cluster=0xFF6;
        !           461:   }
        !           462: 
        !           463:   /* adapt max_cluster according to dos' limits */
        !           464:   dblsb->s_max_cluster2=dblsb->s_max_cluster;
        !           465:   pp=&(bh->b_data[32]);
        !           466:   i=CHL(pp);
        !           467:   pp=&(bh->b_data[22]);
        !           468:   i-=CHS(pp);
        !           469:   pp=&(bh->b_data[14]);
        !           470:   i-=CHS(pp);
        !           471:   i-=dblsb->s_rootdirentries>>4;
        !           472:   /*i=(i>>4)+1;*/
        !           473:   i=(i/dblsb->s_sectperclust)+1;
        !           474:   if(i<=dblsb->s_max_cluster)
        !           475:   { dblsb->s_max_cluster=i;
        !           476:   }
        !           477:   else
        !           478:   { printk(KERN_WARNING "DMSDOS: dos max_cluster=%d too large, cutting to %d.\n",
        !           479:            i,dblsb->s_max_cluster);
        !           480:   }
        !           481:   
        !           482:   LOG_REST("DMSDOS: dcluster=%d\n",dblsb->s_dcluster);
        !           483:   LOG_REST("DMSDOS: mdfatstart=%d\n",dblsb->s_mdfatstart);
        !           484:   LOG_REST("DMSDOS: rootdirentries=%d\n",dblsb->s_rootdirentries);
        !           485:   LOG_REST("DMSDOS: sectperclust=%d\n",dblsb->s_sectperclust);
        !           486:   LOG_REST("DMSDOS: fatstart=%d\n",dblsb->s_fatstart);
        !           487:   LOG_REST("DMSDOS: rootdir=%d\n",dblsb->s_rootdir);
        !           488:   LOG_REST("DMSDOS: %d bit FAT\n",dblsb->s_16bitfat ? 16 : 12);
        !           489: 
        !           490:   dblsb->s_lastnear=0;
        !           491:   dblsb->s_lastbig=0;
        !           492:   dblsb->s_free_sectors=-1;  /* -1 means unknown */
        !           493: 
        !           494:   /* error test (counts sectors) */
        !           495:   if(repair!=-1) /* repair==-1 means do not even check */
        !           496:   {
        !           497:     i=simple_check(sb,repair&1);
        !           498:     if(i==-1||i==-2)
        !           499:     { printk(KERN_WARNING "DMSDOS: CVF has serious errors or compatibility problems, setting to read-only.\n");
        !           500:       dblsb->s_comp=READ_ONLY;
        !           501:     }
        !           502:     if(i==-3)
        !           503:     { if(repair&2)
        !           504:       { printk(KERN_WARNING "DMSDOS: CVF has bitfat mismatches, ignored.\n");
        !           505:       }
        !           506:       else
        !           507:       { printk(KERN_WARNING "DMSDOS: CVF has bitfat mismatches, setting to read-only.\n");
        !           508:         dblsb->s_comp=READ_ONLY;
        !           509:       }
        !           510:     }
        !           511:   }
        !           512: 
        !           513:   /* if still unknown then count now */
        !           514:   if(dblsb->s_free_sectors<0)check_free_sectors(sb);
        !           515: 
        !           516:   /* print doublespace version */
        !           517:   if(dblsb->s_cvf_version==DBLSP&&dblsb->s_sectperclust==16)
        !           518:   { printk(KERN_INFO "DMSDOS: CVF is in doublespace format (version 1).\n");
        !           519:   }
        !           520:   else if(dblsb->s_cvf_version==DRVSP&&dblsb->s_sectperclust==16)
        !           521:   { printk(KERN_INFO "DMSDOS: CVF is in drivespace format (version 2).\n");
        !           522:   }
        !           523:   else if(dblsb->s_cvf_version==DRVSP3&&dblsb->s_sectperclust==64)
        !           524:   { printk(KERN_INFO "DMSDOS: CVF is in drivespace 3 format.\n");
        !           525:   }
        !           526:   else
        !           527:   { printk(KERN_INFO "DMSDOS: CVF is in unknown (new?) format, please report.\n");
        !           528:     printk(KERN_INFO "DMSDOS: version_flag=%d sectperclust=%d\n",version_flag,
        !           529:            dblsb->s_sectperclust);
        !           530:     printk(KERN_NOTICE "DMSDOS: CVF set to read-only.\n");
        !           531:     dblsb->s_comp=READ_ONLY;
        !           532:   }
        !           533:         
        !           534:   raw_brelse(sb,bh);
        !           535: 
        !           536:   /* set some msdos fs important stuff */
        !           537:   MSDOS_SB(sb)->dir_start=FAKED_ROOT_DIR_OFFSET;
        !           538:   MSDOS_SB(sb)->dir_entries=dblsb->s_rootdirentries;
        !           539:   MSDOS_SB(sb)->data_start=FAKED_DATA_START_OFFSET; /*begin of virtual cluster 2*/
        !           540:   MSDOS_SB(sb)->clusters=dblsb->s_max_cluster;
        !           541:   if(MSDOS_SB(sb)->fat_bits!=dblsb->s_16bitfat?16:12)
        !           542:   { LOG_REST("DMSDOS: fat bit size mismatch in fat driver, trying to correct\n");
        !           543:     MSDOS_SB(sb)->fat_bits=dblsb->s_16bitfat?16:12;
        !           544:   }
        !           545:   MSDOS_SB(sb)->cluster_size=dblsb->s_sectperclust;
        !           546:   
        !           547:   /* these *must* always match */
        !           548:   if(dblsb->s_comp==READ_ONLY)sb->s_flags |= MS_RDONLY;
        !           549:   
        !           550:   /* we allow using the daemon - calling this more than once doesn't matter */
        !           551:   init_daemon();
        !           552:   
        !           553:   return 0;
        !           554: }
        !           555: #endif    
        !           556: 
        !           557: int unmount_dblspace(struct super_block*sb)
        !           558: { int j;
        !           559: #if defined(__KERNEL__)||defined(DMSDOS_CONFIG_STAC)
        !           560:   Dblsb*dblsb=MSDOS_SB(sb)->private_data;
        !           561: #endif
        !           562:   
        !           563:   LOG_REST("DMSDOS: CVF on device 0x%x unmounted.\n",sb->s_dev);
        !           564: 
        !           565:   /* discard/write cached clusters */
        !           566:   free_ccache_dev(sb);
        !           567:   /* the same for the daemon if it is running */
        !           568:   clear_list_dev(sb);
        !           569: 
        !           570: #ifdef DMSDOS_CONFIG_STAC
        !           571:   /* mark stacker bitfat as up to date and unmounted */
        !           572:   if(dblsb->s_cvf_version>=STAC3)
        !           573:         stac_bitfat_state(sb,1);
        !           574: #endif
        !           575: 
        !           576:       /* kill buffers used by unmounted cvf */
        !           577:       for(j=0;j<MDFATCACHESIZE;++j)
        !           578:       { if(mdfat[j].a_buffer!=NULL)
        !           579:         { if(mdfat[j].a_sb->s_dev==sb->s_dev)
        !           580:           { raw_brelse(sb,mdfat[j].a_buffer);
        !           581:             mdfat[j].a_buffer=NULL;
        !           582:           }
        !           583:           mdfat[j].a_time=0;
        !           584:           mdfat[j].a_acc=0;
        !           585:         }
        !           586:       }
        !           587:       for(j=0;j<DFATCACHESIZE;++j)
        !           588:       { if(dfat[j].a_buffer!=NULL)
        !           589:         { if(dfat[j].a_sb->s_dev==sb->s_dev)              
        !           590:           { raw_brelse(sb,dfat[j].a_buffer);
        !           591:             dfat[j].a_buffer=NULL;
        !           592:           }
        !           593:           dfat[j].a_time=0;
        !           594:           dfat[j].a_acc=0;
        !           595:         }
        !           596:       }
        !           597:       for(j=0;j<BITFATCACHESIZE;++j)
        !           598:       { if(bitfat[j].a_buffer!=NULL)
        !           599:         { if(bitfat[j].a_sb->s_dev==sb->s_dev)
        !           600:           { raw_brelse(sb,bitfat[j].a_buffer);
        !           601:             bitfat[j].a_buffer=NULL;
        !           602:           }
        !           603:           bitfat[j].a_time=0;
        !           604:           bitfat[j].a_acc=0;
        !           605:         }
        !           606:       }
        !           607: 
        !           608: #ifdef __KERNEL__
        !           609: #ifdef USE_READA_LIST
        !           610:   /* throw away all stacked reada entries for this dev */
        !           611:   kill_reada_list_dev(sb->s_dev);
        !           612: #endif
        !           613:   /* this is unused in the library */
        !           614:   kfree(dblsb->mdfat_alloc_semp);
        !           615: #endif
        !           616:   kfree(MSDOS_SB(sb)->private_data);
        !           617:   MSDOS_SB(sb)->private_data=NULL;
        !           618:   /*MSDOS_SB(sb)->cvf_format=NULL;*/ /*this causes a segfault in 
        !           619:                                        dec_cvf_format_use_count_by_version*/
        !           620:   exit_daemon();
        !           621:   MOD_DEC_USE_COUNT;
        !           622:   return 0;
        !           623: }
        !           624: 
        !           625: #ifdef DMSDOS_CONFIG_STAC
        !           626: int detect_stacker(struct super_block*sb)
        !           627: { struct buffer_head*bh;
        !           628: 
        !           629:   MOD_INC_USE_COUNT;
        !           630:   bh=raw_bread(sb,0);
        !           631:   if(bh==NULL)
        !           632:   { printk(KERN_ERR "DMSDOS: unable to read super block\n");
        !           633:     MOD_DEC_USE_COUNT;
        !           634:     return 0;
        !           635:   }
        !           636:   if(strncmp(bh->b_data,"STACKER",7)==0)
        !           637:   { raw_brelse(sb,bh);
        !           638:     MOD_DEC_USE_COUNT;
        !           639:     return 1;
        !           640:   }
        !           641:   raw_brelse(sb,bh);
        !           642:   MOD_DEC_USE_COUNT;
        !           643:   return 0;
        !           644: }
        !           645: 
        !           646: int mount_stacker(struct super_block*sb,char*options)
        !           647: { 
        !           648:   struct buffer_head*bh;
        !           649:   struct buffer_head*bh2;
        !           650:   int i;
        !           651:   unsigned char * pp, *p;
        !           652:   unsigned char buf[512];
        !           653:   unsigned char b,c;
        !           654:   int SectSize, ClustSects, ClustSize, ReservSects, FATCnt;
        !           655:   int RootDirEnt, TotalSects, FATSize, HidenSects, FirstRootSect;
        !           656:   int FirstDataSect, FirstDataSect2, FAT12, FirstFATSect;
        !           657:   int StacVersion;
        !           658:   /* parameters of virtual DOS drive */
        !           659:   int BB_FirstDataSect, BB_ClustCnt, BB_SectSize, BB_TotalSects;
        !           660:   Dblsb*dblsb;
        !           661:   int repair=0;
        !           662:   
        !           663:   MOD_INC_USE_COUNT;
        !           664:   LOG_REST("DMSDOS: stacker 3/4 module mounting...\n");
        !           665:     
        !           666:   LOG_REST("DMSDOS: reading super block...\n");
        !           667:   bh=raw_bread(sb,0);
        !           668:   if(bh==NULL)
        !           669:   { printk(KERN_ERR "DMSDOS: unable to read super block of CVF\n");
        !           670:     MOD_DEC_USE_COUNT;
        !           671:     return -1;
        !           672:   }
        !           673:   LOG_REST("DMSDOS: super block read finished\n");
        !           674:   pp=&(bh->b_data[0]);
        !           675:   if(strncmp(pp,"STACKER",7)!=0)
        !           676:   { printk(KERN_ERR "DMSDOS: STACKER signature not found\n");
        !           677:     raw_brelse(sb,bh);
        !           678:     MOD_DEC_USE_COUNT;
        !           679:     return -1;
        !           680:   }
        !           681:     
        !           682:   /* copy block (must not directly modify kernel buffer!!!) */
        !           683:   memcpy(buf,bh->b_data,SECTOR_SIZE);
        !           684:   /* decode super block */
        !           685:   for(i=0x30,p=buf+0x50,b=buf[0x4c];i--;p++)
        !           686:   { b=0xc4-b;
        !           687:     b=b<0x80?b*2:b*2+1;
        !           688:     b^=c=*p;
        !           689:     *p=b;b=c;
        !           690:   }
        !           691:   if(buf[0x4e]!=0xa||buf[0x4f]!=0x1a)
        !           692:   { printk(KERN_ERR "DMSDOS: Stacker 0x1A0A signature not found\n");
        !           693:     raw_brelse(sb,bh);
        !           694:     MOD_DEC_USE_COUNT;
        !           695:     return -1;
        !           696:   }
        !           697: 
        !           698:   dblsb=kmalloc(sizeof(Dblsb),GFP_KERNEL);
        !           699:   if(dblsb==NULL)
        !           700:   { printk(KERN_ERR "DMSDOS: mount_stacker: out of memory\n");
        !           701:     raw_brelse(sb,bh);
        !           702:     MOD_DEC_USE_COUNT;
        !           703:     return -1;
        !           704:   }
        !           705:   MSDOS_SB(sb)->private_data=dblsb;
        !           706:   /*dblsb->mdfat_alloc_sem=MUTEX;*/
        !           707:   
        !           708: #ifdef __KERNEL__
        !           709:   { struct semaphore* sem;
        !           710: 
        !           711:     sem=kmalloc(sizeof(struct semaphore),GFP_KERNEL);
        !           712:     if(sem==NULL)
        !           713:     { printk(KERN_ERR "DMSDOS: mount_stacker: out of memory\n");
        !           714:       raw_brelse(sb,bh);
        !           715:       MOD_DEC_USE_COUNT;
        !           716:       return -1;
        !           717:     }  
        !           718:     *sem=MUTEX;
        !           719:     dblsb->mdfat_alloc_semp=sem;
        !           720:   }
        !           721: #endif
        !           722: 
        !           723:   /* find out size */
        !           724:   dblsb->s_dataend=blk_size[MAJOR(sb->s_dev)][MINOR(sb->s_dev)]*2;
        !           725:     
        !           726:   dblsb->s_comp=GUESS;
        !           727:   dblsb->s_cfaktor=DEFAULT_CF;
        !           728: 
        !           729:   if(parse_dmsdos_options(options,dblsb,&repair))
        !           730:   {
        !           731:     raw_brelse(sb,bh);
        !           732:     MOD_DEC_USE_COUNT;
        !           733:     return -1;
        !           734:   }
        !           735:   
        !           736:   if(sb->s_flags & MS_RDONLY)dblsb->s_comp=READ_ONLY;
        !           737:   printk(KERN_NOTICE "DMSDOS: mounting CVF on device 0x%x %s...\n",
        !           738:            sb->s_dev,
        !           739:            dblsb->s_comp==READ_ONLY?"read-only":"read-write");
        !           740: 
        !           741:   /* extract important info */
        !           742:   pp=&(buf[0x6C]);
        !           743:   TotalSects=CHL(pp);
        !           744:   pp=&(buf[0x70]);
        !           745:   dblsb->s_bootblock=CHS(pp);
        !           746:   pp=&(buf[0x74]);
        !           747:   dblsb->s_mdfatstart=CHS(pp); /* here it's AMAP start !!! */
        !           748:   pp=&(buf[0x76]);
        !           749:   FirstFATSect=dblsb->s_fatstart=CHS(pp);
        !           750:   pp=&(buf[0x7a]);
        !           751:   FirstDataSect2=dblsb->s_datastart=CHS(pp);
        !           752:   pp=&(buf[0x60]);
        !           753:   StacVersion=CHS(pp);
        !           754:   if(StacVersion>=410)dblsb->s_cvf_version=STAC4;
        !           755:   else dblsb->s_cvf_version=STAC3;
        !           756:   /* if(buf[0x64]==9)dblsb->s_cvf_version=STAC4;
        !           757:   else dblsb->s_cvf_version=STAC3; */
        !           758: 
        !           759: #ifndef DMSDOS_CONFIG_STAC3
        !           760:   if(dblsb->s_cvf_version==STAC3)
        !           761:   { printk(KERN_ERR "DMSDOS: support for stacker 3 not compiled in.\n");
        !           762:     raw_brelse(sb,bh);
        !           763:     MOD_DEC_USE_COUNT;
        !           764:     return -1;
        !           765:   }
        !           766: #endif
        !           767: #ifndef DMSDOS_CONFIG_STAC4
        !           768:   if(dblsb->s_cvf_version==STAC4)
        !           769:   { printk(KERN_ERR "DMSDOS: support for stacker 4 not compiled in.\n");
        !           770:     raw_brelse(sb,bh);
        !           771:     MOD_DEC_USE_COUNT;
        !           772:     return -1;
        !           773:   }
        !           774: #endif
        !           775:     
        !           776:   /* now we need the boot block */    
        !           777:   bh2=raw_bread(sb,dblsb->s_bootblock);
        !           778:   if(bh2==NULL)
        !           779:   { printk(KERN_ERR "DMSDOS: unable to read emulated boot block of CVF\n");
        !           780:     raw_brelse(sb,bh);
        !           781:     MOD_DEC_USE_COUNT;
        !           782:     return -1;
        !           783:   }
        !           784:   /* read values */
        !           785:   dblsb->s_sectperclust=bh2->b_data[0xd];
        !           786:   dblsb->s_spc_bits=ilog2(dblsb->s_sectperclust);  
        !           787:   pp=&(bh2->b_data[0x11]);
        !           788:   dblsb->s_rootdirentries=CHS(pp);
        !           789:   
        !           790:   pp=&(buf[0x62]);         SectSize=CHS(pp);
        !           791:   pp=&(bh2->b_data[0xB]);  BB_SectSize=CHS(pp);
        !           792:   if(SectSize!=SECTOR_SIZE||BB_SectSize!=SECTOR_SIZE)
        !           793:     printk(KERN_WARNING "DMSDOS: Stacker sector size not 512 bytes, hmm...\n");
        !           794:   ClustSects=bh2->b_data[0xD];
        !           795:   ClustSize=ClustSects*SectSize;
        !           796:   pp=&(bh2->b_data[0xE]);  ReservSects=CHS(pp);
        !           797:   FATCnt=bh2->b_data[0x10];
        !           798:   pp=&(bh2->b_data[0x11]); RootDirEnt=CHS(pp);
        !           799:   pp=&(bh2->b_data[0x13]); BB_TotalSects=CHS(pp);
        !           800:   if(!BB_TotalSects)
        !           801:     { pp=&(bh2->b_data[0x20]); BB_TotalSects=CHL(pp);};
        !           802:   pp=&(bh2->b_data[0x16]); FATSize=CHS(pp);
        !           803:   pp=&(bh2->b_data[0x1B]); HidenSects=CHS(pp);
        !           804:   if(BB_SectSize!=SectSize)printk(KERN_WARNING "DMSDOS: Inconsistent sector length\n");
        !           805:   FirstRootSect=FirstFATSect+3*FATCnt*FATSize;
        !           806:     
        !           807:   dblsb->s_2nd_fat_offset=3*(FATCnt-1)*FATSize;
        !           808:     
        !           809:   /* Number of sectors in root directory */
        !           810:   FirstDataSect=((long)RootDirEnt*0x20+SectSize-1)/SectSize;
        !           811:   /* Emulated data start sector for DOS */
        !           812:   BB_FirstDataSect=FirstDataSect+FATCnt*FATSize+ReservSects;
        !           813:     /* ??? +HidenSects; */
        !           814:   /* Real data start sector */
        !           815:   FirstDataSect+=FirstRootSect;
        !           816:   /* Counting BB_ClustCnt from emulated boot block */
        !           817:   BB_ClustCnt=(BB_TotalSects-BB_FirstDataSect)/ClustSects;
        !           818:   if(BB_ClustCnt>=0xFED)FAT12=0; else FAT12=1;
        !           819:   if(BB_ClustCnt<2||BB_ClustCnt>0xfff7)
        !           820:   { printk(KERN_ERR "DMSDOS: BB_ClustCnt=0x%x impossible (FAT32?)\n",BB_ClustCnt);
        !           821:     raw_brelse(sb,bh2);
        !           822:     raw_brelse(sb,bh);
        !           823:     MOD_DEC_USE_COUNT;
        !           824:     return -1;    
        !           825:   }
        !           826:   if(FirstDataSect2!=FirstDataSect)
        !           827:   { printk(KERN_WARNING "DMSDOS: Inconsistent first data sector number. Mounting READ ONLY.\n");
        !           828:     printk(KERN_WARNING "In header found %u but computed %u\n",(unsigned)FirstDataSect2,(unsigned)FirstDataSect);
        !           829:     dblsb->s_comp=READ_ONLY;
        !           830:   } 
        !           831:             
        !           832:   LOG_REST("DMSDOS: Stac version %u start of FAT %u, root %u, data %u; FATSize %u; FATCnt %u; clusts %u; sects %u\n",
        !           833:    (unsigned)StacVersion,(unsigned)FirstFATSect,(unsigned)FirstRootSect,
        !           834:    (unsigned)FirstDataSect,(unsigned)FATSize,(unsigned)FATCnt,
        !           835:    (unsigned)BB_ClustCnt,(unsigned)BB_TotalSects);
        !           836:    
        !           837:   /* try dos standard method to detect fat bit size - does not work */
        !           838:   /* pp=&(bh2->b_data[57]); */
        !           839:   /* if(CHL(pp)==0x20203631)dblsb->s_16bitfat=1; */
        !           840:   /* else if(CHL(pp)==0x20203231)dblsb->s_16bitfat=0; else */
        !           841: 
        !           842:   /* used only stacker method for fat entry size now */ 
        !           843:   dblsb->s_16bitfat=FAT12? 0: 1;
        !           844:   LOG_REST("DMSDOS: FAT bit size of CVF is %d bit\n",
        !           845:          (FAT12) ? 12 : 16 );
        !           846: 
        !           847:   /* check if clusters fits in FAT */
        !           848:   if(BB_ClustCnt+2>(FAT12?(SECTOR_SIZE*FATSize*2)/3:(SECTOR_SIZE*FATSize)/2))
        !           849:   { printk(KERN_WARNING "DMSDOS: FAT size does not match cluster count. Mounting READ ONLY.\n");
        !           850:     dblsb->s_comp=READ_ONLY;
        !           851:   }
        !           852: 
        !           853:   /* check size of physical media against stacvol parameters */
        !           854:   if((TotalSects<=0)||(TotalSects-1)>dblsb->s_dataend)
        !           855:   { printk(KERN_WARNING "DMSDOS: CVF is shorter about %d sectors. Mounting READ ONLY.\n",
        !           856:       (int)TotalSects-1-dblsb->s_dataend);
        !           857:     dblsb->s_comp=READ_ONLY;
        !           858:   } 
        !           859:   else if((TotalSects-1)<dblsb->s_dataend)
        !           860:   { printk(KERN_INFO "DMSDOS: CVF end padding %d sectors.\n",
        !           861:       (int)dblsb->s_dataend-TotalSects+1);
        !           862:     dblsb->s_dataend=TotalSects-1;
        !           863:   }
        !           864: 
        !           865:   raw_brelse(sb,bh2); 
        !           866:   dblsb->s_full=0;
        !           867:   raw_brelse(sb,bh);
        !           868:     
        !           869:   dblsb->s_rootdir=FirstRootSect;
        !           870:   dblsb->s_max_cluster=dblsb->s_max_cluster2=BB_ClustCnt+1;
        !           871: 
        !           872:   LOG_REST("DMSDOS: mdfatstart=%d\n",dblsb->s_mdfatstart);
        !           873:   LOG_REST("DMSDOS: rootdirentries=%d\n",dblsb->s_rootdirentries);
        !           874:   LOG_REST("DMSDOS: sectperclust=%d\n",dblsb->s_sectperclust);
        !           875:   LOG_REST("DMSDOS: fatstart=%d\n",dblsb->s_fatstart);
        !           876:   LOG_REST("DMSDOS: rootdir=%d\n",dblsb->s_rootdir);
        !           877:   LOG_REST("DMSDOS: %d bit FAT\n",dblsb->s_16bitfat ? 16 : 12);
        !           878: 
        !           879:   /* allocation informations */
        !           880:   dblsb->s_lastnear=0;
        !           881:   dblsb->s_lastbig=0;
        !           882:   dblsb->s_free_sectors=-1;  /* -1 means unknown */
        !           883:  
        !           884:   /* set some msdos fs important stuff */
        !           885:   MSDOS_SB(sb)->dir_start=FAKED_ROOT_DIR_OFFSET;
        !           886:   MSDOS_SB(sb)->dir_entries=dblsb->s_rootdirentries;
        !           887:   MSDOS_SB(sb)->data_start=FAKED_DATA_START_OFFSET; /*begin of virtual cluster 2*/
        !           888:   MSDOS_SB(sb)->clusters=BB_ClustCnt;
        !           889:   if(MSDOS_SB(sb)->fat_bits!=dblsb->s_16bitfat?16:12)
        !           890:   { LOG_REST("DMSDOS: fat bit size mismatch in fat driver, trying to correct\n");
        !           891:     MSDOS_SB(sb)->fat_bits=dblsb->s_16bitfat?16:12;
        !           892:   }
        !           893:   MSDOS_SB(sb)->cluster_size=dblsb->s_sectperclust;
        !           894: 
        !           895:   /* error test */
        !           896:   if(repair!=-1) /* repair==-1 means do not even check */
        !           897:   {
        !           898:     i=simple_check(sb,repair&1);
        !           899:     if(i==-1||i==-2)
        !           900:     { printk(KERN_WARNING "DMSDOS: CVF has serious errors or compatibility problems, setting to read-only.\n");
        !           901:       dblsb->s_comp=READ_ONLY;
        !           902:     }
        !           903:     if(i==-3)
        !           904:     { if(repair&2)
        !           905:       { printk(KERN_WARNING "DMSDOS: CVF has bitfat mismatches, ignored.\n");
        !           906:       }
        !           907:       else
        !           908:       { printk(KERN_WARNING "DMSDOS: CVF has bitfat mismatches, setting to read-only.\n");
        !           909:         dblsb->s_comp=READ_ONLY;
        !           910:       }
        !           911:     }
        !           912:   }
        !           913:   
        !           914:   /* print stacker version */
        !           915:   if(dblsb->s_cvf_version==STAC3)
        !           916:   { printk(KERN_NOTICE "DMSDOS: CVF is in stacker 3 format.\n");
        !           917:   }
        !           918:   else if(dblsb->s_cvf_version==STAC4)
        !           919:   { printk(KERN_NOTICE "DMSDOS: CVF is in stacker 4 format.\n");
        !           920:   }
        !           921:   
        !           922:   /* if still unknown then count now */
        !           923:   if(dblsb->s_free_sectors<0)check_free_sectors(sb);
        !           924: 
        !           925:   /* these *must* always match */
        !           926:   if(dblsb->s_comp==READ_ONLY)sb->s_flags |= MS_RDONLY;
        !           927:   
        !           928:   /* mark stacker bitfat as mounted and changing */
        !           929:   /* if not regulary unmounted, it must be repaired before */
        !           930:   /* next write access */
        !           931:   if((sb->s_flags&MS_RDONLY)==0)stac_bitfat_state(sb,2);
        !           932:     
        !           933:   /* we allow using the daemon - calling this more than once doesn't matter */
        !           934:   init_daemon();
        !           935: 
        !           936:   return 0;
        !           937: }
        !           938: #endif
        !           939: 
        !           940: #ifdef DMSDOS_USE_READPAGE
        !           941: #define READPAGE dblspace_readpage
        !           942: #define MMAP NULL
        !           943: #define RMFLAG CVF_USE_READPAGE
        !           944: #else
        !           945: #define READPAGE NULL
        !           946: #define MMAP dblspace_mmap
        !           947: #define RMFLAG 0
        !           948: #endif
        !           949: 
        !           950: #ifndef __DMSDOS_LIB__
        !           951: #ifdef DMSDOS_CONFIG_DBL
        !           952: struct cvf_format dblspace_format = {
        !           953:   0x0001,                     /* version id */
        !           954:   "dblspace",                 /* version text */
        !           955:   RMFLAG,                     /* flags */
        !           956:   detect_dblspace,            /* detect */
        !           957:   mount_dblspace,             /* mount */
        !           958:   unmount_dblspace,           /* unmount */
        !           959:   dblspace_bread,             /* bread */
        !           960:   dblspace_getblk,            /* getblk */
        !           961:   dblspace_brelse,            /* brelse */
        !           962:   dblspace_mark_buffer_dirty, /* mark_buffer_dirty */
        !           963:   dblspace_set_uptodate,      /* set_uptodate */
        !           964:   dblspace_is_uptodate,       /* is_uptodate */
        !           965:   dblspace_ll_rw_block,       /* ll_rw_block */
        !           966:   dblspace_fat_access,        /* fat_access */
        !           967:   NULL,                       /* statfs */
        !           968:   dblspace_bmap,              /* bmap */
        !           969:   dblspace_smap,              /* smap */
        !           970:   dblspace_file_read,         /* file_read */
        !           971:   dblspace_file_write,        /* file_write */
        !           972:   MMAP,                       /* mmap */
        !           973:   READPAGE,                   /* readpage */
        !           974:   NULL,                       /* writepage */
        !           975:   dmsdos_ioctl_dir,           /* dir ioctl */
        !           976:   dblspace_zero_new_cluster   /* zero_new_cluster */
        !           977: };
        !           978: #endif
        !           979: 
        !           980: #ifdef DMSDOS_CONFIG_STAC
        !           981: struct cvf_format stacker_format = {
        !           982:   0x0002,                     /* version id */       /**** only ****/
        !           983:   "stacker",                  /* version text */     /**** these ****/
        !           984:   RMFLAG,                     /* flags */
        !           985:   detect_stacker,             /* detect */           /**** four ****/
        !           986:   mount_stacker,              /* mount */            /**** differ :) ****/
        !           987:   unmount_dblspace,           /* unmount */
        !           988:   dblspace_bread,             /* bread */
        !           989:   dblspace_getblk,            /* getblk */
        !           990:   dblspace_brelse,            /* brelse */
        !           991:   dblspace_mark_buffer_dirty, /* mark_buffer_dirty */
        !           992:   dblspace_set_uptodate,      /* set_uptodate */
        !           993:   dblspace_is_uptodate,       /* is_uptodate */
        !           994:   dblspace_ll_rw_block,       /* ll_rw_block */
        !           995:   dblspace_fat_access,        /* fat_access */
        !           996:   NULL,                       /* statfs */
        !           997:   dblspace_bmap,              /* bmap */
        !           998:   dblspace_smap,              /* smap */
        !           999:   dblspace_file_read,         /* file_read */
        !          1000:   dblspace_file_write,        /* file_write */
        !          1001:   MMAP,                       /* mmap */
        !          1002:   READPAGE,                   /* readpage */
        !          1003:   NULL,                       /* writepage */
        !          1004:   dmsdos_ioctl_dir,           /* dir ioctl */
        !          1005:   dblspace_zero_new_cluster   /* zero_new_cluster */
        !          1006: };
        !          1007: #endif
        !          1008: 
        !          1009: int init_module(void)
        !          1010: { int i;
        !          1011: 
        !          1012:   do_spc_init();
        !          1013: #ifdef DMSDOS_CONFIG_DBL
        !          1014:   i=register_cvf_format(&dblspace_format);
        !          1015:   if(i<0)
        !          1016:   { printk(KERN_ERR "register_cvf_format failed, module not loaded successfully\n");
        !          1017:     do_spc_exit();
        !          1018:     return i;
        !          1019:   } 
        !          1020: #endif
        !          1021: #ifdef DMSDOS_CONFIG_STAC
        !          1022:   i=register_cvf_format(&stacker_format);
        !          1023:   if(i<0)
        !          1024:   { printk(KERN_ERR "register_cvf_format failed, module not loaded successfully\n");
        !          1025:     do_spc_exit();
        !          1026: #ifdef DMSDOS_CONFIG_DBL
        !          1027:     unregister_cvf_format(&dblspace_format);
        !          1028: #endif
        !          1029:     return i;
        !          1030:   }
        !          1031: #endif
        !          1032:   LOG_REST("CVF format(s) successfully registered\n");
        !          1033:   
        !          1034:   return 0;
        !          1035: }
        !          1036: 
        !          1037: void cleanup_module(void)
        !          1038: { do_spc_exit();
        !          1039: #ifdef DMSDOS_CONFIG_DBL
        !          1040:   unregister_cvf_format(&dblspace_format);
        !          1041: #endif
        !          1042: #ifdef DMSDOS_CONFIG_STAC
        !          1043:   unregister_cvf_format(&stacker_format);
        !          1044: #endif
        !          1045: }
        !          1046: #endif /* ifndef __DMSDOS_LIB__ */
        !          1047: 
        !          1048: char seq[]="000000";
        !          1049: 
        !          1050: #ifdef __DMSDOS_LIB__
        !          1051: /* we don't need locking in the library */
        !          1052: void lock_prseq(void) {}
        !          1053: void unlock_prseq(void) {}
        !          1054: #else
        !          1055: struct semaphore prseq_sem=MUTEX;   /* Must be initialized to green light */
        !          1056: void lock_prseq(void) {down(&prseq_sem);}
        !          1057: void unlock_prseq(void) {up(&prseq_sem);}
        !          1058: #endif
        !          1059: 
        !          1060: int log_prseq(void)
        !          1061: { int i;
        !          1062: 
        !          1063:   lock_prseq();
        !          1064:     
        !          1065:   i=5;
        !          1066:   while(i>=0)
        !          1067:   { ++seq[i];
        !          1068:     if(seq[i]<='9')break;
        !          1069:     seq[i]='0';
        !          1070:     --i;
        !          1071:   }
        !          1072:   
        !          1073:   printk(seq);
        !          1074:   
        !          1075:   unlock_prseq();
        !          1076:   
        !          1077:   return 1;
        !          1078: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.