Permalink
Browse files

Add zt_path_exists and zt_find_basedir

zt_path_exists just saves local allocation of a stat call
zt_find_basedir searches for the longest matching real path containing a
trigger file or directory name. ie find the first 'dot' directory in
a path shortening the path one step for each check.
  • Loading branch information...
1 parent c809e26 commit 3295ecec92edc1ed80318ab7ebf4a038344ea575 @zerotao committed Feb 16, 2012
Showing with 61 additions and 3 deletions.
  1. +54 −0 src/zt_path.c
  2. +2 −2 src/zt_path.h
  3. +5 −1 tests/path_test.c
View
@@ -59,3 +59,57 @@ zt_mkdir(char * path, mode_t mode, zt_mkdir_flags flags) {
return 0;
} /* zt_mkdir */
+
+/* simple utility to remove the need for the local function to
+ * allocate a stat struct when existance is the only thing that matters
+ */
+int
+zt_path_exists(const char * path) {
+ struct stat sbuf;
+
+ errno = 0;
+ if (stat(path, &sbuf) == 0) {
+ return 0;
+ }
+ return -1;
+}
+
+/* find the longest matching directory containing a specific file or directory.
+ * eg. the path /home/jshiffer/test/env and the trigger .ssh
+ * would return /home/jshiffer unless there was a .ssh in a higher directory (env or test).
+ */
+char *zt_find_basedir(const char * path, const char * trigger) {
+ struct stat sbuf;
+ size_t len;
+ ssize_t offt;
+ char * result = NULL;
+ char cpath[PATH_MAX + 1];
+ char lpath[PATH_MAX + 1];
+
+ len = strlen(path);
+ memset(lpath, 0, sizeof(lpath));
+ memcpy(lpath, path, MIN(len, sizeof(cpath)));
+
+ do {
+ memset(cpath, 0, sizeof(cpath));
+ snprintf(cpath, sizeof(cpath), "%s%s%s", lpath, PATH_SEPERATOR, trigger);
+ errno = 0;
+ if (stat(cpath, &sbuf) == 0) {
+ /* found it */
+ len = strlen(lpath) + strlen(PATH_SEPERATOR) + 1;
+ result = zt_callocs(sizeof(char), len);
+ snprintf(result, len, "%s%s", lpath, PATH_SEPERATOR);
+ break;
+ }
+
+ if ((strlen(lpath) == 0) ||
+ (offt = zt_cstr_rfind(lpath, 0, -1, PATH_SEPERATOR)) == -1) {
+ break;
+ }
+ lpath[offt] = '\0';
+ } while (1);
+
+ return result;
+} /* zt_find_basedir */
+
+
View
@@ -32,8 +32,8 @@ typedef enum {
}zt_mkdir_flags;
int zt_mkdir(char * path, mode_t mode, zt_mkdir_flags flags);
-
-
+int zt_path_exists(const char * path);
+char *zt_find_basedir(const char * path, const char * trigger);
END_C_DECLS
#endif /* _ZT_PATH_ */
View
@@ -19,11 +19,15 @@ basic_tests(struct zt_unit_test *test, void *data UNUSED)
{
struct stat stat_buf;
+ ZT_UNIT_ASSERT(test, zt_path_exists("foo/bar/baz") == -1);
ZT_UNIT_ASSERT(test, zt_mkdir("foo/bar/baz", 0777, zt_mkdir_create_parent) == 0);
ZT_UNIT_ASSERT(test, stat("foo/bar/baz", &stat_buf) == 0);
-
+ ZT_UNIT_ASSERT(test, zt_path_exists("foo/bar/baz") == 0);
ZT_UNIT_ASSERT(test, zt_mkdir("foo/bar/baz", 0777, zt_mkdir_create_parent) == 0);
+ ZT_UNIT_ASSERT(test, strcmp(zt_find_basedir("foo/bar/baz/spin", "baz"), "foo/bar/") == 0);
+ ZT_UNIT_ASSERT(test, zt_find_basedir("foo/bar/baz/spin", ".baz") == NULL);
+
rmdir("foo/bar/baz");
rmdir("foo/bar");
rmdir("foo");

0 comments on commit 3295ece

Please sign in to comment.