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

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
1.1.1.2 ! root       50:   extern long int blk_size[1][1];
1.1       root       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;
1.1.1.2 ! root      266:   bh=raw_bread(sb,0); 
1.1       root      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: 
1.1.1.2 ! root      283: /* setup fresh dblsb structure */
        !           284: Dblsb* malloc_dblsb(void)
        !           285: { Dblsb*dblsb;
        !           286:   
        !           287:   dblsb=kmalloc(sizeof(Dblsb),GFP_KERNEL);
        !           288:   if(dblsb==NULL)return NULL;
        !           289:   dblsb->mdfat_alloc_semp=NULL;
        !           290:   
        !           291:   return dblsb;
        !           292: }
        !           293: 
        !           294: /* ensure all memory is released */
        !           295: void free_dblsb(Dblsb*dblsb)
        !           296: { if(dblsb==NULL)return;
        !           297:   if(dblsb->mdfat_alloc_semp)
        !           298:   { kfree(dblsb->mdfat_alloc_semp);
        !           299:     dblsb->mdfat_alloc_semp=NULL;
        !           300:   }
        !           301:   kfree(dblsb);
        !           302: }
        !           303: 
1.1       root      304: int mount_dblspace(struct super_block*sb,char*options)
                    305: { struct buffer_head*bh;
                    306:   struct buffer_head*bh2;
                    307:   int i,mdfatb,fatb;
                    308:   unsigned int version_flag;
                    309:   unsigned char * pp;
                    310:   Dblsb* dblsb;
                    311:   int repair=0;
                    312:   int mdrc,m_sector=0;
                    313:   
                    314:   MOD_INC_USE_COUNT;
                    315:   LOG_REST("DMSDOS: dblspace/drvspace module mounting...\n");
1.1.1.2 ! root      316: 
        !           317:   dblsb=malloc_dblsb();
1.1       root      318:   if(dblsb==NULL)
                    319:   { printk(KERN_ERR "DMSDOS: mount_dblspace: out of memory\n");
                    320:     MOD_DEC_USE_COUNT;
                    321:     return -1;
                    322:   }
                    323:   MSDOS_SB(sb)->private_data=dblsb;
                    324:   
                    325: #ifdef __KERNEL__
                    326:   { struct semaphore* sem;
                    327: 
                    328:     sem=kmalloc(sizeof(struct semaphore),GFP_KERNEL);
                    329:     if(sem==NULL)
                    330:     { printk(KERN_ERR "DMSDOS: mount_dblspace: out of memory\n");
1.1.1.2 ! root      331:       free_dblsb(dblsb);
        !           332:       MSDOS_SB(sb)->private_data=NULL;
1.1       root      333:       MOD_DEC_USE_COUNT;
                    334:       return -1;
                    335:     }  
1.1.1.2 ! root      336:     init_MUTEX(sem);
1.1       root      337:     dblsb->mdfat_alloc_semp=sem;
                    338:   }
                    339: #endif
1.1.1.2 ! root      340: 
1.1       root      341:   dblsb->s_comp=GUESS;
                    342:   dblsb->s_cfaktor=DEFAULT_CF;
                    343: 
                    344:   if(parse_dmsdos_options(options,dblsb,&repair))
                    345:   {
1.1.1.2 ! root      346:     free_dblsb(dblsb);
        !           347:     MSDOS_SB(sb)->private_data=NULL;
        !           348:     MOD_DEC_USE_COUNT;
        !           349:     return -1;
        !           350:   }
        !           351:   
        !           352:   dblsb->s_dataend=blk_size[MAJOR(sb->s_dev)][MINOR(sb->s_dev)]*2;
        !           353: 
        !           354:   bh=raw_bread(sb,0);
        !           355:   if(bh==NULL)
        !           356:   { printk(KERN_ERR "DMSDOS: unable to read super block\n");
        !           357:     free_dblsb(dblsb);
        !           358:     MSDOS_SB(sb)->private_data=NULL;
        !           359:     MOD_DEC_USE_COUNT;
        !           360:     return -1;
        !           361:   }
        !           362:   if(strncmp(bh->b_data+3,"MSDBL6.0",8)&&strncmp(bh->b_data+3,"MSDSP6.0",8))
        !           363:   { printk(KERN_ERR "DMSDOS: MSDBL/MSDSP signature not found, CVF skipped\n");
1.1       root      364:     raw_brelse(sb,bh);
1.1.1.2 ! root      365:     free_dblsb(dblsb);
        !           366:     MSDOS_SB(sb)->private_data=NULL;
1.1       root      367:     MOD_DEC_USE_COUNT;
                    368:     return -1;
                    369:   }
                    370:   
                    371:   if(sb->s_flags & MS_RDONLY)dblsb->s_comp=READ_ONLY;
                    372:   printk(KERN_INFO "DMSDOS: mounting CVF on device 0x%x %s...\n",
                    373:            sb->s_dev,
                    374:            dblsb->s_comp==READ_ONLY?"read-only":"read-write");
                    375:   
                    376:   /* dblspace correction was relocated. Pavel */
                    377:   dblsb->s_dataend-=1;
                    378:   
                    379:   pp=&(bh->b_data[45]);
                    380:   dblsb->s_dcluster=CHS(pp);
                    381:   if(dblsb->s_dcluster&0x8000)dblsb->s_dcluster|=0xffff0000;
                    382:   pp=&(bh->b_data[36]);
                    383:   dblsb->s_mdfatstart=CHS(pp)+1;
                    384:   pp=&(bh->b_data[17]);
                    385:   dblsb->s_rootdirentries=CHS(pp);
                    386:   dblsb->s_sectperclust=((unsigned long)(bh->b_data[13]));
                    387:   dblsb->s_spc_bits=ilog2(dblsb->s_sectperclust);
                    388:   pp=&(bh->b_data[39]);i=CHS(pp);/*i=res0*/
                    389:   dblsb->s_bootblock=i;
                    390:   pp=&(bh->b_data[14]);
                    391:   dblsb->s_fatstart=i+CHS(pp);
                    392:   pp=&(bh->b_data[41]);
                    393:   dblsb->s_rootdir=i+CHS(pp);
                    394:   pp=&(bh->b_data[43]);
                    395:   dblsb->s_datastart=i+CHS(pp)+2;
                    396:   dblsb->s_2nd_fat_offset=0; /* dblsp doesn't have a second fat */
                    397:   dblsb->s_cvf_version=DBLSP;
                    398:   version_flag=bh->b_data[51];
                    399:   if(version_flag==2)dblsb->s_cvf_version=DRVSP;
                    400:   if(version_flag==3||dblsb->s_sectperclust>16)dblsb->s_cvf_version=DRVSP3;
                    401:   if(version_flag>3)printk(KERN_WARNING "DMSDOS: strange version flag %d, assuming 0.\n",
                    402:                            version_flag);
                    403:                            
                    404: #ifndef DMSDOS_CONFIG_DBLSP_DRVSP
                    405:   if(dblsb->s_cvf_version<=DRVSP)
                    406:   { printk(KERN_ERR "DMSDOS: support for doublespace/drivespace(<3) not compiled in.\n");
                    407:     raw_brelse(sb,bh);
1.1.1.2 ! root      408:     free_dblsb(dblsb);
        !           409:     MSDOS_SB(sb)->private_data=NULL;
1.1       root      410:     MOD_DEC_USE_COUNT;
                    411:     return -1;
                    412:   }
                    413: #endif
                    414: #ifndef DMSDOS_CONFIG_DRVSP3
                    415:   if(dblsb->s_cvf_version==DRVSP3)
                    416:   { printk(KERN_ERR "DMSDOS: support for drivespace 3 not compiled in.\n");
                    417:     raw_brelse(sb,bh);
1.1.1.2 ! root      418:     free_dblsb(dblsb);
        !           419:     MSDOS_SB(sb)->private_data=NULL;
1.1       root      420:     MOD_DEC_USE_COUNT;
                    421:     return -1;
                    422:   }
                    423: #endif
                    424:   
                    425:   bh2=raw_bread(sb,dblsb->s_bootblock);
                    426:   if(bh2==NULL)
                    427:   { printk(KERN_ERR "DMSDOS: unable to read emulated boot block\n");
                    428:     raw_brelse(sb,bh);
1.1.1.2 ! root      429:     free_dblsb(dblsb);
        !           430:     MSDOS_SB(sb)->private_data=NULL;
1.1       root      431:     MOD_DEC_USE_COUNT;
                    432:     return -1;
                    433:   }
                    434:   pp=&(bh2->b_data[57]);
                    435:   if(CHL(pp)==0x20203631)dblsb->s_16bitfat=1;
                    436:   else if(CHL(pp)==0x20203231)dblsb->s_16bitfat=0;
                    437:   else if(CHL(pp)==0x20203233)
                    438:   { printk(KERN_ERR "DMSDOS: CVF has FAT32 signature, not mounted. Please report this.\n");
                    439:     raw_brelse(sb,bh2);
                    440:     raw_brelse(sb,bh);
1.1.1.2 ! root      441:     free_dblsb(dblsb);
        !           442:     MSDOS_SB(sb)->private_data=NULL;
1.1       root      443:     MOD_DEC_USE_COUNT;
                    444:     return -1;
                    445:   }
                    446:   else
                    447:   { pp=&(bh->b_data[62]);
                    448:     dblsb->s_16bitfat=(CHS(pp)>32) ? 1 : 0;
                    449:     printk(KERN_WARNING "DMSDOS: FAT bit size not recognized, guessed %d bit\n",
                    450:            CHS(pp)>32 ? 16 : 12 );
                    451:   }
                    452:   raw_brelse(sb,bh2); 
                    453:    
                    454:   /* try to verify correct end of CVF */
                    455:   mdrc=0;
                    456:   for(i=-1;i<=1;++i)
                    457:   { bh2=raw_bread(sb,dblsb->s_dataend+i);
                    458:     if(bh2==NULL)
                    459:     { LOG_REST("DMSDOS: MDR test breaks at i=%d\n",i);
                    460:       break;
                    461:     }
                    462:     if(strcmp(bh2->b_data,"MDR")==0)
                    463:     { ++mdrc;
                    464:       m_sector=dblsb->s_dataend+i;
                    465:       LOG_REST("DMSDOS: MDR signature found at sector %d\n",m_sector);
                    466:     }
                    467:     raw_brelse(sb,bh2);
                    468:   }
                    469:   if(mdrc!=1)
                    470:     printk(KERN_WARNING "DMSDOS: could not find MDR signature or found more than one, mdrc=%d (ignored)\n",
                    471:            mdrc);
                    472:   else
                    473:   { if(dblsb->s_dataend!=m_sector-1)
                    474:     { LOG_REST("DMSDOS: dataend corrected due to MDR signature old=%d new=%d\n",
                    475:              dblsb->s_dataend,m_sector-1);
                    476:       dblsb->s_dataend=m_sector-1;
                    477:     }
                    478:   }
                    479:   
                    480:   dblsb->s_full=0;
                    481:     
                    482:   /* calculate maximum cluster nr (fixes lost cluster messages) */
                    483:   mdfatb=(dblsb->s_bootblock-dblsb->s_mdfatstart);
                    484:   mdfatb*=((dblsb->s_sectperclust>16)?102:128);
                    485:   mdfatb-=dblsb->s_dcluster;
                    486:   fatb=512*(dblsb->s_rootdir-dblsb->s_fatstart);
                    487:   if(dblsb->s_16bitfat)fatb/=2; else fatb=(2*fatb)/3;
                    488:   dblsb->s_max_cluster=((mdfatb<fatb)?mdfatb:fatb)-1;
                    489:   if(dblsb->s_16bitfat)
                    490:   { if(dblsb->s_max_cluster>0xFFF6)dblsb->s_max_cluster=0xFFF6;
                    491:   }
                    492:   else
                    493:   { if(dblsb->s_max_cluster>0xFF6)dblsb->s_max_cluster=0xFF6;
                    494:   }
                    495: 
                    496:   /* adapt max_cluster according to dos' limits */
                    497:   dblsb->s_max_cluster2=dblsb->s_max_cluster;
                    498:   pp=&(bh->b_data[32]);
                    499:   i=CHL(pp);
                    500:   pp=&(bh->b_data[22]);
                    501:   i-=CHS(pp);
                    502:   pp=&(bh->b_data[14]);
                    503:   i-=CHS(pp);
                    504:   i-=dblsb->s_rootdirentries>>4;
                    505:   /*i=(i>>4)+1;*/
                    506:   i=(i/dblsb->s_sectperclust)+1;
                    507:   if(i<=dblsb->s_max_cluster)
                    508:   { dblsb->s_max_cluster=i;
                    509:   }
                    510:   else
                    511:   { printk(KERN_WARNING "DMSDOS: dos max_cluster=%d too large, cutting to %d.\n",
                    512:            i,dblsb->s_max_cluster);
                    513:   }
                    514:   
                    515:   LOG_REST("DMSDOS: dcluster=%d\n",dblsb->s_dcluster);
                    516:   LOG_REST("DMSDOS: mdfatstart=%d\n",dblsb->s_mdfatstart);
                    517:   LOG_REST("DMSDOS: rootdirentries=%d\n",dblsb->s_rootdirentries);
                    518:   LOG_REST("DMSDOS: sectperclust=%d\n",dblsb->s_sectperclust);
                    519:   LOG_REST("DMSDOS: fatstart=%d\n",dblsb->s_fatstart);
                    520:   LOG_REST("DMSDOS: rootdir=%d\n",dblsb->s_rootdir);
                    521:   LOG_REST("DMSDOS: %d bit FAT\n",dblsb->s_16bitfat ? 16 : 12);
                    522: 
                    523:   dblsb->s_lastnear=0;
                    524:   dblsb->s_lastbig=0;
                    525:   dblsb->s_free_sectors=-1;  /* -1 means unknown */
                    526: 
                    527:   /* error test (counts sectors) */
                    528:   if(repair!=-1) /* repair==-1 means do not even check */
                    529:   {
                    530:     i=simple_check(sb,repair&1);
                    531:     if(i==-1||i==-2)
                    532:     { printk(KERN_WARNING "DMSDOS: CVF has serious errors or compatibility problems, setting to read-only.\n");
                    533:       dblsb->s_comp=READ_ONLY;
                    534:     }
                    535:     if(i==-3)
                    536:     { if(repair&2)
                    537:       { printk(KERN_WARNING "DMSDOS: CVF has bitfat mismatches, ignored.\n");
                    538:       }
                    539:       else
                    540:       { printk(KERN_WARNING "DMSDOS: CVF has bitfat mismatches, setting to read-only.\n");
                    541:         dblsb->s_comp=READ_ONLY;
                    542:       }
                    543:     }
                    544:   }
                    545: 
                    546:   /* if still unknown then count now */
                    547:   if(dblsb->s_free_sectors<0)check_free_sectors(sb);
                    548: 
                    549:   /* print doublespace version */
                    550:   if(dblsb->s_cvf_version==DBLSP&&dblsb->s_sectperclust==16)
                    551:   { printk(KERN_INFO "DMSDOS: CVF is in doublespace format (version 1).\n");
                    552:   }
                    553:   else if(dblsb->s_cvf_version==DRVSP&&dblsb->s_sectperclust==16)
                    554:   { printk(KERN_INFO "DMSDOS: CVF is in drivespace format (version 2).\n");
                    555:   }
                    556:   else if(dblsb->s_cvf_version==DRVSP3&&dblsb->s_sectperclust==64)
                    557:   { printk(KERN_INFO "DMSDOS: CVF is in drivespace 3 format.\n");
                    558:   }
                    559:   else
                    560:   { printk(KERN_INFO "DMSDOS: CVF is in unknown (new?) format, please report.\n");
                    561:     printk(KERN_INFO "DMSDOS: version_flag=%d sectperclust=%d\n",version_flag,
                    562:            dblsb->s_sectperclust);
                    563:     printk(KERN_NOTICE "DMSDOS: CVF set to read-only.\n");
                    564:     dblsb->s_comp=READ_ONLY;
                    565:   }
                    566:         
                    567:   raw_brelse(sb,bh);
                    568: 
                    569:   /* set some msdos fs important stuff */
                    570:   MSDOS_SB(sb)->dir_start=FAKED_ROOT_DIR_OFFSET;
                    571:   MSDOS_SB(sb)->dir_entries=dblsb->s_rootdirentries;
                    572:   MSDOS_SB(sb)->data_start=FAKED_DATA_START_OFFSET; /*begin of virtual cluster 2*/
                    573:   MSDOS_SB(sb)->clusters=dblsb->s_max_cluster;
                    574:   if(MSDOS_SB(sb)->fat_bits!=dblsb->s_16bitfat?16:12)
                    575:   { LOG_REST("DMSDOS: fat bit size mismatch in fat driver, trying to correct\n");
                    576:     MSDOS_SB(sb)->fat_bits=dblsb->s_16bitfat?16:12;
                    577:   }
                    578:   MSDOS_SB(sb)->cluster_size=dblsb->s_sectperclust;
1.1.1.2 ! root      579:  #ifdef HAS_SB_CLUSTER_BITS
        !           580:   for(MSDOS_SB(sb)->cluster_bits=0;
        !           581:       (1<<MSDOS_SB(sb)->cluster_bits)<MSDOS_SB(sb)->cluster_size;)
        !           582:         MSDOS_SB(sb)->cluster_bits++;
        !           583:   MSDOS_SB(sb)->cluster_bits+=SECTOR_BITS;
        !           584:  #endif
1.1       root      585:   
                    586:   /* these *must* always match */
                    587:   if(dblsb->s_comp==READ_ONLY)sb->s_flags |= MS_RDONLY;
                    588:   
                    589:   /* we allow using the daemon - calling this more than once doesn't matter */
                    590:   init_daemon();
                    591:   
                    592:   return 0;
                    593: }
                    594: #endif    
                    595: 
                    596: int unmount_dblspace(struct super_block*sb)
                    597: { int j;
                    598:   Dblsb*dblsb=MSDOS_SB(sb)->private_data;
                    599:   
                    600:   LOG_REST("DMSDOS: CVF on device 0x%x unmounted.\n",sb->s_dev);
                    601: 
                    602:   /* discard/write cached clusters */
                    603:   free_ccache_dev(sb);
                    604:   /* the same for the daemon if it is running */
                    605:   clear_list_dev(sb);
                    606: 
                    607: #ifdef DMSDOS_CONFIG_STAC
                    608:   /* mark stacker bitfat as up to date and unmounted */
                    609:   if(dblsb->s_cvf_version>=STAC3)
                    610:         stac_bitfat_state(sb,1);
                    611: #endif
                    612: 
                    613:       /* kill buffers used by unmounted cvf */
                    614:       for(j=0;j<MDFATCACHESIZE;++j)
                    615:       { if(mdfat[j].a_buffer!=NULL)
                    616:         { if(mdfat[j].a_sb->s_dev==sb->s_dev)
                    617:           { raw_brelse(sb,mdfat[j].a_buffer);
                    618:             mdfat[j].a_buffer=NULL;
                    619:           }
                    620:           mdfat[j].a_time=0;
                    621:           mdfat[j].a_acc=0;
                    622:         }
                    623:       }
                    624:       for(j=0;j<DFATCACHESIZE;++j)
                    625:       { if(dfat[j].a_buffer!=NULL)
                    626:         { if(dfat[j].a_sb->s_dev==sb->s_dev)              
                    627:           { raw_brelse(sb,dfat[j].a_buffer);
                    628:             dfat[j].a_buffer=NULL;
                    629:           }
                    630:           dfat[j].a_time=0;
                    631:           dfat[j].a_acc=0;
                    632:         }
                    633:       }
                    634:       for(j=0;j<BITFATCACHESIZE;++j)
                    635:       { if(bitfat[j].a_buffer!=NULL)
                    636:         { if(bitfat[j].a_sb->s_dev==sb->s_dev)
                    637:           { raw_brelse(sb,bitfat[j].a_buffer);
                    638:             bitfat[j].a_buffer=NULL;
                    639:           }
                    640:           bitfat[j].a_time=0;
                    641:           bitfat[j].a_acc=0;
                    642:         }
                    643:       }
                    644: 
                    645: #ifdef __KERNEL__
                    646: #ifdef USE_READA_LIST
                    647:   /* throw away all stacked reada entries for this dev */
                    648:   kill_reada_list_dev(sb->s_dev);
                    649: #endif
                    650:   /* this is unused in the library */
1.1.1.2 ! root      651:   /* looks like we don't need this here... */
        !           652:   /*kfree(dblsb->mdfat_alloc_semp);*/
        !           653:   /*dblsb->mdfat_alloc_semp=NULL;*/
1.1       root      654: #endif
1.1.1.2 ! root      655:   /*kfree(MSDOS_SB(sb)->private_data);*/
        !           656:   free_dblsb(dblsb);
1.1       root      657:   MSDOS_SB(sb)->private_data=NULL;
                    658:   /*MSDOS_SB(sb)->cvf_format=NULL;*/ /*this causes a segfault in 
                    659:                                        dec_cvf_format_use_count_by_version*/
                    660:   exit_daemon();
                    661:   MOD_DEC_USE_COUNT;
                    662:   return 0;
                    663: }
                    664: 
                    665: #ifdef DMSDOS_CONFIG_STAC
                    666: int detect_stacker(struct super_block*sb)
                    667: { struct buffer_head*bh;
                    668: 
                    669:   MOD_INC_USE_COUNT;
                    670:   bh=raw_bread(sb,0);
                    671:   if(bh==NULL)
                    672:   { printk(KERN_ERR "DMSDOS: unable to read super block\n");
                    673:     MOD_DEC_USE_COUNT;
                    674:     return 0;
                    675:   }
                    676:   if(strncmp(bh->b_data,"STACKER",7)==0)
                    677:   { raw_brelse(sb,bh);
                    678:     MOD_DEC_USE_COUNT;
                    679:     return 1;
                    680:   }
                    681:   raw_brelse(sb,bh);
                    682:   MOD_DEC_USE_COUNT;
                    683:   return 0;
                    684: }
                    685: 
                    686: int mount_stacker(struct super_block*sb,char*options)
                    687: { 
                    688:   struct buffer_head*bh;
                    689:   struct buffer_head*bh2;
                    690:   int i;
                    691:   unsigned char * pp, *p;
                    692:   unsigned char buf[512];
                    693:   unsigned char b,c;
                    694:   int SectSize, ClustSects, ClustSize, ReservSects, FATCnt;
                    695:   int RootDirEnt, TotalSects, FATSize, HidenSects, FirstRootSect;
                    696:   int FirstDataSect, FirstDataSect2, FAT12, FirstFATSect;
                    697:   int StacVersion;
                    698:   /* parameters of virtual DOS drive */
                    699:   int BB_FirstDataSect, BB_ClustCnt, BB_SectSize, BB_TotalSects;
                    700:   Dblsb*dblsb;
                    701:   int repair=0;
                    702:   
                    703:   MOD_INC_USE_COUNT;
                    704:   LOG_REST("DMSDOS: stacker 3/4 module mounting...\n");
                    705:     
1.1.1.2 ! root      706:   dblsb=malloc_dblsb();
        !           707:   if(dblsb==NULL)
        !           708:   { printk(KERN_ERR "DMSDOS: mount_stacker: out of memory\n");
        !           709:     MOD_DEC_USE_COUNT;
        !           710:     return -1;
        !           711:   }
        !           712:   MSDOS_SB(sb)->private_data=dblsb;
        !           713:   
        !           714: #ifdef __KERNEL__
        !           715:   { struct semaphore* sem;
        !           716: 
        !           717:     sem=kmalloc(sizeof(struct semaphore),GFP_KERNEL);
        !           718:     if(sem==NULL)
        !           719:     { printk(KERN_ERR "DMSDOS: mount_stacker: out of memory\n");
        !           720:       free_dblsb(dblsb);
        !           721:       MSDOS_SB(sb)->private_data=NULL;
        !           722:       MOD_DEC_USE_COUNT;
        !           723:       return -1;
        !           724:     }  
        !           725:     init_MUTEX(sem);
        !           726:     dblsb->mdfat_alloc_semp=sem;
        !           727:   }
        !           728: #endif
        !           729: 
        !           730:   dblsb->s_comp=GUESS;
        !           731:   dblsb->s_cfaktor=DEFAULT_CF;
        !           732: 
        !           733:   if(parse_dmsdos_options(options,dblsb,&repair))
        !           734:   {
        !           735:     free_dblsb(dblsb);
        !           736:     MSDOS_SB(sb)->private_data=NULL;
        !           737:     MOD_DEC_USE_COUNT;
        !           738:     return -1;
        !           739:   }
        !           740: 
        !           741:   dblsb->s_dataend=blk_size[MAJOR(sb->s_dev)][MINOR(sb->s_dev)]*2;
        !           742:    
1.1       root      743:   LOG_REST("DMSDOS: reading super block...\n");
                    744:   bh=raw_bread(sb,0);
                    745:   if(bh==NULL)
                    746:   { printk(KERN_ERR "DMSDOS: unable to read super block of CVF\n");
1.1.1.2 ! root      747:     free_dblsb(dblsb);
        !           748:     MSDOS_SB(sb)->private_data=NULL;
1.1       root      749:     MOD_DEC_USE_COUNT;
                    750:     return -1;
                    751:   }
                    752:   LOG_REST("DMSDOS: super block read finished\n");
                    753:   pp=&(bh->b_data[0]);
                    754:   if(strncmp(pp,"STACKER",7)!=0)
                    755:   { printk(KERN_ERR "DMSDOS: STACKER signature not found\n");
                    756:     raw_brelse(sb,bh);
1.1.1.2 ! root      757:     free_dblsb(dblsb);
        !           758:     MSDOS_SB(sb)->private_data=NULL;
1.1       root      759:     MOD_DEC_USE_COUNT;
                    760:     return -1;
                    761:   }
                    762:     
                    763:   /* copy block (must not directly modify kernel buffer!!!) */
                    764:   memcpy(buf,bh->b_data,SECTOR_SIZE);
                    765:   /* decode super block */
                    766:   for(i=0x30,p=buf+0x50,b=buf[0x4c];i--;p++)
                    767:   { b=0xc4-b;
                    768:     b=b<0x80?b*2:b*2+1;
                    769:     b^=c=*p;
                    770:     *p=b;b=c;
                    771:   }
                    772:   if(buf[0x4e]!=0xa||buf[0x4f]!=0x1a)
                    773:   { printk(KERN_ERR "DMSDOS: Stacker 0x1A0A signature not found\n");
                    774:     raw_brelse(sb,bh);
1.1.1.2 ! root      775:     free_dblsb(dblsb);
        !           776:     MSDOS_SB(sb)->private_data=NULL;
1.1       root      777:     MOD_DEC_USE_COUNT;
                    778:     return -1;
                    779:   }
                    780: 
                    781:   if(sb->s_flags & MS_RDONLY)dblsb->s_comp=READ_ONLY;
                    782:   printk(KERN_NOTICE "DMSDOS: mounting CVF on device 0x%x %s...\n",
                    783:            sb->s_dev,
                    784:            dblsb->s_comp==READ_ONLY?"read-only":"read-write");
                    785: 
                    786:   /* extract important info */
                    787:   pp=&(buf[0x6C]);
                    788:   TotalSects=CHL(pp);
                    789:   pp=&(buf[0x70]);
                    790:   dblsb->s_bootblock=CHS(pp);
                    791:   pp=&(buf[0x74]);
                    792:   dblsb->s_mdfatstart=CHS(pp); /* here it's AMAP start !!! */
                    793:   pp=&(buf[0x76]);
                    794:   FirstFATSect=dblsb->s_fatstart=CHS(pp);
                    795:   pp=&(buf[0x7a]);
                    796:   FirstDataSect2=dblsb->s_datastart=CHS(pp);
                    797:   pp=&(buf[0x60]);
                    798:   StacVersion=CHS(pp);
                    799:   if(StacVersion>=410)dblsb->s_cvf_version=STAC4;
                    800:   else dblsb->s_cvf_version=STAC3;
                    801:   /* if(buf[0x64]==9)dblsb->s_cvf_version=STAC4;
                    802:   else dblsb->s_cvf_version=STAC3; */
                    803: 
                    804: #ifndef DMSDOS_CONFIG_STAC3
                    805:   if(dblsb->s_cvf_version==STAC3)
                    806:   { printk(KERN_ERR "DMSDOS: support for stacker 3 not compiled in.\n");
                    807:     raw_brelse(sb,bh);
1.1.1.2 ! root      808:     free_dblsb(dblsb);
        !           809:     MSDOS_SB(sb)->private_data=NULL;
1.1       root      810:     MOD_DEC_USE_COUNT;
                    811:     return -1;
                    812:   }
                    813: #endif
                    814: #ifndef DMSDOS_CONFIG_STAC4
                    815:   if(dblsb->s_cvf_version==STAC4)
                    816:   { printk(KERN_ERR "DMSDOS: support for stacker 4 not compiled in.\n");
                    817:     raw_brelse(sb,bh);
1.1.1.2 ! root      818:     free_dblsb(dblsb);
        !           819:     MSDOS_SB(sb)->private_data=NULL;
1.1       root      820:     MOD_DEC_USE_COUNT;
                    821:     return -1;
                    822:   }
                    823: #endif
                    824:     
                    825:   /* now we need the boot block */    
                    826:   bh2=raw_bread(sb,dblsb->s_bootblock);
                    827:   if(bh2==NULL)
                    828:   { printk(KERN_ERR "DMSDOS: unable to read emulated boot block of CVF\n");
                    829:     raw_brelse(sb,bh);
1.1.1.2 ! root      830:     free_dblsb(dblsb);
        !           831:     MSDOS_SB(sb)->private_data=NULL;
1.1       root      832:     MOD_DEC_USE_COUNT;
                    833:     return -1;
                    834:   }
                    835:   /* read values */
                    836:   dblsb->s_sectperclust=bh2->b_data[0xd];
                    837:   dblsb->s_spc_bits=ilog2(dblsb->s_sectperclust);  
                    838:   pp=&(bh2->b_data[0x11]);
                    839:   dblsb->s_rootdirentries=CHS(pp);
                    840:   
                    841:   pp=&(buf[0x62]);         SectSize=CHS(pp);
                    842:   pp=&(bh2->b_data[0xB]);  BB_SectSize=CHS(pp);
                    843:   if(SectSize!=SECTOR_SIZE||BB_SectSize!=SECTOR_SIZE)
                    844:     printk(KERN_WARNING "DMSDOS: Stacker sector size not 512 bytes, hmm...\n");
                    845:   ClustSects=bh2->b_data[0xD];
                    846:   ClustSize=ClustSects*SectSize;
                    847:   pp=&(bh2->b_data[0xE]);  ReservSects=CHS(pp);
                    848:   FATCnt=bh2->b_data[0x10];
                    849:   pp=&(bh2->b_data[0x11]); RootDirEnt=CHS(pp);
                    850:   pp=&(bh2->b_data[0x13]); BB_TotalSects=CHS(pp);
                    851:   if(!BB_TotalSects)
                    852:     { pp=&(bh2->b_data[0x20]); BB_TotalSects=CHL(pp);};
                    853:   pp=&(bh2->b_data[0x16]); FATSize=CHS(pp);
                    854:   pp=&(bh2->b_data[0x1B]); HidenSects=CHS(pp);
                    855:   if(BB_SectSize!=SectSize)printk(KERN_WARNING "DMSDOS: Inconsistent sector length\n");
                    856:   FirstRootSect=FirstFATSect+3*FATCnt*FATSize;
                    857:     
                    858:   dblsb->s_2nd_fat_offset=3*(FATCnt-1)*FATSize;
                    859:     
                    860:   /* Number of sectors in root directory */
                    861:   FirstDataSect=((long)RootDirEnt*0x20+SectSize-1)/SectSize;
                    862:   /* Emulated data start sector for DOS */
                    863:   BB_FirstDataSect=FirstDataSect+FATCnt*FATSize+ReservSects;
                    864:     /* ??? +HidenSects; */
                    865:   /* Real data start sector */
                    866:   FirstDataSect+=FirstRootSect;
                    867:   /* Counting BB_ClustCnt from emulated boot block */
                    868:   BB_ClustCnt=(BB_TotalSects-BB_FirstDataSect)/ClustSects;
                    869:   if(BB_ClustCnt>=0xFED)FAT12=0; else FAT12=1;
                    870:   if(BB_ClustCnt<2||BB_ClustCnt>0xfff7)
                    871:   { printk(KERN_ERR "DMSDOS: BB_ClustCnt=0x%x impossible (FAT32?)\n",BB_ClustCnt);
                    872:     raw_brelse(sb,bh2);
                    873:     raw_brelse(sb,bh);
1.1.1.2 ! root      874:     free_dblsb(dblsb);
        !           875:     MSDOS_SB(sb)->private_data=NULL;
1.1       root      876:     MOD_DEC_USE_COUNT;
                    877:     return -1;    
                    878:   }
                    879:   if(FirstDataSect2!=FirstDataSect)
                    880:   { printk(KERN_WARNING "DMSDOS: Inconsistent first data sector number. Mounting READ ONLY.\n");
                    881:     printk(KERN_WARNING "In header found %u but computed %u\n",(unsigned)FirstDataSect2,(unsigned)FirstDataSect);
                    882:     dblsb->s_comp=READ_ONLY;
                    883:   } 
                    884:             
                    885:   LOG_REST("DMSDOS: Stac version %u start of FAT %u, root %u, data %u; FATSize %u; FATCnt %u; clusts %u; sects %u\n",
                    886:    (unsigned)StacVersion,(unsigned)FirstFATSect,(unsigned)FirstRootSect,
                    887:    (unsigned)FirstDataSect,(unsigned)FATSize,(unsigned)FATCnt,
                    888:    (unsigned)BB_ClustCnt,(unsigned)BB_TotalSects);
                    889:    
                    890:   /* try dos standard method to detect fat bit size - does not work */
                    891:   /* pp=&(bh2->b_data[57]); */
                    892:   /* if(CHL(pp)==0x20203631)dblsb->s_16bitfat=1; */
                    893:   /* else if(CHL(pp)==0x20203231)dblsb->s_16bitfat=0; else */
                    894: 
                    895:   /* used only stacker method for fat entry size now */ 
                    896:   dblsb->s_16bitfat=FAT12? 0: 1;
                    897:   LOG_REST("DMSDOS: FAT bit size of CVF is %d bit\n",
                    898:          (FAT12) ? 12 : 16 );
                    899: 
                    900:   /* check if clusters fits in FAT */
                    901:   if(BB_ClustCnt+2>(FAT12?(SECTOR_SIZE*FATSize*2)/3:(SECTOR_SIZE*FATSize)/2))
                    902:   { printk(KERN_WARNING "DMSDOS: FAT size does not match cluster count. Mounting READ ONLY.\n");
                    903:     dblsb->s_comp=READ_ONLY;
                    904:   }
                    905: 
                    906:   /* check size of physical media against stacvol parameters */
                    907:   if((TotalSects<=0)||(TotalSects-1)>dblsb->s_dataend)
                    908:   { printk(KERN_WARNING "DMSDOS: CVF is shorter about %d sectors. Mounting READ ONLY.\n",
                    909:       (int)TotalSects-1-dblsb->s_dataend);
                    910:     dblsb->s_comp=READ_ONLY;
                    911:   } 
                    912:   else if((TotalSects-1)<dblsb->s_dataend)
                    913:   { printk(KERN_INFO "DMSDOS: CVF end padding %d sectors.\n",
                    914:       (int)dblsb->s_dataend-TotalSects+1);
                    915:     dblsb->s_dataend=TotalSects-1;
                    916:   }
                    917: 
                    918:   raw_brelse(sb,bh2); 
                    919:   dblsb->s_full=0;
                    920:   raw_brelse(sb,bh);
                    921:     
                    922:   dblsb->s_rootdir=FirstRootSect;
                    923:   dblsb->s_max_cluster=dblsb->s_max_cluster2=BB_ClustCnt+1;
                    924: 
                    925:   LOG_REST("DMSDOS: mdfatstart=%d\n",dblsb->s_mdfatstart);
                    926:   LOG_REST("DMSDOS: rootdirentries=%d\n",dblsb->s_rootdirentries);
                    927:   LOG_REST("DMSDOS: sectperclust=%d\n",dblsb->s_sectperclust);
                    928:   LOG_REST("DMSDOS: fatstart=%d\n",dblsb->s_fatstart);
                    929:   LOG_REST("DMSDOS: rootdir=%d\n",dblsb->s_rootdir);
                    930:   LOG_REST("DMSDOS: %d bit FAT\n",dblsb->s_16bitfat ? 16 : 12);
                    931: 
                    932:   /* allocation informations */
                    933:   dblsb->s_lastnear=0;
                    934:   dblsb->s_lastbig=0;
                    935:   dblsb->s_free_sectors=-1;  /* -1 means unknown */
                    936:  
                    937:   /* set some msdos fs important stuff */
                    938:   MSDOS_SB(sb)->dir_start=FAKED_ROOT_DIR_OFFSET;
                    939:   MSDOS_SB(sb)->dir_entries=dblsb->s_rootdirentries;
                    940:   MSDOS_SB(sb)->data_start=FAKED_DATA_START_OFFSET; /*begin of virtual cluster 2*/
                    941:   MSDOS_SB(sb)->clusters=BB_ClustCnt;
                    942:   if(MSDOS_SB(sb)->fat_bits!=dblsb->s_16bitfat?16:12)
                    943:   { LOG_REST("DMSDOS: fat bit size mismatch in fat driver, trying to correct\n");
                    944:     MSDOS_SB(sb)->fat_bits=dblsb->s_16bitfat?16:12;
                    945:   }
                    946:   MSDOS_SB(sb)->cluster_size=dblsb->s_sectperclust;
1.1.1.2 ! root      947:  #ifdef HAS_SB_CLUSTER_BITS
        !           948:   for(MSDOS_SB(sb)->cluster_bits=0;
        !           949:       (1<<MSDOS_SB(sb)->cluster_bits)<MSDOS_SB(sb)->cluster_size;)
        !           950:         MSDOS_SB(sb)->cluster_bits++;
        !           951:   MSDOS_SB(sb)->cluster_bits+=SECTOR_BITS;
        !           952:  #endif
1.1       root      953: 
                    954:   /* error test */
                    955:   if(repair!=-1) /* repair==-1 means do not even check */
                    956:   {
                    957:     i=simple_check(sb,repair&1);
                    958:     if(i==-1||i==-2)
                    959:     { printk(KERN_WARNING "DMSDOS: CVF has serious errors or compatibility problems, setting to read-only.\n");
                    960:       dblsb->s_comp=READ_ONLY;
                    961:     }
                    962:     if(i==-3)
                    963:     { if(repair&2)
                    964:       { printk(KERN_WARNING "DMSDOS: CVF has bitfat mismatches, ignored.\n");
                    965:       }
                    966:       else
                    967:       { printk(KERN_WARNING "DMSDOS: CVF has bitfat mismatches, setting to read-only.\n");
                    968:         dblsb->s_comp=READ_ONLY;
                    969:       }
                    970:     }
                    971:   }
                    972:   
                    973:   /* print stacker version */
                    974:   if(dblsb->s_cvf_version==STAC3)
                    975:   { printk(KERN_NOTICE "DMSDOS: CVF is in stacker 3 format.\n");
                    976:   }
                    977:   else if(dblsb->s_cvf_version==STAC4)
                    978:   { printk(KERN_NOTICE "DMSDOS: CVF is in stacker 4 format.\n");
                    979:   }
                    980:   
                    981:   /* if still unknown then count now */
                    982:   if(dblsb->s_free_sectors<0)check_free_sectors(sb);
                    983: 
                    984:   /* these *must* always match */
                    985:   if(dblsb->s_comp==READ_ONLY)sb->s_flags |= MS_RDONLY;
                    986:   
                    987:   /* mark stacker bitfat as mounted and changing */
                    988:   /* if not regulary unmounted, it must be repaired before */
                    989:   /* next write access */
                    990:   if((sb->s_flags&MS_RDONLY)==0)stac_bitfat_state(sb,2);
                    991:     
                    992:   /* we allow using the daemon - calling this more than once doesn't matter */
                    993:   init_daemon();
                    994: 
                    995:   return 0;
                    996: }
                    997: #endif
                    998: 
                    999: #ifdef DMSDOS_USE_READPAGE
                   1000: #define READPAGE dblspace_readpage
                   1001: #define MMAP NULL
                   1002: #define RMFLAG CVF_USE_READPAGE
                   1003: #else
                   1004: #define READPAGE NULL
                   1005: #define MMAP dblspace_mmap
                   1006: #define RMFLAG 0
                   1007: #endif
                   1008: 
                   1009: #ifndef __DMSDOS_LIB__
                   1010: #ifdef DMSDOS_CONFIG_DBL
                   1011: struct cvf_format dblspace_format = {
                   1012:   0x0001,                     /* version id */
                   1013:   "dblspace",                 /* version text */
                   1014:   RMFLAG,                     /* flags */
                   1015:   detect_dblspace,            /* detect */
                   1016:   mount_dblspace,             /* mount */
                   1017:   unmount_dblspace,           /* unmount */
                   1018:   dblspace_bread,             /* bread */
                   1019:   dblspace_getblk,            /* getblk */
                   1020:   dblspace_brelse,            /* brelse */
                   1021:   dblspace_mark_buffer_dirty, /* mark_buffer_dirty */
                   1022:   dblspace_set_uptodate,      /* set_uptodate */
                   1023:   dblspace_is_uptodate,       /* is_uptodate */
                   1024:   dblspace_ll_rw_block,       /* ll_rw_block */
                   1025:   dblspace_fat_access,        /* fat_access */
                   1026:   NULL,                       /* statfs */
                   1027:   dblspace_bmap,              /* bmap */
1.1.1.2 ! root     1028:  #ifndef __FOR_KERNEL_2_3_10
1.1       root     1029:   dblspace_smap,              /* smap */
1.1.1.2 ! root     1030:  #endif
1.1       root     1031:   dblspace_file_read,         /* file_read */
                   1032:   dblspace_file_write,        /* file_write */
                   1033:   MMAP,                       /* mmap */
                   1034:   READPAGE,                   /* readpage */
                   1035:   NULL,                       /* writepage */
                   1036:   dmsdos_ioctl_dir,           /* dir ioctl */
                   1037:   dblspace_zero_new_cluster   /* zero_new_cluster */
                   1038: };
                   1039: #endif
                   1040: 
                   1041: #ifdef DMSDOS_CONFIG_STAC
                   1042: struct cvf_format stacker_format = {
                   1043:   0x0002,                     /* version id */       /**** only ****/
                   1044:   "stacker",                  /* version text */     /**** these ****/
                   1045:   RMFLAG,                     /* flags */
                   1046:   detect_stacker,             /* detect */           /**** four ****/
                   1047:   mount_stacker,              /* mount */            /**** differ :) ****/
                   1048:   unmount_dblspace,           /* unmount */
                   1049:   dblspace_bread,             /* bread */
                   1050:   dblspace_getblk,            /* getblk */
                   1051:   dblspace_brelse,            /* brelse */
                   1052:   dblspace_mark_buffer_dirty, /* mark_buffer_dirty */
                   1053:   dblspace_set_uptodate,      /* set_uptodate */
                   1054:   dblspace_is_uptodate,       /* is_uptodate */
                   1055:   dblspace_ll_rw_block,       /* ll_rw_block */
                   1056:   dblspace_fat_access,        /* fat_access */
                   1057:   NULL,                       /* statfs */
                   1058:   dblspace_bmap,              /* bmap */
1.1.1.2 ! root     1059:  #ifndef __FOR_KERNEL_2_3_10
1.1       root     1060:   dblspace_smap,              /* smap */
1.1.1.2 ! root     1061:  #endif
1.1       root     1062:   dblspace_file_read,         /* file_read */
                   1063:   dblspace_file_write,        /* file_write */
                   1064:   MMAP,                       /* mmap */
                   1065:   READPAGE,                   /* readpage */
                   1066:   NULL,                       /* writepage */
                   1067:   dmsdos_ioctl_dir,           /* dir ioctl */
                   1068:   dblspace_zero_new_cluster   /* zero_new_cluster */
                   1069: };
                   1070: #endif
                   1071: 
