LCOV - code coverage report
Current view: top level - lib/dpkg - buffer.c (source / functions) Coverage Total Hit
Test: dpkg 1.22.7-3-g89f48 C code coverage Lines: 82.3 % 141 116
Test Date: 2024-07-17 02:53:43 Functions: 100.0 % 13 13
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 65.5 % 55 36

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * libdpkg - Debian packaging suite library routines
       3                 :             :  * buffer.c - buffer I/O handling routines
       4                 :             :  *
       5                 :             :  * Copyright © 1999, 2000 Wichert Akkerman <wakkerma@debian.org>
       6                 :             :  * Copyright © 2000-2003 Adam Heath <doogie@debian.org>
       7                 :             :  * Copyright © 2008-2012 Guillem Jover <guillem@debian.org>
       8                 :             :  *
       9                 :             :  * This is free software; you can redistribute it and/or modify
      10                 :             :  * it under the terms of the GNU General Public License as published by
      11                 :             :  * the Free Software Foundation; either version 2 of the License, or
      12                 :             :  * (at your option) any later version.
      13                 :             :  *
      14                 :             :  * This is distributed in the hope that it will be useful,
      15                 :             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16                 :             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17                 :             :  * GNU General Public License for more details.
      18                 :             :  *
      19                 :             :  * You should have received a copy of the GNU General Public License
      20                 :             :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21                 :             :  */
      22                 :             : 
      23                 :             : #include <config.h>
      24                 :             : #include <compat.h>
      25                 :             : 
      26                 :             : #include <sys/types.h>
      27                 :             : 
      28                 :             : #include <errno.h>
      29                 :             : #include <md5.h>
      30                 :             : #include <string.h>
      31                 :             : #include <unistd.h>
      32                 :             : #include <stdlib.h>
      33                 :             : 
      34                 :             : #include <dpkg/i18n.h>
      35                 :             : #include <dpkg/dpkg.h>
      36                 :             : #include <dpkg/varbuf.h>
      37                 :             : #include <dpkg/fdio.h>
      38                 :             : #include <dpkg/buffer.h>
      39                 :             : 
      40                 :             : struct buffer_md5_ctx {
      41                 :             :         MD5_CTX ctx;
      42                 :             :         char *hash;
      43                 :             : };
      44                 :             : 
      45                 :             : static void
      46                 :           5 : buffer_md5_init(struct buffer_data *data)
      47                 :             : {
      48                 :             :         struct buffer_md5_ctx *ctx;
      49                 :             : 
      50                 :           5 :         ctx = m_malloc(sizeof(*ctx));
      51                 :           5 :         ctx->hash = data->arg.ptr;
      52                 :           5 :         data->arg.ptr = ctx;
      53                 :           5 :         MD5Init(&ctx->ctx);
      54                 :           5 : }
      55                 :             : 
      56                 :             : static off_t
      57                 :         122 : buffer_digest_init(struct buffer_data *data)
      58                 :             : {
      59      [ +  +  - ]:         122 :         switch (data->type) {
      60                 :         117 :         case BUFFER_DIGEST_NULL:
      61                 :         117 :                 break;
      62                 :           5 :         case BUFFER_DIGEST_MD5:
      63                 :           5 :                 buffer_md5_init(data);
      64                 :           5 :                 break;
      65                 :             :         }
      66                 :         122 :         return 0;
      67                 :             : }
      68                 :             : 
      69                 :             : static off_t
      70                 :         824 : buffer_digest_update(struct buffer_data *digest, const void *buf, off_t length)
      71                 :             : {
      72                 :         824 :         off_t ret = length;
      73                 :             : 
      74      [ +  +  - ]:         824 :         switch (digest->type) {
      75                 :         756 :         case BUFFER_DIGEST_NULL:
      76                 :         756 :                 break;
      77                 :          68 :         case BUFFER_DIGEST_MD5:
      78                 :          68 :                 MD5Update(&(((struct buffer_md5_ctx *)digest->arg.ptr)->ctx),
      79                 :             :                           buf, length);
      80                 :          68 :                 break;
      81                 :           0 :         default:
      82                 :           0 :                 internerr("unknown data type %i", digest->type);
      83                 :             :         }
      84                 :             : 
      85                 :         824 :         return ret;
      86                 :             : }
      87                 :             : 
      88                 :             : static void
      89                 :           5 : buffer_md5_done(struct buffer_data *data)
      90                 :             : {
      91                 :             :         struct buffer_md5_ctx *ctx;
      92                 :           5 :         unsigned char digest[16], *p = digest;
      93                 :             :         char *hash;
      94                 :             :         int i;
      95                 :             : 
      96                 :           5 :         ctx = (struct buffer_md5_ctx *)data->arg.ptr;
      97                 :           5 :         hash = ctx->hash;
      98                 :           5 :         MD5Final(digest, &ctx->ctx);
      99         [ +  + ]:          85 :         for (i = 0; i < 16; ++i) {
     100                 :          80 :                 sprintf(hash, "%02x", *p++);
     101                 :          80 :                 hash += 2;
     102                 :             :         }
     103                 :           5 :         *hash = '\0';
     104                 :           5 :         free(ctx);
     105                 :           5 : }
     106                 :             : 
     107                 :             : static off_t
     108                 :         122 : buffer_digest_done(struct buffer_data *data)
     109                 :             : {
     110      [ +  +  - ]:         122 :         switch (data->type) {
     111                 :         117 :         case BUFFER_DIGEST_NULL:
     112                 :         117 :                 break;
     113                 :           5 :         case BUFFER_DIGEST_MD5:
     114                 :           5 :                 buffer_md5_done(data);
     115                 :           5 :                 break;
     116                 :             :         }
     117                 :         122 :         return 0;
     118                 :             : }
     119                 :             : 
     120                 :             : static off_t
     121                 :         822 : buffer_write(struct buffer_data *data, const void *buf, off_t length,
     122                 :             :              struct dpkg_error *err)
     123                 :             : {
     124                 :         822 :         off_t ret = length;
     125                 :             : 
     126   [ +  +  +  - ]:         822 :         switch (data->type) {
     127                 :           1 :         case BUFFER_WRITE_VBUF:
     128                 :           1 :                 varbuf_add_buf((struct varbuf *)data->arg.ptr, buf, length);
     129                 :           1 :                 break;
     130                 :         755 :         case BUFFER_WRITE_FD:
     131                 :         755 :                 ret = fd_write(data->arg.i, buf, length);
     132         [ -  + ]:         755 :                 if (ret < 0)
     133                 :           0 :                         dpkg_put_errno(err, _("failed to write"));
     134                 :         755 :                 break;
     135                 :          66 :         case BUFFER_WRITE_NULL:
     136                 :          66 :                 break;
     137                 :           0 :         default:
     138                 :           0 :                 internerr("unknown data type %i", data->type);
     139                 :             :         }
     140                 :             : 
     141                 :         822 :         return ret;
     142                 :             : }
     143                 :             : 
     144                 :             : static off_t
     145                 :         852 : buffer_read(struct buffer_data *data, void *buf, off_t length,
     146                 :             :             struct dpkg_error *err)
     147                 :             : {
     148                 :             :         off_t ret;
     149                 :             : 
     150         [ +  - ]:         852 :         switch (data->type) {
     151                 :         852 :         case BUFFER_READ_FD:
     152                 :         852 :                 ret = fd_read(data->arg.i, buf, length);
     153         [ -  + ]:         852 :                 if (ret < 0)
     154                 :           0 :                         dpkg_put_errno(err, _("failed to read"));
     155                 :         852 :                 break;
     156                 :           0 :         default:
     157                 :           0 :                 internerr("unknown data type %i", data->type);
     158                 :             :         }
     159                 :             : 
     160                 :         852 :         return ret;
     161                 :             : }
     162                 :             : 
     163                 :             : off_t
     164                 :           2 : buffer_digest(const void *input, void *output, int type, off_t limit)
     165                 :             : {
     166                 :           2 :         struct buffer_data data = { .arg.ptr = output, .type = type };
     167                 :             :         off_t ret;
     168                 :             : 
     169                 :           2 :         buffer_digest_init(&data);
     170                 :           2 :         ret = buffer_digest_update(&data, input, limit);
     171                 :           2 :         buffer_digest_done(&data);
     172                 :             : 
     173                 :           2 :         return ret;
     174                 :             : }
     175                 :             : 
     176                 :             : static off_t
     177                 :         120 : buffer_copy(struct buffer_data *read_data,
     178                 :             :             struct buffer_data *digest,
     179                 :             :             struct buffer_data *write_data,
     180                 :             :             off_t limit, struct dpkg_error *err)
     181                 :             : {
     182                 :             :         char *buf;
     183                 :         120 :         int bufsize = DPKG_BUFFER_SIZE;
     184                 :         120 :         off_t bytesread = 0, byteswritten = 0;
     185                 :         120 :         off_t totalread = 0, totalwritten = 0;
     186                 :             : 
     187   [ +  +  +  + ]:         120 :         if ((limit >= 0) && (limit < bufsize))
     188                 :          42 :                 bufsize = limit;
     189         [ -  + ]:         120 :         if (bufsize == 0)
     190                 :           0 :                 buf = NULL;
     191                 :             :         else
     192                 :         120 :                 buf = m_malloc(bufsize);
     193                 :             : 
     194                 :         120 :         buffer_digest_init(digest);
     195                 :             : 
     196         [ +  + ]:         942 :         while (bufsize > 0) {
     197                 :         852 :                 bytesread = buffer_read(read_data, buf, bufsize, err);
     198         [ -  + ]:         852 :                 if (bytesread < 0)
     199                 :           0 :                         break;
     200         [ +  + ]:         852 :                 if (bytesread == 0)
     201                 :          30 :                         break;
     202                 :             : 
     203                 :         822 :                 totalread += bytesread;
     204                 :             : 
     205         [ +  + ]:         822 :                 if (limit >= 0) {
     206                 :         513 :                         limit -= bytesread;
     207         [ +  + ]:         513 :                         if (limit < bufsize)
     208                 :         138 :                                 bufsize = limit;
     209                 :             :                 }
     210                 :             : 
     211                 :         822 :                 buffer_digest_update(digest, buf, bytesread);
     212                 :             : 
     213                 :         822 :                 byteswritten = buffer_write(write_data, buf, bytesread, err);
     214         [ -  + ]:         822 :                 if (byteswritten < 0)
     215                 :           0 :                         break;
     216         [ -  + ]:         822 :                 if (byteswritten == 0)
     217                 :           0 :                         break;
     218                 :             : 
     219                 :         822 :                 totalwritten += byteswritten;
     220                 :             :         }
     221                 :             : 
     222                 :         120 :         buffer_digest_done(digest);
     223                 :             : 
     224                 :         120 :         free(buf);
     225                 :             : 
     226   [ +  -  -  + ]:         120 :         if (bytesread < 0 || byteswritten < 0)
     227                 :           0 :                 return -1;
     228         [ -  + ]:         120 :         if (totalread != totalwritten)
     229                 :           0 :                 return -1;
     230         [ -  + ]:         120 :         if (limit > 0)
     231                 :           0 :                 return dpkg_put_error(err, _("unexpected end of file or stream"));
     232                 :             : 
     233                 :         120 :         return totalread;
     234                 :             : }
     235                 :             : 
     236                 :             : off_t
     237                 :         116 : buffer_copy_IntInt(int Iin, int Tin,
     238                 :             :                    void *Pdigest, int Tdigest,
     239                 :             :                    int Iout, int Tout,
     240                 :             :                    off_t limit, struct dpkg_error *err)
     241                 :             : {
     242                 :         116 :         struct buffer_data read_data = { .type = Tin, .arg.i = Iin };
     243                 :         116 :         struct buffer_data digest = { .type = Tdigest, .arg.ptr = Pdigest };
     244                 :         116 :         struct buffer_data write_data = { .type = Tout, .arg.i = Iout };
     245                 :             : 
     246                 :         116 :         return buffer_copy(&read_data, &digest, &write_data, limit, err);
     247                 :             : }
     248                 :             : 
     249                 :             : off_t
     250                 :           4 : buffer_copy_IntPtr(int Iin, int Tin,
     251                 :             :                    void *Pdigest, int Tdigest,
     252                 :             :                    void *Pout, int Tout,
     253                 :             :                    off_t limit, struct dpkg_error *err)
     254                 :             : {
     255                 :           4 :         struct buffer_data read_data = { .type = Tin, .arg.i = Iin };
     256                 :           4 :         struct buffer_data digest = { .type = Tdigest, .arg.ptr = Pdigest };
     257                 :           4 :         struct buffer_data write_data = { .type = Tout, .arg.ptr = Pout };
     258                 :             : 
     259                 :           4 :         return buffer_copy(&read_data, &digest, &write_data, limit, err);
     260                 :             : }
     261                 :             : 
     262                 :             : static off_t
     263                 :          33 : buffer_skip(struct buffer_data *input, off_t limit, struct dpkg_error *err)
     264                 :             : {
     265                 :             :         struct buffer_data output;
     266                 :             :         struct buffer_data digest;
     267                 :             : 
     268         [ +  - ]:          33 :         switch (input->type) {
     269                 :          33 :         case BUFFER_READ_FD:
     270         [ +  - ]:          33 :                 if (lseek(input->arg.i, limit, SEEK_CUR) >= 0)
     271                 :          33 :                         return limit;
     272         [ #  # ]:           0 :                 if (errno != ESPIPE)
     273                 :           0 :                         return dpkg_put_errno(err, _("failed to seek"));
     274                 :           0 :                 break;
     275                 :           0 :         default:
     276                 :           0 :                 internerr("unknown data type %i", input->type);
     277                 :             :         }
     278                 :             : 
     279                 :           0 :         output.type = BUFFER_WRITE_NULL;
     280                 :           0 :         output.arg.ptr = NULL;
     281                 :           0 :         digest.type = BUFFER_DIGEST_NULL;
     282                 :           0 :         digest.arg.ptr = NULL;
     283                 :             : 
     284                 :           0 :         return buffer_copy(input, &digest, &output, limit, err);
     285                 :             : }
     286                 :             : 
     287                 :             : off_t
     288                 :          33 : buffer_skip_Int(int I, int T, off_t limit, struct dpkg_error *err)
     289                 :             : {
     290                 :          33 :         struct buffer_data input = { .type = T, .arg.i = I };
     291                 :             : 
     292                 :          33 :         return buffer_skip(&input, limit, err);
     293                 :             : }
        

Generated by: LCOV version 2.0-1