The following changes since commit a3b4cf7dcae447729f0f4a4ea122f605b909ed70:

  diskutil: separate out stats from name (2014-04-11 12:17:53 -0600)

are available in the git repository at:

  git://git.kernel.dk/fio.git master

for you to fetch changes up to fb73340c52bcab712dfb175dafbcb5156abdda12:

  Windows: set sizeof(sun_path) to 260 (MAX_PATH). (2014-04-14 20:19:54 -0600)

----------------------------------------------------------------
Bruce Cran (1):
      Windows: set sizeof(sun_path) to 260 (MAX_PATH).

Jens Axboe (43):
      init: fix more cases of leaking pid_file
      stat: check that TEMP environment variable is half-way sane
      server: ensure that dus->name is always NULL terminated
      init: fix potential buffer overrun in make_filename()
      verify: fix potential buffer overrun in dump_buf()
      file: fix potential buffer overrun in get_fs_free_counts()
      net engine: fix potential buffer overrun in socket path
      client: fix potential buffer overrun in socket path
      server: fix potential buffer overrun in bind string
      server: fix potential buffer overrun in socket setup path
      stat: fix wrong check for whether we have a description or not
      Fix missing sign conversion in ignore_error_type()
      Make td_verror() use an unsigned type
      gettime: use unsigned loop counter
      server: fix missing comma in fio_server_ops[] strings
      eta: fix potential divide by zero
      idletime: fix potential divide-by-zero
      stat: fix potential divide-by-zero
      backend: fix potential divide-by-zero
      init: remove dead code
      Error check fcntl() calls
      make_filename: another off-by-one buffer issue
      num2str: ensure we never access postfix[] out-of-bounds
      backend: better NULL termination fix for IO scheduler switching
      server: sanity check incoming command size (and payload)
      server: ensure that incoming iolog name is NULL terminated
      net engine: get rid of unused struct sockaddr_in6
      td_verror() needs errno style error
      e4defrag: pass 'error' into td_verror()
      filesetup: silence bogus warning on close(-1)
      init: silence bogus td == NULL warning
      gettime: handle pthread_create() failure
      stat: warn on failure to detach DU thread
      gettime: init 'failed' before use
      Avoid overwriting allocated pid_file
      idletime: unlock ->start_lock in error cases
      Fix is_power_of_2() for longs
      parse: make it clear that 'cp' can't be NULL for o->off1
      diskutil: make it clear that parent != NULL for json output
      Fix potential NULL dereference in alloc_mem_mmap()
      disk util: fix bug in strncpy() conversion
      init: fix leak bug fix from commit 60c5ec73
      init: improve command line check for when to print usage/help

 backend.c                         |   11 ++++--
 client.c                          |    2 +-
 diskutil.c                        |   12 ++++--
 engines/binject.c                 |    7 ++--
 engines/e4defrag.c                |    4 +-
 engines/net.c                     |    9 ++---
 engines/sg.c                      |    7 ++--
 eta.c                             |   24 ++++++++---
 filesetup.c                       |   16 ++++++--
 fio.h                             |    5 ++-
 gettime.c                         |   12 ++++--
 idletime.c                        |   13 ++++--
 init.c                            |   79 +++++++++++++++++++++++++++++--------
 io_u.c                            |    2 +-
 lib/num2str.c                     |    5 +++
 libfio.c                          |   16 ++++++++
 memory.c                          |    5 ++-
 options.c                         |    2 +-
 os/windows/posix/include/sys/un.h |    2 +-
 parse.c                           |    2 +-
 server.c                          |   40 +++++++++++++------
 server.h                          |    1 +
 stat.c                            |   26 +++++++++---
 verify.c                          |   22 +++++++++--
 24 files changed, 239 insertions(+), 85 deletions(-)

---

Diff of recent changes:

