diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2024-08-15 00:37:08 -0700 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2024-08-15 00:37:08 -0700 |
commit | cc79233013551bdec8b94cee86dd8053244114b0 (patch) | |
tree | d72f3d42b66faeb74cb206eb8e00627e23a7e252 /src/libvmon | |
parent | 77fe3c826652b0697359c65ead688f4f4bf4a742 (diff) |
libvmon: tidy up some elastic buffer handling
Much of this stuff is pretty sloppy ever since it was first
written as a casual experiment. Fixup types to use
size_t/ssize_t where appropriate, and free the actual realloc'd
member of the char_array struct - the container struct with the
assumption that the member is at the struct start.
Diffstat (limited to 'src/libvmon')
-rw-r--r-- | src/libvmon/vmon.c | 68 | ||||
-rw-r--r-- | src/libvmon/vmon.h | 8 |
2 files changed, 38 insertions, 38 deletions
diff --git a/src/libvmon/vmon.c b/src/libvmon/vmon.c index c930dc4..ec33b2d 100644 --- a/src/libvmon/vmon.c +++ b/src/libvmon/vmon.c @@ -120,23 +120,29 @@ typedef enum _vmon_load_flags_t { } vmon_load_flags_t; /* we enlarge *alloc if necessary, but never shrink it. changed[changed_pos] bit is set if a difference is detected, supply LOAD_FLAGS_NOTRUNCATE if we don't want empty contents to truncate last-known data */ -static char * load_contents_fd(vmon_t *vmon, vmon_char_array_t *array, int fd, vmon_load_flags_t flags, char *changed, int changed_pos) +static int load_contents_fd(vmon_t *vmon, vmon_char_array_t *array, int fd, vmon_load_flags_t flags, char *changed, int changed_pos) { - int total = 0, len, alloc_len = array->alloc_len; - char *alloc = array->array, *tmp; + size_t total = 0; + ssize_t len; + /* FIXME: this is used to read proc files, you can't actually read proc files iteratively + * without race conditions; it needs to be all done as a single read. + */ while ((len = pread(fd, vmon->buf, sizeof(vmon->buf), total)) > 0) { - if (total + len > alloc_len) { - /* realloc to accomodate the new total */ - tmp = realloc(alloc, total + len); + size_t newsize = total + len; + + if (newsize > array->alloc_len) { + char *tmp; + + tmp = realloc(array->array, newsize); if (!tmp) - return NULL; + return -ENOMEM; - alloc_len = total + len; - alloc = tmp; + array->array = tmp; + array->alloc_len = newsize; } - memcmpcpy(&alloc[total], vmon->buf, len, changed, changed_pos); + memcmpcpy(&array->array[total], vmon->buf, len, changed, changed_pos); total += len; @@ -147,9 +153,6 @@ static char * load_contents_fd(vmon_t *vmon, vmon_char_array_t *array, int fd, v } } - array->array = alloc; - array->alloc_len = alloc_len; - /* if we read something or didn't encounter an error, store the new total */ if (total || (len == 0 && !(flags & LOAD_FLAGS_NOTRUNCATE))) { /* if the new length differs ensure the changed bit is set */ @@ -159,7 +162,7 @@ static char * load_contents_fd(vmon_t *vmon, vmon_char_array_t *array, int fd, v array->len = total; } - return alloc; + return 0; } @@ -200,51 +203,48 @@ static DIR * opendirf(vmon_t *vmon, DIR *dir, char *fmt, ...) /* enlarge an array by the specified amount */ -static int grow_array(vmon_char_array_t *array, int amount) +static int grow_array(vmon_char_array_t *array, size_t amount) { char *tmp; tmp = realloc(array->array, array->alloc_len + amount); if (!tmp) - return 0; + return -ENOMEM; array->alloc_len += amount; array->array = tmp; - return 1; + return 0; } /* load the contents of a symlink, dir is not optional */ #define READLINKF_GROWINIT 10 #define READLINKF_GROWBY 2 -static char * readlinkf(vmon_t *vmon, vmon_char_array_t *array, DIR *dir, char *fmt, ...) +static int readlinkf(vmon_t *vmon, vmon_char_array_t *array, DIR *dir, char *fmt, ...) { - va_list va_arg; - int len; char buf[4096]; + va_list va_arg; + ssize_t len; va_start(va_arg, fmt); vsnprintf(buf, sizeof(buf), fmt, va_arg); va_end(va_arg); - if (!array->array && !grow_array(array, READLINKF_GROWINIT)) - goto _fail; + if (!array->array && grow_array(array, READLINKF_GROWINIT) < 0) + return -ENOMEM; do { len = readlinkat(dirfd(dir), buf, array->array, (array->alloc_len - 1)); - } while (len != -1 && len == (array->alloc_len - 1) && (len = grow_array(array, READLINKF_GROWBY))); + } while (len != -1 && len == (array->alloc_len - 1) && (len = grow_array(array, READLINKF_GROWBY)) >= 0); - if (len <= 0) - goto _fail; + if (len < 0) + return -errno; array->len = len; array->array[array->len] = '\0'; - return array->array; - -_fail: - return NULL; + return 0; } @@ -268,14 +268,14 @@ static sample_ret_t proc_sample_stat(vmon_t *vmon, vmon_proc_t *proc, vmon_proc_ if (!proc) { /* dtor */ try_close(&(*store)->comm_fd); - try_free((void **)&(*store)->comm); + try_free((void **)&(*store)->comm.array); try_close(&(*store)->cmdline_fd); - try_free((void **)&(*store)->cmdline); + try_free((void **)&(*store)->cmdline.array); try_free((void **)&(*store)->argv); try_close(&(*store)->wchan_fd); - try_free((void **)&(*store)->wchan); + try_free((void **)&(*store)->wchan.array); try_close(&(*store)->stat_fd); - try_free((void **)&(*store)->exe); + try_free((void **)&(*store)->exe.array); return DTOR_FREE; } @@ -643,7 +643,7 @@ static void del_fd(vmon_t *vmon, vmon_proc_fd_t *fd) list_del(&fd->fds); if (fd->object) fobject_unref(vmon, fd->object, fd); /* note we supply both the fobject ptr and proc_fd ptr (fd) */ - try_free((void **)&fd->object_path); + try_free((void **)&fd->object_path.array); free(fd); } diff --git a/src/libvmon/vmon.h b/src/libvmon/vmon.h index 2373140..cf282b0 100644 --- a/src/libvmon/vmon.h +++ b/src/libvmon/vmon.h @@ -49,14 +49,14 @@ typedef enum _vmon_proc_wants_t { /* we add some new complex types */ typedef struct _vmon_char_array_t { char *array; - int len; - int alloc_len; + size_t len; + size_t alloc_len; } vmon_char_array_t; typedef struct _vmon_str_array_t { char **array; - int len; - int alloc_len; + size_t len; + size_t alloc_len; } vmon_str_array_t; |