ctdb-protocol: Avoid fgets in ctdb_connection_list_read
authorAmitay Isaacs <amitay@gmail.com>
Wed, 11 Jul 2018 08:35:46 +0000 (18:35 +1000)
committerMartin Schwenke <martins@samba.org>
Sat, 28 Jul 2018 01:50:11 +0000 (03:50 +0200)
C library buffering API can behave in unexpected fashion if underlying
fd for stdin, stdout or stderr is closed and re-opened.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13520

Signed-off-by: Amitay Isaacs <amitay@gmail.com>
Reviewed-by: Martin Schwenke <martin@meltin.net>
ctdb/protocol/protocol_util.c
ctdb/wscript

index 69bd67bf5c5a39eed1c4ab8edbfbbef8b0885d0b..7ce19c1f79c7bb2dd102e981c2f25509c054d99c 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <talloc.h>
 
+#include "common/line.h"
+
 #include "protocol.h"
 #include "protocol_util.h"
 
@@ -642,56 +644,66 @@ const char *ctdb_connection_list_to_string(
        return out;
 }
 
-int ctdb_connection_list_read(TALLOC_CTX *mem_ctx, bool client_first,
-                             struct ctdb_connection_list **conn_list)
-{
+struct ctdb_connection_list_read_state {
        struct ctdb_connection_list *list;
-       char line[128]; /* long enough for IPv6 */
+       bool client_first;
+};
+
+static int ctdb_connection_list_read_line(char *line, void *private_data)
+{
+       struct ctdb_connection_list_read_state *state =
+               (struct ctdb_connection_list_read_state *)private_data;
+       struct ctdb_connection conn;
        int ret;
 
-       if (conn_list == NULL) {
-               return EINVAL;
+       /* Skip empty lines */
+       if (line[0] == '\0') {
+               return 0;
        }
 
-       list = talloc_zero(mem_ctx, struct ctdb_connection_list);
-       if (list == NULL) {
-               return ENOMEM;
+       /* Comment */
+       if (line[0] == '#') {
+               return 0;
        }
 
-       while (fgets(line, sizeof(line), stdin) != NULL) {
-               char *t;
-               struct ctdb_connection conn;
+       ret = ctdb_connection_from_string(line, state->client_first, &conn);
+       if (ret != 0) {
+               return ret;
+       }
 
-               /* Skip empty lines */
-               if (line[0] == '\n') {
-                       continue;
-               }
+       ret = ctdb_connection_list_add(state->list, &conn);
+       if (ret != 0) {
+               return ret;
+       }
 
-               /* Comment */
-               if (line[0] == '#') {
-                       continue;
-               }
+       return 0;
+}
 
-               t = strtok(line, "\n");
-               if (t == NULL) {
-                       goto fail;
-               }
+int ctdb_connection_list_read(TALLOC_CTX *mem_ctx, bool client_first,
+                             struct ctdb_connection_list **conn_list)
+{
+       struct ctdb_connection_list_read_state state;
+       int ret;
 
-               ret = ctdb_connection_from_string(t, client_first, &conn);
-               if (ret != 0) {
-                       goto fail;
-               }
+       if (conn_list == NULL) {
+               return EINVAL;
+       }
 
-               ret = ctdb_connection_list_add(list, &conn);
-               if (ret != 0) {
-                       goto fail;
-               }
+       state.list = talloc_zero(mem_ctx, struct ctdb_connection_list);
+       if (state.list == NULL) {
+               return ENOMEM;
        }
 
-       *conn_list = list;
-       return 0;
+       state.client_first = client_first;
+
+       ret = line_read(0,
+                       128,
+                       mem_ctx,
+                       ctdb_connection_list_read_line,
+                       &state,
+                       NULL);
 
-fail:
-       talloc_free(list);
-       return EINVAL;
+       *conn_list = state.list;
+
+       return ret;
 }
index 6d69545b6aa505257c3bc61f01168860768af285..6e69e4999858e3b6ab886bacb209d7750e1e584e 100644 (file)
@@ -434,7 +434,7 @@ def build(bld):
 
     bld.SAMBA_SUBSYSTEM('ctdb-protocol-util',
                         source='protocol/protocol_util.c',
-                        deps='replace talloc tdb')
+                        deps='ctdb-util replace talloc tdb')
 
     bld.SAMBA_SUBSYSTEM('ctdb-client',
                         source=bld.SUBDIR('client',
@@ -938,7 +938,7 @@ def build(bld):
         bld.SAMBA_BINARY(target,
                          source=src,
                          deps='''ctdb-protocol-tests-common
-                                 samba-util talloc tdb''',
+                                 samba-util ctdb-util talloc tdb''',
                          install_path='${CTDB_TEST_LIBEXECDIR}')
 
     bld.SAMBA_BINARY('event_protocol_test',