URI: 
       tclump.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tclump.c (5316B)
       ---
            1 #include "stdinc.h"
            2 #include "dat.h"
            3 #include "fns.h"
            4 #include "whack.h"
            5 
            6 /*
            7  * Write a lump to disk.  Updates ia with an index address
            8  * for the newly-written lump.  Upon return, the lump will
            9  * have been placed in the disk cache but will likely not be on disk yet.
           10  */
           11 int
           12 storeclump(Index *ix, ZBlock *zb, u8int *sc, int type, u32int creator, IAddr *ia)
           13 {
           14         ZBlock *cb;
           15         Clump cl;
           16         u64int a;
           17         u8int bh[VtScoreSize];
           18         int size, dsize;
           19 
           20         trace(TraceLump, "storeclump enter", sc, type);
           21         size = zb->len;
           22         if(size > VtMaxLumpSize){
           23                 seterr(EStrange, "lump too large");
           24                 return -1;
           25         }
           26         if(vttypevalid(type) < 0){
           27                 seterr(EStrange, "invalid lump type");
           28                 return -1;
           29         }
           30 
           31         if(0){
           32                 scoremem(bh, zb->data, size);
           33                 if(scorecmp(sc, bh) != 0){
           34                         seterr(ECorrupt, "storing clump: corrupted; expected=%V got=%V, size=%d", sc, bh, size);
           35                         return -1;
           36                 }
           37         }
           38 
           39         cb = alloczblock(size + ClumpSize + U32Size, 0, 0);
           40         if(cb == nil)
           41                 return -1;
           42 
           43         cl.info.type = type;
           44         cl.info.uncsize = size;
           45         cl.creator = creator;
           46         cl.time = now();
           47         scorecp(cl.info.score, sc);
           48 
           49         trace(TraceLump, "storeclump whackblock");
           50         dsize = whackblock(&cb->data[ClumpSize], zb->data, size);
           51         if(dsize > 0 && dsize < size){
           52                 cl.encoding = ClumpECompress;
           53         }else{
           54                 if(dsize > size){
           55                         fprint(2, "whack error: dsize=%d size=%d\n", dsize, size);
           56                         abort();
           57                 }
           58                 cl.encoding = ClumpENone;
           59                 dsize = size;
           60                 memmove(&cb->data[ClumpSize], zb->data, size);
           61         }
           62         memset(cb->data+ClumpSize+dsize, 0, 4);
           63         cl.info.size = dsize;
           64 
           65         a = writeiclump(ix, &cl, cb->data);
           66         trace(TraceLump, "storeclump exit %lld", a);
           67         freezblock(cb);
           68         if(a == TWID64)
           69                 return -1;
           70 
           71         ia->addr = a;
           72         ia->type = type;
           73         ia->size = size;
           74         ia->blocks = (dsize + ClumpSize + (1 << ABlockLog) - 1) >> ABlockLog;
           75 
           76 /*
           77         qlock(&stats.lock);
           78         stats.clumpwrites++;
           79         stats.clumpbwrites += size;
           80         stats.clumpbcomp += dsize;
           81         qunlock(&stats.lock);
           82 */
           83 
           84         return 0;
           85 }
           86 
           87 u32int
           88 clumpmagic(Arena *arena, u64int aa)
           89 {
           90         u8int buf[U32Size];
           91 
           92         if(readarena(arena, aa, buf, U32Size) == TWID32)
           93                 return TWID32;
           94         return unpackmagic(buf);
           95 }
           96 
           97 /*
           98  * fetch a block based at addr.
           99  * score is filled in with the block's score.
          100  * blocks is roughly the length of the clump on disk;
          101  * if zero, the length is unknown.
          102  */
          103 ZBlock*
          104 loadclump(Arena *arena, u64int aa, int blocks, Clump *cl, u8int *score, int verify)
          105 {
          106         Unwhack uw;
          107         ZBlock *zb, *cb;
          108         u8int bh[VtScoreSize], *buf;
          109         u32int n;
          110         int nunc;
          111 
          112 /*
          113         qlock(&stats.lock);
          114         stats.clumpreads++;
          115         qunlock(&stats.lock);
          116 */
          117 
          118         if(blocks <= 0)
          119                 blocks = 1;
          120 
          121         trace(TraceLump, "loadclump enter");
          122 
          123         cb = alloczblock(blocks << ABlockLog, 0, 0);
          124         if(cb == nil)
          125                 return nil;
          126         n = readarena(arena, aa, cb->data, blocks << ABlockLog);
          127         if(n < ClumpSize){
          128                 if(n != 0)
          129                         seterr(ECorrupt, "loadclump read less than a header");
          130                 freezblock(cb);
          131                 return nil;
          132         }
          133         trace(TraceLump, "loadclump unpack");
          134         if(unpackclump(cl, cb->data, arena->clumpmagic) < 0){
          135                 seterr(ECorrupt, "loadclump %s %llud: %r", arena->name, aa);
          136                 freezblock(cb);
          137                 return nil;
          138         }
          139         if(cl->info.type == VtCorruptType){
          140                 seterr(EOk, "clump is marked corrupt");
          141                 freezblock(cb);
          142                 return nil;
          143         }
          144         n -= ClumpSize;
          145         if(n < cl->info.size){
          146                 freezblock(cb);
          147                 n = cl->info.size;
          148                 cb = alloczblock(n, 0, 0);
          149                 if(cb == nil)
          150                         return nil;
          151                 if(readarena(arena, aa + ClumpSize, cb->data, n) != n){
          152                         seterr(ECorrupt, "loadclump read too little data");
          153                         freezblock(cb);
          154                         return nil;
          155                 }
          156                 buf = cb->data;
          157         }else
          158                 buf = cb->data + ClumpSize;
          159 
          160         scorecp(score, cl->info.score);
          161 
          162         zb = alloczblock(cl->info.uncsize, 0, 0);
          163         if(zb == nil){
          164                 freezblock(cb);
          165                 return nil;
          166         }
          167         switch(cl->encoding){
          168         case ClumpECompress:
          169                 trace(TraceLump, "loadclump decompress");
          170                 unwhackinit(&uw);
          171                 nunc = unwhack(&uw, zb->data, cl->info.uncsize, buf, cl->info.size);
          172                 if(nunc != cl->info.uncsize){
          173                         if(nunc < 0)
          174                                 seterr(ECorrupt, "decompression of %llud failed: %s", aa, uw.err);
          175                         else
          176                                 seterr(ECorrupt, "decompression of %llud gave partial block: %d/%d\n", aa, nunc, cl->info.uncsize);
          177                         freezblock(cb);
          178                         freezblock(zb);
          179                         return nil;
          180                 }
          181                 break;
          182         case ClumpENone:
          183                 if(cl->info.size != cl->info.uncsize){
          184                         seterr(ECorrupt, "loading clump: bad uncompressed size for uncompressed block %llud", aa);
          185                         freezblock(cb);
          186                         freezblock(zb);
          187                         return nil;
          188                 }
          189                 scoremem(bh, buf, cl->info.uncsize);
          190                 if(scorecmp(cl->info.score, bh) != 0)
          191                         seterr(ECorrupt, "pre-copy sha1 wrong at %s %llud: expected=%V got=%V", arena->name, aa, cl->info.score, bh);
          192                 memmove(zb->data, buf, cl->info.uncsize);
          193                 break;
          194         default:
          195                 seterr(ECorrupt, "unknown encoding in loadlump %llud", aa);
          196                 freezblock(cb);
          197                 freezblock(zb);
          198                 return nil;
          199         }
          200         freezblock(cb);
          201 
          202         if(verify){
          203                 trace(TraceLump, "loadclump verify");
          204                 scoremem(bh, zb->data, cl->info.uncsize);
          205                 if(scorecmp(cl->info.score, bh) != 0){
          206                         seterr(ECorrupt, "loading clump: corrupted at %s %llud; expected=%V got=%V", arena->name, aa, cl->info.score, bh);
          207                         freezblock(zb);
          208                         return nil;
          209                 }
          210                 if(vttypevalid(cl->info.type) < 0){
          211                         seterr(ECorrupt, "loading lump at %s %llud: invalid lump type %d", arena->name, aa, cl->info.type);
          212                         freezblock(zb);
          213                         return nil;
          214                 }
          215         }
          216 
          217         trace(TraceLump, "loadclump exit");
          218 /*
          219         qlock(&stats.lock);
          220         stats.clumpbreads += cl->info.size;
          221         stats.clumpbuncomp += cl->info.uncsize;
          222         qunlock(&stats.lock);
          223 */
          224         return zb;
          225 }