1.1.1.2 ! root     1072: int init_dmsdos(void)
1.1       root     1073: { int i;
                   1074: 
                   1075:   do_spc_init();
                   1076: #ifdef DMSDOS_CONFIG_DBL
                   1077:   i=register_cvf_format(&dblspace_format);
                   1078:   if(i<0)
1.1.1.2 ! root     1079:   { printk(KERN_ERR "register_cvf_format failed, dmsdos not loaded successfully\n");
1.1       root     1080:     do_spc_exit();
                   1081:     return i;
                   1082:   } 
                   1083: #endif
                   1084: #ifdef DMSDOS_CONFIG_STAC
                   1085:   i=register_cvf_format(&stacker_format);
                   1086:   if(i<0)
1.1.1.2 ! root     1087:   { printk(KERN_ERR "register_cvf_format failed, dmsdos not loaded successfully\n");
1.1       root     1088:     do_spc_exit();
                   1089: #ifdef DMSDOS_CONFIG_DBL
                   1090:     unregister_cvf_format(&dblspace_format);
                   1091: #endif
                   1092:     return i;
                   1093:   }
                   1094: #endif
                   1095:   LOG_REST("CVF format(s) successfully registered\n");
                   1096:   
                   1097:   return 0;
                   1098: }
                   1099: 
