gator: Version 5.18

Signed-off-by: Jon Medhurst <tixy@linaro.org>
diff --git a/tools/gator/daemon/DynBuf.cpp b/tools/gator/daemon/DynBuf.cpp
new file mode 100644
index 0000000..6f92b33
--- /dev/null
+++ b/tools/gator/daemon/DynBuf.cpp
@@ -0,0 +1,139 @@
+/**
+ * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "DynBuf.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "Logging.h"
+
+// Pick an aggressive size as buffer is primarily used for disk IO
+#define MIN_BUFFER_FREE (1 << 12)
+
+int DynBuf::resize(const size_t minCapacity) {
+	size_t scaledCapacity = 2 * capacity;
+	if (scaledCapacity < minCapacity) {
+		scaledCapacity = minCapacity;
+	}
+	if (scaledCapacity < 2 * MIN_BUFFER_FREE) {
+		scaledCapacity = 2 * MIN_BUFFER_FREE;
+	}
+	capacity = scaledCapacity;
+
+	buf = static_cast<char *>(realloc(buf, capacity));
+	if (buf == NULL) {
+		return -errno;
+	}
+
+	return 0;
+}
+
+bool DynBuf::read(const char *const path) {
+	int result = false;
+
+	const int fd = open(path, O_RDONLY);
+	if (fd < 0) {
+		logg->logMessage("%s(%s:%i): open failed", __FUNCTION__, __FILE__, __LINE__);
+		return false;
+	}
+
+	length = 0;
+
+	for (;;) {
+		const size_t minCapacity = length + MIN_BUFFER_FREE + 1;
+		if (capacity < minCapacity) {
+			if (resize(minCapacity) != 0) {
+				logg->logMessage("%s(%s:%i): DynBuf::resize failed", __FUNCTION__, __FILE__, __LINE__);
+				goto fail;
+			}
+		}
+
+		const ssize_t bytes = ::read(fd, buf + length, capacity - length - 1);
+		if (bytes < 0) {
+			logg->logMessage("%s(%s:%i): read failed", __FUNCTION__, __FILE__, __LINE__);
+			goto fail;
+		} else if (bytes == 0) {
+			break;
+		}
+		length += bytes;
+	}
+
+	buf[length] = '\0';
+	result = true;
+
+ fail:
+	close(fd);
+
+	return result;
+}
+
+int DynBuf::readlink(const char *const path) {
+	ssize_t bytes = MIN_BUFFER_FREE;
+
+	for (;;) {
+		if (static_cast<size_t>(bytes) >= capacity) {
+			const int err = resize(2 * bytes);
+			if (err != 0) {
+				return err;
+			}
+		}
+		bytes = ::readlink(path, buf, capacity);
+		if (bytes < 0) {
+			return -errno;
+		} else if (static_cast<size_t>(bytes) < capacity) {
+			break;
+		}
+	}
+
+	length = bytes;
+	buf[bytes] = '\0';
+
+	return 0;
+}
+
+bool DynBuf::printf(const char *format, ...) {
+	va_list ap;
+
+	if (capacity <= 0) {
+		if (resize(2 * MIN_BUFFER_FREE) != 0) {
+			logg->logMessage("%s(%s:%i): DynBuf::resize failed", __FUNCTION__, __FILE__, __LINE__);
+			return false;
+		}
+	}
+
+	va_start(ap, format);
+	int bytes = vsnprintf(buf, capacity, format, ap);
+	va_end(ap);
+	if (bytes < 0) {
+		logg->logMessage("%s(%s:%i): fsnprintf failed", __FUNCTION__, __FILE__, __LINE__);
+		return false;
+	}
+
+	if (static_cast<size_t>(bytes) > capacity) {
+		if (resize(bytes + 1) != 0) {
+			logg->logMessage("%s(%s:%i): DynBuf::resize failed", __FUNCTION__, __FILE__, __LINE__);
+			return false;
+		}
+
+		va_start(ap, format);
+		bytes = vsnprintf(buf, capacity, format, ap);
+		va_end(ap);
+		if (bytes < 0) {
+			logg->logMessage("%s(%s:%i): fsnprintf failed", __FUNCTION__, __FILE__, __LINE__);
+			return false;
+		}
+	}
+
+	length = bytes;
+
+	return true;
+}