11cb0ef41Sopenharmony_ci/* 21cb0ef41Sopenharmony_ci * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. 31cb0ef41Sopenharmony_ci * 41cb0ef41Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 51cb0ef41Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 61cb0ef41Sopenharmony_ci * in the file LICENSE in the source distribution or at 71cb0ef41Sopenharmony_ci * https://www.openssl.org/source/license.html 81cb0ef41Sopenharmony_ci */ 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci#include <stdio.h> 111cb0ef41Sopenharmony_ci#include <errno.h> 121cb0ef41Sopenharmony_ci#include "bio_local.h" 131cb0ef41Sopenharmony_ci#include "internal/cryptlib.h" 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_cistatic int mem_write(BIO *h, const char *buf, int num); 161cb0ef41Sopenharmony_cistatic int mem_read(BIO *h, char *buf, int size); 171cb0ef41Sopenharmony_cistatic int mem_puts(BIO *h, const char *str); 181cb0ef41Sopenharmony_cistatic int mem_gets(BIO *h, char *str, int size); 191cb0ef41Sopenharmony_cistatic long mem_ctrl(BIO *h, int cmd, long arg1, void *arg2); 201cb0ef41Sopenharmony_cistatic int mem_new(BIO *h); 211cb0ef41Sopenharmony_cistatic int secmem_new(BIO *h); 221cb0ef41Sopenharmony_cistatic int mem_free(BIO *data); 231cb0ef41Sopenharmony_cistatic int mem_buf_free(BIO *data); 241cb0ef41Sopenharmony_cistatic int mem_buf_sync(BIO *h); 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_cistatic const BIO_METHOD mem_method = { 271cb0ef41Sopenharmony_ci BIO_TYPE_MEM, 281cb0ef41Sopenharmony_ci "memory buffer", 291cb0ef41Sopenharmony_ci bwrite_conv, 301cb0ef41Sopenharmony_ci mem_write, 311cb0ef41Sopenharmony_ci bread_conv, 321cb0ef41Sopenharmony_ci mem_read, 331cb0ef41Sopenharmony_ci mem_puts, 341cb0ef41Sopenharmony_ci mem_gets, 351cb0ef41Sopenharmony_ci mem_ctrl, 361cb0ef41Sopenharmony_ci mem_new, 371cb0ef41Sopenharmony_ci mem_free, 381cb0ef41Sopenharmony_ci NULL, /* mem_callback_ctrl */ 391cb0ef41Sopenharmony_ci}; 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_cistatic const BIO_METHOD secmem_method = { 421cb0ef41Sopenharmony_ci BIO_TYPE_MEM, 431cb0ef41Sopenharmony_ci "secure memory buffer", 441cb0ef41Sopenharmony_ci bwrite_conv, 451cb0ef41Sopenharmony_ci mem_write, 461cb0ef41Sopenharmony_ci bread_conv, 471cb0ef41Sopenharmony_ci mem_read, 481cb0ef41Sopenharmony_ci mem_puts, 491cb0ef41Sopenharmony_ci mem_gets, 501cb0ef41Sopenharmony_ci mem_ctrl, 511cb0ef41Sopenharmony_ci secmem_new, 521cb0ef41Sopenharmony_ci mem_free, 531cb0ef41Sopenharmony_ci NULL, /* mem_callback_ctrl */ 541cb0ef41Sopenharmony_ci}; 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci/* 571cb0ef41Sopenharmony_ci * BIO memory stores buffer and read pointer 581cb0ef41Sopenharmony_ci * however the roles are different for read only BIOs. 591cb0ef41Sopenharmony_ci * In that case the readp just stores the original state 601cb0ef41Sopenharmony_ci * to be used for reset. 611cb0ef41Sopenharmony_ci */ 621cb0ef41Sopenharmony_citypedef struct bio_buf_mem_st { 631cb0ef41Sopenharmony_ci struct buf_mem_st *buf; /* allocated buffer */ 641cb0ef41Sopenharmony_ci struct buf_mem_st *readp; /* read pointer */ 651cb0ef41Sopenharmony_ci} BIO_BUF_MEM; 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci/* 681cb0ef41Sopenharmony_ci * bio->num is used to hold the value to return on 'empty', if it is 0, 691cb0ef41Sopenharmony_ci * should_retry is not set 701cb0ef41Sopenharmony_ci */ 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ciconst BIO_METHOD *BIO_s_mem(void) 731cb0ef41Sopenharmony_ci{ 741cb0ef41Sopenharmony_ci return &mem_method; 751cb0ef41Sopenharmony_ci} 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ciconst BIO_METHOD *BIO_s_secmem(void) 781cb0ef41Sopenharmony_ci{ 791cb0ef41Sopenharmony_ci return(&secmem_method); 801cb0ef41Sopenharmony_ci} 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ciBIO *BIO_new_mem_buf(const void *buf, int len) 831cb0ef41Sopenharmony_ci{ 841cb0ef41Sopenharmony_ci BIO *ret; 851cb0ef41Sopenharmony_ci BUF_MEM *b; 861cb0ef41Sopenharmony_ci BIO_BUF_MEM *bb; 871cb0ef41Sopenharmony_ci size_t sz; 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ci if (buf == NULL) { 901cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); 911cb0ef41Sopenharmony_ci return NULL; 921cb0ef41Sopenharmony_ci } 931cb0ef41Sopenharmony_ci sz = (len < 0) ? strlen(buf) : (size_t)len; 941cb0ef41Sopenharmony_ci if ((ret = BIO_new(BIO_s_mem())) == NULL) 951cb0ef41Sopenharmony_ci return NULL; 961cb0ef41Sopenharmony_ci bb = (BIO_BUF_MEM *)ret->ptr; 971cb0ef41Sopenharmony_ci b = bb->buf; 981cb0ef41Sopenharmony_ci /* Cast away const and trust in the MEM_RDONLY flag. */ 991cb0ef41Sopenharmony_ci b->data = (void *)buf; 1001cb0ef41Sopenharmony_ci b->length = sz; 1011cb0ef41Sopenharmony_ci b->max = sz; 1021cb0ef41Sopenharmony_ci *bb->readp = *bb->buf; 1031cb0ef41Sopenharmony_ci ret->flags |= BIO_FLAGS_MEM_RDONLY; 1041cb0ef41Sopenharmony_ci /* Since this is static data retrying won't help */ 1051cb0ef41Sopenharmony_ci ret->num = 0; 1061cb0ef41Sopenharmony_ci return ret; 1071cb0ef41Sopenharmony_ci} 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_cistatic int mem_init(BIO *bi, unsigned long flags) 1101cb0ef41Sopenharmony_ci{ 1111cb0ef41Sopenharmony_ci BIO_BUF_MEM *bb = OPENSSL_zalloc(sizeof(*bb)); 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ci if (bb == NULL) 1141cb0ef41Sopenharmony_ci return 0; 1151cb0ef41Sopenharmony_ci if ((bb->buf = BUF_MEM_new_ex(flags)) == NULL) { 1161cb0ef41Sopenharmony_ci OPENSSL_free(bb); 1171cb0ef41Sopenharmony_ci return 0; 1181cb0ef41Sopenharmony_ci } 1191cb0ef41Sopenharmony_ci if ((bb->readp = OPENSSL_zalloc(sizeof(*bb->readp))) == NULL) { 1201cb0ef41Sopenharmony_ci BUF_MEM_free(bb->buf); 1211cb0ef41Sopenharmony_ci OPENSSL_free(bb); 1221cb0ef41Sopenharmony_ci return 0; 1231cb0ef41Sopenharmony_ci } 1241cb0ef41Sopenharmony_ci *bb->readp = *bb->buf; 1251cb0ef41Sopenharmony_ci bi->shutdown = 1; 1261cb0ef41Sopenharmony_ci bi->init = 1; 1271cb0ef41Sopenharmony_ci bi->num = -1; 1281cb0ef41Sopenharmony_ci bi->ptr = (char *)bb; 1291cb0ef41Sopenharmony_ci return 1; 1301cb0ef41Sopenharmony_ci} 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_cistatic int mem_new(BIO *bi) 1331cb0ef41Sopenharmony_ci{ 1341cb0ef41Sopenharmony_ci return mem_init(bi, 0L); 1351cb0ef41Sopenharmony_ci} 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_cistatic int secmem_new(BIO *bi) 1381cb0ef41Sopenharmony_ci{ 1391cb0ef41Sopenharmony_ci return mem_init(bi, BUF_MEM_FLAG_SECURE); 1401cb0ef41Sopenharmony_ci} 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_cistatic int mem_free(BIO *a) 1431cb0ef41Sopenharmony_ci{ 1441cb0ef41Sopenharmony_ci BIO_BUF_MEM *bb; 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ci if (a == NULL) 1471cb0ef41Sopenharmony_ci return 0; 1481cb0ef41Sopenharmony_ci 1491cb0ef41Sopenharmony_ci bb = (BIO_BUF_MEM *)a->ptr; 1501cb0ef41Sopenharmony_ci if (!mem_buf_free(a)) 1511cb0ef41Sopenharmony_ci return 0; 1521cb0ef41Sopenharmony_ci OPENSSL_free(bb->readp); 1531cb0ef41Sopenharmony_ci OPENSSL_free(bb); 1541cb0ef41Sopenharmony_ci return 1; 1551cb0ef41Sopenharmony_ci} 1561cb0ef41Sopenharmony_ci 1571cb0ef41Sopenharmony_cistatic int mem_buf_free(BIO *a) 1581cb0ef41Sopenharmony_ci{ 1591cb0ef41Sopenharmony_ci if (a == NULL) 1601cb0ef41Sopenharmony_ci return 0; 1611cb0ef41Sopenharmony_ci 1621cb0ef41Sopenharmony_ci if (a->shutdown && a->init && a->ptr != NULL) { 1631cb0ef41Sopenharmony_ci BIO_BUF_MEM *bb = (BIO_BUF_MEM *)a->ptr; 1641cb0ef41Sopenharmony_ci BUF_MEM *b = bb->buf; 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci if (a->flags & BIO_FLAGS_MEM_RDONLY) 1671cb0ef41Sopenharmony_ci b->data = NULL; 1681cb0ef41Sopenharmony_ci BUF_MEM_free(b); 1691cb0ef41Sopenharmony_ci } 1701cb0ef41Sopenharmony_ci return 1; 1711cb0ef41Sopenharmony_ci} 1721cb0ef41Sopenharmony_ci 1731cb0ef41Sopenharmony_ci/* 1741cb0ef41Sopenharmony_ci * Reallocate memory buffer if read pointer differs 1751cb0ef41Sopenharmony_ci * NOT FOR RDONLY 1761cb0ef41Sopenharmony_ci */ 1771cb0ef41Sopenharmony_cistatic int mem_buf_sync(BIO *b) 1781cb0ef41Sopenharmony_ci{ 1791cb0ef41Sopenharmony_ci if (b != NULL && b->init != 0 && b->ptr != NULL) { 1801cb0ef41Sopenharmony_ci BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; 1811cb0ef41Sopenharmony_ci 1821cb0ef41Sopenharmony_ci if (bbm->readp->data != bbm->buf->data) { 1831cb0ef41Sopenharmony_ci memmove(bbm->buf->data, bbm->readp->data, bbm->readp->length); 1841cb0ef41Sopenharmony_ci bbm->buf->length = bbm->readp->length; 1851cb0ef41Sopenharmony_ci bbm->readp->data = bbm->buf->data; 1861cb0ef41Sopenharmony_ci } 1871cb0ef41Sopenharmony_ci } 1881cb0ef41Sopenharmony_ci return 0; 1891cb0ef41Sopenharmony_ci} 1901cb0ef41Sopenharmony_ci 1911cb0ef41Sopenharmony_cistatic int mem_read(BIO *b, char *out, int outl) 1921cb0ef41Sopenharmony_ci{ 1931cb0ef41Sopenharmony_ci int ret = -1; 1941cb0ef41Sopenharmony_ci BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; 1951cb0ef41Sopenharmony_ci BUF_MEM *bm = bbm->readp; 1961cb0ef41Sopenharmony_ci 1971cb0ef41Sopenharmony_ci if (b->flags & BIO_FLAGS_MEM_RDONLY) 1981cb0ef41Sopenharmony_ci bm = bbm->buf; 1991cb0ef41Sopenharmony_ci BIO_clear_retry_flags(b); 2001cb0ef41Sopenharmony_ci ret = (outl >= 0 && (size_t)outl > bm->length) ? (int)bm->length : outl; 2011cb0ef41Sopenharmony_ci if ((out != NULL) && (ret > 0)) { 2021cb0ef41Sopenharmony_ci memcpy(out, bm->data, ret); 2031cb0ef41Sopenharmony_ci bm->length -= ret; 2041cb0ef41Sopenharmony_ci bm->max -= ret; 2051cb0ef41Sopenharmony_ci bm->data += ret; 2061cb0ef41Sopenharmony_ci } else if (bm->length == 0) { 2071cb0ef41Sopenharmony_ci ret = b->num; 2081cb0ef41Sopenharmony_ci if (ret != 0) 2091cb0ef41Sopenharmony_ci BIO_set_retry_read(b); 2101cb0ef41Sopenharmony_ci } 2111cb0ef41Sopenharmony_ci return ret; 2121cb0ef41Sopenharmony_ci} 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_cistatic int mem_write(BIO *b, const char *in, int inl) 2151cb0ef41Sopenharmony_ci{ 2161cb0ef41Sopenharmony_ci int ret = -1; 2171cb0ef41Sopenharmony_ci int blen; 2181cb0ef41Sopenharmony_ci BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; 2191cb0ef41Sopenharmony_ci 2201cb0ef41Sopenharmony_ci if (b->flags & BIO_FLAGS_MEM_RDONLY) { 2211cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_BIO, BIO_R_WRITE_TO_READ_ONLY_BIO); 2221cb0ef41Sopenharmony_ci goto end; 2231cb0ef41Sopenharmony_ci } 2241cb0ef41Sopenharmony_ci BIO_clear_retry_flags(b); 2251cb0ef41Sopenharmony_ci if (inl == 0) 2261cb0ef41Sopenharmony_ci return 0; 2271cb0ef41Sopenharmony_ci if (in == NULL) { 2281cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); 2291cb0ef41Sopenharmony_ci goto end; 2301cb0ef41Sopenharmony_ci } 2311cb0ef41Sopenharmony_ci blen = bbm->readp->length; 2321cb0ef41Sopenharmony_ci mem_buf_sync(b); 2331cb0ef41Sopenharmony_ci if (BUF_MEM_grow_clean(bbm->buf, blen + inl) == 0) 2341cb0ef41Sopenharmony_ci goto end; 2351cb0ef41Sopenharmony_ci memcpy(bbm->buf->data + blen, in, inl); 2361cb0ef41Sopenharmony_ci *bbm->readp = *bbm->buf; 2371cb0ef41Sopenharmony_ci ret = inl; 2381cb0ef41Sopenharmony_ci end: 2391cb0ef41Sopenharmony_ci return ret; 2401cb0ef41Sopenharmony_ci} 2411cb0ef41Sopenharmony_ci 2421cb0ef41Sopenharmony_cistatic long mem_ctrl(BIO *b, int cmd, long num, void *ptr) 2431cb0ef41Sopenharmony_ci{ 2441cb0ef41Sopenharmony_ci long ret = 1; 2451cb0ef41Sopenharmony_ci char **pptr; 2461cb0ef41Sopenharmony_ci BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; 2471cb0ef41Sopenharmony_ci BUF_MEM *bm, *bo; /* bio_mem, bio_other */ 2481cb0ef41Sopenharmony_ci long off, remain; 2491cb0ef41Sopenharmony_ci 2501cb0ef41Sopenharmony_ci if (b->flags & BIO_FLAGS_MEM_RDONLY) { 2511cb0ef41Sopenharmony_ci bm = bbm->buf; 2521cb0ef41Sopenharmony_ci bo = bbm->readp; 2531cb0ef41Sopenharmony_ci } else { 2541cb0ef41Sopenharmony_ci bm = bbm->readp; 2551cb0ef41Sopenharmony_ci bo = bbm->buf; 2561cb0ef41Sopenharmony_ci } 2571cb0ef41Sopenharmony_ci off = (bm->data == bo->data) ? 0 : bm->data - bo->data; 2581cb0ef41Sopenharmony_ci remain = bm->length; 2591cb0ef41Sopenharmony_ci 2601cb0ef41Sopenharmony_ci switch (cmd) { 2611cb0ef41Sopenharmony_ci case BIO_CTRL_RESET: 2621cb0ef41Sopenharmony_ci bm = bbm->buf; 2631cb0ef41Sopenharmony_ci if (bm->data != NULL) { 2641cb0ef41Sopenharmony_ci if (!(b->flags & BIO_FLAGS_MEM_RDONLY)) { 2651cb0ef41Sopenharmony_ci if (!(b->flags & BIO_FLAGS_NONCLEAR_RST)) { 2661cb0ef41Sopenharmony_ci memset(bm->data, 0, bm->max); 2671cb0ef41Sopenharmony_ci bm->length = 0; 2681cb0ef41Sopenharmony_ci } 2691cb0ef41Sopenharmony_ci *bbm->readp = *bbm->buf; 2701cb0ef41Sopenharmony_ci } else { 2711cb0ef41Sopenharmony_ci /* For read only case just reset to the start again */ 2721cb0ef41Sopenharmony_ci *bbm->buf = *bbm->readp; 2731cb0ef41Sopenharmony_ci } 2741cb0ef41Sopenharmony_ci } 2751cb0ef41Sopenharmony_ci break; 2761cb0ef41Sopenharmony_ci case BIO_C_FILE_SEEK: 2771cb0ef41Sopenharmony_ci if (num < 0 || num > off + remain) 2781cb0ef41Sopenharmony_ci return -1; /* Can't see outside of the current buffer */ 2791cb0ef41Sopenharmony_ci 2801cb0ef41Sopenharmony_ci bm->data = (num != 0) ? bo->data + num : bo->data; 2811cb0ef41Sopenharmony_ci bm->length = bo->length - num; 2821cb0ef41Sopenharmony_ci bm->max = bo->max - num; 2831cb0ef41Sopenharmony_ci off = num; 2841cb0ef41Sopenharmony_ci /* FALLTHRU */ 2851cb0ef41Sopenharmony_ci case BIO_C_FILE_TELL: 2861cb0ef41Sopenharmony_ci ret = off; 2871cb0ef41Sopenharmony_ci break; 2881cb0ef41Sopenharmony_ci case BIO_CTRL_EOF: 2891cb0ef41Sopenharmony_ci ret = (long)(bm->length == 0); 2901cb0ef41Sopenharmony_ci break; 2911cb0ef41Sopenharmony_ci case BIO_C_SET_BUF_MEM_EOF_RETURN: 2921cb0ef41Sopenharmony_ci b->num = (int)num; 2931cb0ef41Sopenharmony_ci break; 2941cb0ef41Sopenharmony_ci case BIO_CTRL_INFO: 2951cb0ef41Sopenharmony_ci ret = (long)bm->length; 2961cb0ef41Sopenharmony_ci if (ptr != NULL) { 2971cb0ef41Sopenharmony_ci pptr = (char **)ptr; 2981cb0ef41Sopenharmony_ci *pptr = (char *)(bm->data); 2991cb0ef41Sopenharmony_ci } 3001cb0ef41Sopenharmony_ci break; 3011cb0ef41Sopenharmony_ci case BIO_C_SET_BUF_MEM: 3021cb0ef41Sopenharmony_ci mem_buf_free(b); 3031cb0ef41Sopenharmony_ci b->shutdown = (int)num; 3041cb0ef41Sopenharmony_ci bbm->buf = ptr; 3051cb0ef41Sopenharmony_ci *bbm->readp = *bbm->buf; 3061cb0ef41Sopenharmony_ci break; 3071cb0ef41Sopenharmony_ci case BIO_C_GET_BUF_MEM_PTR: 3081cb0ef41Sopenharmony_ci if (ptr != NULL) { 3091cb0ef41Sopenharmony_ci if (!(b->flags & BIO_FLAGS_MEM_RDONLY)) 3101cb0ef41Sopenharmony_ci mem_buf_sync(b); 3111cb0ef41Sopenharmony_ci bm = bbm->buf; 3121cb0ef41Sopenharmony_ci pptr = (char **)ptr; 3131cb0ef41Sopenharmony_ci *pptr = (char *)bm; 3141cb0ef41Sopenharmony_ci } 3151cb0ef41Sopenharmony_ci break; 3161cb0ef41Sopenharmony_ci case BIO_CTRL_GET_CLOSE: 3171cb0ef41Sopenharmony_ci ret = (long)b->shutdown; 3181cb0ef41Sopenharmony_ci break; 3191cb0ef41Sopenharmony_ci case BIO_CTRL_SET_CLOSE: 3201cb0ef41Sopenharmony_ci b->shutdown = (int)num; 3211cb0ef41Sopenharmony_ci break; 3221cb0ef41Sopenharmony_ci case BIO_CTRL_WPENDING: 3231cb0ef41Sopenharmony_ci ret = 0L; 3241cb0ef41Sopenharmony_ci break; 3251cb0ef41Sopenharmony_ci case BIO_CTRL_PENDING: 3261cb0ef41Sopenharmony_ci ret = (long)bm->length; 3271cb0ef41Sopenharmony_ci break; 3281cb0ef41Sopenharmony_ci case BIO_CTRL_DUP: 3291cb0ef41Sopenharmony_ci case BIO_CTRL_FLUSH: 3301cb0ef41Sopenharmony_ci ret = 1; 3311cb0ef41Sopenharmony_ci break; 3321cb0ef41Sopenharmony_ci case BIO_CTRL_PUSH: 3331cb0ef41Sopenharmony_ci case BIO_CTRL_POP: 3341cb0ef41Sopenharmony_ci default: 3351cb0ef41Sopenharmony_ci ret = 0; 3361cb0ef41Sopenharmony_ci break; 3371cb0ef41Sopenharmony_ci } 3381cb0ef41Sopenharmony_ci return ret; 3391cb0ef41Sopenharmony_ci} 3401cb0ef41Sopenharmony_ci 3411cb0ef41Sopenharmony_cistatic int mem_gets(BIO *bp, char *buf, int size) 3421cb0ef41Sopenharmony_ci{ 3431cb0ef41Sopenharmony_ci int i, j; 3441cb0ef41Sopenharmony_ci int ret = -1; 3451cb0ef41Sopenharmony_ci char *p; 3461cb0ef41Sopenharmony_ci BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)bp->ptr; 3471cb0ef41Sopenharmony_ci BUF_MEM *bm = bbm->readp; 3481cb0ef41Sopenharmony_ci 3491cb0ef41Sopenharmony_ci if (bp->flags & BIO_FLAGS_MEM_RDONLY) 3501cb0ef41Sopenharmony_ci bm = bbm->buf; 3511cb0ef41Sopenharmony_ci BIO_clear_retry_flags(bp); 3521cb0ef41Sopenharmony_ci j = bm->length; 3531cb0ef41Sopenharmony_ci if ((size - 1) < j) 3541cb0ef41Sopenharmony_ci j = size - 1; 3551cb0ef41Sopenharmony_ci if (j <= 0) { 3561cb0ef41Sopenharmony_ci *buf = '\0'; 3571cb0ef41Sopenharmony_ci return 0; 3581cb0ef41Sopenharmony_ci } 3591cb0ef41Sopenharmony_ci p = bm->data; 3601cb0ef41Sopenharmony_ci for (i = 0; i < j; i++) { 3611cb0ef41Sopenharmony_ci if (p[i] == '\n') { 3621cb0ef41Sopenharmony_ci i++; 3631cb0ef41Sopenharmony_ci break; 3641cb0ef41Sopenharmony_ci } 3651cb0ef41Sopenharmony_ci } 3661cb0ef41Sopenharmony_ci 3671cb0ef41Sopenharmony_ci /* 3681cb0ef41Sopenharmony_ci * i is now the max num of bytes to copy, either j or up to 3691cb0ef41Sopenharmony_ci * and including the first newline 3701cb0ef41Sopenharmony_ci */ 3711cb0ef41Sopenharmony_ci 3721cb0ef41Sopenharmony_ci i = mem_read(bp, buf, i); 3731cb0ef41Sopenharmony_ci if (i > 0) 3741cb0ef41Sopenharmony_ci buf[i] = '\0'; 3751cb0ef41Sopenharmony_ci ret = i; 3761cb0ef41Sopenharmony_ci return ret; 3771cb0ef41Sopenharmony_ci} 3781cb0ef41Sopenharmony_ci 3791cb0ef41Sopenharmony_cistatic int mem_puts(BIO *bp, const char *str) 3801cb0ef41Sopenharmony_ci{ 3811cb0ef41Sopenharmony_ci int n, ret; 3821cb0ef41Sopenharmony_ci 3831cb0ef41Sopenharmony_ci n = strlen(str); 3841cb0ef41Sopenharmony_ci ret = mem_write(bp, str, n); 3851cb0ef41Sopenharmony_ci /* memory semantics is that it will always work */ 3861cb0ef41Sopenharmony_ci return ret; 3871cb0ef41Sopenharmony_ci} 388