aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--configure.ac3
-rw-r--r--src/misc.c26
-rw-r--r--src/misc.h8
-rw-r--r--tests/Makefile.am4
-rw-r--r--tests/internals/Makefile.am8
-rw-r--r--tests/internals/test_internals.c65
-rwxr-xr-xtests/internals/test_internals_valgrind.sh3
8 files changed, 118 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index ccdac85..3d7daaa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,4 +35,6 @@ Makefile
src/bindfs
tests/readdir_inode
tests/*.log
+tests/internals/test_internals
+tests/internals/*.log
diff --git a/configure.ac b/configure.ac
index 6d3e348..a4c26a0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -45,6 +45,7 @@ PKG_CHECK_MODULES([fuse], [fuse >= 2.5.3])
AC_CONFIG_FILES([Makefile \
src/Makefile \
- tests/Makefile])
+ tests/Makefile \
+ tests/internals/Makefile])
AC_OUTPUT
diff --git a/src/misc.c b/src/misc.c
index c130b86..bb838c7 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -82,6 +82,32 @@ const char *my_basename(const char *path)
return path;
}
+const char *my_dirname(char *path)
+{
+ if (strcmp(path, ".") == 0) {
+ return "..";
+ } else if (strcmp(path, "/") == 0) {
+ return "/";
+ } else {
+ int len = strlen(path);
+ char *p = path + len - 1;
+ while (p > path) {
+ if (*p == '/') {
+ break;
+ }
+ --p;
+ }
+ if (p > path) {
+ *p = '\0';
+ return path;
+ } else if (*path == '/') {
+ return "/";
+ } else {
+ return ".";
+ }
+ }
+}
+
void grow_array_impl(void **array, int* capacity, int member_size)
{
int new_cap = *capacity;
diff --git a/src/misc.h b/src/misc.h
index 2ef8f6d..8b00f8d 100644
--- a/src/misc.h
+++ b/src/misc.h
@@ -38,6 +38,14 @@ char *strdup_until(const char *s, const char *endchars);
Returns NULL if path is NULL. */
const char *my_basename(const char *path);
+/* A thread-safe version of dirname, with slightly different behavior.
+ If path is ".", returns "..".
+ If path is "/", returns "/".
+ If path has an initial slash but no other slashes, returns "/".
+ If path contains a slash, replaces the last slash with a '\0' and returns path.
+ Otherwise, returns ".". */
+const char *my_dirname(char *path);
+
/* Reallocs `*array` (may be NULL) to be at least one larger
than `*capacity` (may be 0) and stores the new capacity
in `*capacity`. */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ce11f95..8210f2b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -2,4 +2,8 @@
noinst_PROGRAMS = readdir_inode
readdir_inode_SOURCES = readdir_inode.c
+test_internals_CPPFLAGS = ${my_CPPFLAGS} ${fuse_CFLAGS}
+test_internals_CFLAGS = ${my_CFLAGS}
+
TESTS = test_bindfs.rb
+SUBDIRS = internals
diff --git a/tests/internals/Makefile.am b/tests/internals/Makefile.am
new file mode 100644
index 0000000..7f1568b
--- /dev/null
+++ b/tests/internals/Makefile.am
@@ -0,0 +1,8 @@
+
+noinst_PROGRAMS = test_internals
+test_internals_SOURCES = test_internals.c $(top_builddir)/src/misc.c
+
+test_internals_CPPFLAGS = ${my_CPPFLAGS} ${fuse_CFLAGS} -I$(top_builddir)/src
+test_internals_CFLAGS = ${my_CFLAGS}
+
+TESTS = test_internals_valgrind.sh
diff --git a/tests/internals/test_internals.c b/tests/internals/test_internals.c
new file mode 100644
index 0000000..b388ddb
--- /dev/null
+++ b/tests/internals/test_internals.c
@@ -0,0 +1,65 @@
+
+#include "misc.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int failures = 0;
+
+#define TEST_ASSERT(expr) do { if (!(expr)) { printf("Assertion failed: `%s'\n", #expr); failures++; } } while (0);
+
+void test_my_dirname(char *arg, const char *expected)
+{
+ char *orig = strdup(arg);
+
+ const char *ret = my_dirname(arg);
+ if (strcmp(ret, expected) != 0) {
+ printf("Expected my_dirname(`%s') to return `%s' but got `%s'\n", orig, expected, ret);
+ failures++;
+ }
+
+ free(orig);
+}
+
+void my_dirname_suite()
+{
+ char buf[256];
+
+ strcpy(buf, "/foo/bar/baz");
+ test_my_dirname(buf, "/foo/bar");
+
+ strcpy(buf, "/foo/bar");
+ test_my_dirname(buf, "/foo");
+
+ strcpy(buf, "/foo");
+ test_my_dirname(buf, "/");
+
+ strcpy(buf, "/foo/");
+ test_my_dirname(buf, "/foo");
+
+ strcpy(buf, "/");
+ test_my_dirname(buf, "/");
+
+ strcpy(buf, "foo");
+ test_my_dirname(buf, ".");
+
+ strcpy(buf, "foo/bar");
+ test_my_dirname(buf, "foo");
+
+ strcpy(buf, "./foo/bar");
+ test_my_dirname(buf, "./foo");
+
+ strcpy(buf, "./foo");
+ test_my_dirname(buf, ".");
+
+ strcpy(buf, ".");
+ test_my_dirname(buf, "..");
+}
+
+int main()
+{
+ my_dirname_suite();
+
+ return (failures > 0) ? 1 : 0;
+}
+
diff --git a/tests/internals/test_internals_valgrind.sh b/tests/internals/test_internals_valgrind.sh
new file mode 100755
index 0000000..a84c664
--- /dev/null
+++ b/tests/internals/test_internals_valgrind.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+cd `dirname "$0"`
+valgrind --error-exitcode=100 ./test_internals