diff --git a/Makefile.am b/Makefile.am
index 44d39bba..5fb213bc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -16,6 +16,7 @@ snapraid_SOURCES = \
tommyds/tommy.c \
cmdline/snapraid.c \
cmdline/util.c \
+ cmdline/support.c \
cmdline/elem.c \
cmdline/state.c \
cmdline/scan.c \
@@ -66,6 +67,7 @@ noinst_HEADERS = \
cmdline/portable.h \
cmdline/snapraid.h \
cmdline/util.h \
+ cmdline/support.h \
cmdline/elem.h \
cmdline/state.h \
cmdline/parity.h \
@@ -82,7 +84,8 @@ noinst_HEADERS = \
mktest_SOURCES = \
cmdline/mktest.c \
- cmdline/mingw.c
+ cmdline/mingw.c \
+ cmdline/support.c
EXTRA_DIST = \
autogen.sh \
diff --git a/cmdline/check.c b/cmdline/check.c
index be32a7e7..7f1978b9 100644
--- a/cmdline/check.c
+++ b/cmdline/check.c
@@ -17,6 +17,7 @@
#include "portable.h"
+#include "support.h"
#include "util.h"
#include "elem.h"
#include "import.h"
diff --git a/cmdline/dup.c b/cmdline/dup.c
index 806e0961..dc4d2e10 100644
--- a/cmdline/dup.c
+++ b/cmdline/dup.c
@@ -17,6 +17,7 @@
#include "portable.h"
+#include "support.h"
#include "util.h"
#include "elem.h"
#include "state.h"
diff --git a/cmdline/elem.c b/cmdline/elem.c
index 4b0edeeb..e3cab4fd 100644
--- a/cmdline/elem.c
+++ b/cmdline/elem.c
@@ -18,6 +18,7 @@
#include "portable.h"
#include "elem.h"
+#include "support.h"
#include "util.h"
/****************************************************************************/
diff --git a/cmdline/handle.c b/cmdline/handle.c
index 3ebea4e6..11958248 100644
--- a/cmdline/handle.c
+++ b/cmdline/handle.c
@@ -18,7 +18,7 @@
#include "portable.h"
#include "elem.h"
-#include "util.h"
+#include "support.h"
#include "handle.h"
/****************************************************************************/
diff --git a/cmdline/import.c b/cmdline/import.c
index b18f160d..fe85404c 100644
--- a/cmdline/import.c
+++ b/cmdline/import.c
@@ -17,6 +17,7 @@
#include "portable.h"
+#include "support.h"
#include "import.h"
/****************************************************************************/
diff --git a/cmdline/nano.c b/cmdline/nano.c
index 1fdedae9..80e795ff 100644
--- a/cmdline/nano.c
+++ b/cmdline/nano.c
@@ -17,7 +17,7 @@
#include "portable.h"
-#include "util.h"
+#include "support.h"
#include "elem.h"
#include "state.h"
#include "handle.h"
diff --git a/cmdline/parity.c b/cmdline/parity.c
index 53d64228..880541df 100644
--- a/cmdline/parity.c
+++ b/cmdline/parity.c
@@ -17,6 +17,7 @@
#include "portable.h"
+#include "support.h"
#include "elem.h"
#include "state.h"
#include "parity.h"
diff --git a/cmdline/pool.c b/cmdline/pool.c
index 0bc7da36..48de6c4e 100644
--- a/cmdline/pool.c
+++ b/cmdline/pool.c
@@ -17,7 +17,7 @@
#include "portable.h"
-#include "util.h"
+#include "support.h"
#include "elem.h"
#include "state.h"
diff --git a/cmdline/scan.c b/cmdline/scan.c
index cf92252e..53bb3712 100644
--- a/cmdline/scan.c
+++ b/cmdline/scan.c
@@ -17,7 +17,7 @@
#include "portable.h"
-#include "util.h"
+#include "support.h"
#include "elem.h"
#include "state.h"
diff --git a/cmdline/scrub.c b/cmdline/scrub.c
index cec1c7a9..3961dcd9 100644
--- a/cmdline/scrub.c
+++ b/cmdline/scrub.c
@@ -17,7 +17,7 @@
#include "portable.h"
-#include "util.h"
+#include "support.h"
#include "elem.h"
#include "state.h"
#include "parity.h"
diff --git a/cmdline/search.c b/cmdline/search.c
index 87e6e524..5ebf7ffc 100644
--- a/cmdline/search.c
+++ b/cmdline/search.c
@@ -17,6 +17,7 @@
#include "portable.h"
+#include "support.h"
#include "search.h"
/****************************************************************************/
diff --git a/cmdline/snapraid.c b/cmdline/snapraid.c
index 675b7d81..14ce7138 100644
--- a/cmdline/snapraid.c
+++ b/cmdline/snapraid.c
@@ -18,7 +18,7 @@
#include "portable.h"
#include "snapraid.h"
-#include "util.h"
+#include "support.h"
#include "elem.h"
#include "import.h"
#include "search.h"
diff --git a/cmdline/spin.c b/cmdline/spin.c
index d7bf135b..8b6eee21 100644
--- a/cmdline/spin.c
+++ b/cmdline/spin.c
@@ -17,6 +17,7 @@
#include "portable.h"
+#include "support.h"
#include "state.h"
void state_spin(struct snapraid_state* state, int operation)
diff --git a/cmdline/state.c b/cmdline/state.c
index eac77fdc..6d18fc25 100644
--- a/cmdline/state.c
+++ b/cmdline/state.c
@@ -21,7 +21,7 @@
#include "import.h"
#include "search.h"
#include "state.h"
-#include "util.h"
+#include "support.h"
#include "parity.h"
#include "raid/raid.h"
#include "raid/cpu.h"
diff --git a/cmdline/status.c b/cmdline/status.c
index 40639c59..9f375cd8 100644
--- a/cmdline/status.c
+++ b/cmdline/status.c
@@ -17,7 +17,7 @@
#include "portable.h"
-#include "util.h"
+#include "support.h"
#include "elem.h"
#include "state.h"
#include "parity.h"
diff --git a/cmdline/support.c b/cmdline/support.c
new file mode 100644
index 00000000..63b81672
--- /dev/null
+++ b/cmdline/support.c
@@ -0,0 +1,397 @@
+/*
+ * Copyright (C) 2011 Andrea Mazzoleni
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "portable.h"
+
+#include "support.h"
+
+/****************************************************************************/
+/* path */
+
+void pathcpy(char* dst, size_t size, const char* src)
+{
+ size_t len = strlen(src);
+
+ if (len + 1 > size) {
+ /* LCOV_EXCL_START */
+ fprintf(stderr, "Path too long\n");
+ exit(EXIT_FAILURE);
+ /* LCOV_EXCL_STOP */
+ }
+
+ memcpy(dst, src, len + 1);
+}
+
+void pathcat(char* dst, size_t size, const char* src)
+{
+ size_t dst_len = strlen(dst);
+ size_t src_len = strlen(src);
+
+ if (dst_len + src_len + 1 > size) {
+ /* LCOV_EXCL_START */
+ fprintf(stderr, "Path too long\n");
+ exit(EXIT_FAILURE);
+ /* LCOV_EXCL_STOP */
+ }
+
+ memcpy(dst + dst_len, src, src_len + 1);
+}
+
+void pathcatc(char* dst, size_t size, char c)
+{
+ size_t dst_len = strlen(dst);
+
+ if (dst_len + 2 > size) {
+ /* LCOV_EXCL_START */
+ fprintf(stderr, "Path too long\n");
+ exit(EXIT_FAILURE);
+ /* LCOV_EXCL_STOP */
+ }
+
+ dst[dst_len] = c;
+ dst[dst_len + 1] = 0;
+}
+
+void pathimport(char* dst, size_t size, const char* src)
+{
+ pathcpy(dst, size, src);
+
+#ifdef _WIN32
+ /* convert all Windows '\' to C '/' */
+ while (*dst) {
+ if (*dst == '\\')
+ *dst = '/';
+ ++dst;
+ }
+#endif
+}
+
+void pathexport(char* dst, size_t size, const char* src)
+{
+ pathcpy(dst, size, src);
+
+#ifdef _WIN32
+ /* convert all C '/' to Windows '\' */
+ while (*dst) {
+ if (*dst == '/')
+ *dst = '\\';
+ ++dst;
+ }
+#endif
+}
+
+void pathprint(char* dst, size_t size, const char* format, ...)
+{
+ size_t len;
+ va_list ap;
+
+ va_start(ap, format);
+ len = vsnprintf(dst, size, format, ap);
+ va_end(ap);
+
+ if (len >= size) {
+ /* LCOV_EXCL_START */
+ fprintf(stderr, "Path too long\n");
+ exit(EXIT_FAILURE);
+ /* LCOV_EXCL_STOP */
+ }
+}
+
+void pathslash(char* dst, size_t size)
+{
+ size_t len = strlen(dst);
+
+ if (len > 0 && dst[len - 1] != '/') {
+ if (len + 2 >= size) {
+ /* LCOV_EXCL_START */
+ fprintf(stderr, "Path too long\n");
+ exit(EXIT_FAILURE);
+ /* LCOV_EXCL_STOP */
+ }
+
+ dst[len] = '/';
+ dst[len + 1] = 0;
+ }
+}
+
+void pathcut(char* dst)
+{
+ char* slash = strrchr(dst, '/');
+ if (slash)
+ slash[1] = 0;
+ else
+ dst[0] = 0;
+}
+
+int pathcmp(const char* a, const char* b)
+{
+#ifdef _WIN32
+ char ai[PATH_MAX];
+ char bi[PATH_MAX];
+
+ /* import to convert \ to / */
+ pathimport(ai, sizeof(ai), a);
+ pathimport(bi, sizeof(bi), b);
+
+ /* case insensitive compare in Windows */
+ return stricmp(ai, bi);
+#else
+ return strcmp(a, b);
+#endif
+}
+
+/****************************************************************************/
+/* filesystem */
+
+int mkancestor(const char* file)
+{
+ char dir[PATH_MAX];
+ struct stat st;
+ char* c;
+
+ pathcpy(dir, sizeof(dir), file);
+
+ c = strrchr(dir, '/');
+ if (!c) {
+ /* no ancestor */
+ return 0;
+ }
+
+ /* clear the file */
+ *c = 0;
+
+ /* if it's the root dir */
+ if (*dir == 0) {
+ /* nothing more to do */
+ return 0;
+ }
+
+#ifdef _WIN32
+ /* if it's a drive specificaion like "C:" */
+ if (isalpha(dir[0]) && dir[1] == ':' && dir[2] == 0) {
+ /* nothing more to do */
+ return 0;
+ }
+#endif
+
+ /*
+ * Check if the dir already exists using lstat().
+ *
+ * Note that in Windows when dealing with read-only media
+ * you cannot try to create the directory, and expecting
+ * the EEXIST error because the call will fail with ERROR_WRITE_PROTECTED.
+ *
+ * Also in Windows it's better to use lstat() than stat() because it
+ * doen't need to open the dir with CreateFile().
+ */
+ if (lstat(dir, &st) == 0) {
+ /* it already exists */
+ return 0;
+ }
+
+ /* recursively create them all */
+ if (mkancestor(dir) != 0) {
+ /* LCOV_EXCL_START */
+ return -1;
+ /* LCOV_EXCL_STOP */
+ }
+
+ /* create it */
+ if (mkdir(dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
+ /* LCOV_EXCL_START */
+ fprintf(stderr, "Error creating directory '%s'. %s.\n", dir, strerror(errno));
+ return -1;
+ /* LCOV_EXCL_STOP */
+ }
+
+ return 0;
+}
+
+int fmtime(int f, int64_t mtime_sec, int mtime_nsec)
+{
+#if HAVE_FUTIMENS
+ struct timespec tv[2];
+#else
+ struct timeval tv[2];
+#endif
+ int ret;
+
+#if HAVE_FUTIMENS /* futimens() is preferred because it gives nanosecond precision */
+ tv[0].tv_sec = mtime_sec;
+ if (mtime_nsec != STAT_NSEC_INVALID)
+ tv[0].tv_nsec = mtime_nsec;
+ else
+ tv[0].tv_nsec = 0;
+ tv[1].tv_sec = tv[0].tv_sec;
+ tv[1].tv_nsec = tv[0].tv_nsec;
+
+ ret = futimens(f, tv);
+#elif HAVE_FUTIMES /* fallback to futimes() if nanosecond precision is not available */
+ tv[0].tv_sec = mtime_sec;
+ if (mtime_nsec != STAT_NSEC_INVALID)
+ tv[0].tv_usec = mtime_nsec / 1000;
+ else
+ tv[0].tv_usec = 0;
+ tv[1].tv_sec = tv[0].tv_sec;
+ tv[1].tv_usec = tv[0].tv_usec;
+
+ ret = futimes(f, tv);
+#elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */
+ tv[0].tv_sec = mtime_sec;
+ if (mtime_nsec != STAT_NSEC_INVALID)
+ tv[0].tv_usec = mtime_nsec / 1000;
+ else
+ tv[0].tv_usec = 0;
+ tv[1].tv_sec = tv[0].tv_sec;
+ tv[1].tv_usec = tv[0].tv_usec;
+
+ ret = futimesat(f, 0, tv);
+#else
+#error No function available to set file timestamps with sub-second precision
+#endif
+
+ return ret;
+}
+
+/****************************************************************************/
+/* memory */
+
+static size_t mcounter;
+
+size_t malloc_counter(void)
+{
+ return mcounter;
+}
+
+static ssize_t malloc_print(int f, const char* str)
+{
+ ssize_t len = 0;
+ while (str[len])
+ ++len;
+ return write(f, str, len);
+}
+
+static ssize_t malloc_printn(int f, size_t value)
+{
+ char buf[32];
+ int i;
+
+ if (!value)
+ return write(f, "0", 1);
+
+ i = sizeof(buf);
+ while (value) {
+ buf[--i] = (value % 10) + '0';
+ value /= 10;
+ }
+
+ return write(f, buf + i, sizeof(buf) - i);
+}
+
+void malloc_fail(size_t size)
+{
+ /* don't use printf to avoid any possible extra allocation */
+ /* LCOV_EXCL_START */
+ int f = 2; /* stderr */
+
+ malloc_print(f, "Failed for Low Memory!\n");
+ malloc_print(f, "Allocating ");
+ malloc_printn(f, size);
+ malloc_print(f, " bytes.\n");
+ malloc_print(f, "Already allocated ");
+ malloc_printn(f, malloc_counter());
+ malloc_print(f, " bytes.\n");
+ if (sizeof(void*) == 4) {
+ malloc_print(f, "You are currently using a 32 bits executable.\n");
+ malloc_print(f, "If you have more than 4GB of memory, please upgrade to a 64 bits one.\n");
+ }
+ /* LCOV_EXCL_STOP */
+}
+
+void* malloc_nofail(size_t size)
+{
+ void* ptr = malloc(size);
+
+ if (!ptr) {
+ /* LCOV_EXCL_START */
+ malloc_fail(size);
+ exit(EXIT_FAILURE);
+ /* LCOV_EXCL_STOP */
+ }
+
+#ifndef CHECKER /* Don't preinitialize when running for valgrind */
+ /* Here we preinitialize the memory to ensure that the OS is really allocating it */
+ /* and not only reserving the addressable space. */
+ /* Otherwise we are risking that the OOM (Out Of Memory) killer in Linux will kill the process. */
+ /* Filling the memory doesn't ensure to disable OOM, but it increase a lot the chances to */
+ /* get a real error from malloc() instead than a process killed. */
+ /* Note that calloc() doesn't have the same effect. */
+ memset(ptr, 0xA5, size);
+#endif
+
+ mcounter += size;
+
+ return ptr;
+}
+
+void* calloc_nofail(size_t count, size_t size)
+{
+ void* ptr;
+
+ size *= count;
+
+ /* see the note in malloc_nofail() of why we don't use calloc() */
+ ptr = malloc(size);
+
+ if (!ptr) {
+ /* LCOV_EXCL_START */
+ malloc_fail(size);
+ exit(EXIT_FAILURE);
+ /* LCOV_EXCL_STOP */
+ }
+
+ memset(ptr, 0, size);
+
+ mcounter += size;
+
+ return ptr;
+}
+
+char* strdup_nofail(const char* str)
+{
+ size_t size;
+ char* ptr;
+
+ size = strlen(str) + 1;
+
+ ptr = malloc(size);
+
+ if (!ptr) {
+ /* LCOV_EXCL_START */
+ malloc_fail(size);
+ exit(EXIT_FAILURE);
+ /* LCOV_EXCL_STOP */
+ }
+
+ memcpy(ptr, str, size);
+
+ mcounter += size;
+
+ return ptr;
+}
+
+
diff --git a/cmdline/support.h b/cmdline/support.h
new file mode 100644
index 00000000..99f82cce
--- /dev/null
+++ b/cmdline/support.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2011 Andrea Mazzoleni
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef __SUPPORT_H
+#define __SUPPORT_H
+
+/****************************************************************************/
+/* path */
+
+/**
+ * Copies a path limiting the size.
+ * Aborts if too long.
+ */
+void pathcpy(char* dst, size_t size, const char* src);
+
+/**
+ * Concatenates a path limiting the size.
+ * Aborts if too long.
+ */
+void pathcat(char* dst, size_t size, const char* src);
+
+/**
+ * Concatenates a path limiting the size.
+ * Aborts if too long.
+ */
+void pathcatc(char* dst, size_t size, char c);
+
+/**
+ * Imports a path limiting the size.
+ * In Windows all the backslash are converted to the C standard of forward slash.
+ * Aborts if too long.
+ */
+void pathimport(char* dst, size_t size, const char* src);
+
+/**
+ * Exports a path limiting the size.
+ * In Windows all the C slashes are converted to the Windows backslash.
+ * Aborts if too long.
+ */
+void pathexport(char* dst, size_t size, const char* src);
+
+/**
+ * Prints a path.
+ * Aborts if too long.
+ */
+void pathprint(char* dst, size_t size, const char* format, ...);
+
+/**
+ * Ensures the presence of a terminating slash, if it isn't empty.
+ * Aborts if too long.
+ */
+void pathslash(char* dst, size_t size);
+
+/**
+ * Cuts everything after the latest slash.
+ */
+void pathcut(char* dst);
+
+/**
+ * Compare two paths.
+ * In Windows it's case insentive and assumes \ equal at /.
+ */
+int pathcmp(const char* a, const char* b);
+
+/****************************************************************************/
+/* filesystem */
+
+/**
+ * Creates all the ancestor directories if missing.
+ * The file name, after the last /, is ignored.
+ */
+int mkancestor(const char* file);
+
+/**
+ * Changes the modification time of an open file.
+ */
+int fmtime(int f, int64_t mtime_sec, int mtime_nsec);
+
+/****************************************************************************/
+/* memory */
+
+/**
+ * Return the size of the allocated memory.
+ */
+size_t malloc_counter(void);
+
+/**
+ * Safe malloc.
+ * If no memory is available, it aborts.
+ */
+void* malloc_nofail(size_t size);
+
+/**
+ * Safe cmalloc.
+ * If no memory is available, it aborts.
+ */
+void* calloc_nofail(size_t count, size_t size);
+
+/**
+ * Safe strdup.
+ * If no memory is available, it aborts.
+ */
+char* strdup_nofail(const char* str);
+
+/**
+ * Helper for printing an error about a failed allocation.
+ */
+void malloc_fail(size_t size);
+
+#endif
+
diff --git a/cmdline/sync.c b/cmdline/sync.c
index 835180d1..e7a75687 100644
--- a/cmdline/sync.c
+++ b/cmdline/sync.c
@@ -17,7 +17,7 @@
#include "portable.h"
-#include "util.h"
+#include "support.h"
#include "elem.h"
#include "state.h"
#include "parity.h"
diff --git a/cmdline/unix.c b/cmdline/unix.c
index 304ddaa4..fc96796b 100644
--- a/cmdline/unix.c
+++ b/cmdline/unix.c
@@ -19,7 +19,7 @@
#ifndef __MINGW32__ /* Only for Unix */
-#include "util.h"
+#include "support.h"
/**
* Standard exit codes.
diff --git a/cmdline/util.c b/cmdline/util.c
index ef6ef0a5..1d737c84 100644
--- a/cmdline/util.c
+++ b/cmdline/util.c
@@ -17,6 +17,7 @@
#include "portable.h"
+#include "support.h"
#include "util.h"
#include "raid/cpu.h"
#include "raid/memory.h"
@@ -886,6 +887,52 @@ int ssync(STREAM* s)
}
#endif
+/****************************************************************************/
+/* memory */
+
+void* malloc_nofail_align(size_t size, void** freeptr)
+{
+ void* ptr;
+
+ ptr = raid_malloc_align(size, freeptr);
+
+ if (!ptr) {
+ /* LCOV_EXCL_START */
+ malloc_fail(size);
+ exit(EXIT_FAILURE);
+ /* LCOV_EXCL_STOP */
+ }
+
+ return ptr;
+}
+
+void** malloc_nofail_vector_align(int nd, int n, size_t size, void** freeptr)
+{
+ void* ptr;
+
+ ptr = raid_malloc_vector(nd, n, size, freeptr);
+
+ if (!ptr) {
+ /* LCOV_EXCL_START */
+ malloc_fail(n * size);
+ exit(EXIT_FAILURE);
+ /* LCOV_EXCL_STOP */
+ }
+
+ return ptr;
+}
+
+void mtest_vector(int n, size_t size, void** vv)
+{
+ if (raid_mtest_vector(n, size, vv) != 0) {
+ /* LCOV_EXCL_START */
+ fprintf(stderr, "DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n");
+ fprintf(stderr, "Try running a memory test like http://www.memtest86.com/\n");
+ exit(EXIT_FAILURE);
+ /* LCOV_EXCL_STOP */
+ }
+}
+
/****************************************************************************/
/* crc */
@@ -1234,378 +1281,6 @@ void crc32c_init(void)
#endif
}
-/****************************************************************************/
-/* path */
-
-void pathcpy(char* dst, size_t size, const char* src)
-{
- size_t len = strlen(src);
-
- if (len + 1 > size) {
- /* LCOV_EXCL_START */
- fprintf(stderr, "Path too long\n");
- exit(EXIT_FAILURE);
- /* LCOV_EXCL_STOP */
- }
-
- memcpy(dst, src, len + 1);
-}
-
-void pathcat(char* dst, size_t size, const char* src)
-{
- size_t dst_len = strlen(dst);
- size_t src_len = strlen(src);
-
- if (dst_len + src_len + 1 > size) {
- /* LCOV_EXCL_START */
- fprintf(stderr, "Path too long\n");
- exit(EXIT_FAILURE);
- /* LCOV_EXCL_STOP */
- }
-
- memcpy(dst + dst_len, src, src_len + 1);
-}
-
-void pathcatc(char* dst, size_t size, char c)
-{
- size_t dst_len = strlen(dst);
-
- if (dst_len + 2 > size) {
- /* LCOV_EXCL_START */
- fprintf(stderr, "Path too long\n");
- exit(EXIT_FAILURE);
- /* LCOV_EXCL_STOP */
- }
-
- dst[dst_len] = c;
- dst[dst_len + 1] = 0;
-}
-
-void pathimport(char* dst, size_t size, const char* src)
-{
- pathcpy(dst, size, src);
-
-#ifdef _WIN32
- /* convert all Windows '\' to C '/' */
- while (*dst) {
- if (*dst == '\\')
- *dst = '/';
- ++dst;
- }
-#endif
-}
-
-void pathexport(char* dst, size_t size, const char* src)
-{
- pathcpy(dst, size, src);
-
-#ifdef _WIN32
- /* convert all C '/' to Windows '\' */
- while (*dst) {
- if (*dst == '/')
- *dst = '\\';
- ++dst;
- }
-#endif
-}
-
-void pathprint(char* dst, size_t size, const char* format, ...)
-{
- size_t len;
- va_list ap;
-
- va_start(ap, format);
- len = vsnprintf(dst, size, format, ap);
- va_end(ap);
-
- if (len >= size) {
- /* LCOV_EXCL_START */
- fprintf(stderr, "Path too long\n");
- exit(EXIT_FAILURE);
- /* LCOV_EXCL_STOP */
- }
-}
-
-void pathslash(char* dst, size_t size)
-{
- size_t len = strlen(dst);
-
- if (len > 0 && dst[len - 1] != '/') {
- if (len + 2 >= size) {
- /* LCOV_EXCL_START */
- fprintf(stderr, "Path too long\n");
- exit(EXIT_FAILURE);
- /* LCOV_EXCL_STOP */
- }
-
- dst[len] = '/';
- dst[len + 1] = 0;
- }
-}
-
-void pathcut(char* dst)
-{
- char* slash = strrchr(dst, '/');
- if (slash)
- slash[1] = 0;
- else
- dst[0] = 0;
-}
-
-int pathcmp(const char* a, const char* b)
-{
-#ifdef _WIN32
- char ai[PATH_MAX];
- char bi[PATH_MAX];
-
- /* import to convert \ to / */
- pathimport(ai, sizeof(ai), a);
- pathimport(bi, sizeof(bi), b);
-
- /* case insensitive compare in Windows */
- return stricmp(ai, bi);
-#else
- return strcmp(a, b);
-#endif
-}
-
-/****************************************************************************/
-/* filesystem */
-
-int mkancestor(const char* file)
-{
- char dir[PATH_MAX];
- struct stat st;
- char* c;
-
- pathcpy(dir, sizeof(dir), file);
-
- c = strrchr(dir, '/');
- if (!c) {
- /* no ancestor */
- return 0;
- }
-
- /* clear the file */
- *c = 0;
-
- /* if it's the root dir */
- if (*dir == 0) {
- /* nothing more to do */
- return 0;
- }
-
-#ifdef _WIN32
- /* if it's a drive specificaion like "C:" */
- if (isalpha(dir[0]) && dir[1] == ':' && dir[2] == 0) {
- /* nothing more to do */
- return 0;
- }
-#endif
-
- /*
- * Check if the dir already exists using lstat().
- *
- * Note that in Windows when dealing with read-only media
- * you cannot try to create the directory, and expecting
- * the EEXIST error because the call will fail with ERROR_WRITE_PROTECTED.
- *
- * Also in Windows it's better to use lstat() than stat() because it
- * doen't need to open the dir with CreateFile().
- */
- if (lstat(dir, &st) == 0) {
- /* it already exists */
- return 0;
- }
-
- /* recursively create them all */
- if (mkancestor(dir) != 0) {
- /* LCOV_EXCL_START */
- return -1;
- /* LCOV_EXCL_STOP */
- }
-
- /* create it */
- if (mkdir(dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
- /* LCOV_EXCL_START */
- fprintf(stderr, "Error creating directory '%s'. %s.\n", dir, strerror(errno));
- return -1;
- /* LCOV_EXCL_STOP */
- }
-
- return 0;
-}
-
-/****************************************************************************/
-/* mem */
-
-static size_t mcounter;
-
-size_t malloc_counter(void)
-{
- return mcounter;
-}
-
-static ssize_t malloc_print(int f, const char* str)
-{
- ssize_t len = 0;
- while (str[len])
- ++len;
- return write(f, str, len);
-}
-
-static ssize_t malloc_printn(int f, size_t value)
-{
- char buf[32];
- int i;
-
- if (!value)
- return write(f, "0", 1);
-
- i = sizeof(buf);
- while (value) {
- buf[--i] = (value % 10) + '0';
- value /= 10;
- }
-
- return write(f, buf + i, sizeof(buf) - i);
-}
-
-static void malloc_fail(size_t size)
-{
- /* don't use printf to avoid any possible extra allocation */
- /* LCOV_EXCL_START */
- int f = 2; /* stderr */
-
- malloc_print(f, "Failed for Low Memory!\n");
- malloc_print(f, "Allocating ");
- malloc_printn(f, size);
- malloc_print(f, " bytes.\n");
- malloc_print(f, "Already allocated ");
- malloc_printn(f, malloc_counter());
- malloc_print(f, " bytes.\n");
- if (sizeof(void*) == 4) {
- malloc_print(f, "You are currently using a 32 bits executable.\n");
- malloc_print(f, "If you have more than 4GB of memory, please upgrade to a 64 bits one.\n");
- }
- /* LCOV_EXCL_STOP */
-}
-
-void* malloc_nofail(size_t size)
-{
- void* ptr = malloc(size);
-
- if (!ptr) {
- /* LCOV_EXCL_START */
- malloc_fail(size);
- exit(EXIT_FAILURE);
- /* LCOV_EXCL_STOP */
- }
-
-#ifndef CHECKER /* Don't preinitialize when running for valgrind */
- /* Here we preinitialize the memory to ensure that the OS is really allocating it */
- /* and not only reserving the addressable space. */
- /* Otherwise we are risking that the OOM (Out Of Memory) killer in Linux will kill the process. */
- /* Filling the memory doesn't ensure to disable OOM, but it increase a lot the chances to */
- /* get a real error from malloc() instead than a process killed. */
- /* Note that calloc() doesn't have the same effect. */
- memset(ptr, 0xA5, size);
-#endif
-
- mcounter += size;
-
- return ptr;
-}
-
-void* calloc_nofail(size_t count, size_t size)
-{
- void* ptr;
-
- size *= count;
-
- /* see the note in malloc_nofail() of why we don't use calloc() */
- ptr = malloc(size);
-
- if (!ptr) {
- /* LCOV_EXCL_START */
- malloc_fail(size);
- exit(EXIT_FAILURE);
- /* LCOV_EXCL_STOP */
- }
-
- memset(ptr, 0, size);
-
- mcounter += size;
-
- return ptr;
-}
-
-char* strdup_nofail(const char* str)
-{
- size_t size;
- char* ptr;
-
- size = strlen(str) + 1;
-
- ptr = malloc(size);
-
- if (!ptr) {
- /* LCOV_EXCL_START */
- malloc_fail(size);
- exit(EXIT_FAILURE);
- /* LCOV_EXCL_STOP */
- }
-
- memcpy(ptr, str, size);
-
- mcounter += size;
-
- return ptr;
-}
-
-void* malloc_nofail_align(size_t size, void** freeptr)
-{
- void* ptr;
-
- ptr = raid_malloc_align(size, freeptr);
-
- if (!ptr) {
- /* LCOV_EXCL_START */
- malloc_fail(size);
- exit(EXIT_FAILURE);
- /* LCOV_EXCL_STOP */
- }
-
- return ptr;
-}
-
-void** malloc_nofail_vector_align(int nd, int n, size_t size, void** freeptr)
-{
- void* ptr;
-
- ptr = raid_malloc_vector(nd, n, size, freeptr);
-
- if (!ptr) {
- /* LCOV_EXCL_START */
- malloc_fail(n * size);
- exit(EXIT_FAILURE);
- /* LCOV_EXCL_STOP */
- }
-
- return ptr;
-}
-
-void mtest_vector(int n, size_t size, void** vv)
-{
- if (raid_mtest_vector(n, size, vv) != 0) {
- /* LCOV_EXCL_START */
- fprintf(stderr, "DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n");
- fprintf(stderr, "Try running a memory test like http://www.memtest86.com/\n");
- exit(EXIT_FAILURE);
- /* LCOV_EXCL_STOP */
- }
-}
-
/****************************************************************************/
/* byte operations */
@@ -1737,52 +1412,3 @@ int lock_unlock(int f)
}
#endif
-/****************************************************************************/
-/* file */
-
-int fmtime(int f, int64_t mtime_sec, int mtime_nsec)
-{
-#if HAVE_FUTIMENS
- struct timespec tv[2];
-#else
- struct timeval tv[2];
-#endif
- int ret;
-
-#if HAVE_FUTIMENS /* futimens() is preferred because it gives nanosecond precision */
- tv[0].tv_sec = mtime_sec;
- if (mtime_nsec != STAT_NSEC_INVALID)
- tv[0].tv_nsec = mtime_nsec;
- else
- tv[0].tv_nsec = 0;
- tv[1].tv_sec = tv[0].tv_sec;
- tv[1].tv_nsec = tv[0].tv_nsec;
-
- ret = futimens(f, tv);
-#elif HAVE_FUTIMES /* fallback to futimes() if nanosecond precision is not available */
- tv[0].tv_sec = mtime_sec;
- if (mtime_nsec != STAT_NSEC_INVALID)
- tv[0].tv_usec = mtime_nsec / 1000;
- else
- tv[0].tv_usec = 0;
- tv[1].tv_sec = tv[0].tv_sec;
- tv[1].tv_usec = tv[0].tv_usec;
-
- ret = futimes(f, tv);
-#elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */
- tv[0].tv_sec = mtime_sec;
- if (mtime_nsec != STAT_NSEC_INVALID)
- tv[0].tv_usec = mtime_nsec / 1000;
- else
- tv[0].tv_usec = 0;
- tv[1].tv_sec = tv[0].tv_sec;
- tv[1].tv_usec = tv[0].tv_usec;
-
- ret = futimesat(f, 0, tv);
-#else
-#error No function available to set file timestamps with sub-second precision
-#endif
-
- return ret;
-}
-
diff --git a/cmdline/util.h b/cmdline/util.h
index 8f99990c..6867a027 100644
--- a/cmdline/util.h
+++ b/cmdline/util.h
@@ -388,93 +388,9 @@ int sputble32(uint32_t value, STREAM* s);
*/
int sputbs(const char* str, STREAM* s);
-/****************************************************************************/
-/* path */
-
-/**
- * Copies a path limiting the size.
- * Aborts if too long.
- */
-void pathcpy(char* dst, size_t size, const char* src);
-
-/**
- * Concatenates a path limiting the size.
- * Aborts if too long.
- */
-void pathcat(char* dst, size_t size, const char* src);
-
-/**
- * Concatenates a path limiting the size.
- * Aborts if too long.
- */
-void pathcatc(char* dst, size_t size, char c);
-
-/**
- * Imports a path limiting the size.
- * In Windows all the backslash are converted to the C standard of forward slash.
- * Aborts if too long.
- */
-void pathimport(char* dst, size_t size, const char* src);
-
-/**
- * Exports a path limiting the size.
- * In Windows all the C slashes are converted to the Windows backslash.
- * Aborts if too long.
- */
-void pathexport(char* dst, size_t size, const char* src);
-
-/**
- * Prints a path.
- * Aborts if too long.
- */
-void pathprint(char* dst, size_t size, const char* format, ...);
-
-/**
- * Ensures the presence of a terminating slash, if it isn't empty.
- * Aborts if too long.
- */
-void pathslash(char* dst, size_t size);
-
-/**
- * Cuts everything after the latest slash.
- */
-void pathcut(char* dst);
-
-/**
- * Compare two paths.
- * In Windows it's case insentive and assumes \ equal at /.
- */
-int pathcmp(const char* a, const char* b);
-
-/****************************************************************************/
-/* filesystem */
-
-/**
- * Creates all the ancestor directories if missing.
- * The file name, after the last /, is ignored.
- */
-int mkancestor(const char* file);
-
/****************************************************************************/
/* memory */
-/**
- * Return the size of the allocated memory.
- */
-size_t malloc_counter(void);
-
-/**
- * Safe malloc.
- * If no memory is available, it aborts.
- */
-void* malloc_nofail(size_t size);
-
-/**
- * Safe cmalloc.
- * If no memory is available, it aborts.
- */
-void* calloc_nofail(size_t count, size_t size);
-
/**
* Safe aligned malloc.
* If no memory is available, it aborts.
@@ -487,23 +403,12 @@ void* malloc_nofail_align(size_t size, void** freeptr);
*/
void** malloc_nofail_vector_align(int nd, int n, size_t size, void** freeptr);
-/**
- * Fills the memory vector with random data.
- */
-void mrand_vector(unsigned seed, int n, size_t size, void** vv);
-
/**
* Tests the memory vector for RAM problems.
* If a problem is found, it crashes.
*/
void mtest_vector(int n, size_t size, void** vv);
-/**
- * Safe strdup.
- * If no memory is available, it aborts.
- */
-char* strdup_nofail(const char* str);
-
/****************************************************************************/
/* hash */
@@ -561,13 +466,5 @@ int lock_lock(const char* file);
*/
int lock_unlock(int f);
-/****************************************************************************/
-/* file */
-
-/**
- * Changes the modification time of an open file.
- */
-int fmtime(int f, int64_t mtime_sec, int mtime_nsec);
-
#endif
diff --git a/tommyds/tommy.c b/tommyds/tommy.c
index b69d9de1..68316587 100644
--- a/tommyds/tommy.c
+++ b/tommyds/tommy.c
@@ -31,7 +31,7 @@
#define tommy_free free
#include "cmdline/portable.h"
-#include "cmdline/util.h" /* for malloc_nofail() */
+#include "cmdline/support.h" /* for malloc/calloc_nofail() */
#include "tommyhash.c"
#include "tommyarray.c"