Logo Search packages:      
Sourcecode: rainbow version File versions  Download package

buf.c

#define _GNU_SOURCE
#include <errno.h>
#include <stdio.h>
#include <syslog.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>

#include "cgen.h"
#include "buf.h"

#include "config/debug.h"


int write_buf(char** buf, size_t * buflen, const char* val)
{
  /* write_buf will not write outside of (*buf)[0..(*buflen-1)]
   * if *buflen > strlen(val), then write_buf will ensure that *buf points to a null-terminated string.
   * on success, write_buf will advance *buf to the next free char,
   *                            set *buflen to indicate the quantity of remaining space,
   *                            and return 0.
   * on error, write_buf will set errno, return 1, and will not modify *buf or *buflen.
   * *buf and val should not overlap.
   */

  LET(size_t copy_amt = strlen(val) + 1, copy_amt == 0,
      "Integer overflow.", out_err_overflow);

  if (*buflen < copy_amt)
    goto out_err_range;

  memcpy(*buf, val, copy_amt);

  *buf += copy_amt;
  *buflen -= copy_amt;
  return 0;

out_err_overflow:
  errno = EOVERFLOW;
  return 1;

out_err_range:
  errno = ERANGE;
  return 1;
}

int format_buf(char** buf, size_t* buflen, const char* fmt, ...)
{
  /* format_buf will not write outside of (*buf)[0..(*buflen-1)]
   * if *buflen > 0, format_buf will ensure that *buf points to a null-terminated string.
   * on success, format_buf will advance *buf to the next free char,
   *                             set *buflen to indicate the quantity of remaining space,
   *                             and return 0.
   * on error, format_buf will set errno, return 1, and will not modify *buf or *buflen.
   * *buf should know overlap with fmt or any optional arguments.
   */
  if (*buflen < 1)
  {
    errno = ERANGE;
    return 1;
  }

  size_t safe_buflen = *buflen - 1;

  va_list ap;
  va_start(ap, fmt);
  int status = vsnprintf(*buf, safe_buflen, fmt, ap);
  SAVE_ERR(va_end(ap));

  if (status < 0)
    goto out_err;

  size_t written = (size_t) status;
  if (safe_buflen < written) {
    errno = ERANGE;
    goto out_err;
  }

  *buf += written+1;
  *buflen -= written+1;
  return 0;

out_err:
  (*buf)[safe_buflen] = '\0';
  return 1;
}

Generated by  Doxygen 1.6.0   Back to index