1.1.1.2 ! root     1100: #ifdef MODULE
        !          1101: int init_module(void)
        !          1102: { return init_dmsdos();
        !          1103: }
        !          1104: 
1.1       root     1105: void cleanup_module(void)
                   1106: { do_spc_exit();
                   1107: #ifdef DMSDOS_CONFIG_DBL
                   1108:   unregister_cvf_format(&dblspace_format);
                   1109: #endif
                   1110: #ifdef DMSDOS_CONFIG_STAC
                   1111:   unregister_cvf_format(&stacker_format);
                   1112: #endif
                   1113: }
1.1.1.2 ! root     1114: #endif /* MODULE */
1.1       root     1115: #endif /* ifndef __DMSDOS_LIB__ */
                   1116: 
                   1117: char seq[]="000000";
                   1118: 
                   1119: #ifdef __DMSDOS_LIB__
                   1120: /* we don't need locking in the library */
                   1121: void lock_prseq(void) {}
                   1122: void unlock_prseq(void) {}
                   1123: #else
1.1.1.2 ! root     1124: DECLARE_MUTEX(prseq_sem);   /* Must be initialized to green light */
1.1       root     1125: void lock_prseq(void) {down(&prseq_sem);}
                   1126: void unlock_prseq(void) {up(&prseq_sem);}
                   1127: #endif
                   1128: 
                   1129: int log_prseq(void)
                   1130: { int i;
                   1131: 
                   1132:   lock_prseq();
                   1133:     
                   1134:   i=5;
                   1135:   while(i>=0)
                   1136:   { ++seq[i];
                   1137:     if(seq[i]<='9')break;
                   1138:     seq[i]='0';
                   1139:     --i;
                   1140:   }
                   1141:   
                   1142:   printk(seq);
                   1143:   
                   1144:   unlock_prseq();
                   1145:   
                   1146:   return 1;
                   1147: }

unix.superglobalmegacorp.com

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