*/
#include <stdio.h>
+#include <sys/stat.h>
#include "chunk.h"
+#include <debug.h>
#include <printf_hook.h>
/**
/**
* Described in header.
*/
-chunk_t chunk_clone(chunk_t chunk)
+chunk_t chunk_create(u_char *ptr, size_t len)
+{
+ chunk_t chunk = {ptr, len};
+ return chunk;
+}
+
+/**
+ * Described in header.
+ */
+chunk_t chunk_create_clone(u_char *ptr, chunk_t chunk)
{
chunk_t clone = chunk_empty;
if (chunk.ptr && chunk.len > 0)
{
- clone.ptr = malloc(chunk.len);
+ clone.ptr = ptr;
clone.len = chunk.len;
memcpy(clone.ptr, chunk.ptr, chunk.len);
}
/**
* Decribed in header.
*/
-chunk_t chunk_cat(const char* mode, ...)
+size_t chunk_length(const char* mode, ...)
{
- chunk_t construct;
va_list chunks;
- u_char *pos;
- int i;
- int count = strlen(mode);
-
- /* sum up lengths of individual chunks */
+ size_t length = 0;
+
va_start(chunks, mode);
- construct.len = 0;
- for (i = 0; i < count; i++)
+ while (TRUE)
{
- chunk_t ch = va_arg(chunks, chunk_t);
- construct.len += ch.len;
+ switch (*mode++)
+ {
+ case 'm':
+ case 'c':
+ {
+ chunk_t ch = va_arg(chunks, chunk_t);
+ length += ch.len;
+ continue;
+ }
+ default:
+ break;
+ }
+ break;
}
va_end(chunks);
+ return length;
+}
- /* allocate needed memory for construct */
- construct.ptr = malloc(construct.len);
- pos = construct.ptr;
-
- /* copy or move the chunks */
+/**
+ * Decribed in header.
+ */
+chunk_t chunk_create_cat(u_char *ptr, const char* mode, ...)
+{
+ va_list chunks;
+ chunk_t construct = chunk_create(ptr, 0);
+
va_start(chunks, mode);
- for (i = 0; i < count; i++)
+ while (TRUE)
{
- chunk_t ch = va_arg(chunks, chunk_t);
+ bool free_chunk = FALSE;
switch (*mode++)
{
case 'm':
- memcpy(pos, ch.ptr, ch.len);
- pos += ch.len;
- free(ch.ptr);
- break;
+ {
+ free_chunk = TRUE;
+ }
case 'c':
+ {
+ chunk_t ch = va_arg(chunks, chunk_t);
+ memcpy(ptr, ch.ptr, ch.len);
+ ptr += ch.len;
+ construct.len += ch.len;
+ if (free_chunk)
+ {
+ free(ch.ptr);
+ }
+ continue;
+ }
default:
- memcpy(pos, ch.ptr, ch.len);
- pos += ch.len;
+ break;
}
+ break;
}
va_end(chunks);
}
/**
+ * Decribed in header.
+ */
+void chunk_split(chunk_t chunk, const char *mode, ...)
+{
+ va_list chunks;
+ size_t len;
+ chunk_t *ch;
+
+ va_start(chunks, mode);
+ while (TRUE)
+ {
+ if (*mode == '\0')
+ {
+ break;
+ }
+ len = va_arg(chunks, size_t);
+ ch = va_arg(chunks, chunk_t*);
+ /* a null chunk means skip len bytes */
+ if (ch == NULL)
+ {
+ chunk = chunk_skip(chunk, len);
+ continue;
+ }
+ switch (*mode++)
+ {
+ case 'm':
+ {
+ ch->len = min(chunk.len, len);
+ if (ch->len)
+ {
+ ch->ptr = chunk.ptr;
+ }
+ else
+ {
+ ch->ptr = NULL;
+ }
+ chunk = chunk_skip(chunk, ch->len);
+ continue;
+ }
+ case 'a':
+ {
+ ch->len = min(chunk.len, len);
+ if (ch->len)
+ {
+ ch->ptr = malloc(ch->len);
+ memcpy(ch->ptr, chunk.ptr, ch->len);
+ }
+ else
+ {
+ ch->ptr = NULL;
+ }
+ chunk = chunk_skip(chunk, ch->len);
+ continue;
+ }
+ case 'c':
+ {
+ ch->len = min(ch->len, chunk.len);
+ ch->len = min(ch->len, len);
+ if (ch->len)
+ {
+ memcpy(ch->ptr, chunk.ptr, ch->len);
+ }
+ else
+ {
+ ch->ptr = NULL;
+ }
+ chunk = chunk_skip(chunk, ch->len);
+ continue;
+ }
+ default:
+ break;
+ }
+ break;
+ }
+ va_end(chunks);
+}
+
+/**
+ * Described in header.
+ */
+bool chunk_write(chunk_t chunk, const char *path, const char *label, mode_t mask, bool force)
+{
+ mode_t oldmask;
+ FILE *fd;
+
+ if (!force)
+ {
+ fd = fopen(path, "r");
+ if (fd)
+ {
+ fclose(fd);
+ DBG1(" %s file '%s' already exists", label, path);
+ return FALSE;
+ }
+ }
+
+ /* set umask */
+ oldmask = umask(mask);
+
+ fd = fopen(path, "w");
+
+ if (fd)
+ {
+ fwrite(chunk.ptr, sizeof(u_char), chunk.len, fd);
+ fclose(fd);
+ DBG1(" written %s file '%s' (%u bytes)", label, path, chunk.len);
+ umask(oldmask);
+ return TRUE;
+ }
+ else
+ {
+ DBG1(" could not open %s file '%s' for writing", label, path);
+ umask(oldmask);
+ return FALSE;
+ }
+}
+
+/**
* Described in header.
*/
void chunk_free(chunk_t *chunk)
/**
* Described in header.
*/
-chunk_t chunk_alloc(size_t bytes)
+chunk_t chunk_skip(chunk_t chunk, size_t bytes)
{
- chunk_t new_chunk;
- new_chunk.ptr = malloc(bytes);
- new_chunk.len = bytes;
- return new_chunk;
+ if (chunk.len > bytes)
+ {
+ chunk.ptr += bytes;
+ chunk.len -= bytes;
+ return chunk;
+ }
+ return chunk_empty;
}
/**
* Described in header.
*/
+int chunk_compare(chunk_t a, chunk_t b)
+{
+ int compare_len = a.len - b.len;
+ int len = (compare_len < 0)? a.len : b.len;
+
+ if (compare_len != 0 || len == 0)
+ {
+ return compare_len;
+ }
+ return memcmp(a.ptr, b.ptr, len);
+};
+
+/**
+ * Described in header.
+ */
bool chunk_equals(chunk_t a, chunk_t b)
{
return a.ptr != NULL && b.ptr != NULL &&