Annotation of dmsdos/src/dblspace_dec.c, revision 1.1.1.1

1.1       root        1: /*
                      2: dblspace_dec.c
                      3: 
                      4: DMSDOS CVF-FAT module: [dbl|drv]space cluster read and decompression routines.
                      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/kernel.h>
                     31: #include <linux/sched.h>
                     32: #include <linux/errno.h>
                     33: #include <linux/string.h>
                     34: #include <linux/stat.h>
                     35: #include <linux/mm.h>
                     36: #include <linux/locks.h>
                     37: #include <linux/fs.h>
                     38: #include <linux/malloc.h>
                     39: #include <linux/msdos_fs.h>
                     40: #include <asm/system.h>
                     41: #include <asm/segment.h>
                     42: #include <asm/bitops.h>
                     43: #include <asm/byteorder.h>
                     44: #endif
                     45: 
                     46: #include "dmsdos.h"
                     47: 
                     48: #ifdef __DMSDOS_LIB__
                     49: /* some interface hacks */
                     50: #include"lib_interface.h"
                     51: #include<malloc.h>
                     52: #include<string.h>
                     53: #include<errno.h>
                     54: #include <asm/byteorder.h>
                     55: #endif
                     56: 
                     57: #define INLINE static inline
                     58: 
                     59: /* we always need DS decompression */
                     60: 
                     61: #if defined(__GNUC__) && defined(__i386__) && defined(USE_ASM)
                     62: #define USE_GNU_ASM_i386
                     63: 
                     64: /* copy block, overlaping part is replaced by repeat of previous part */
                     65: /* pointers and counter are modified to point after block */
                     66: #define M_MOVSB(D,S,C) \
                     67: __asm__ /*__volatile__*/(\
                     68:        "cld\n\t" \
                     69:        "rep\n\t" \
                     70:        "movsb\n" \
                     71:        :"=D" (D),"=S" (S),"=c" (C) \
                     72:        :"0" (D),"1" (S),"2" (C) \
                     73:        :"memory")
                     74: 
                     75: 
                     76: #else
                     77: 
                     78: #warning USE_GNU_ASM_I386 not defined, using "C" equivalent
                     79: 
                     80: #define M_MOVSB(D,S,C) for(;(C);(C)--) *((__u8*)(D)++)=*((__u8*)(S)++)
                     81: 
                     82: #endif
                     83: 
                     84: #if !defined(le16_to_cpu)
                     85:     /* for old kernel versions - works only on i386 */
                     86:     #define le16_to_cpu(v) (v)
                     87: #endif
                     88: 
                     89: /* for reading and writting from/to bitstream */
                     90: typedef
                     91:  struct {
                     92:    __u32 buf;  /* bit buffer */
                     93:      int pb;   /* already readed bits from buf */
                     94:    __u16 *pd;  /* first not readed input data */
                     95:    __u16 *pe;  /* after end of data */
                     96:  } bits_t;
                     97: 
                     98: const unsigned dblb_bmsk[]=
                     99:    {0x0,0x1,0x3,0x7,0xF,0x1F,0x3F,0x7F,0xFF,
                    100:     0x1FF,0x3FF,0x7FF,0xFFF,0x1FFF,0x3FFF,0x7FFF,0xFFFF};
                    101: 
                    102: /* read next 16 bits from input */
                    103: #define RDN_G16(bits) \
                    104:    { \
                    105:     (bits).buf>>=16; \
                    106:     (bits).pb-=16; \
                    107:     if((bits).pd<(bits).pe) \
                    108:     { \
                    109:      (bits).buf|=((__u32)(le16_to_cpu(*((bits).pd++))))<<16; \
                    110:     }; \
                    111:    }
                    112: 
                    113: /* prepares at least 16 bits for reading */
                    114: #define RDN_PR(bits,u) \
                    115:    { \
                    116:     if((bits).pb>=16) RDN_G16(bits); \
                    117:     u=(bits).buf>>(bits).pb; \
                    118:    }
                    119: 
                    120: /* initializes reading from bitstream */
                    121: INLINE void dblb_rdi(bits_t *pbits,void *pin,unsigned lin)
                    122: {
                    123:   pbits->pb=32;
                    124:   pbits->pd=(__u16*)pin;
                    125:   pbits->pe=pbits->pd+((lin+1)>>1);
                    126: }
                    127: 
                    128: /* reads n<=16 bits from bitstream *pbits */
                    129: INLINE unsigned dblb_rdn(bits_t *pbits,int n)
                    130: {
                    131:   unsigned u;
                    132:   RDN_PR(*pbits,u);
                    133:   pbits->pb+=n;
                    134:   u&=dblb_bmsk[n];
                    135:   return u;
                    136: }
                    137: 
                    138: INLINE int dblb_rdoffs(bits_t *pbits)
                    139: { unsigned u;
                    140:   RDN_PR(*pbits,u);
                    141:   switch (u&3)
                    142:   {
                    143:     case 0: case 2:
                    144:       pbits->pb+=1+6;  return 63&(u>>1);
                    145:     case 1:
                    146:       pbits->pb+=2+8;  return (255&(u>>2))+64;
                    147:   }
                    148:   pbits->pb+=2+12; return (4095&(u>>2))+320;
                    149: }
                    150: 
                    151: INLINE int dblb_rdlen(bits_t *pbits)
                    152: { unsigned u;
                    153:   RDN_PR(*pbits,u);
                    154:   switch (u&15)
                    155:   { case  1: case  3: case  5: case  7:
                    156:     case  9: case 11: case 13: case 15:
                    157:       pbits->pb++;     return 3;
                    158:     case  2: case  6:
                    159:     case 10: case 14:
                    160:       pbits->pb+=2+1;  return (1&(u>>2))+4;
                    161:     case  4: case 12:
                    162:       pbits->pb+=3+2;  return (3&(u>>3))+6;
                    163:     case  8:
                    164:       pbits->pb+=4+3;  return (7&(u>>4))+10;
                    165:     case  0: ;
                    166:   }
                    167:   switch ((u>>4)&15)
                    168:   { case  1: case  3: case  5: case  7:
                    169:     case  9: case 11: case 13: case 15:
                    170:       pbits->pb+=5+4;  return (15&(u>>5))+18;
                    171:     case  2: case  6:
                    172:     case 10: case 14:
                    173:       pbits->pb+=6+5;  return (31&(u>>6))+34;
                    174:     case  4: case 12:
                    175:       pbits->pb+=7+6;  return (63&(u>>7))+66;
                    176:     case  8:
                    177:       pbits->pb+=8+7;  return (127&(u>>8))+130;
                    178:     case  0: ;
                    179:   }
                    180:   pbits->pb+=9;
                    181:   if(u&256) return dblb_rdn(pbits,8)+258;
                    182:   return -1;
                    183: }
                    184: 
                    185: INLINE int dblb_decrep(bits_t *pbits, __u8 **p, void *pout, __u8 *pend,
                    186:                 int repoffs, int k, int flg)
                    187: { int replen;
                    188:   __u8 *r;
                    189: 
                    190:   if(repoffs==0){LOG_DECOMP("DMSDOS: decrb: zero offset ?\n");return -2;}
                    191:   if(repoffs==0x113f)
                    192:   { 
                    193:     int pos=*p-(__u8*)pout;
                    194:     LOG_DECOMP("DMSDOS: decrb: 0x113f sync found.\n");
                    195:     if((pos%512) && !(flg&0x4000))
                    196:     { LOG_DECOMP("DMSDOS: decrb: sync at decompressed pos %d ?\n",pos);
                    197:       return -2;
                    198:     }
                    199:     return 0;
                    200:   }
                    201:   replen=dblb_rdlen(pbits)+k;
                    202: 
                    203:   if(replen<=0)
                    204:     {LOG_DECOMP("DMSDOS: decrb: illegal count ?\n");return -2;}
                    205:   if((__u8*)pout+repoffs>*p)
                    206:     {LOG_DECOMP("DMSDOS: decrb: of>pos ?\n");return -2;}
                    207:   if(*p+replen>pend)
                    208:     {LOG_DECOMP("DMSDOS: decrb: output overfill ?\n");return -2;}
                    209:   r=*p-repoffs;
                    210:   M_MOVSB(*p,r,replen);
                    211:   return 0;
                    212: }
                    213: 
                    214: /* DS decompression */
                    215: /* flg=0x4000 is used, when called from stacker_dec.c, because of
                    216:    stacker does not store original cluster size and it can mean,
                    217:    that last cluster in file can be ended by garbage */
                    218: int ds_dec(void* pin,int lin, void* pout, int lout, int flg)
                    219: { 
                    220:   __u8 *p, *pend;
                    221:   unsigned u, repoffs;
                    222:   int r;
                    223:   bits_t bits;
                    224: 
                    225:   dblb_rdi(&bits,pin,lin);
                    226:   p=(__u8*)pout;pend=p+lout;
                    227:   if((dblb_rdn(&bits,16))!=0x5344) return -1;
                    228:     
                    229:   u=dblb_rdn(&bits,16);
                    230:   LOG_DECOMP("DMSDOS: DS decompression version %d\n",u);
                    231:   
                    232:   do
                    233:   { r=0;
                    234:     RDN_PR(bits,u);
                    235:     switch(u&3)
                    236:     {
                    237:       case 0:
                    238:        bits.pb+=2+6;
                    239:        repoffs=(u>>2)&63;
                    240:        r=dblb_decrep(&bits,&p,pout,pend,repoffs,-1,flg);
                    241:        break;
                    242:       case 1:
                    243:        bits.pb+=2+7;
                    244:        *(p++)=(u>>2)|128;
                    245:        break;
                    246:       case 2:
                    247:        bits.pb+=2+7;
                    248:        *(p++)=(u>>2)&127;
                    249:        break;
                    250:       case 3:
                    251:        if(u&4) {  bits.pb+=3+12; repoffs=((u>>3)&4095)+320; }
                    252:        else  {  bits.pb+=3+8;  repoffs=((u>>3)&255)+64; };
                    253:        r=dblb_decrep(&bits,&p,pout,pend,repoffs,-1,flg);
                    254:        break;
                    255:     }
                    256:   }while((r==0)&&(p<pend));
                    257:   
                    258:   if(r<0) return r;
                    259: 
                    260:   if(!(flg&0x4000))
                    261:   { 
                    262:     u=dblb_rdn(&bits,3);if(u==7) u=dblb_rdn(&bits,12)+320;
                    263:     if(u!=0x113f)
                    264:     { LOG_DECOMP("DMSDOS: decrb: final sync not found?\n");
                    265:       return -2;
                    266:     }
                    267:   }
                    268: 
                    269:   return p-(__u8*)pout;
                    270: }
                    271: 
                    272: /* JM decompression */
                    273: int jm_dec(void* pin,int lin, void* pout, int lout, int flg)
                    274: { 
                    275:   __u8 *p, *pend;
                    276:   unsigned u, repoffs;
                    277:   int r;
                    278:   bits_t bits;
                    279: 
                    280:   dblb_rdi(&bits,pin,lin);
                    281:   p=(__u8*)pout;pend=p+lout;
                    282:   if((dblb_rdn(&bits,16))!=0x4D4A) return -1;
                    283: 
                    284:   u=dblb_rdn(&bits,16);
                    285:   LOG_DECOMP("DMSDOS: JM decompression version %d\n",u);
                    286: 
                    287:   do
                    288:   { r=0;
                    289:     RDN_PR(bits,u);
                    290:     switch(u&3)
                    291:     {
                    292:       case 0:
                    293:       case 2:
                    294:        bits.pb+=8;
                    295:        *(p++)=(u>>1)&127;
                    296:        break;
                    297:       case 1:
                    298:        bits.pb+=2;
                    299:        repoffs=dblb_rdoffs(&bits);
                    300:        r=dblb_decrep(&bits,&p,pout,pend,repoffs,0,flg);
                    301:        break;
                    302:       case 3:
                    303:        bits.pb+=9;
                    304:        *(p++)=((u>>2)&127)|128;
                    305:        break;
                    306:     }
                    307:   }
                    308:   while((r==0)&&(p<pend));
                    309: 
                    310:   if(r<0) return r;
                    311: 
                    312:   if(!(flg&0x4000))
                    313:   { 
                    314:     u=dblb_rdn(&bits,2);if(u==1) u=dblb_rdoffs(&bits);
                    315:     if(u!=0x113f)
                    316:     { LOG_DECOMP("DMSDOS: decrb: final sync not found?\n");
                    317:       return -2;
                    318:     }
                    319:   }
                    320: 
                    321:   return p-(__u8*)pout;
                    322: }
                    323: 
                    324: 
                    325: /* decompress a compressed doublespace/drivespace cluster clusterk to clusterd
                    326: */
                    327: int dbl_decompress(unsigned char*clusterd, unsigned char*clusterk,
                    328:                Mdfat_entry*mde)
                    329: {
                    330:        int sekcount;
                    331:        int r, lin, lout;
                    332: 
                    333:        sekcount=mde->size_hi_minus_1+1;
                    334:        lin=(mde->size_lo_minus_1+1)*SECTOR_SIZE;
                    335:        lout=(mde->size_hi_minus_1+1)*SECTOR_SIZE;
                    336: 
                    337:   switch(clusterk[0]+((int)clusterk[1]<<8)+
                    338:          ((int)clusterk[2]<<16)+((int)clusterk[3]<<24))
                    339:   {
                    340:     case DS_0_0:
                    341:     case DS_0_1:
                    342:     case DS_0_2:
                    343:         LOG_DECOMP("DMSDOS: decompressing DS-0-x\n");
                    344:         r=ds_dec(clusterk,lin,clusterd,lout,0);
                    345:         if(r<=0)
                    346:         { printk(KERN_ERR "DMSDOS: error in DS-0-x compressed data.\n");
                    347:           return -2;
                    348:         }      
                    349:         LOG_DECOMP("DMSDOS: decompress finished.\n");
                    350:        return 0;
                    351:        
                    352:     case JM_0_0:
                    353:     case JM_0_1:
                    354:         LOG_DECOMP("DMSDOS: decompressing JM-0-x\n");
                    355:         r=jm_dec(clusterk,lin,clusterd,lout,0);
                    356:        if(r<=0)
                    357:        { printk(KERN_ERR "DMSDOS: error in JM-0-x compressed data.\n");
                    358:          return -2;
                    359:        }
                    360:        LOG_DECOMP("DMSDOS: decompress finished.\n");
                    361:        return 0;
                    362: 
                    363: #ifdef DMSDOS_CONFIG_DRVSP3
                    364:     case SQ_0_0:
                    365:         LOG_DECOMP("DMSDOS: decompressing SQ-0-0\n"); 
                    366:         r=sq_dec(clusterk,lin,clusterd,lout,0);
                    367:         if(r<=0)
                    368:         { printk(KERN_ERR "DMSDOS: SQ-0-0 decompression failed.\n");   
                    369:           return -1;
                    370:         }
                    371:        LOG_DECOMP("DMSDOS: decompress finished.\n");
                    372:        return 0;
                    373: #endif
                    374:         
                    375:     default:   
                    376:        printk(KERN_ERR "DMSDOS: compression method not recognized.\n");
                    377:        return -1;
                    378:        
                    379:   } /* end switch */
                    380:   
                    381:   return 0;
                    382: }
                    383: 
                    384: #ifdef DMSDOS_CONFIG_DRVSP3
                    385: /* read the fragments of a fragmented cluster and assemble them */
                    386: /* warning: this is guessed from low level viewing drivespace 3 disks
                    387:    and may be awfully wrong... we'll see... */
                    388: int read_fragments(struct super_block*sb,Mdfat_entry*mde, unsigned char*data)
                    389: { struct buffer_head*bh;
                    390:   struct buffer_head*bh2;
                    391:   int fragcount;
                    392:   int fragpnt;
                    393:   int offset;
                    394:   int sector;
                    395:   int seccount;
                    396:   int membytes;
                    397:   int safety_counter;
                    398:   Dblsb*dblsb=MSDOS_SB(sb)->private_data;
                    399:     
                    400:   /* read first sector */
                    401:   sector=mde->sector_minus_1+1;
                    402:   bh=raw_bread(sb,sector);
                    403:   if(bh==NULL)return -EIO;
                    404:   fragcount=bh->b_data[0];
                    405:   if(bh->b_data[1]!=0||bh->b_data[2]!=0||bh->b_data[3]!=0||fragcount<=0||
                    406:      fragcount>dblsb->s_sectperclust)
                    407:   { printk(KERN_ERR "DMSDOS: read_fragments: cluster does not look fragmented!\n");
                    408:     raw_brelse(sb,bh);
                    409:     return -EIO;
                    410:   }
                    411:   membytes=dblsb->s_sectperclust*SECTOR_SIZE;
                    412:   if(mde->flags&1)
                    413:   { offset=0;
                    414:     safety_counter=0;
                    415:   }
                    416:   else
                    417:   { offset=(fragcount+1)*4;  
                    418:     /* copy the rest of the sector */
                    419:     memcpy(data,&(bh->b_data[offset]),SECTOR_SIZE-offset);
                    420:     data+=(SECTOR_SIZE-offset);
                    421:     safety_counter=SECTOR_SIZE-offset;
                    422:   }
                    423:   ++sector;
                    424:   seccount=mde->size_lo_minus_1;
                    425:   fragpnt=1;
                    426:   while(fragpnt<=fragcount)
                    427:   { if(fragpnt>1)
                    428:     { /* read next fragment pointers */
                    429:       seccount=bh->b_data[fragpnt*4+3];
                    430:       seccount&=0xff;
                    431:       seccount/=4;
                    432:       seccount+=1;
                    433:       sector=bh->b_data[fragpnt*4];
                    434:       sector&=0xff;
                    435:       sector+=bh->b_data[fragpnt*4+1]<<8;
                    436:       sector&=0xffff;
                    437:       sector+=bh->b_data[fragpnt*4+2]<<16;
                    438:       sector&=0xffffff;
                    439:       sector+=1;
                    440:     }
                    441:     while(seccount)
                    442:     { bh2=raw_bread(sb,sector);
                    443:       if(bh2==NULL){raw_brelse(sb,bh);return -EIO;}
                    444:       /*printk(KERN_DEBUG "DMSDOS: read_fragments: data=0x%p safety_counter=0x%x sector=%d\n",
                    445:              data,safety_counter,sector);*/
                    446:       if(safety_counter+SECTOR_SIZE>membytes)
                    447:       { int maxbytes=membytes-safety_counter;
                    448:         if(maxbytes<=0)
                    449:         { printk(KERN_WARNING "DMSDOS: read_fragments: safety_counter exceeds membytes!\n");
                    450:           raw_brelse(sb,bh2);
                    451:           raw_brelse(sb,bh);
                    452:           return -EIO;
                    453:         }
                    454:         printk(KERN_DEBUG "DMSDOS: read_fragments: size limit reached.\n");
                    455:         memcpy(data,bh2->b_data,maxbytes);
                    456:         raw_brelse(sb,bh2);
                    457:         raw_brelse(sb,bh);
                    458:         return membytes;
                    459:       }
                    460:       else memcpy(data,bh2->b_data,SECTOR_SIZE);
                    461:       raw_brelse(sb,bh2);
                    462:       data+=SECTOR_SIZE;
                    463:       safety_counter+=SECTOR_SIZE;
                    464:       ++sector;
                    465:       --seccount;
                    466:     }
                    467:     ++fragpnt;
                    468:   }
                    469:   raw_brelse(sb,bh);
                    470:   
                    471:   return safety_counter;
                    472: }
                    473: #endif
                    474: 
                    475: #ifdef DMSDOS_CONFIG_DBL
                    476: /* read a complete file cluster and decompress it if necessary; 
                    477:    this function is unable to read cluster 0 (CVF root directory) */
                    478: /* returns cluster length in bytes or error (<0) */
                    479: /* this function is specific to doublespace/drivespace */
                    480: int dbl_read_cluster(struct super_block*sb,
                    481:                         unsigned char*clusterd, int clusternr)
                    482: {      Mdfat_entry mde;
                    483:        unsigned char*clusterk;
                    484:        int nr_of_sectors;
                    485:        int i;
                    486:        struct buffer_head*bh;
                    487:        int membytes;
                    488:        int sector;
                    489:        Dblsb*dblsb=MSDOS_SB(sb)->private_data;
                    490: 
                    491:        LOG_CLUST("DMSDOS: dbl_read_cluster %d\n",clusternr);
                    492: 
                    493:        dbl_mdfat_value(sb,clusternr,NULL,&mde);
                    494:        
                    495:        if((mde.flags&2)==0)
                    496:        { /* hmm, cluster is unused (it's a lost or ghost cluster)
                    497:             and contains undefined data, but it *is* readable */
                    498:          /* oh no, it contains ZEROD data per definition...
                    499:             this is really important */
                    500:          if(clusterd) /*clusterd==NULL means read_ahead - don't do anything*/
                    501:                 memset(clusterd,0,dblsb->s_sectperclust*SECTOR_SIZE);
                    502:          LOG_CLUST("DMSDOS: lost cluster %d detected\n",clusternr);
                    503:          return 0; /* yes, has length zero */
                    504:        }
                    505:        
                    506:         sector=mde.sector_minus_1+1;
                    507:         nr_of_sectors=mde.size_lo_minus_1+1;/* real sectors on disk */
                    508:         if(nr_of_sectors>dblsb->s_sectperclust)
                    509:         { printk(KERN_WARNING "DMSDOS: read_cluster: mdfat sectors > sectperclust, cutting\n");
                    510:           nr_of_sectors=dblsb->s_sectperclust;
                    511:         }
                    512:         
                    513:         if(clusterd==NULL)
                    514:         { /* read-ahead */
                    515:           dblspace_reada(sb,sector,nr_of_sectors);
                    516:           return 0;
                    517:         }
                    518:         
                    519: #ifdef DMSDOS_CONFIG_DRVSP3
                    520:         if(mde.unknown&2)
                    521:         { /* we suppose this bit indicates a fragmented cluster */
                    522:           /* this is *not sure* and may be awfully wrong - reports
                    523:              whether success or not are welcome
                    524:           */
                    525:           
                    526:           LOG_CLUST("DMSDOS: cluster %d has unknown bit #1 set. Assuming fragmented cluster.\n",
                    527:                  clusternr);
                    528:           
                    529:           if(mde.flags&1) /* not compressed */
                    530:           { LOG_CLUST("DMSDOS: uncompressed fragmented cluster\n");
                    531:             i=read_fragments(sb,&mde,clusterd);
                    532:             if(i<0)
                    533:             { printk(KERN_ERR "DMSDOS: read_fragments failed!\n");
                    534:               return i;
                    535:             }
                    536:           }
                    537:           else
                    538:           { LOG_CLUST("DMSDOS: compressed fragmented cluster\n");
                    539:             membytes=SECTOR_SIZE*dblsb->s_sectperclust;
                    540:             
                    541:             clusterk=(unsigned char*)MALLOC(membytes);
                    542:             if(clusterk==NULL)
                    543:             { printk(KERN_ERR "DMSDOS: no memory for decompression!\n");
                    544:               return -2;
                    545:             }
                    546:             /* returns length in bytes */
                    547:             i=read_fragments(sb,&mde,clusterk);
                    548:             if(i<0)
                    549:             { printk(KERN_ERR "DMSDOS: read_fragments failed!\n"); 
                    550:               return i;
                    551:             }
                    552:             /* correct wrong size_lo information (sq_dec needs it) */
                    553:             if(i>0)mde.size_lo_minus_1=(i-1)/SECTOR_SIZE;
                    554:             i=dbl_decompress(clusterd,clusterk,&mde);
                    555:            
                    556:             FREE(clusterk);
                    557:            
                    558:             if(i)
                    559:             { printk(KERN_ERR "DMSDOS: decompression of cluster %d in CVF failed.\n",
                    560:                     clusternr);
                    561:               return i;
                    562:             }
                    563:             
                    564:           }
                    565:         
                    566:           /* the slack must be zerod out */
                    567:           if(mde.size_hi_minus_1+1<dblsb->s_sectperclust)
                    568:           { memset(clusterd+(mde.size_hi_minus_1+1)*SECTOR_SIZE,0,
                    569:                   (dblsb->s_sectperclust-mde.size_hi_minus_1-1)*
                    570:                                                               SECTOR_SIZE);
                    571:           }
                    572:         
                    573:          return (mde.size_hi_minus_1+1)*SECTOR_SIZE;
                    574:           
                    575:         } /* end of read routine for fragmented cluster */
                    576: #endif
                    577: 
                    578:         if(mde.flags&1)
                    579:         {  /* cluster is not compressed */
                    580:           for(i=0;i<nr_of_sectors;++i)
                    581:           {  bh=raw_bread(sb,sector+i);
                    582:              if(bh==NULL)return -EIO;
                    583:              memcpy(&clusterd[i*SECTOR_SIZE],bh->b_data,SECTOR_SIZE);
                    584:              raw_brelse(sb,bh);
                    585:           }
                    586:         }
                    587:         else
                    588:         {  /* cluster is compressed */
                    589:            
                    590:            membytes=SECTOR_SIZE*nr_of_sectors;
                    591:            
                    592:            clusterk=(unsigned char*)MALLOC(membytes);
                    593:            if(clusterk==NULL)
                    594:            { printk(KERN_ERR "DMSDOS: no memory for decompression!\n");
                    595:              return -2;
                    596:            }
                    597:            
                    598:            for(i=0;i<nr_of_sectors;++i)
                    599:           {  bh=raw_bread(sb,sector+i);
                    600:              if(bh==NULL)
                    601:              { FREE(clusterk);
                    602:                return -EIO;
                    603:              }
                    604:              memcpy(&clusterk[i*SECTOR_SIZE],bh->b_data,SECTOR_SIZE);
                    605:              raw_brelse(sb,bh);
                    606:           }
                    607:           
                    608:            i=dbl_decompress(clusterd,clusterk,&mde);
                    609:            
                    610:            FREE(clusterk);
                    611:            
                    612:            if(i)
                    613:            { printk(KERN_ERR "DMSDOS: decompression of cluster %d in CVF failed.\n",
                    614:                     clusternr);
                    615:              return i;
                    616:            }
                    617:            
                    618:         }
                    619: 
                    620:         /* the slack must be zerod out */
                    621:         if(mde.size_hi_minus_1+1<dblsb->s_sectperclust)
                    622:         { memset(clusterd+(mde.size_hi_minus_1+1)*SECTOR_SIZE,0,
                    623:                   (dblsb->s_sectperclust-mde.size_hi_minus_1-1)*
                    624:                                                               SECTOR_SIZE);
                    625:         }
                    626:         
                    627:        return (mde.size_hi_minus_1+1)*SECTOR_SIZE;
                    628: }
                    629: #endif
                    630: 
                    631: /* read a complete file cluster and decompress it if necessary; 
                    632:    it must be able to read directories
                    633:    this function is unable to read cluster 0 (CVF root directory) */
                    634: /* returns cluster length in bytes or error (<0) */
                    635: /* this function is a generic wrapper */
                    636: int dmsdos_read_cluster(struct super_block*sb,
                    637:                         unsigned char*clusterd, int clusternr)
                    638: { int ret;
                    639:   Dblsb*dblsb=MSDOS_SB(sb)->private_data;
                    640:          
                    641:   LOG_CLUST("DMSDOS: read_cluster %d\n",clusternr);
                    642: 
                    643:   switch(dblsb->s_cvf_version)
                    644:   {
                    645: #ifdef DMSDOS_CONFIG_DBL  
                    646:     case DBLSP:
                    647:     case DRVSP:
                    648:     case DRVSP3:
                    649:       ret=dbl_read_cluster(sb,clusterd,clusternr);
                    650:       break;
                    651: #endif
                    652: #ifdef DMSDOS_CONFIG_STAC
                    653:     case STAC3:
                    654:     case STAC4:
                    655:       ret=stac_read_cluster(sb,clusterd,clusternr);
                    656:       break;
                    657: #endif
                    658:     default:
                    659:       printk(KERN_ERR "DMSDOS: read_cluster: illegal cvf version flag!\n");
                    660:       ret=-EIO;
                    661:   }
                    662:   
                    663:   return ret;
                    664: }

unix.superglobalmegacorp.com

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