|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.