The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/opencrypto/deflate.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: deflate.c,v 1.11.10.1 2009/05/03 17:24:45 snj Exp $ */
    2 /*      $FreeBSD: src/sys/opencrypto/deflate.c,v 1.1.2.1 2002/11/21 23:34:23 sam Exp $  */
    3 /* $OpenBSD: deflate.c,v 1.3 2001/08/20 02:45:22 hugh Exp $ */
    4 
    5 /*
    6  * Copyright (c) 2001 Jean-Jacques Bernard-Gundol (jj@wabbitt.org)
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  *
   12  * 1. Redistributions of source code must retain the above copyright
   13  *   notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *   notice, this list of conditions and the following disclaimer in the
   16  *   documentation and/or other materials provided with the distribution.
   17  * 3. The name of the author may not be used to endorse or promote products
   18  *   derived from this software without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 /*
   33  * This file contains a wrapper around the deflate algo compression
   34  * functions using the zlib library (see net/zlib.{c,h})
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __KERNEL_RCSID(0, "$NetBSD: deflate.c,v 1.11.10.1 2009/05/03 17:24:45 snj Exp $");
   39 
   40 #include <sys/types.h>
   41 #include <sys/malloc.h>
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <net/zlib.h>
   45 
   46 #include <opencrypto/cryptodev.h>
   47 #include <opencrypto/deflate.h>
   48 
   49 
   50 int window_inflate = -1 * MAX_WBITS;
   51 int window_deflate = -12;
   52 
   53 /*
   54  * This function takes a block of data and (de)compress it using the deflate
   55  * algorithm
   56  */
   57 
   58 static void *
   59 ocf_zalloc(void *nil, u_int type, u_int size)
   60 {
   61         void *ptr;
   62 
   63         ptr = malloc(type *size, M_CRYPTO_DATA, M_NOWAIT);
   64         return ptr;
   65 }
   66 
   67 static void
   68 ocf_zfree(void *nil, void *ptr)
   69 {
   70         free(ptr, M_CRYPTO_DATA);
   71 }
   72 
   73 u_int32_t
   74 deflate_global(data, size, decomp, out)
   75         u_int8_t *data;
   76         u_int32_t size;
   77         int decomp;
   78         u_int8_t **out;
   79 {
   80         /* decomp indicates whether we compress (0) or decompress (1) */
   81 
   82         z_stream zbuf;
   83         u_int8_t *output;
   84         u_int32_t count, result;
   85         int error, i = 0, j;
   86         struct deflate_buf *buf, *tmp;
   87         size_t len, old_len;
   88 
   89         DPRINTF(("deflate_global: size %d\n", size));
   90 
   91         len = ZBUF;
   92         buf = malloc(len*sizeof(struct deflate_buf), M_CRYPTO_DATA, M_NOWAIT);
   93         if (buf == NULL)
   94                 return 0;
   95 
   96         memset(&zbuf, 0, sizeof(z_stream));
   97         for (j = 0; j < len; j++)
   98                 buf[j].flag = 0;
   99 
  100         zbuf.next_in = data;    /* data that is going to be processed */
  101         zbuf.zalloc = ocf_zalloc;
  102         zbuf.zfree = ocf_zfree;
  103         zbuf.opaque = Z_NULL;
  104         zbuf.avail_in = size;   /* Total length of data to be processed */
  105 
  106         if (!decomp) {
  107                 buf[i].out = malloc(size, M_CRYPTO_DATA, M_NOWAIT);
  108                 if (buf[i].out == NULL)
  109                         goto bad;
  110                 buf[i].size = size;
  111                 buf[i].flag = 1;
  112                 i++;
  113         } else {
  114                 /*
  115                  * Choose a buffer with 4x the size of the input buffer
  116                  * for the size of the output buffer in the case of
  117                  * decompression. If it's not sufficient, it will need to be
  118                  * updated while the decompression is going on
  119                  */
  120 
  121                 buf[i].size = size * 4;
  122                 buf[i].out = malloc(buf[i].size, M_CRYPTO_DATA, M_NOWAIT);
  123                 if (buf[i].out == NULL)
  124                         goto bad;
  125                 buf[i].flag = 1;
  126                 i++;
  127         }
  128 
  129         zbuf.next_out = buf[0].out;
  130         zbuf.avail_out = buf[0].size;
  131 
  132         error = decomp ? inflateInit2(&zbuf, window_inflate) :
  133             deflateInit2(&zbuf, Z_DEFAULT_COMPRESSION, Z_METHOD,
  134                     window_deflate, Z_MEMLEVEL, Z_DEFAULT_STRATEGY);
  135 
  136         if (error != Z_OK)
  137                 goto bad;
  138         for (;;) {
  139                 error = decomp ? inflate(&zbuf, Z_PARTIAL_FLUSH) :
  140                                  deflate(&zbuf, Z_PARTIAL_FLUSH);
  141                 if (error != Z_OK && error != Z_STREAM_END)
  142                         goto bad;
  143                 else if (zbuf.avail_in == 0 && zbuf.avail_out != 0)
  144                         goto end;
  145                 else if (zbuf.avail_out == 0) {
  146                         if (i == (len-1)) {
  147                                 old_len = i;
  148                                 len += ZBUF;
  149                                 tmp = realloc(buf,len*sizeof(struct deflate_buf),
  150                                                           M_CRYPTO_DATA, M_NOWAIT);
  151                                 if (tmp == NULL)
  152                                         goto bad;
  153                                 buf = tmp;
  154                                 for (j = old_len; j < len; j++)
  155                                         buf[j].flag = 0;
  156                         }
  157                         /* we need more output space, allocate size */
  158                         buf[i].out = malloc(size, M_CRYPTO_DATA, M_NOWAIT);
  159                         if (buf[i].out == NULL)
  160                                 goto bad;
  161                         zbuf.next_out = buf[i].out;
  162                         buf[i].size = size;
  163                         buf[i].flag = 1;
  164                         zbuf.avail_out = buf[i].size;
  165                         i++;
  166                 } else
  167                         goto bad;
  168         }
  169 
  170 end:
  171         result = count = zbuf.total_out;
  172 
  173         *out = malloc(result, M_CRYPTO_DATA, M_NOWAIT);
  174         if (*out == NULL)
  175                 goto bad;
  176         if (decomp)
  177                 inflateEnd(&zbuf);
  178         else
  179                 deflateEnd(&zbuf);
  180         output = *out;
  181         for (j = 0; buf[j].flag != 0; j++) {
  182                 if (count > buf[j].size) {
  183                         memcpy(*out, buf[j].out, buf[j].size);
  184                         *out += buf[j].size;
  185                         free(buf[j].out, M_CRYPTO_DATA);
  186                         count -= buf[j].size;
  187                 } else {
  188                         /* it should be the last buffer */
  189                         memcpy(*out, buf[j].out, count);
  190                         *out += count;
  191                         free(buf[j].out, M_CRYPTO_DATA);
  192                         count = 0;
  193                 }
  194         }
  195         free(buf, M_CRYPTO_DATA);
  196         *out = output;
  197         return result;
  198 
  199 bad:
  200         *out = NULL;
  201         for (j = 0; buf[j].flag != 0; j++)
  202                 free(buf[j].out, M_CRYPTO_DATA);
  203         free(buf, M_CRYPTO_DATA);
  204         if (decomp)
  205                 inflateEnd(&zbuf);
  206         else
  207                 deflateEnd(&zbuf);
  208         return 0;
  209 }
  210 
  211 /*
  212  * Initial version will perform a single gzip encapsulation,
  213  * filling in the header,
  214  * and appending the crc and uncompressed length.
  215  *
  216  * Later version will support multiple buffers with 
  217  * a flag indication final buffer.  The crc is maintained
  218  * over all buffers and appended to the output along with 
  219  * the uncompressed length after the final data buffer
  220  * has been compressed and output.
  221  *
  222  * Ditto for uncompress - CRC is extracted from the final packed
  223  * and compared against CRC of uncompressed data.
  224  *
  225  */
  226 
  227 /* constant header for the gzip */
  228 static const char gzip_header[10] = {
  229         0x1f, 0x8b,     /* ID1 ID2      */
  230         Z_DEFLATED,     /* CM           */
  231         0,              /* FLG          */
  232         0, 0, 0, 0,     /* MTIME        */
  233         0,              /* XFL          */
  234         0x03            /* OS (Unix)    */
  235 };
  236 
  237 /* Followed by compressed payload */
  238 /* Followed by uint32_t CRC32 and uint32_t ISIZE */
  239 #define GZIP_TAIL_SIZE  8
  240 
  241 u_int32_t
  242 gzip_global(u_int8_t *data, u_int32_t size,
  243         int decomp, u_int8_t **out)
  244 {
  245         /* decomp indicates whether we compress (0) or decompress (1) */
  246         z_stream zbuf;
  247         u_int8_t *output;
  248         u_int32_t count, result;
  249         int error, i = 0, j;
  250         struct deflate_buf *buf, *tmp;
  251         size_t nbufs, old_nbufs;
  252         u_int32_t crc;
  253         u_int32_t isize;
  254 
  255         DPRINTF(("gzip_global: decomp %d, size %d\n", decomp, size));
  256 
  257         nbufs = ZBUF;
  258         buf = malloc(nbufs*sizeof(struct deflate_buf), M_CRYPTO_DATA, M_NOWAIT);
  259         if (buf == NULL) {
  260                 DPRINTF(("gzip_global.%d: failed to malloc %d\n",
  261                                 __LINE__, nbufs*sizeof(struct deflate_buf)));
  262                 return 0;
  263         }
  264 
  265         memset(&zbuf, 0, sizeof(z_stream));
  266         for (j = 0; j < nbufs; j++)
  267                 buf[j].flag = 0;
  268 
  269         zbuf.zalloc = ocf_zalloc;
  270         zbuf.zfree = ocf_zfree;
  271         zbuf.opaque = Z_NULL;
  272 
  273         crc = crc32(0, NULL, 0);        /* get initial crc value */
  274 
  275         zbuf.avail_in = size;   /* Total length of data to be processed */
  276         zbuf.next_in = data;    /* data that is going to be processed */
  277 
  278         if (!decomp) {
  279                 /* compress */
  280                 DPRINTF(("gzip_global: compress[%d] malloc %d + %d + %d = %d\n",
  281                                 i, size, sizeof(gzip_header), GZIP_TAIL_SIZE,
  282                                 size + sizeof(gzip_header) + GZIP_TAIL_SIZE));
  283 
  284                 buf[i].out = malloc(size, M_CRYPTO_DATA, M_NOWAIT);
  285                 if (buf[i].out == NULL)
  286                         goto bad2;
  287                 buf[i].size = size;
  288                 buf[i].flag = 1;
  289 
  290                 zbuf.next_out = buf[i].out;
  291                 zbuf.avail_out = buf[i].size;
  292                 i++;
  293                 
  294                 crc = crc32(crc, data, size);
  295                 DPRINTF(("gzip_compress: size %d, crc 0x%x\n", size, crc));
  296         } else {
  297                 /* decompress */
  298                 /* check the gzip header */
  299                 if (zbuf.avail_in <= 0) {
  300                         /* Not enough data for the header & tail */
  301                         DPRINTF(("gzip_global: not enough data (%d)\n",
  302                                         size));
  303                         goto bad2;
  304                 }
  305 
  306                 /* XXX this is pretty basic,
  307                  * needs to be expanded to ignore MTIME, OS, 
  308                  * but still ensure flags are 0.
  309                  * Q. Do we need to support the flags and 
  310                  * optional header fields? Likely.
  311                  * XXX add flag and field support too.
  312                  */
  313                 if (memcmp(data, gzip_header, sizeof(gzip_header)) != 0) {
  314                         DPRINTF(("gzip_global: unsupported gzip header (%02x%02x)\n",
  315                                         data[0], data[1]));
  316                         goto bad2;
  317                 } else {
  318                         DPRINTF(("gzip_global.%d: gzip header ok\n",__LINE__));
  319                 }
  320 
  321                 isize = *((uint32_t *)&data[size-sizeof(uint32_t)]);
  322 
  323                 DPRINTF(("gzip_global: isize = %d (%02x %02x %02x %02x)\n",
  324                                 isize,
  325                                 data[size-4],
  326                                 data[size-3],
  327                                 data[size-2],
  328                                 data[size-1]));
  329 
  330                 buf[i].size = isize;
  331                 buf[i].out = malloc(buf[i].size, M_CRYPTO_DATA, M_NOWAIT);
  332                 if (buf[i].out == NULL)
  333                         goto bad2;
  334                 buf[i].flag = 1;
  335                 zbuf.next_out = buf[i].out;
  336                 zbuf.avail_out = buf[i].size;
  337                 i++;
  338 
  339                 /* skip over the gzip header */
  340                 zbuf.next_in = data + sizeof(gzip_header);
  341 
  342                 /* actual payload size stripped of gzip header and tail */
  343                 zbuf.avail_in = size - sizeof(gzip_header) - GZIP_TAIL_SIZE;
  344                 DPRINTF(("zbuf avail_in %d, avail_out %d\n",
  345                                         zbuf.avail_in, zbuf.avail_out));
  346 
  347         }
  348 
  349 
  350         error = decomp ? inflateInit2(&zbuf, window_inflate) :
  351             deflateInit2(&zbuf, Z_DEFAULT_COMPRESSION, Z_METHOD,
  352                     window_deflate, Z_MEMLEVEL, Z_DEFAULT_STRATEGY);
  353 
  354         if (error != Z_OK) {
  355                 printf("deflateInit2() failed\n");
  356                 goto bad;
  357         }
  358         for (;;) {
  359                 DPRINTF(("pre: %s in:%d out:%d\n", decomp ? "deflate()" : "inflate()", 
  360                                 zbuf.avail_in, zbuf.avail_out));
  361                 error = decomp ? inflate(&zbuf, Z_PARTIAL_FLUSH) :
  362                                  deflate(&zbuf, Z_PARTIAL_FLUSH);
  363                 DPRINTF(("post: %s in:%d out:%d\n", decomp ? "deflate()" : "inflate()", 
  364                                 zbuf.avail_in, zbuf.avail_out));
  365                 if (error != Z_OK && error != Z_STREAM_END) {
  366                         printf("deflate() or inflate() failed, error=%d\n", error);
  367                         goto bad;
  368                 } else if (zbuf.avail_in == 0 && zbuf.avail_out != 0) {
  369                         DPRINTF(("gzip_global: avail_in == 0, ending\n"));
  370                         goto end;
  371                 } else if (zbuf.avail_in == 0 && zbuf.avail_out == 0) {
  372                         DPRINTF(("gzip_global: avail_in == 0, avail_out == 0, ending\n"));
  373                         goto end;
  374                 } else if (zbuf.avail_out == 0) {
  375                         if (i == (nbufs-1)) {
  376                                 old_nbufs = i;
  377                                 nbufs += ZBUF;
  378                                 tmp = realloc(buf,nbufs*sizeof(struct deflate_buf),
  379                                                           M_CRYPTO_DATA, M_NOWAIT);
  380                                 if (tmp == NULL)
  381                                         goto bad;
  382                                 buf = tmp;
  383                                 for (j = old_nbufs; j < nbufs; j++)
  384                                         buf[j].flag = 0;
  385                         }
  386                         /* we need more output space, allocate size */
  387                         buf[i].out = malloc(size, M_CRYPTO_DATA, M_NOWAIT);
  388                         if (buf[i].out == NULL)
  389                                 goto bad;
  390                         zbuf.next_out = buf[i].out;
  391                         buf[i].size = size;
  392                         buf[i].flag = 1;
  393                         zbuf.avail_out = buf[i].size;
  394                         i++;
  395                 } else
  396                         goto bad;
  397         }
  398 
  399 end:
  400         if (decomp) {
  401                 count = result = zbuf.total_out;
  402         } else {
  403                 /* need room for header, CRC, and ISIZE */
  404                 result = zbuf.total_out + sizeof(gzip_header) + GZIP_TAIL_SIZE;
  405                 count = zbuf.total_out;
  406         }
  407 
  408         DPRINTF(("gzip_global: in %d -> out %d\n", size, result));
  409 
  410         *out = malloc(result, M_CRYPTO_DATA, M_NOWAIT);
  411         if (*out == NULL)
  412                 goto bad;
  413         output = *out;
  414         if (decomp)
  415                 inflateEnd(&zbuf);
  416         else {
  417                 deflateEnd(&zbuf);
  418 
  419                 /* fill in gzip header */
  420                 memcpy(output, gzip_header, sizeof(gzip_header));
  421                 output += sizeof(gzip_header);
  422         }
  423         for (j = 0; buf[j].flag != 0; j++) {
  424                 if (decomp) {
  425                         /* update crc for decompressed data */
  426                         crc = crc32(crc, buf[j].out, buf[j].size);
  427                 }
  428                 if (count > buf[j].size) {
  429                         memcpy(output, buf[j].out, buf[j].size);
  430                         output += buf[j].size;
  431                         free(buf[j].out, M_CRYPTO_DATA);
  432                         count -= buf[j].size;
  433                 } else {
  434                         /* it should be the last buffer */
  435                         memcpy(output, buf[j].out, count);
  436                         output += count;
  437                         free(buf[j].out, M_CRYPTO_DATA);
  438                         count = 0;
  439                 }
  440         }
  441         free(buf, M_CRYPTO_DATA);
  442 
  443         if (!decomp) {
  444                 /* fill in CRC and ISIZE */
  445                 ((uint32_t *)output)[0] = crc;
  446                 ((uint32_t *)output)[1] = size;
  447 
  448                 DPRINTF(("gzip_global: size = 0x%x (%02x %02x %02x %02x)\n",
  449                                 size,
  450                                 output[7],
  451                                 output[3],
  452                                 output[5],
  453                                 output[4]));
  454         }
  455 
  456         return result;
  457 
  458 bad:
  459         if (decomp)
  460                 inflateEnd(&zbuf);
  461         else
  462                 deflateEnd(&zbuf);
  463 bad2:
  464         *out = NULL;
  465         for (j = 0; buf[j].flag != 0; j++)
  466                 free(buf[j].out, M_CRYPTO_DATA);
  467         free(buf, M_CRYPTO_DATA);
  468         return 0;
  469 }

Cache object: 8052a101d61a508174295a75533492bc


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.