Logo Search packages:      
Sourcecode: nmap version File versions

blob.c

/*
 * blob.c
 *
 * Copyright (c) 2002 Dug Song <dugsong@monkey.org>
 *
 * $Id: blob.c,v 1.4 2002/08/20 05:18:49 dugsong Exp $
 */

#ifdef _WIN32
#include "dnet_winconfig.h"
#else
#include "config.h"
#endif

#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "dnet.h"

static void *(*bl_malloc)(size_t) = malloc;
static void *(*bl_realloc)(void *, size_t) = realloc;
static void  (*bl_free)(void *) = free;
static int     bl_size = BUFSIZ;

static int     fmt_D(int, int, blob_t *, va_list *);
static int     fmt_H(int, int, blob_t *, va_list *);
static int     fmt_b(int, int, blob_t *, va_list *);
static int     fmt_c(int, int, blob_t *, va_list *);
static int     fmt_d(int, int, blob_t *, va_list *);
static int     fmt_h(int, int, blob_t *, va_list *);
static int     fmt_s(int, int, blob_t *, va_list *);

static void    print_hexl(blob_t *);

static blob_fmt_cb blob_ascii_fmt[] = {
      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
      NULL, NULL, NULL, NULL, fmt_D,      NULL, NULL, NULL,
      fmt_H,      NULL, NULL, NULL, NULL, NULL, NULL, NULL,
      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
      NULL, NULL, fmt_b,      fmt_c,      fmt_d,      NULL, NULL, NULL,
      fmt_h,      NULL, NULL, NULL, NULL, NULL, NULL, NULL,
      NULL, NULL, NULL, fmt_s,      NULL, NULL, NULL, NULL,
      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};

struct blob_printer {
      char    *name;
      void   (*print)(blob_t *);
} blob_printers[] = {
      { "hexl",   print_hexl },
      { NULL,           NULL },
};

blob_t *
blob_new(void)
{
      blob_t *b;

      if ((b = bl_malloc(sizeof(*b))) != NULL) {
            b->off = b->end = 0;
            b->size = bl_size;
            if ((b->base = bl_malloc(b->size)) == NULL) {
                  bl_free(b);
                  b = NULL;
            }
      }
      return (b);
}

static int
blob_reserve(blob_t *b, int len)
{
      void *p;
      int nsize;

      if (b->size < b->end + len) {
            if (b->size == 0)
                  return (-1);

            if ((nsize = b->end + len) > bl_size)
                  nsize = ((nsize / bl_size) + 1) * bl_size;
            
            if ((p = bl_realloc(b->base, nsize)) == NULL)
                  return (-1);
            
            b->base = p;
            b->size = nsize;
      }
      b->end += len;
      
      return (0);
}

int
blob_read(blob_t *b, void *buf, int len)
{
      if (b->end - b->off < len)
            len = b->end - b->off;
      
      memcpy(buf, b->base + b->off, len);
      b->off += len;
      
      return (len);
}

int
blob_write(blob_t *b, const void *buf, int len)
{
      if (b->off + len <= b->end ||
          blob_reserve(b, b->off + len - b->end) == 0) {
            memcpy(b->base + b->off, (u_char *)buf, len);
            b->off += len;
            return (len);
      }
      return (-1);
}

int
blob_insert(blob_t *b, const void *buf, int len)
{
      if (blob_reserve(b, len) == 0 && b->size) {
            if (b->end - b->off > 0)
                  memmove(b->base + b->off, b->base + b->off + len,
                      b->end - b->off);
            memcpy(b->base + b->off, buf, len);
            b->off += len;
            return (len);
      }
      return (-1);
}

int
blob_delete(blob_t *b, void *buf, int len)
{
      if (b->off + len <= b->end && b->size) {
            if (buf != NULL)
                  memcpy(buf, b->base + b->off, len);
            memmove(b->base + b->off, b->base + b->off + len,
                b->end - (b->off + len));
            b->end -= len;
            return (len);
      }
      return (-1);
}

static int
blob_fmt(blob_t *b, int pack, const char *fmt, va_list *ap)
{
      blob_fmt_cb fmt_cb;
      char *p;
      int len;

      for (p = (char *)fmt; *p != '\0'; p++) {
            if (*p == '%') {
                  p++;
                  if (isdigit((int)*p)) {
                        len = strtol(p, &p, 10);
                  } else if (*p == '*') {
                        len = va_arg(*ap, int);
                        p++;
                  } else
                        len = 0;
                  
                  if ((fmt_cb = blob_ascii_fmt[(int)*p]) == NULL)
                        return (-1);

                  if ((*fmt_cb)(pack, len, b, ap) < 0)
                        return (-1);
            } else {
                  if (pack) {
                        if (b->off + 1 < b->end ||
                            blob_reserve(b, b->off + 1 - b->end) == 0)
                              b->base[b->off++] = *p;
                        else
                              return (-1);
                  } else {
                        if (b->base[b->off++] != *p)
                              return (-1);
                  }
            }
      }
      return (0);
}

int
blob_pack(blob_t *b, const char *fmt, ...)
{
      va_list ap;
      va_start(ap, fmt);
      return (blob_fmt(b, 1, fmt, &ap));
}

int
blob_unpack(blob_t *b, const char *fmt, ...)
{
      va_list ap;
      va_start(ap, fmt);
      return (blob_fmt(b, 0, fmt, &ap));
}

int
blob_seek(blob_t *b, int off, int whence)
{
      if (whence == SEEK_CUR)
            off += b->off;
      else if (whence == SEEK_END)
            off += b->end;

      if (off < 0 || off > b->end)
            return (-1);
      
      return ((b->off = off));
}

