summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorStef Walter <stef@thewalter.net>2013-06-14 12:53:15 +0200
committerStef Walter <stef@thewalter.net>2013-06-14 12:59:29 +0200
commit045df29606ea9853b4fc8bdba062a5e4a7a5be95 (patch)
treeef19ba4bb04471cf3c42d6bd3d1f4c11a1d4d754 /common
parent8c6dd48789bdaf2a3dc800df7ed3416ddc3b7e1f (diff)
path: Add p11_path_parent() function
Gets the parent element of the path, removing the last component. Handles trailing and duplicate path separators correctly.
Diffstat (limited to 'common')
-rw-r--r--common/path.c36
-rw-r--r--common/path.h2
-rw-r--r--common/tests/test-path.c17
3 files changed, 55 insertions, 0 deletions
diff --git a/common/path.c b/common/path.c
index d3d881d..a2ba6ec 100644
--- a/common/path.c
+++ b/common/path.c
@@ -262,3 +262,39 @@ p11_path_build (const char *path,
built[at] = '\0';
return built;
}
+
+char *
+p11_path_parent (const char *path)
+{
+ const char *e;
+ char *parent;
+ bool had = false;
+
+ return_val_if_fail (path != NULL, NULL);
+
+ /* Find the end of the last component */
+ e = path + strlen (path);
+ while (e != path && is_path_component_or_null (*e))
+ e--;
+
+ /* Find the beginning of the last component */
+ while (e != path && !is_path_component_or_null (*e)) {
+ had = true;
+ e--;
+ }
+
+ /* Find the end of the last component */
+ while (e != path && is_path_component_or_null (*e))
+ e--;
+
+ if (e == path) {
+ if (!had)
+ return NULL;
+ parent = strdup ("/");
+ } else {
+ parent = strndup (path, (e - path) + 1);
+ }
+
+ return_val_if_fail (parent != NULL, NULL);
+ return parent;
+}
diff --git a/common/path.h b/common/path.h
index a518008..1fce607 100644
--- a/common/path.h
+++ b/common/path.h
@@ -59,4 +59,6 @@ char * p11_path_build (const char *path,
bool p11_path_absolute (const char *path);
+char * p11_path_parent (const char *path);
+
#endif /* P11_PATH_H__ */
diff --git a/common/tests/test-path.c b/common/tests/test-path.c
index f1bccbd..ec2c200 100644
--- a/common/tests/test-path.c
+++ b/common/tests/test-path.c
@@ -173,6 +173,22 @@ test_absolute (void)
#endif
}
+static void
+test_parent (void)
+{
+ check_equals_and_free ("/", p11_path_parent ("/root"));
+ check_equals_and_free ("/", p11_path_parent ("/root/"));
+ check_equals_and_free ("/", p11_path_parent ("/root//"));
+ check_equals_and_free ("/root", p11_path_parent ("/root/second"));
+ check_equals_and_free ("/root", p11_path_parent ("/root//second"));
+ check_equals_and_free ("/root", p11_path_parent ("/root//second//"));
+ check_equals_and_free ("/root", p11_path_parent ("/root///second"));
+ check_equals_and_free ("/root/second", p11_path_parent ("/root/second/test.file"));
+ assert_ptr_eq (NULL, p11_path_parent ("/"));
+ assert_ptr_eq (NULL, p11_path_parent ("//"));
+ assert_ptr_eq (NULL, p11_path_parent (""));
+}
+
int
main (int argc,
char *argv[])
@@ -181,6 +197,7 @@ main (int argc,
p11_test (test_build, "/path/build");
p11_test (test_expand, "/path/expand");
p11_test (test_absolute, "/path/absolute");
+ p11_test (test_parent, "/path/parent");
return p11_test_run (argc, argv);
}