URI: 
       tentry.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
       ---
       tentry.c (2550B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <venti.h>
            4 #include "cvt.h"
            5 
            6 static int
            7 checksize(int n)
            8 {
            9         if(n < 256) {
           10                 werrstr("bad block size %#ux", n);
           11                 return -1;
           12         }
           13         return 0;
           14 }
           15 
           16 // _VtEntryBig integer format is floating-point:
           17 // (n>>5) << (n&31).
           18 // Convert this number; must be exact or return -1.
           19 int
           20 vttobig(ulong n)
           21 {
           22         int shift;
           23         ulong n0;
           24 
           25         n0 = n;
           26         shift = 0;
           27         while(n >= (1<<(16 - 5))) {
           28                 if(n & 1)
           29                         return -1;
           30                 shift++;
           31                 n >>= 1;
           32         }
           33 
           34         n = (n<<5) | shift;
           35         if(((n>>5)<<(n&31)) != n0)
           36                 sysfatal("vttobig %#lux => %#lux failed", n0, n);
           37         return n;
           38 }
           39 
           40 void
           41 vtentrypack(VtEntry *e, uchar *p, int index)
           42 {
           43         ulong t32;
           44         int flags;
           45         uchar *op;
           46         int depth;
           47         int psize, dsize;
           48 
           49         p += index * VtEntrySize;
           50         op = p;
           51 
           52         depth = e->type&VtTypeDepthMask;
           53         flags = (e->flags&~(_VtEntryDir|_VtEntryDepthMask));
           54         flags |= depth << _VtEntryDepthShift;
           55         if(e->type - depth == VtDirType)
           56                 flags |= _VtEntryDir;
           57         U32PUT(p, e->gen);
           58         p += 4;
           59         psize = e->psize;
           60         dsize = e->dsize;
           61         if(psize >= (1<<16) || dsize >= (1<<16)) {
           62                 flags |= _VtEntryBig;
           63                 psize = vttobig(psize);
           64                 dsize = vttobig(dsize);
           65                 if(psize < 0 || dsize < 0)
           66                         sysfatal("invalid entry psize/dsize: %ld/%ld", e->psize, e->dsize);
           67         }
           68         U16PUT(p, psize);
           69         p += 2;
           70         U16PUT(p, dsize);
           71         p += 2;
           72         U8PUT(p, flags);
           73         p++;
           74         memset(p, 0, 5);
           75         p += 5;
           76         U48PUT(p, e->size, t32);
           77         p += 6;
           78         memmove(p, e->score, VtScoreSize);
           79         p += VtScoreSize;
           80 
           81         assert(p-op == VtEntrySize);
           82 }
           83 
           84 int
           85 vtentryunpack(VtEntry *e, uchar *p, int index)
           86 {
           87         uchar *op;
           88 
           89         p += index * VtEntrySize;
           90         op = p;
           91 
           92         e->gen = U32GET(p);
           93         p += 4;
           94         e->psize = U16GET(p);
           95         p += 2;
           96         e->dsize = U16GET(p);
           97         p += 2;
           98         e->flags = U8GET(p);
           99         p++;
          100         if(e->flags & _VtEntryBig) {
          101                 e->psize = (e->psize>>5)<<(e->psize & 31);
          102                 e->dsize = (e->dsize>>5)<<(e->dsize & 31);
          103         }
          104         e->type = (e->flags&_VtEntryDir) ? VtDirType : VtDataType;
          105         e->type += (e->flags & _VtEntryDepthMask) >> _VtEntryDepthShift;
          106         e->flags &= ~(_VtEntryDir|_VtEntryDepthMask|_VtEntryBig);
          107         p += 5;
          108         e->size = U48GET(p);
          109         p += 6;
          110         memmove(e->score, p, VtScoreSize);
          111         p += VtScoreSize;
          112 
          113         assert(p-op == VtEntrySize);
          114 
          115         if(!(e->flags & VtEntryActive))
          116                 return 0;
          117 
          118         /*
          119          * Some old vac files use psize==0 and dsize==0 when the
          120          * file itself has size 0 or is zeros.  Just to make programs not
          121          * have to figure out what block sizes of 0 means, rewrite them.
          122          */
          123         if(e->psize == 0 && e->dsize == 0
          124         && memcmp(e->score, vtzeroscore, VtScoreSize) == 0){
          125                 e->psize = 4096;
          126                 e->dsize = 4096;
          127         }
          128         if(checksize(e->psize) < 0 || checksize(e->dsize) < 0)
          129                 return -1;
          130 
          131         return 0;
          132 }