gp: Skip site GP list if no site is found
[Samba.git] / ctdb / common / line.c
blobc4c6726875bf2a8e350d2ca9e3303da6f3d8bbe4
1 /*
2 Line based I/O over fds
4 Copyright (C) Amitay Isaacs 2018
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.
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.
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/>.
20 #include "replace.h"
22 #include <talloc.h>
24 #include "lib/util/sys_rw.h"
26 #include "common/line.h"
28 struct line_read_state {
29 line_process_fn_t callback;
30 void *private_data;
31 char *buf;
32 size_t hint, len, offset;
33 int num_lines;
36 static bool line_read_one(char *buf, size_t start, size_t len, size_t *pos)
38 size_t i;
40 for (i=start; i<len; i++) {
41 if (buf[i] == '\n' || buf[i] == '\0') {
42 *pos = i;
43 return true;
47 return false;
50 static int line_read_process(struct line_read_state *state)
52 size_t start = 0;
53 size_t pos = 0;
55 while (1) {
56 int ret;
57 bool ok;
59 ok = line_read_one(state->buf, start, state->offset, &pos);
60 if (! ok) {
61 break;
64 state->buf[pos] = '\0';
65 state->num_lines += 1;
67 ret = state->callback(state->buf + start, state->private_data);
68 if (ret != 0) {
69 return ret;
72 start = pos+1;
75 if (pos > 0) {
76 if (pos+1 < state->offset) {
77 memmove(state->buf,
78 state->buf + pos+1,
79 state->offset - (pos+1));
81 state->offset -= (pos+1);
84 return 0;
87 int line_read(int fd,
88 size_t length,
89 TALLOC_CTX *mem_ctx,
90 line_process_fn_t callback,
91 void *private_data,
92 int *num_lines)
94 struct line_read_state state;
96 if (length < 32) {
97 length = 32;
100 state = (struct line_read_state) {
101 .callback = callback,
102 .private_data = private_data,
103 .hint = length,
106 while (1) {
107 ssize_t n;
108 int ret;
110 if (state.offset == state.len) {
111 state.len += state.hint;
112 state.buf = talloc_realloc_size(mem_ctx,
113 state.buf,
114 state.len);
115 if (state.buf == NULL) {
116 return ENOMEM;
120 n = sys_read(fd,
121 state.buf + state.offset,
122 state.len - state.offset);
123 if (n < 0) {
124 return errno;
126 if (n == 0) {
127 break;
130 state.offset += n;
132 ret = line_read_process(&state);
133 if (ret != 0) {
134 if (num_lines != NULL) {
135 *num_lines = state.num_lines;
137 return ret;
141 if (num_lines != NULL) {
142 *num_lines = state.num_lines;
144 return 0;