libnm: buffer reads in nm_vpn_service_plugin_read_vpn_details()
It seems very ugly to read one byte at a time. Use a naive buffered reader, so that we can read multiple bytes at a time, and return them one by one. Also, this now keeps state of any error/EOF. Once we reach EOF, we won't read again. The previous code did that too, but I think this code is easier to read.
This commit is contained in:
@@ -729,6 +729,54 @@ nm_vpn_service_plugin_secrets_required(NMVpnServicePlugin *plugin,
|
|||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *buf;
|
||||||
|
gsize n_buf;
|
||||||
|
int fd;
|
||||||
|
bool eof : 1;
|
||||||
|
char buf_full[1024];
|
||||||
|
} ReadFdBuf;
|
||||||
|
|
||||||
|
static inline gboolean
|
||||||
|
_read_fd_buf_c(ReadFdBuf *read_buf, char *ch)
|
||||||
|
{
|
||||||
|
gssize n_read;
|
||||||
|
|
||||||
|
if (read_buf->n_buf > 0)
|
||||||
|
goto out_data;
|
||||||
|
if (read_buf->eof)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
again:
|
||||||
|
n_read = read(read_buf->fd, read_buf->buf_full, sizeof(read_buf->buf_full));
|
||||||
|
if (n_read <= 0) {
|
||||||
|
if (n_read < 0 && errno == EAGAIN) {
|
||||||
|
struct pollfd pfd;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
memset(&pfd, 0, sizeof(pfd));
|
||||||
|
pfd.fd = read_buf->fd;
|
||||||
|
pfd.events = POLLIN;
|
||||||
|
|
||||||
|
r = poll(&pfd, 1, -1);
|
||||||
|
if (r > 0)
|
||||||
|
goto again;
|
||||||
|
/* error or timeout. Fall through and set EOF. */
|
||||||
|
}
|
||||||
|
read_buf->eof = TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
read_buf->buf = read_buf->buf_full;
|
||||||
|
read_buf->n_buf = n_read;
|
||||||
|
|
||||||
|
out_data:
|
||||||
|
read_buf->n_buf--;
|
||||||
|
*ch = read_buf->buf[0];
|
||||||
|
read_buf->buf++;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
#define DATA_KEY_TAG "DATA_KEY="
|
#define DATA_KEY_TAG "DATA_KEY="
|
||||||
#define DATA_VAL_TAG "DATA_VAL="
|
#define DATA_VAL_TAG "DATA_VAL="
|
||||||
#define SECRET_KEY_TAG "SECRET_KEY="
|
#define SECRET_KEY_TAG "SECRET_KEY="
|
||||||
@@ -759,8 +807,8 @@ nm_vpn_service_plugin_read_vpn_details(int fd, GHashTable **out_data, GHashTable
|
|||||||
nm_auto_free_gstring GString *key = NULL;
|
nm_auto_free_gstring GString *key = NULL;
|
||||||
nm_auto_free_gstring GString *val = NULL;
|
nm_auto_free_gstring GString *val = NULL;
|
||||||
nm_auto_free_gstring GString *line = NULL;
|
nm_auto_free_gstring GString *line = NULL;
|
||||||
char c;
|
GString * str = NULL;
|
||||||
GString * str = NULL;
|
ReadFdBuf read_buf;
|
||||||
|
|
||||||
if (out_data)
|
if (out_data)
|
||||||
g_return_val_if_fail(*out_data == NULL, FALSE);
|
g_return_val_if_fail(*out_data == NULL, FALSE);
|
||||||
@@ -771,31 +819,21 @@ nm_vpn_service_plugin_read_vpn_details(int fd, GHashTable **out_data, GHashTable
|
|||||||
secrets =
|
secrets =
|
||||||
g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, (GDestroyNotify) nm_free_secret);
|
g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, (GDestroyNotify) nm_free_secret);
|
||||||
|
|
||||||
|
read_buf.buf = NULL;
|
||||||
|
read_buf.n_buf = 0;
|
||||||
|
read_buf.fd = fd;
|
||||||
|
read_buf.eof = FALSE;
|
||||||
|
|
||||||
line = g_string_new(NULL);
|
line = g_string_new(NULL);
|
||||||
|
|
||||||
/* Read stdin for data and secret items until we get a DONE */
|
/* Read stdin for data and secret items until we get a DONE */
|
||||||
while (1) {
|
while (1) {
|
||||||
ssize_t nr;
|
gboolean eof;
|
||||||
|
char c;
|
||||||
|
|
||||||
nr = read(fd, &c, 1);
|
eof = !_read_fd_buf_c(&read_buf, &c);
|
||||||
if (nr < 0) {
|
|
||||||
if (errno == EAGAIN) {
|
|
||||||
struct pollfd pfd;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
memset(&pfd, 0, sizeof(pfd));
|
if (!eof && c != '\n') {
|
||||||
pfd.fd = fd;
|
|
||||||
pfd.events = POLLIN;
|
|
||||||
|
|
||||||
r = poll(&pfd, 1, -1);
|
|
||||||
if (r > 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* error or timeout. Fall through and break. */
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (nr > 0 && c != '\n') {
|
|
||||||
g_string_append_c(line, c);
|
g_string_append_c(line, c);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -841,7 +879,7 @@ nm_vpn_service_plugin_read_vpn_details(int fd, GHashTable **out_data, GHashTable
|
|||||||
|
|
||||||
g_string_truncate(line, 0);
|
g_string_truncate(line, 0);
|
||||||
|
|
||||||
if (nr == 0)
|
if (eof)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user