1ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin/* 2ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin * Copyright (c) 2015 Dmitry V. Levin <ldv@altlinux.org> 3ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin * All rights reserved. 4ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin * 5ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin * Redistribution and use in source and binary forms, with or without 6ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin * modification, are permitted provided that the following conditions 7ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin * are met: 8ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin * 1. Redistributions of source code must retain the above copyright 9ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin * notice, this list of conditions and the following disclaimer. 10ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin * 2. Redistributions in binary form must reproduce the above copyright 11ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin * notice, this list of conditions and the following disclaimer in the 12ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin * documentation and/or other materials provided with the distribution. 13ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin * 3. The name of the author may not be used to endorse or promote products 14ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin * derived from this software without specific prior written permission. 15ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin * 16ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin */ 27ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 28ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin#include "defs.h" 29ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 30ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin#ifdef HAVE_LINUX_BPF_H 31ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin# include <linux/bpf.h> 32ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin#endif 33ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 34ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin#include "xlat/bpf_commands.h" 35ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin#include "xlat/bpf_map_types.h" 36ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin#include "xlat/bpf_prog_types.h" 37ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin#include "xlat/bpf_map_update_elem_flags.h" 38ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 39ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levinstatic int 40ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levinbpf_map_create(struct tcb *tcp, const long addr, unsigned int size) 41ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin{ 42ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin struct { 43ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin uint32_t map_type, key_size, value_size, max_entries; 44ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin } attr = {}; 45ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 46ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin if (!size) { 47ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin printaddr(addr); 48ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin return RVAL_DECODED | RVAL_FD; 49ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin } 50ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin if (size > sizeof(attr)) 51ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin size = sizeof(attr); 52ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin if (umoven_or_printaddr(tcp, addr, size, &attr)) 53ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin return RVAL_DECODED | RVAL_FD; 54ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 55ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin tprints("{map_type="); 56ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin printxval(bpf_map_types, attr.map_type, "BPF_MAP_TYPE_???"); 57ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin tprintf(", key_size=%u, value_size=%u, max_entries=%u}", 58ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin attr.key_size, attr.value_size, attr.max_entries); 59ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 60ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin return RVAL_DECODED | RVAL_FD; 61ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin} 62ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 63ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levinstatic void 64ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levinbpf_map_update_elem(struct tcb *tcp, const long addr, unsigned int size) 65ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin{ 66ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin struct { 67ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin uint32_t map_fd; 68ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin uint64_t ATTRIBUTE_ALIGNED(8) key; 69ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin uint64_t ATTRIBUTE_ALIGNED(8) value; 70ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin uint64_t flags; 71ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin } attr = {}; 72ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 73ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin if (!size) { 74ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin printaddr(addr); 75ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin return; 76ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin } 77ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin if (size > sizeof(attr)) 78ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin size = sizeof(attr); 79ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin if (umoven_or_printaddr(tcp, addr, size, &attr)) 80ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin return; 81ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 82ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin tprints("{map_fd="); 83ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin printfd(tcp, attr.map_fd); 84ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin tprintf(", key=%#" PRIx64 ", value=%#" PRIx64 ", flags=", 85ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin attr.key, attr.value); 86ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin printxval(bpf_map_update_elem_flags, attr.flags, "BPF_???"); 87ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin tprints("}"); 88ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin} 89ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 90ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levinstatic void 91ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levinbpf_map_delete_elem(struct tcb *tcp, const long addr, unsigned int size) 92ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin{ 93ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin struct { 94ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin uint32_t map_fd; 95ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin uint64_t ATTRIBUTE_ALIGNED(8) key; 96ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin } attr = {}; 97ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 98ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin if (!size) { 99ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin printaddr(addr); 100ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin return; 101ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin } 102ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin if (size > sizeof(attr)) 103ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin size = sizeof(attr); 104ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin if (umoven_or_printaddr(tcp, addr, size, &attr)) 105ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin return; 106ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 107ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin tprints("{map_fd="); 108ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin printfd(tcp, attr.map_fd); 109ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin tprintf(", key=%#" PRIx64 "}", attr.key); 110ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin} 111ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 112ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levinstatic int 113ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levinbpf_map_io(struct tcb *tcp, const long addr, unsigned int size, const char *text) 114ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin{ 115ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin struct bpf_io_elem_struct { 116ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin uint32_t map_fd; 117ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin uint64_t ATTRIBUTE_ALIGNED(8) key; 118ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin uint64_t ATTRIBUTE_ALIGNED(8) value; 119ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin } attr = {}; 120ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 121ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin if (exiting(tcp)) { 122ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin if (!syserror(tcp) && !umove_or_printaddr(tcp, addr, &attr)) 123ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin tprintf(", %s=%#" PRIx64, text, attr.value); 124ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin tprints("}"); 125ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin return RVAL_DECODED; 126ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin } 127ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 128ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin if (!size) { 129ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin printaddr(addr); 130ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin return RVAL_DECODED; 131ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin } 132ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin if (size > sizeof(attr)) 133ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin size = sizeof(attr); 134ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin if (umoven_or_printaddr(tcp, addr, size, &attr)) 135ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin return RVAL_DECODED; 136ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 137ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin tprints("{map_fd="); 138ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin printfd(tcp, attr.map_fd); 139ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin tprintf(", key=%#" PRIx64, attr.key); 140ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 141ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin return 0; 142ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin} 143ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 144ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levinstatic int 145ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levinbpf_prog_load(struct tcb *tcp, const long addr, unsigned int size) 146ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin{ 147ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin struct { 148ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin uint32_t prog_type, insn_cnt; 149ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin uint64_t ATTRIBUTE_ALIGNED(8) insns, license; 150ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin uint32_t log_level, log_size; 151ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin uint64_t ATTRIBUTE_ALIGNED(8) log_buf; 152ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin uint32_t kern_version; 153ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin } attr = {}; 154ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 155ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin if (!size) { 156ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin printaddr(addr); 157ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin return RVAL_DECODED | RVAL_FD; 158ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin } 159ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin if (size > sizeof(attr)) 160ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin size = sizeof(attr); 161ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin if (umoven_or_printaddr(tcp, addr, size, &attr)) 162ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin return RVAL_DECODED | RVAL_FD; 163ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 164ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin tprints("{prog_type="); 165ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin printxval(bpf_prog_types, attr.prog_type, "BPF_PROG_TYPE_???"); 166ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin tprintf(", insn_cnt=%u, insns=%#" PRIx64 ", license=", 167ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin attr.insn_cnt, attr.insns); 168ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin printstr(tcp, attr.license, -1); 169ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin tprintf(", log_level=%u, log_size=%u, log_buf=%#" PRIx64 ", kern_version=%u}", 170ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin attr.log_level, attr.log_size, attr.log_buf, attr.kern_version); 171ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 172ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin return RVAL_DECODED | RVAL_FD; 173ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin} 174ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 175ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. LevinSYS_FUNC(bpf) 176ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin{ 177ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin const int cmd = tcp->u_arg[0]; 178ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin const long addr = tcp->u_arg[1]; 179ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin const unsigned int size = tcp->u_arg[2]; 180ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin int rc = RVAL_DECODED; 181ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 182ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin if (entering(tcp)) { 183ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin printxval(bpf_commands, cmd, "BPF_???"); 184ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin tprints(", "); 185ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin } 186ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 187ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin switch (cmd) { 188ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin case BPF_MAP_CREATE: 189ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin rc = bpf_map_create(tcp, addr, size); 190ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin break; 191ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin case BPF_MAP_LOOKUP_ELEM: 192ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin rc = bpf_map_io(tcp, addr, size, "value"); 193ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin break; 194ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin case BPF_MAP_UPDATE_ELEM: 195ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin bpf_map_update_elem(tcp, addr, size); 196ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin break; 197ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin case BPF_MAP_DELETE_ELEM: 198ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin bpf_map_delete_elem(tcp, addr, size); 199ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin break; 200ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin case BPF_MAP_GET_NEXT_KEY: 201ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin rc = bpf_map_io(tcp, addr, size, "next_key"); 202ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin break; 203ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin case BPF_PROG_LOAD: 204ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin rc = bpf_prog_load(tcp, addr, size); 205ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin break; 206ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin default: 207ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin printaddr(addr); 208ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin break; 209ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin } 210ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 211ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin if (rc & RVAL_DECODED) 212ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin tprintf(", %u", size); 213ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin 214ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin return rc; 215ddb53dd142ea6702afbc1ff238840969183a709dDmitry V. Levin} 216