[stgt] [PATCH 1/4] struct concat_buf and concat_printf() for printing to buffers

Fubo Chen fubo.chen at gmail.com
Sat Nov 26 12:43:23 CET 2011


On Sat, Nov 26, 2011 at 12:21 PM, Alexander Nezhinsky
<alexandern at mellanox.com> wrote:
> Text queries issued through tgtadm use a fixed-size buffer that is filled,
> step by step, typically by a few calls to snprintf() or an equivalent.
> This requires tracking the current position within the buffer and guarding
> against overflows. Currently these goals are achived by few separate macros:
> shprintf(), buffer_check() and _buffer_check().
> This approach relies upon local/global counter variables that describe
> the buffer state and in some cases a label to escape through on errors.
> Two kinds of problems arise in such settings:
> First, using hardcoded variable names and especially 'goto' statements in
> macros is unsafe, and second, it becomes difficult to use nested function
> calls if the called functions also append some strings to the buffer.
>
> The alternative offered by this patch uses a buffer descriptor context,
> 'struct concat_buf', which stores the buffer pointer and relevant counters
> and error code. This internal state information avoids writes when buffer is
> full and in all cases of previosuly encountered errors.
>
> Thus we can continue with the function flow as if the buffer is unlimited
> and in the end return an appropriate error code using concat_buf_ret().
> Code is simplified and the tedious checks afer each snprintf are avoided.
>
> As the context may be passed to other functions easily and its state is
> preserved upon return, nested calls are naturally enabled.
>
> Signed-off-by: Alexander Nezhinsky <alexandern at mellanox.com>
> ---
>  usr/util.c |   26 ++++++++++++++++++++++++++
>  usr/util.h |   40 +++++++++++++++++++++++++++++-----------
>  2 files changed, 55 insertions(+), 11 deletions(-)
>
> diff --git a/usr/util.c b/usr/util.c
> index c78a999..43d2690 100644
> --- a/usr/util.c
> +++ b/usr/util.c
> @@ -194,3 +194,29 @@ int get_blk_shift(unsigned int size)
>        return shift;
>  }
>
> +int concat_printf(struct concat_buf *b, const char *format, ...)
> +{
> +       va_list args;
> +       int rest = b->size - b->used;
> +       int nprinted;
> +
> +       if (b->err)
> +               return b->err;
> +       if (!rest)
> +               return (b->err = -ENOSPC);
> +
> +       va_start(args, format);
> +       nprinted = vsnprintf(b->buf + b->used, rest, format, args);
> +       va_end(args);
> +
> +       if (nprinted < 0)
> +               return (b->err = nprinted);
> +
> +       if (nprinted >= rest) {
> +               nprinted = rest;
> +               b->err = -ENOSPC;
> +       }
> +       b->used += nprinted;
> +       return b->err;
> +}
> +
> diff --git a/usr/util.h b/usr/util.h
> index 8abdb94..18d81b8 100644
> --- a/usr/util.h
> +++ b/usr/util.h
> @@ -8,6 +8,7 @@
>  #include <signal.h>
>  #include <syscall.h>
>  #include <unistd.h>
> +#include <stdarg.h>
>  #include <limits.h>
>  #include <linux/types.h>
>
> @@ -88,17 +89,6 @@ static inline int between(uint32_t seq1, uint32_t seq2, uint32_t seq3)
>        return seq3 - seq2 >= seq1 - seq2;
>  }
>
> -#define shprintf(total, buf, rest, fmt, args...)                       \
> -do {                                                                   \
> -       int len;                                                        \
> -       len = snprintf(buf, rest, fmt, ##args);                         \
> -       if (len > rest)                                                 \
> -               goto overflow;                                          \
> -       buf += len;                                                     \
> -       total += len;                                                   \
> -       rest -= len;                                                    \
> -} while (0)
> -
>  extern unsigned long pagesize, pageshift;
>
>  #if defined(__NR_signalfd) && defined(USE_SIGNALFD)
> @@ -151,4 +141,32 @@ struct signalfd_siginfo {
>        ret;                                            \
>  })
>
> +struct concat_buf {
> +       char *buf;
> +       int size;
> +       int used;
> +       int err;
> +};
> +
> +static inline void concat_buf_init(struct concat_buf *b,
> +                                  char *buf, int size)
> +{
> +       b->buf = buf;
> +       b->size = size;
> +       b->used = 0;
> +       b->err = 0;
> +}
> +
> +static inline int concat_buf_ret(struct concat_buf *b)
> +{
> +       return !b->err ? b->used : b->err;
> +}
> +
> +static inline const char *concat_delim(struct concat_buf *b, const char *delim)
> +{
> +       return !b->used ? "" : delim;
> +}
> +
> +extern int concat_printf(struct concat_buf *b, const char *format, ...);
> +
>  #endif

Looks like a duplicate of asprintf() ? See also
http://www.gnu.org/s/libc/manual/html_node/Dynamic-Output.html.

Fubo.
--
To unsubscribe from this list: send the line "unsubscribe stgt" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html



More information about the stgt mailing list