diff --git a/backend.c b/backend.c
index b05e543..62bca29 100644
--- a/backend.c
+++ b/backend.c
@@ -182,7 +182,11 @@ static int __check_min_rate(struct thread_data *td, struct 
timeval *now,
                                                                ratemin);
                                return 1;
                        } else {
-                               rate = ((bytes - td->rate_bytes[ddir]) * 1000) 
/ spent;
+                               if (spent)
+                                       rate = ((bytes - td->rate_bytes[ddir]) 
* 1000) / spent;
+                               else
+                                       rate = 0;
+
                                if (rate < ratemin ||
                                    bytes < td->rate_bytes[ddir]) {
                                        log_err("%s: min rate %u not met, got"
@@ -1110,13 +1114,14 @@ static int switch_ioscheduler(struct thread_data *td)
        /*
         * Read back and check that the selected scheduler is now the default.
         */
-       memset(tmp, 0, sizeof(tmp));
-       ret = fread(tmp, 1, sizeof(tmp) - 1, f);
+       ret = fread(tmp, sizeof(tmp), 1, f);
        if (ferror(f) || ret < 0) {
                td_verror(td, errno, "fread");
                fclose(f);
                return 1;
        }
+       tmp[sizeof(tmp) - 1] = '\0';
+
 
        sprintf(tmp2, "[%s]", td->o.ioscheduler);
        if (!strstr(tmp, tmp2)) {
diff --git a/client.c b/client.c
index 05439e1..af6621d 100644
--- a/client.c
+++ b/client.c
@@ -388,7 +388,7 @@ static int fio_client_connect_sock(struct fio_client 
*client)
 
        memset(addr, 0, sizeof(*addr));
        addr->sun_family = AF_UNIX;
-       strcpy(addr->sun_path, client->hostname);
+       strncpy(addr->sun_path, client->hostname, sizeof(addr->sun_path) - 1);
 
        fd = socket(AF_UNIX, SOCK_STREAM, 0);
        if (fd < 0) {
diff --git a/diskutil.c b/diskutil.c
index d97c5ca..cb285cf 100644
--- a/diskutil.c
+++ b/diskutil.c
@@ -6,6 +6,7 @@
 #include <dirent.h>
 #include <libgen.h>
 #include <math.h>
+#include <assert.h>
 
 #include "fio.h"
 #include "smalloc.h"
@@ -299,7 +300,7 @@ static struct disk_util *disk_util_add(struct thread_data 
*td, int majdev,
                sfree(du);
                return NULL;
        }
-       strncpy((char *) du->dus.name, basename(path) - 1, FIO_DU_NAME_SZ);
+       strncpy((char *) du->dus.name, basename(path), FIO_DU_NAME_SZ - 1);
        du->sysfs_root = path;
        du->major = majdev;
        du->minor = mindev;
@@ -686,12 +687,15 @@ void show_disk_util(int terse, struct json_object *parent)
                return;
        }
 
-       if (!terse && !parent)
+       if (output_format == FIO_OUTPUT_JSON)
+               assert(parent);
+
+       if (!terse && output_format != FIO_OUTPUT_JSON)
                log_info("\nDisk stats (read/write):\n");
 
-       if (output_format == FIO_OUTPUT_JSON) {
+       if (output_format == FIO_OUTPUT_JSON)
                json_object_add_disk_utils(parent, &disk_list);
-       } else
+       else
                flist_for_each(entry, &disk_list) {
                        du = flist_entry(entry, struct disk_util, list);
 
diff --git a/engines/binject.c b/engines/binject.c
index fb19062..0264d0a 100644
--- a/engines/binject.c
+++ b/engines/binject.c
@@ -109,10 +109,9 @@ static int fio_binject_getevents(struct thread_data *td, 
unsigned int min,
                /*
                 * don't block for min events == 0
                 */
-               if (!min) {
-                       bd->fd_flags[i] = fcntl(bf->fd, F_GETFL);
-                       fcntl(bf->fd, F_SETFL, bd->fd_flags[i] | O_NONBLOCK);
-               }
+               if (!min)
+                       fio_set_fd_nonblocking(bf->fd, "binject");
+
                bd->pfds[i].fd = bf->fd;
                bd->pfds[i].events = POLLIN;
        }
diff --git a/engines/e4defrag.c b/engines/e4defrag.c
index 4d87f67..3599ab8 100644
--- a/engines/e4defrag.c
+++ b/engines/e4defrag.c
@@ -80,7 +80,7 @@ static int fio_e4defrag_init(struct thread_data *td)
 
        ed = malloc(sizeof(*ed));
        if (!ed) {
-               td_verror(td, -ENOMEM, "io_queue_init");
+               td_verror(td, ENOMEM, "io_queue_init");
                return 1;
        }
        memset(ed, 0 ,sizeof(*ed));
@@ -91,7 +91,7 @@ static int fio_e4defrag_init(struct thread_data *td)
 
        ed->donor_fd = open(donor_name, O_CREAT|O_WRONLY, 0644);
        if (ed->donor_fd < 0) {
-               td_verror(td, ed->donor_fd, "io_queue_init");
+               td_verror(td, errno, "io_queue_init");
                log_err("Can't open donor file %s err:%d", donor_name, 
ed->donor_fd);
                free(ed);
                return 1;
diff --git a/engines/net.c b/engines/net.c
index d036a58..8087207 100644
--- a/engines/net.c
+++ b/engines/net.c
@@ -945,7 +945,8 @@ static int fio_netio_setup_connect_unix(struct thread_data 
*td,
        struct sockaddr_un *soun = &nd->addr_un;
 
        soun->sun_family = AF_UNIX;
-       strcpy(soun->sun_path, path);
+       memset(soun->sun_path, 0, sizeof(soun->sun_path));
+       strncpy(soun->sun_path, path, sizeof(soun->sun_path) - 1);
        return 0;
 }
 
@@ -976,7 +977,7 @@ static int fio_netio_setup_listen_unix(struct thread_data 
*td, const char *path)
 
        memset(addr, 0, sizeof(*addr));
        addr->sun_family = AF_UNIX;
-       strcpy(addr->sun_path, path);
+       strncpy(addr->sun_path, path, sizeof(addr->sun_path) - 1);
        unlink(path);
 
        len = sizeof(addr->sun_family) + strlen(path) + 1;
@@ -998,13 +999,11 @@ static int fio_netio_setup_listen_inet(struct thread_data 
*td, short port)
        struct netio_options *o = td->eo;
        struct ip_mreq mr;
        struct sockaddr_in sin;
-       struct sockaddr_in6 sin6;
        struct sockaddr *saddr;
        int fd, opt, type, domain;
        socklen_t len;
 
        memset(&sin, 0, sizeof(sin));
-       memset(&sin6, 0, sizeof(sin6));
 
        if (o->proto == FIO_TYPE_TCP) {
                type = SOCK_STREAM;
@@ -1087,7 +1086,7 @@ static int fio_netio_setup_listen_inet(struct thread_data 
*td, short port)
                len = sizeof(nd->addr6);
 
                nd->addr6.sin6_family = AF_INET6;
-               nd->addr6.sin6_addr = sin6.sin6_addr.s6_addr ? sin6.sin6_addr : 
in6addr_any;
+               nd->addr6.sin6_addr = in6addr_any;
                nd->addr6.sin6_port = htons(port);
        }
 
diff --git a/engines/sg.c b/engines/sg.c
index 88d9125..fcd9c41 100644
--- a/engines/sg.c
+++ b/engines/sg.c
@@ -77,10 +77,9 @@ static int fio_sgio_getevents(struct thread_data *td, 
unsigned int min,
                /*
                 * don't block for min events == 0
                 */
-               if (!min) {
-                       sd->fd_flags[i] = fcntl(f->fd, F_GETFL);
-                       fcntl(f->fd, F_SETFL, sd->fd_flags[i] | O_NONBLOCK);
-               }
+               if (!min)
+                       fio_set_fd_nonblocking(f->fd, "sg");
+
                sd->pfds[i].fd = f->fd;
                sd->pfds[i].events = POLLIN;
        }
diff --git a/eta.c b/eta.c
index 42066e0..7500082 100644
--- a/eta.c
+++ b/eta.c
@@ -174,14 +174,26 @@ static int thread_eta(struct thread_data *td)
                double perc, perc_t;
 
                bytes_done = ddir_rw_sum(td->io_bytes);
-               perc = (double) bytes_done / (double) bytes_total;
-               if (perc > 1.0)
-                       perc = 1.0;
+
+               if (bytes_total) {
+                       perc = (double) bytes_done / (double) bytes_total;
+                       if (perc > 1.0)
+                               perc = 1.0;
+               } else
+                       perc = 0.0;
 
                if (td->o.time_based) {
-                       perc_t = (double) elapsed / (double) timeout;
-                       if (perc_t < perc)
-                               perc = perc_t;
+                       if (timeout) {
+                               perc_t = (double) elapsed / (double) timeout;
+                               if (perc_t < perc)
+                                       perc = perc_t;
+                       } else {
+                               /*
+                                * Will never hit, we can't have time_based
+                                * without a timeout set.
+                                */
+                               perc = 0.0;
+                       }
                }
 
                eta_sec = (unsigned long) (elapsed * (1.0 / perc)) - elapsed;
diff --git a/filesetup.c b/filesetup.c
index bf56112..490f0fc 100644
--- a/filesetup.c
+++ b/filesetup.c
@@ -688,7 +688,8 @@ static unsigned long long get_fs_free_counts(struct 
thread_data *td)
                } else if (f->filetype != FIO_TYPE_FILE)
                        continue;
 
-               strcpy(buf, f->file_name);
+               buf[255] = '\0';
+               strncpy(buf, f->file_name, 255);
 
                if (stat(buf, &sb) < 0) {
                        if (errno != ENOENT)
@@ -914,7 +915,13 @@ int setup_files(struct thread_data *td)
 
                        err = __file_invalidate_cache(td, f, old_len,
                                                                extend_len);
-                       close(f->fd);
+
+                       /*
+                        * Shut up static checker
+                        */
+                       if (f->fd != -1)
+                               close(f->fd);
+
                        f->fd = -1;
                        if (err)
                                break;
@@ -1325,8 +1332,11 @@ int put_file(struct thread_data *td, struct fio_file *f)
        if (--f->references)
                return 0;
 
-       if (should_fsync(td) && td->o.fsync_on_close)
+       if (should_fsync(td) && td->o.fsync_on_close) {
                f_ret = fsync(f->fd);
+               if (f_ret < 0)
+                       f_ret = errno;
+       }
 
        if (td->io_ops->close_file)
                ret = td->io_ops->close_file(td, f);
diff --git a/fio.h b/fio.h
index 3df5bd9..544916f 100644
--- a/fio.h
+++ b/fio.h
@@ -351,7 +351,7 @@ enum {
 
 #define __td_verror(td, err, msg, func)                                        
\
        do {                                                            \
-               int ____e = (err);                                              
\
+               unsigned int ____e = (err);                             \
                if ((td)->error)                                        \
                        break;                                          \
                (td)->error = ____e;                                    \
@@ -441,6 +441,7 @@ extern char *num2str(unsigned long, int, int, int, int);
 extern int ioengine_load(struct thread_data *);
 extern int parse_dryrun(void);
 extern int fio_running_or_pending_io_threads(void);
+extern void fio_set_fd_nonblocking(int, const char *);
 
 extern uintptr_t page_mask;
 extern uintptr_t page_size;
@@ -587,7 +588,7 @@ static inline unsigned int td_min_bs(struct thread_data *td)
        return min(td->o.min_bs[DDIR_TRIM], min_bs);
 }
 
-static inline int is_power_of_2(unsigned int val)
+static inline int is_power_of_2(unsigned long val)
 {
        return (val != 0 && ((val & (val - 1)) == 0));
 }
diff --git a/gettime.c b/gettime.c
index c6d45f8..fa750ec 100644
--- a/gettime.c
+++ b/gettime.c
@@ -534,10 +534,10 @@ int fio_monotonic_clocktest(void)
        struct clock_thread *threads;
        unsigned int nr_cpus = cpus_online();
        struct clock_entry *entries;
-       unsigned long tentries, failed;
+       unsigned long tentries, failed = 0;
        struct clock_entry *prev, *this;
        uint32_t seq = 0;
-       int i;
+       unsigned int i;
 
        log_info("cs: reliable_tsc: %s\n", tsc_reliable ? "yes" : "no");
 
@@ -560,7 +560,11 @@ int fio_monotonic_clocktest(void)
                pthread_mutex_init(&t->lock, NULL);
                pthread_mutex_init(&t->started, NULL);
                pthread_mutex_lock(&t->lock);
-               pthread_create(&t->thread, NULL, clock_thread_fn, t);
+               if (pthread_create(&t->thread, NULL, clock_thread_fn, t)) {
+                       failed++;
+                       nr_cpus = i;
+                       break;
+               }
        }
 
        for (i = 0; i < nr_cpus; i++) {
@@ -575,7 +579,7 @@ int fio_monotonic_clocktest(void)
                pthread_mutex_unlock(&t->lock);
        }
 
-       for (failed = i = 0; i < nr_cpus; i++) {
+       for (i = 0; i < nr_cpus; i++) {
                struct clock_thread *t = &threads[i];
                void *ret;
 
diff --git a/idletime.c b/idletime.c
index c0bc0bf..8d23154 100644
--- a/idletime.c
+++ b/idletime.c
@@ -109,12 +109,16 @@ static void *idle_prof_thread_fn(void *data)
        pthread_mutex_lock(&ipt->start_lock);
 
        /* exit if other threads failed to initialize */
-       if (ipc.status == IDLE_PROF_STATUS_ABORT)
+       if (ipc.status == IDLE_PROF_STATUS_ABORT) {
+               pthread_mutex_unlock(&ipt->start_lock);
                return NULL;
+       }
 
        /* exit if we are doing calibration only */
-       if (ipc.status == IDLE_PROF_STATUS_CALI_STOP)
+       if (ipc.status == IDLE_PROF_STATUS_CALI_STOP) {
+               pthread_mutex_unlock(&ipt->start_lock);
                return NULL;
+       }
 
        fio_gettime(&ipt->tps, NULL);
        ipt->state = TD_RUNNING;
@@ -336,7 +340,10 @@ void fio_idle_prof_stop(void)
                /* calculate idleness */
                if (ipc.cali_mean != 0.0) {
                        runt = utime_since(&ipt->tps, &ipt->tpe);
-                       ipt->idleness = ipt->loops * ipc.cali_mean / runt;
+                       if (runt)
+                               ipt->idleness = ipt->loops * ipc.cali_mean / 
runt;
+                       else
+                               ipt->idleness = 0.0;
                } else
                        ipt->idleness = 0.0;
        }
diff --git a/init.c b/init.c
index 215b60d..7630978 100644
--- a/init.c
+++ b/init.c
@@ -942,6 +942,7 @@ static char *make_filename(char *buf, struct thread_options 
*o,
 {
        struct fpre_keyword *f;
        char copy[PATH_MAX];
+       size_t dst_left = PATH_MAX - 1;
 
        if (!o->filename_format || !strlen(o->filename_format)) {
                sprintf(buf, "%s.%d.%d", jobname, jobnum, filenum);
@@ -969,25 +970,47 @@ static char *make_filename(char *buf, struct 
thread_options *o,
                        if (pre_len) {
                                strncpy(dst, buf, pre_len);
                                dst += pre_len;
+                               dst_left -= pre_len;
                        }
 
                        switch (f->key) {
-                       case FPRE_JOBNAME:
-                               dst += sprintf(dst, "%s", jobname);
+                       case FPRE_JOBNAME: {
+                               int ret;
+
+                               ret = snprintf(dst, dst_left, "%s", jobname);
+                               if (ret < 0)
+                                       break;
+                               dst += ret;
+                               dst_left -= ret;
                                break;
-                       case FPRE_JOBNUM:
-                               dst += sprintf(dst, "%d", jobnum);
+                               }
+                       case FPRE_JOBNUM: {
+                               int ret;
+
+                               ret = snprintf(dst, dst_left, "%d", jobnum);
+                               if (ret < 0)
+                                       break;
+                               dst += ret;
+                               dst_left -= ret;
                                break;
-                       case FPRE_FILENUM:
-                               dst += sprintf(dst, "%d", filenum);
+                               }
+                       case FPRE_FILENUM: {
+                               int ret;
+
+                               ret = snprintf(dst, dst_left, "%d", filenum);
+                               if (ret < 0)
+                                       break;
+                               dst += ret;
+                               dst_left -= ret;
                                break;
+                               }
                        default:
                                assert(0);
                                break;
                        }
 
                        if (post_start)
-                               strcpy(dst, buf + post_start);
+                               strncpy(dst, buf + post_start, dst_left);
 
                        strcpy(buf, copy);
                } while (1);
@@ -1435,9 +1458,6 @@ int parse_jobs_ini(char *file, int is_buf, int 
stonewall_flag, int type)
                i++;
        }
 
-       for (i = 0; i < num_opts; i++)
-               free(opts[i]);
-
        free(string);
        free(name);
        free(opts);
@@ -1694,8 +1714,6 @@ int parse_cmd_line(int argc, char *argv[], int 
client_type)
        optind = 1;
 
        while ((c = getopt_long_only(argc, argv, ostr, l_opts, &lidx)) != -1) {
-               did_arg = 1;
-
                if ((c & FIO_CLIENT_FLAG) || client_flag_set(c)) {
                        parse_cmd_client(cur_client, argv[optind - 1]);
                        c &= ~FIO_CLIENT_FLAG;
@@ -1752,30 +1770,35 @@ int parse_cmd_line(int argc, char *argv[], int 
client_type)
                        append_terse_output = 1;
                        break;
                case 'h':
+                       did_arg = 1;
                        if (!cur_client) {
                                usage(argv[0]);
                                do_exit++;
                        }
                        break;
                case 'c':
+                       did_arg = 1;
                        if (!cur_client) {
                                fio_show_option_help(optarg);
                                do_exit++;
                        }
                        break;
                case 'i':
+                       did_arg = 1;
                        if (!cur_client) {
                                fio_show_ioengine_help(optarg);
                                do_exit++;
                        }
                        break;
                case 's':
+                       did_arg = 1;
                        dump_cmdline = 1;
                        break;
                case 'r':
                        read_only = 1;
                        break;
                case 'v':
+                       did_arg = 1;
                        if (!cur_client) {
                                log_info("%s\n", fio_version_string);
                                do_exit++;
@@ -1812,6 +1835,7 @@ int parse_cmd_line(int argc, char *argv[], int 
client_type)
                                do_exit++;
                        break;
                case 'P':
+                       did_arg = 1;
                        parse_only = 1;
                        break;
                case 'x': {
@@ -1831,6 +1855,7 @@ int parse_cmd_line(int argc, char *argv[], int 
client_type)
                        break;
                        }
                case 'p':
+                       did_arg = 1;
                        if (exec_profile)
                                free(exec_profile);
                        exec_profile = strdup(optarg);
@@ -1842,8 +1867,9 @@ int parse_cmd_line(int argc, char *argv[], int 
client_type)
                        if (!strncmp(opt, "name", 4) && td) {
                                ret = add_job(td, td->o.name ?: "fio", 0, 0, 
client_type);
                                if (ret)
-                                       return 0;
+                                       goto out_free;
                                td = NULL;
+                               did_arg = 1;
                        }
                        if (!td) {
                                int is_section = !strncmp(opt, "name", 4);
@@ -1857,7 +1883,7 @@ int parse_cmd_line(int argc, char *argv[], int 
client_type)
 
                                td = get_new_job(global, &def_thread, 1);
                                if (!td || ioengine_load(td))
-                                       return 0;
+                                       goto out_free;
                                fio_options_set_ioengine_opts(l_opts, td);
                        }
 
@@ -1879,7 +1905,7 @@ int parse_cmd_line(int argc, char *argv[], int 
client_type)
                        if (!ret && !strcmp(opt, "ioengine")) {
                                free_ioengine(td);
                                if (ioengine_load(td))
-                                       return 0;
+                                       goto out_free;
                                fio_options_set_ioengine_opts(l_opts, td);
                        }
                        break;
@@ -1887,7 +1913,12 @@ int parse_cmd_line(int argc, char *argv[], int 
client_type)
                case FIO_GETOPT_IOENGINE: {
                        const char *opt = l_opts[lidx].name;
                        char *val = optarg;
+
+                       if (!td)
+                               break;
+
                        ret = fio_cmd_ioengine_option_parse(td, opt, val);
+                       did_arg = 1;
                        break;
                }
                case 'w':
@@ -1902,6 +1933,7 @@ int parse_cmd_line(int argc, char *argv[], int 
client_type)
                        }
                        break;
                case 'S':
+                       did_arg = 1;
                        if (nr_clients) {
                                log_err("fio: can't be both client and 
server\n");
                                do_exit++;
@@ -1914,17 +1946,21 @@ int parse_cmd_line(int argc, char *argv[], int 
client_type)
                        backend = 1;
                        break;
                case 'D':
+                       if (pid_file)
+                               free(pid_file);
                        pid_file = strdup(optarg);
                        break;
                case 'I':
                        if ((ret = fio_idle_prof_parse_opt(optarg))) {
                                /* exit on error and calibration only */
+                               did_arg = 1;
                                do_exit++;
-                               if (ret == -1) 
+                               if (ret == -1)
                                        exit_val = 1;
                        }
                        break;
                case 'C':
+                       did_arg = 1;
                        if (is_backend) {
                                log_err("fio: can't be both client and 
server\n");
                                do_exit++;
@@ -1951,10 +1987,12 @@ int parse_cmd_line(int argc, char *argv[], int 
client_type)
                        }
                        break;
                case 'T':
+                       did_arg = 1;
                        do_exit++;
                        exit_val = fio_monotonic_clocktest();
                        break;
                case 'G':
+                       did_arg = 1;
                        do_exit++;
                        exit_val = fio_crctest(optarg);
                        break;
@@ -1994,8 +2032,11 @@ int parse_cmd_line(int argc, char *argv[], int 
client_type)
                free(pid_file);
 
        if (td) {
-               if (!ret)
+               if (!ret) {
                        ret = add_job(td, td->o.name ?: "fio", 0, 0, 
client_type);
+                       if (ret)
+                               did_arg = 1;
+               }
        }
 
        while (!ret && optind < argc) {
@@ -2005,6 +2046,10 @@ int parse_cmd_line(int argc, char *argv[], int 
client_type)
                optind++;
        }
 
+out_free:
+       if (pid_file)
+               free(pid_file);
+
        return ini_idx;
 }
 
diff --git a/io_u.c b/io_u.c
index 411da32..4b0b5a7 100644
--- a/io_u.c
+++ b/io_u.c
@@ -678,7 +678,7 @@ static void set_rw_ddir(struct thread_data *td, struct io_u 
*io_u)
 
 void put_file_log(struct thread_data *td, struct fio_file *f)
 {
-       int ret = put_file(td, f);
+       unsigned int ret = put_file(td, f);
 
        if (ret)
                td_verror(td, ret, "file close");
diff --git a/lib/num2str.c b/lib/num2str.c
index 12d6f39..8961868 100644
--- a/lib/num2str.c
+++ b/lib/num2str.c
@@ -4,6 +4,8 @@
 
 #include "../fio.h"
 
+#define ARRAY_LENGTH(arr)      sizeof(arr) / sizeof((arr)[0])
+
 /*
  * Cheesy number->string conversion, complete with carry rounding error.
  */
@@ -46,6 +48,9 @@ char *num2str(unsigned long num, int maxlen, int base, int 
pow2, int unit_base)
 
        if (modulo == -1U) {
 done:
+               if (post_index >= ARRAY_LENGTH(postfix))
+                       post_index = 0;
+
                sprintf(buf, "%lu%s%s", num, postfix[post_index],
                        byte_postfix[byte_post_index]);
                return buf;
diff --git a/libfio.c b/libfio.c
index 3fde492..5ed8c60 100644
--- a/libfio.c
+++ b/libfio.c
@@ -27,6 +27,7 @@
 #include <signal.h>
 #include <stdint.h>
 #include <locale.h>
+#include <fcntl.h>
 
 #include "fio.h"
 #include "smalloc.h"
@@ -233,6 +234,21 @@ int fio_running_or_pending_io_threads(void)
        return 0;
 }
 
+void fio_set_fd_nonblocking(int fd, const char *who)
+{
+       int flags;
+
+       flags = fcntl(fd, F_GETFL);
+       if (flags < 0)
+               log_err("fio: %s failed to get file flags: %s\n", who, 
strerror(errno));
+       else {
+               flags |= O_NONBLOCK;
+               flags = fcntl(fd, F_SETFL, flags);
+               if (flags < 0)
+                       log_err("fio: %s failed to get file flags: %s\n", who, 
strerror(errno));
+       }
+}
+
 static int endian_check(void)
 {
        union {
diff --git a/memory.c b/memory.c
index b208320..8c06d94 100644
--- a/memory.c
+++ b/memory.c
@@ -158,9 +158,10 @@ static int alloc_mem_mmap(struct thread_data *td, size_t 
total_mem)
        if (td->orig_buffer == MAP_FAILED) {
                td_verror(td, errno, "mmap");
                td->orig_buffer = NULL;
-               if (td->mmapfd) {
+               if (td->mmapfd != 1) {
                        close(td->mmapfd);
-                       unlink(td->o.mmapfile);
+                       if (td->o.mmapfile)
+                               unlink(td->o.mmapfile);
                }
 
                return 1;
diff --git a/options.c b/options.c
index 9096a32..50af7b4 100644
--- a/options.c
+++ b/options.c
@@ -269,7 +269,7 @@ static int ignore_error_type(struct thread_data *td, int 
etype, char *str)
                } else {
                        error[i] = atoi(fname);
                        if (error[i] < 0)
-                               error[i] = error[i];
+                               error[i] = -error[i];
                }
                if (!error[i]) {
                        log_err("Unknown error %s, please use number value \n",
diff --git a/os/windows/posix/include/sys/un.h 
b/os/windows/posix/include/sys/un.h
index b9ea630..e418c6d 100644
--- a/os/windows/posix/include/sys/un.h
+++ b/os/windows/posix/include/sys/un.h
@@ -7,7 +7,7 @@ typedef int in_port_t;
  struct sockaddr_un
  {
        sa_family_t     sun_family; /* Address family */
-       char            sun_path[]; /* Socket pathname */
+       char            sun_path[260]; /* Socket pathname */
 };
 
 #endif /* SYS_UN_H */
diff --git a/parse.c b/parse.c
index 83c59f7..188f728 100644
--- a/parse.c
+++ b/parse.c
@@ -624,7 +624,7 @@ static int __handle_option(struct fio_option *o, const char 
*ptr, void *data,
                        ret = 1;
                        for (i = 0; i < PARSE_MAX_VP; i++) {
                                vp = &posval[i];
-                               if (!vp->ival || vp->ival[0] == '\0')
+                               if (!vp->ival || vp->ival[0] == '\0' || !cp)
                                        continue;
                                all_skipped = 0;
                                if (!strncmp(vp->ival, ptr, str_match_len(vp, 
ptr))) {
diff --git a/server.c b/server.c
index 3346445..077dce5 100644
--- a/server.c
+++ b/server.c
@@ -4,7 +4,6 @@
 #include <unistd.h>
 #include <limits.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <sys/poll.h>
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -68,7 +67,7 @@ static const char *fio_server_ops[FIO_NET_CMD_NR] = {
        "DISK_UTIL",
        "SERVER_START",
        "ADD_JOB",
-       "CMD_RUN"
+       "CMD_RUN",
        "CMD_IOLOG",
 };
 
@@ -209,7 +208,7 @@ static int verify_convert_cmd(struct fio_net_cmd *cmd)
  */
 struct fio_net_cmd *fio_net_recv_cmd(int sk)
 {
-       struct fio_net_cmd cmd, *cmdret = NULL;
+       struct fio_net_cmd cmd, *tmp, *cmdret = NULL;
        size_t cmd_size = 0, pdu_offset = 0;
        uint16_t crc;
        int ret, first = 1;
@@ -232,7 +231,19 @@ struct fio_net_cmd *fio_net_recv_cmd(int sk)
                } else
                        cmd_size += cmd.pdu_len;
 
-               cmdret = realloc(cmdret, cmd_size);
+               if (cmd_size / 1024 > FIO_SERVER_MAX_CMD_MB * 1024) {
+                       log_err("fio: cmd+pdu too large (%llu)\n", (unsigned 
long long) cmd_size);
+                       ret = 1;
+                       break;
+               }
+
+               tmp = realloc(cmdret, cmd_size);
+               if (!tmp) {
+                       log_err("fio: server failed allocating cmd\n");
+                       ret = 1;
+                       break;
+               }
+               cmdret = tmp;
 
                if (first)
                        memcpy(cmdret, &cmd, sizeof(cmd));
@@ -843,14 +854,12 @@ static int accept_loop(int listen_sk)
        struct sockaddr_in6 addr6;
        socklen_t len = use_ipv6 ? sizeof(addr6) : sizeof(addr);
        struct pollfd pfd;
-       int ret = 0, sk, flags, exitval = 0;
+       int ret = 0, sk, exitval = 0;
        FLIST_HEAD(conn_list);
 
        dprint(FD_NET, "server enter accept loop\n");
 
-       flags = fcntl(listen_sk, F_GETFL);
-       flags |= O_NONBLOCK;
-       fcntl(listen_sk, F_SETFL, flags);
+       fio_set_fd_nonblocking(listen_sk, "server");
 
        while (!exit_backend) {
                const char *from;
@@ -1095,7 +1104,8 @@ static void convert_dus(struct disk_util_stat *dst, 
struct disk_util_stat *src)
 {
        int i;
 
-       strcpy((char *) dst->name, (char *) src->name);
+       dst->name[FIO_DU_NAME_SZ - 1] = '\0';
+       strncpy((char *) dst->name, (char *) src->name, FIO_DU_NAME_SZ - 1);
 
        for (i = 0; i < 2; i++) {
                dst->s.ios[i]           = cpu_to_le32(src->s.ios[i]);
@@ -1215,7 +1225,9 @@ int fio_send_iolog(struct thread_data *td, struct io_log 
*log, const char *name)
        pdu.nr_samples = __cpu_to_le32(log->nr_samples);
        pdu.log_type = cpu_to_le32(log->log_type);
        pdu.compressed = cpu_to_le32(use_zlib);
-       strcpy((char *) pdu.name, name);
+
+       strncpy((char *) pdu.name, name, FIO_NET_NAME_MAX);
+       pdu.name[FIO_NET_NAME_MAX - 1] = '\0';
 
        for (i = 0; i < log->nr_samples; i++) {
                struct io_sample *s = &log->log[i];
@@ -1338,7 +1350,7 @@ static int fio_init_server_sock(void)
 
        memset(&addr, 0, sizeof(addr));
        addr.sun_family = AF_UNIX;
-       strcpy(addr.sun_path, bind_sock);
+       strncpy(addr.sun_path, bind_sock, sizeof(addr.sun_path) - 1);
 
        len = sizeof(addr.sun_family) + strlen(bind_sock) + 1;
 
@@ -1367,6 +1379,8 @@ static int fio_init_server_connection(void)
        if (sk < 0)
                return sk;
 
+       memset(bind_str, 0, sizeof(bind_str));
+
        if (!bind_sock) {
                char *p, port[16];
                const void *src;
@@ -1386,9 +1400,9 @@ static int fio_init_server_connection(void)
                if (p)
                        strcat(p, port);
                else
-                       strcpy(bind_str, port);
+                       strncpy(bind_str, port, sizeof(bind_str) - 1);
        } else
-               strcpy(bind_str, bind_sock);
+               strncpy(bind_str, bind_sock, sizeof(bind_str) - 1);
 
        log_info("fio: server listening on %s\n", bind_str);
 
diff --git a/server.h b/server.h
index 3a279f0..2958e73 100644
--- a/server.h
+++ b/server.h
@@ -41,6 +41,7 @@ enum {
        FIO_SERVER_VER                  = 33,
 
        FIO_SERVER_MAX_FRAGMENT_PDU     = 1024,
+       FIO_SERVER_MAX_CMD_MB           = 2048,
 
        FIO_NET_CMD_QUIT                = 1,
        FIO_NET_CMD_EXIT                = 2,
diff --git a/stat.c b/stat.c
index 509c6f0..fbf0118 100644
--- a/stat.c
+++ b/stat.c
@@ -831,7 +831,7 @@ static void show_thread_status_terse_v2(struct thread_stat 
*ts,
        log_info("\n");
 
        /* Additional output if description is set */
-       if (ts->description)
+       if (strlen(ts->description))
                log_info(";%s", ts->description);
 
        log_info("\n");
@@ -1471,7 +1471,12 @@ void show_running_run_stats(void)
        fio_mutex_down(stat_mutex);
 
        if (!pthread_create(&thread, NULL, __show_running_run_stats, NULL)) {
-               pthread_detach(thread);
+               int err;
+
+               err = pthread_detach(thread);
+               if (err)
+                       log_err("fio: DU thread detach failed: %s\n", 
strerror(err));
+
                return;
        }
 
@@ -1494,8 +1499,11 @@ static int check_status_file(void)
                return 0;
 
        temp_dir = getenv("TMPDIR");
-       if (temp_dir == NULL)
+       if (temp_dir == NULL) {
                temp_dir = getenv("TEMP");
+               if (temp_dir && strlen(temp_dir) >= PATH_MAX)
+                       temp_dir = NULL;
+       }
        if (temp_dir == NULL)
                temp_dir = "/tmp";
 
@@ -1800,7 +1808,11 @@ void add_bw_sample(struct thread_data *td, enum fio_ddir 
ddir, unsigned int bs,
                if (!delta)
                        continue; /* No entries for interval */
 
-               rate = delta * 1000 / spent / 1024;
+               if (spent)
+                       rate = delta * 1000 / spent / 1024;
+               else
+                       rate = 0;
+
                add_stat_sample(&ts->bw_stat[ddir], rate);
 
                if (td->bw_log)
@@ -1835,7 +1847,11 @@ void add_iops_sample(struct thread_data *td, enum 
fio_ddir ddir, unsigned int bs
                if (!delta)
                        continue; /* No entries for interval */
 
-               iops = (delta * 1000) / spent;
+               if (spent)
+                       iops = (delta * 1000) / spent;
+               else
+                       iops = 0;
+
                add_stat_sample(&ts->iops_stat[ddir], iops);
 
                if (td->iops_log)
diff --git a/verify.c b/verify.c
index 9eb532a..282a8cf 100644
--- a/verify.c
+++ b/verify.c
@@ -226,16 +226,32 @@ struct vcont {
        unsigned int crc_len;
 };
 
+#define DUMP_BUF_SZ    255
+static int dump_buf_warned;
+
 static void dump_buf(char *buf, unsigned int len, unsigned long long offset,
                     const char *type, struct fio_file *f)
 {
-       char *ptr, fname[256];
+       char *ptr, fname[DUMP_BUF_SZ];
+       size_t buf_left = DUMP_BUF_SZ;
        int ret, fd;
 
        ptr = strdup(f->file_name);
-       strcpy(fname, basename(ptr));
 
-       sprintf(fname + strlen(fname), ".%llu.%s", offset, type);
+       fname[DUMP_BUF_SZ - 1] = '\0';
+       strncpy(fname, basename(ptr), DUMP_BUF_SZ - 1);
+
+       buf_left -= strlen(fname);
+       if (buf_left <= 0) {
+               if (!dump_buf_warned) {
+                       log_err("fio: verify failure dump buffer too small\n");
+                       dump_buf_warned = 1;
+               }
+               free(ptr);
+               return;
+       }
+
+       snprintf(fname + strlen(fname), buf_left, ".%llu.%s", offset, type);
 
        fd = open(fname, O_CREAT | O_TRUNC | O_WRONLY, 0644);
        if (fd < 0) {
--
To unsubscribe from this list: send the line "unsubscribe fio" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to