/* Line based I/O over fds Copyright (C) Amitay Isaacs 2018 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ #include "replace.h" #include #include "lib/util/sys_rw.h" #include "common/line.h" struct line_read_state { line_process_fn_t callback; void *private_data; char *buf; size_t hint, len, offset; int num_lines; }; static bool line_read_one(char *buf, size_t start, size_t len, size_t *pos) { size_t i; for (i=start; ibuf, start, state->offset, &pos); if (! ok) { break; } state->buf[pos] = '\0'; state->num_lines += 1; ret = state->callback(state->buf + start, state->private_data); if (ret != 0) { return ret; } start = pos+1; } if (pos > 0) { if (pos+1 < state->offset) { memmove(state->buf, state->buf + pos+1, state->offset - (pos+1)); } state->offset -= (pos+1); } return 0; } int line_read(int fd, size_t length, TALLOC_CTX *mem_ctx, line_process_fn_t callback, void *private_data, int *num_lines) { struct line_read_state state; if (length < 32) { length = 32; } state = (struct line_read_state) { .callback = callback, .private_data = private_data, .hint = length, }; while (1) { ssize_t n; int ret; if (state.offset == state.len) { state.len += state.hint; state.buf = talloc_realloc_size(mem_ctx, state.buf, state.len); if (state.buf == NULL) { return ENOMEM; } } n = sys_read(fd, state.buf + state.offset, state.len - state.offset); if (n < 0) { return errno; } if (n == 0) { break; } state.offset += n; ret = line_read_process(&state); if (ret != 0) { if (num_lines != NULL) { *num_lines = state.num_lines; } return ret; } } if (num_lines != NULL) { *num_lines = state.num_lines; } return 0; }