libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

pack.c (7603B)


      1 /*
      2 Catlib Copyright Notice
      3 
      4 The author of this software is Christopher Adam Telfer
      5 Copyright (c) 1998, 1999, 2000, 2001, 2002
      6 by Christopher Adam Telfer.  All Rights Reserved.
      7 
      8 Permission to use, copy, modify, and distribute this software for any
      9 purpose without fee is hereby granted, provided that the above copyright
     10 notice, this paragraph, and the following two paragraphs appear in all
     11 copies, modifications, and distributions.
     12 
     13 IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
     14 SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
     15 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
     16 THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     17 
     18 THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
     19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
     20 PARTICULAR PURPOSE.  THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF
     21 ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS".   THE AUTHOR HAS NO
     22 OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
     23 MODIFICATIONS.
     24 
     25 */
     26 
     27 #include "platform.h"
     28 #include "pack.h"
     29 #include "le_architecture.h"
     30 
     31 #if ! (defined(_WIN32) && defined(cbNDRContext))
     32 typedef unsigned char byte;
     33 #endif
     34 typedef unsigned short half;
     35 typedef unsigned int word;
     36 typedef signed char sbyte;
     37 typedef signed short shalf;
     38 typedef signed int sword;
     39 
     40 
     41 int
     42 EXTRACTOR_common_cat_unpack (const void *buf,
     43                              const char *fmt,
     44                              ...)
     45 {
     46   va_list ap;
     47   word maxlen, len, *wordp;
     48   void *arr;
     49   byte *bp, *bytep, *newbuf;
     50   half *halfp;
     51   long long *ll;
     52   sbyte *sbytep;
     53   shalf *shalfp;
     54   sword *swordp;
     55   int npacked;
     56   unsigned int nreps, i, isnonprefixed = 1;     /* used for 'a' types only */
     57   struct cat_bvec *cbvp;
     58   char *cp;
     59 
     60   bp = (byte *) buf;
     61   npacked = 0;
     62 
     63   va_start (ap, fmt);
     64 
     65   while (*fmt)
     66   {
     67     nreps = 1;
     68 
     69     if (isdigit ( (unsigned char) *fmt))
     70     {
     71       /* We use cp instead of format to keep the 'const' qualifier of fmt */
     72       nreps = strtoul (fmt, &cp, 0);
     73       fmt = cp;
     74       if (*fmt == 'a')
     75         isnonprefixed = 0;
     76     }
     77 
     78     switch (*fmt)
     79     {
     80     case 'B':
     81     case 'b':
     82       bytep = va_arg (ap, byte *);
     83       for (i = 0; i < nreps; ++i)
     84       {
     85         *bytep = *bp++;
     86         ++bytep;
     87         npacked += 1;
     88       }
     89       break;
     90 
     91 
     92     case 'h':
     93       halfp = va_arg (ap, half *);
     94       for (i = 0; i < nreps; ++i)
     95       {
     96         *halfp = *bp++;
     97         *halfp |= *bp++ << 8;
     98         ++halfp;
     99         npacked += 2;
    100       }
    101       break;
    102 
    103     case 'H':
    104       halfp = va_arg (ap, half *);
    105       for (i = 0; i < nreps; ++i)
    106       {
    107         *halfp = *bp++ << 8;
    108         *halfp |= *bp++;
    109         ++halfp;
    110         npacked += 2;
    111       }
    112       break;
    113 
    114 
    115     case 'w':
    116       wordp = va_arg (ap, word *);
    117       for (i = 0; i < nreps; ++i)
    118       {
    119         *wordp = *bp++;
    120         *wordp |= *bp++ << 8;
    121         *wordp |= *bp++ << 16;
    122         *wordp |= *bp++ << 24;
    123         ++wordp;
    124         npacked += 4;
    125       }
    126       break;
    127 
    128     case 'x':
    129       ll = va_arg (ap, long long *);
    130       for (i = 0; i < nreps; ++i)
    131       {
    132         *ll = ((long long) *bp++);
    133         *ll |= ((long long) *bp++) << 8;
    134         *ll |= ((long long) *bp++) << 16;
    135         *ll |= ((long long) *bp++) << 24;
    136         *ll |= ((long long) *bp++) << 32;
    137         *ll |= ((long long) *bp++) << 40;
    138         *ll |= ((long long) *bp++) << 48;
    139         *ll |= ((long long) *bp++) << 56;
    140         ++ll;
    141         npacked += 8;
    142       }
    143       break;
    144 
    145     case 'W':
    146       wordp = va_arg (ap, word *);
    147       for (i = 0; i < nreps; ++i)
    148       {
    149         *wordp = *bp++ << 24;
    150         *wordp |= *bp++ << 16;
    151         *wordp |= *bp++ << 8;
    152         *wordp |= *bp++;
    153         ++wordp;
    154         npacked += 4;
    155       }
    156       break;
    157 
    158     case 'X':
    159       ll = va_arg (ap, long long *);
    160       for (i = 0; i < nreps; ++i)
    161       {
    162         *ll = ((long long) *bp++) << 56;
    163         *ll |= ((long long) *bp++) << 48;
    164         *ll |= ((long long) *bp++) << 40;
    165         *ll |= ((long long) *bp++) << 32;
    166         *ll |= ((long long) *bp++) << 24;
    167         *ll |= ((long long) *bp++) << 18;
    168         *ll |= ((long long) *bp++) << 8;
    169         *ll |= ((long long) *bp++);
    170         ++ll;
    171         npacked += 8;
    172       }
    173       break;
    174 
    175 
    176     case 'A':
    177       if (isnonprefixed)
    178       {
    179         maxlen = va_arg (ap, word);
    180         arr = va_arg (ap, void *);
    181 
    182         len = *bp++ << 24;
    183         len |= *bp++ << 16;
    184         len |= *bp++ << 8;
    185         len |= *bp++;
    186 
    187         if (len > maxlen)
    188         {
    189           va_end (ap);
    190           return -1;
    191         }
    192 
    193         memmove (arr, bp, len);
    194         bp += len;
    195 
    196         npacked += len;
    197       }
    198       else
    199       {
    200         cbvp = va_arg (ap, struct cat_bvec *);
    201         for (i = 0; i < nreps; ++i)
    202         {
    203           maxlen = cbvp->len;
    204           arr = cbvp->data;
    205 
    206           len = *bp++ << 24;
    207           len |= *bp++ << 16;
    208           len |= *bp++ << 8;
    209           len |= *bp++;
    210 
    211           if (len > maxlen)
    212             return -1;
    213 
    214           memmove (arr, bp, len);
    215           cbvp->len = len;
    216           bp += len;
    217 
    218           ++cbvp;
    219           npacked += len;
    220         }
    221         isnonprefixed = 1;
    222       }
    223       break;
    224 
    225     case 'C':
    226     case 'c':
    227       sbytep = va_arg (ap, sbyte *);
    228       for (i = 0; i < nreps; ++i)
    229       {
    230         *sbytep = *bp++;
    231 
    232         if ((sizeof (sbyte) > 1) && (*sbytep & 0x80))
    233           *sbytep |= (~0) << ((sizeof (sbyte) - 1) * 8);
    234 
    235         ++sbytep;
    236         npacked += 1;
    237       }
    238       break;
    239 
    240 
    241     case 's':
    242       shalfp = va_arg (ap, shalf *);
    243       for (i = 0; i < nreps; ++i)
    244       {
    245         *shalfp = *bp++;
    246         *shalfp |= *bp++ << 8;
    247 
    248         if ((sizeof (shalf) > 2) && (*shalfp & 0x8000))
    249           *shalfp |= (~0) << ((sizeof (shalf) - 2) * 8);
    250 
    251         ++shalfp;
    252         npacked += 2;
    253       }
    254       break;
    255 
    256     case 'S':
    257       shalfp = va_arg (ap, shalf *);
    258       for (i = 0; i < nreps; ++i)
    259       {
    260         *shalfp = *bp++ << 8;
    261         *shalfp |= *bp++;
    262 
    263         if ((sizeof (shalf) > 2) && (*shalfp & 0x8000))
    264           *shalfp |= (~0) << ((sizeof (shalf) - 2) * 8);
    265 
    266         ++shalfp;
    267         npacked += 2;
    268       }
    269       break;
    270 
    271     case 'l':
    272       swordp = va_arg (ap, sword *);
    273       for (i = 0; i < nreps; ++i)
    274       {
    275         *swordp = *bp++;
    276         *swordp |= *bp++ << 8;
    277         *swordp |= *bp++ << 16;
    278         *swordp |= *bp++ << 24;
    279 
    280         if ((sizeof (swordp) > 4) && (*swordp & 0x80000000))
    281           *swordp |= (~0) << ((sizeof (sword) - 4) * 8);
    282 
    283         ++swordp;
    284         npacked += 4;
    285       }
    286       break;
    287 
    288     case 'L':
    289       swordp = va_arg (ap, sword *);
    290       for (i = 0; i < nreps; ++i)
    291       {
    292         *swordp = *bp++ << 24;
    293         *swordp |= *bp++ << 16;
    294         *swordp |= *bp++ << 8;
    295         *swordp |= *bp++;
    296 
    297         if ((sizeof (swordp) > 4) && (*swordp & 0x80000000))
    298           *swordp |= (~0) << ((sizeof (sword) - 4) * 8);
    299 
    300         ++swordp;
    301         npacked += 4;
    302       }
    303       break;
    304 
    305     case 'P':
    306       cbvp = va_arg (ap, struct cat_bvec *);
    307       for (i = 0; i < nreps; ++i)
    308       {
    309         len = *bp++ << 24;
    310         len |= *bp++ << 16;
    311         len |= *bp++ << 8;
    312         len |= *bp++;
    313 
    314         newbuf = (byte *) malloc (len);
    315 
    316         if (! newbuf)
    317         {
    318           int j;
    319           for (j = 0; j < i; j++)
    320             free (cbvp[i].data);
    321           va_end (ap);
    322           return -1;
    323         }
    324 
    325         memmove (newbuf, bp, len);
    326         cbvp[i].data = newbuf;
    327         cbvp[i].len = len;
    328 
    329         bp += len;
    330         npacked += len;
    331       }
    332       break;
    333 
    334     default:
    335       va_end (ap);
    336       return -1;
    337     }
    338 
    339     ++fmt;
    340   }
    341 
    342   va_end (ap);
    343   return 0;
    344 }