int
blob_index(blob_t *b, const void *buf, int len)
{
      int i;

      for (i = b->off; i <= b->end - len; i++) {
            if (memcmp(b->base + i, buf, len) == 0)
                  return (i);
      }
      return (-1);
}

int
blob_rindex(blob_t *b, const void *buf, int len)
{
      int i;

      for (i = b->end - len; i >= 0; i--) {
            if (memcmp(b->base + i, buf, len) == 0)
                  return (i);
      }
      return (-1);
}

int
blob_print(blob_t *b, char *style, int len)
{
      struct blob_printer *bp;

      for (bp = blob_printers; bp->name != NULL; bp++) {
            if (strcmp(bp->name, style) == 0)
                  bp->print(b);
      }
      return (0);
}

int
blob_sprint(blob_t *b, char *style, int len, char *dst, int size)
{
      return (0);
}

blob_t *
blob_free(blob_t *b)
{
      if (b->size)
            bl_free(b->base);
      bl_free(b);
      return (NULL);
}

int
blob_register_alloc(size_t size, void *(bmalloc)(size_t),
    void (*bfree)(void *), void *(*brealloc)(void *, size_t))
{
      bl_size = size;
      if (bmalloc != NULL)
            bl_malloc = bmalloc;
      if (bfree != NULL)
            bl_free = bfree;
      if (brealloc != NULL)
            bl_realloc = brealloc;
      return (0);
}

int
blob_register_pack(char c, blob_fmt_cb fmt_cb)
{
      if (blob_ascii_fmt[(int)c] == NULL) {
            blob_ascii_fmt[(int)c] = fmt_cb;
            return (0);
      }
      return (-1);
}

static int
fmt_D(int pack, int len, blob_t *b, va_list *ap)
{
      if (len) return (-1);
      
      if (pack) {
            uint32_t n = va_arg(*ap, uint32_t);
            n = htonl(n);
            if (blob_write(b, &n, sizeof(n)) < 0)
                  return (-1);
      } else {
            uint32_t *n = va_arg(*ap, uint32_t *);
            if (blob_read(b, n, sizeof(*n)) != sizeof(*n))
                  return (-1);
            *n = ntohl(*n);
      }
      return (0);
}

static int
fmt_H(int pack, int len, blob_t *b, va_list *ap)
{
      if (len) return (-1);
      
      if (pack) {
            uint16_t n = va_arg(*ap, int);
            n = htons(n);
            if (blob_write(b, &n, sizeof(n)) < 0)
                  return (-1);
      } else {
            uint16_t *n = va_arg(*ap, uint16_t *);
            if (blob_read(b, n, sizeof(*n)) != sizeof(*n))
                  return (-1);
            *n = ntohs(*n);
      }
      return (0);
}

static int
fmt_b(int pack, int len, blob_t *b, va_list *ap)
{
      void *p = va_arg(*ap, void *);
      
      if (len <= 0) return (-1);
      
      if (pack)
            return (blob_write(b, p, len));
      else
            return (blob_read(b, p, len));
}

static int
fmt_c(int pack, int len, blob_t *b, va_list *ap)
{
      if (len) return (-1);
      
      if (pack) {
            uint8_t n = va_arg(*ap, int);
            return (blob_write(b, &n, sizeof(n)));
      } else {
            uint8_t *n = va_arg(*ap, uint8_t *);
            return (blob_read(b, n, sizeof(*n)));
      }
}

static int
fmt_d(int pack, int len, blob_t *b, va_list *ap)
{
      if (len) return (-1);
      
      if (pack) {
            uint32_t n = va_arg(*ap, uint32_t);
            return (blob_write(b, &n, sizeof(n)));
      } else {
            uint32_t *n = va_arg(*ap, uint32_t *);
            return (blob_read(b, n, sizeof(*n)));
      }
}

static int
fmt_h(int pack, int len, blob_t *b, va_list *ap)
{
      if (len) return (-1);
      
      if (pack) {
            uint16_t n = va_arg(*ap, int);
            return (blob_write(b, &n, sizeof(n)));
      } else {
            uint16_t *n = va_arg(*ap, uint16_t *);
            return (blob_read(b, n, sizeof(*n)));
      }
}

static int
fmt_s(int pack, int len, blob_t *b, va_list *ap)
{
      char *p = va_arg(*ap, char *);
      char c = '\0';
      int i, end;
      
      if (pack) {
            if (len > 0) {
                  if ((c = p[len - 1]) != '\0')
                        p[len - 1] = '\0';
            } else
                  len = strlen(p) + 1;
            
            if (blob_write(b, p, len) > 0) {
                  if (c != '\0')
                        p[len - 1] = c;
                  return (len);
            }
      } else {
            if (len <= 0) return (-1);

            if ((end = b->end - b->off) < len)
                  end = len;
            
            for (i = 0; i < end; i++) {
                  if ((p[i] = b->base[b->off + i]) == '\0') {
                        b->off += i + 1;
                        return (i);
                  }
            }
      }
      return (-1);
}

static void
print_hexl(blob_t *b)
{
      u_int i, j, jm, len;
      u_char *p;
      int c;

      p = b->base + b->off;
      len = b->end - b->off;
      
      printf("\n");
      
      for (i = 0; i < len; i += 0x10) {
            printf("  %04x: ", (u_int)(i + b->off));
            jm = len - i;
            jm = jm > 16 ? 16 : jm;
            
            for (j = 0; j < jm; j++) {
                  printf((j % 2) ? "%02x " : "%02x", (u_int)p[i + j]);
            }
            for (; j < 16; j++) {
                  printf((j % 2) ? "   " : "  ");
            }
            printf(" ");
            
            for (j = 0; j < jm; j++) {
                  c = p[i + j];
                  printf("%c", isprint(c) ? c : '.');
            }
            printf("\n");
      }
}

Generated by  Doxygen 1.6.0   Back to index