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

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

unix.superglobalmegacorp.com

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