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 : #ifndef __LIB_IOV_BUF_H__ 21 : #define __LIB_IOV_BUF_H__ 22 : 23 : #include "replace.h" 24 : #include <talloc.h> 25 : #include "system/filesys.h" 26 : 27 : static inline 28 8825809 : ssize_t iov_buf(const struct iovec *iov, int iovcnt, 29 : uint8_t *buf, size_t buflen) 30 : { 31 8825809 : size_t needed = 0; 32 8825809 : uint8_t *p = buf; 33 250056 : int i; 34 : 35 38957182 : for (i=0; i<iovcnt; i++) { 36 30131373 : size_t thislen = iov[i].iov_len; 37 695301 : size_t tmp; 38 : 39 30131373 : tmp = needed + thislen; 40 : 41 30131373 : if (tmp < needed) { 42 : /* wrap */ 43 0 : return -1; 44 : } 45 30131373 : needed = tmp; 46 : 47 30131373 : if ((p != NULL) && needed <= buflen && thislen > 0) { 48 4383466 : memcpy(p, iov[i].iov_base, thislen); 49 4383466 : p += thislen; 50 : } 51 : } 52 : 53 8825809 : return needed; 54 : } 55 : 56 : static inline 57 7488681 : ssize_t iov_buflen(const struct iovec *iov, int iovcnt) 58 : { 59 7488681 : return iov_buf(iov, iovcnt, NULL, 0); 60 : } 61 : 62 : static inline 63 31502673 : bool iov_advance(struct iovec **iov, int *iovcnt, size_t n) 64 : { 65 31502673 : struct iovec *v = *iov; 66 31502673 : int cnt = *iovcnt; 67 : 68 71386695 : while (n > 0) { 69 49480816 : if (cnt == 0) { 70 0 : return false; 71 : } 72 49480816 : if (n < v->iov_len) { 73 9596794 : v->iov_base = (char *)v->iov_base + n; 74 9596794 : v->iov_len -= n; 75 9596794 : break; 76 : } 77 39884022 : n -= v->iov_len; 78 39884022 : v += 1; 79 39884022 : cnt -= 1; 80 : } 81 : 82 : /* 83 : * Skip 0-length iovec's 84 : * 85 : * There might be empty buffers at the end of iov. Next time we do a 86 : * readv/writev based on this iov would give 0 transferred bytes, also 87 : * known as EPIPE. So we need to be careful discarding them. 88 : */ 89 : 90 33203509 : while ((cnt > 0) && (v->iov_len == 0)) { 91 1700836 : v += 1; 92 1700836 : cnt -= 1; 93 : } 94 : 95 31502673 : *iov = v; 96 31502673 : *iovcnt = cnt; 97 31502673 : return true; 98 : } 99 : 100 : uint8_t *iov_concat(TALLOC_CTX *mem_ctx, const struct iovec *iov, int count); 101 : 102 : #endif