Line data Source code
1 : /* 2 : * Unix SMB/CIFS implementation. 3 : * Samba system utilities 4 : * Copyright (C) Volker Lendecke 2014 5 : * 6 : * This program is free software; you can redistribute it and/or modify 7 : * it under the terms of the GNU General Public License as published by 8 : * the Free Software Foundation; either version 3 of the License, or 9 : * (at your option) any later version. 10 : * 11 : * This program is distributed in the hope that it will be useful, 12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 : * GNU General Public License for more details. 15 : * 16 : * You should have received a copy of the GNU General Public License 17 : * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 : */ 19 : 20 : #include "replace.h" 21 : #include "system/filesys.h" 22 : #include "iov_buf.h" 23 : #include <talloc.h> 24 : 25 1590445 : ssize_t iov_buflen(const struct iovec *iov, int iovcnt) 26 : { 27 1590445 : return iov_buf(iov, iovcnt, NULL, 0); 28 : } 29 : 30 2000619 : ssize_t iov_buf(const struct iovec *iov, int iovcnt, 31 : uint8_t *buf, size_t buflen) 32 : { 33 2000619 : size_t needed = 0; 34 2000619 : uint8_t *p = buf; 35 : int i; 36 : 37 8992404 : for (i=0; i<iovcnt; i++) { 38 6991785 : size_t thislen = iov[i].iov_len; 39 : size_t tmp; 40 : 41 6991785 : tmp = needed + thislen; 42 : 43 6991785 : if (tmp < needed) { 44 : /* wrap */ 45 0 : return -1; 46 : } 47 6991785 : needed = tmp; 48 : 49 6991785 : if ((p != NULL) && needed <= buflen && thislen > 0) { 50 1487918 : memcpy(p, iov[i].iov_base, thislen); 51 1487918 : p += thislen; 52 : } 53 : } 54 : 55 2000619 : return needed; 56 : } 57 : 58 17831985 : bool iov_advance(struct iovec **iov, int *iovcnt, size_t n) 59 : { 60 17831985 : struct iovec *v = *iov; 61 17831985 : int cnt = *iovcnt; 62 : 63 32021102 : while (n > 0) { 64 23011606 : if (cnt == 0) { 65 0 : return false; 66 : } 67 23011606 : if (n < v->iov_len) { 68 8822489 : v->iov_base = (char *)v->iov_base + n; 69 8822489 : v->iov_len -= n; 70 8822489 : break; 71 : } 72 14189117 : n -= v->iov_len; 73 14189117 : v += 1; 74 14189117 : cnt -= 1; 75 : } 76 : 77 : /* 78 : * Skip 0-length iovec's 79 : * 80 : * There might be empty buffers at the end of iov. Next time we do a 81 : * readv/writev based on this iov would give 0 transferred bytes, also 82 : * known as EPIPE. So we need to be careful discarding them. 83 : */ 84 : 85 18216971 : while ((cnt > 0) && (v->iov_len == 0)) { 86 384986 : v += 1; 87 384986 : cnt -= 1; 88 : } 89 : 90 17831985 : *iov = v; 91 17831985 : *iovcnt = cnt; 92 17831985 : return true; 93 : } 94 : 95 408723 : uint8_t *iov_concat(TALLOC_CTX *mem_ctx, const struct iovec *iov, int count) 96 : { 97 : ssize_t buflen; 98 : uint8_t *buf; 99 : 100 408723 : buflen = iov_buflen(iov, count); 101 408723 : if (buflen == -1) { 102 0 : return NULL; 103 : } 104 : 105 408723 : buf = talloc_array(mem_ctx, uint8_t, buflen); 106 408723 : if (buf == NULL) { 107 0 : return NULL; 108 : } 109 : 110 408723 : iov_buf(iov, count, buf, buflen); 111 : 112 408723 : return buf; 113 : }