client: check return of dup(2)
[fio.git] / client.c
index 970974a00f274ee6e1640c84c1145c13a146c54c..611ee2f5a3f929d9d7ae7c7d14c229196bdfedbb 100644 (file)
--- a/client.c
+++ b/client.c
@@ -28,7 +28,7 @@ static void handle_ts(struct fio_client *client, struct fio_net_cmd *cmd);
 static void handle_gs(struct fio_client *client, struct fio_net_cmd *cmd);
 static void handle_probe(struct fio_client *client, struct fio_net_cmd *cmd);
 static void handle_text(struct fio_client *client, struct fio_net_cmd *cmd);
-static void handle_stop(struct fio_client *client, struct fio_net_cmd *cmd);
+static void handle_stop(struct fio_client *client);
 static void handle_start(struct fio_client *client, struct fio_net_cmd *cmd);
 
 static void convert_text(struct fio_net_cmd *cmd);
@@ -118,6 +118,54 @@ static int read_data(int fd, void *data, size_t size)
        return 0;
 }
 
+static int read_ini_data(int fd, void *data, size_t size)
+{
+       char *p = data;
+       int ret = 0;
+       FILE *fp;
+       int dupfd;
+
+       dupfd = dup(fd);
+       if (dupfd < 0)
+               return errno;
+
+       fp = fdopen(dupfd, "r");
+       if (!fp)
+               return errno;
+
+       while (1) {
+               ssize_t len;
+               char buf[OPT_LEN_MAX+1], *sub;
+
+               if (!fgets(buf, sizeof(buf), fp)) {
+                       if (ferror(fp)) {
+                               if (errno == EAGAIN || errno == EINTR)
+                                       continue;
+                               ret = errno;
+                       }
+                       break;
+               }
+
+               sub = fio_option_dup_subs(buf);
+               len = strlen(sub);
+               if (len + 1 > size) {
+                       log_err("fio: no space left to read data\n");
+                       free(sub);
+                       ret = ENOSPC;
+                       break;
+               }
+
+               memcpy(p, sub, len);
+               free(sub);
+               p += len;
+               *p = '\0';
+               size -= len;
+       }
+
+       fclose(fp);
+       return ret;
+}
+
 static void fio_client_json_init(void)
 {
        char time_buf[32];
@@ -763,13 +811,17 @@ static int __fio_client_send_local_ini(struct fio_client *client,
                return ret;
        }
 
+       /*
+        * Add extra space for variable expansion, but doesn't guarantee.
+        */
+       sb.st_size += OPT_LEN_MAX;
        p_size = sb.st_size + sizeof(*pdu);
        pdu = malloc(p_size);
        buf = pdu->buf;
 
        len = sb.st_size;
        p = buf;
-       if (read_data(fd, p, len)) {
+       if (read_ini_data(fd, p, len)) {
                log_err("fio: failed reading job file %s\n", filename);
                close(fd);
                free(pdu);
@@ -1339,7 +1391,7 @@ static int fio_client_handle_iolog(struct fio_client *client,
        sprintf(log_pathname, "%s.%s", pdu->name, client->hostname);
 
        if (store_direct) {
-               ssize_t ret;
+               ssize_t wrote;
                size_t sz;
                int fd;
 
@@ -1353,10 +1405,10 @@ static int fio_client_handle_iolog(struct fio_client *client,
                }
 
                sz = cmd->pdu_len - sizeof(*pdu);
-               ret = write(fd, pdu->samples, sz);
+               wrote = write(fd, pdu->samples, sz);
                close(fd);
 
-               if (ret != sz) {
+               if (wrote != sz) {
                        log_err("fio: short write on compressed log\n");
                        ret = 1;
                        goto out;
@@ -1441,7 +1493,7 @@ static void handle_start(struct fio_client *client, struct fio_net_cmd *cmd)
        sum_stat_clients += client->nr_stat;
 }
 
-static void handle_stop(struct fio_client *client, struct fio_net_cmd *cmd)
+static void handle_stop(struct fio_client *client)
 {
        if (client->error)
                log_info("client <%s>: exited with error %d\n", client->hostname, client->error);
@@ -1744,7 +1796,7 @@ int fio_handle_client(struct fio_client *client)
                client->state = Client_stopped;
                client->error = le32_to_cpu(pdu->error);
                client->signal = le32_to_cpu(pdu->signal);
-               ops->stop(client, cmd);
+               ops->stop(client);
                break;
                }
        case FIO_NET_CMD_ADD_JOB: {