summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/fileops.c24
-rw-r--r--src/fileops.h20
-rw-r--r--src/git/fileops.h33
-rw-r--r--tests/t0020-dirent.c48
4 files changed, 75 insertions, 50 deletions
diff --git a/src/fileops.c b/src/fileops.c
index 1dd35dc8e..0867c7b57 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -187,31 +187,25 @@ int gitfo_close_cached(gitfo_cache *ioc)
return gitfo_close(fd);
}
-/**
- * Walk a directory and run 'fn' for each encountered entry
- * (except '.' and '..').
- */
-int git_foreach_dirent(const char *wd, int (*fn)(void *, const char *), void *arg)
+int gitfo_dirent(
+ char *path,
+ size_t path_sz,
+ int (*fn)(void *, char *),
+ void *arg)
{
- char path[GIT_PATH_MAX];
- size_t wd_len;
+ size_t wd_len = strlen(path);
DIR *dir;
struct dirent *de;
- if (!wd)
+ if (!wd_len || path_sz < wd_len + 2)
return GIT_ERROR;
- wd_len = strlen(wd);
- if (!wd_len || sizeof(path) < wd_len + 2)
- return GIT_ERROR;
-
- strcpy(path, wd);
while (path[wd_len - 1] == '/')
wd_len--;
path[wd_len++] = '/';
path[wd_len] = '\0';
- dir = opendir(wd);
+ dir = opendir(path);
if (!dir)
return git_os_error();
@@ -228,7 +222,7 @@ int git_foreach_dirent(const char *wd, int (*fn)(void *, const char *), void *ar
}
de_len = strlen(de->d_name);
- if (sizeof(path) < wd_len + de_len + 1) {
+ if (path_sz < wd_len + de_len + 1) {
closedir(dir);
return GIT_ERROR;
}
diff --git a/src/fileops.h b/src/fileops.h
index 336ab27f4..86726c5a8 100644
--- a/src/fileops.h
+++ b/src/fileops.h
@@ -9,6 +9,7 @@
/** Force 64 bit off_t size on POSIX. */
#define _FILE_OFFSET_BITS 64
+#include "common.h"
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
@@ -18,8 +19,6 @@
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
-#include "errors.h"
-#include "git/fileops.h"
#define GITFO_BUF_INIT {NULL, 0}
@@ -43,6 +42,23 @@ extern off_t gitfo_size(git_file fd);
extern int gitfo_read_file(gitfo_buf *obj, const char *path);
extern void gitfo_free_buf(gitfo_buf *obj);
+/**
+ * Walk each directory entry, except '.' and '..', calling fn(state).
+ *
+ * @param pathbuf buffer the function reads the initial directory
+ * path from, and updates with each successive entry's name.
+ * @param pathmax maximum allocation of pathbuf.
+ * @param fn function to invoke with each entry. The first arg is
+ * the input state and the second arg is pathbuf. The function
+ * may modify the pathbuf, but only by appending new text.
+ * @param state to pass to fn as the first arg.
+ */
+extern int gitfo_dirent(
+ char *pathbuf,
+ size_t pathmax,
+ int (*fn)(void *, char *),
+ void *state);
+
extern gitfo_cache *gitfo_enable_caching(git_file fd, size_t cache_size);
extern int gitfo_write_cached(gitfo_cache *ioc, void *buf, size_t len);
extern int gitfo_flush_cached(gitfo_cache *ioc);
diff --git a/src/git/fileops.h b/src/git/fileops.h
deleted file mode 100644
index 657cec148..000000000
--- a/src/git/fileops.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef INCLUDE_git_fileops_h__
-#define INCLUDE_git_fileops_h__
-
-#include "common.h"
-
-/**
- * @file git/fileops.h
- * @brief Git platform agnostic filesystem operations
- * @defgroup git_fileops Git filesystem operations
- * @ingroup Git
- * @{
- */
-GIT_BEGIN_DECL
-
-/**
- * For each directory entry (except "." and ".."), run the function
- * "fn", passing it "arg" as its first argument and the path to
- * the entry as the second argument.
- * @param dir The directory to walk
- * @param fn The callback function to run for each entry in *dir.
- * "fn" may return >0 to signal "I'm done. Stop parsing and
- * return successfully" or <0 to signal an error. All non-zero
- * return codes cause directory traversal to stop.
- * @param arg The first argument that will be passed to 'fn'
- * @return GIT_SUCCESS if all entries were successfully traversed,
- * otherwise the result of fn.
- */
-GIT_EXTERN(int) git_foreach_dirent(const char *dir,
- int (*fn)(void *, const char *), void *arg);
-
-/** @} */
-GIT_END_DECL
-#endif /* INCLUDE_git_fileops_h__ */
diff --git a/tests/t0020-dirent.c b/tests/t0020-dirent.c
new file mode 100644
index 000000000..4c6545319
--- /dev/null
+++ b/tests/t0020-dirent.c
@@ -0,0 +1,48 @@
+#include "test_lib.h"
+#include "fileops.h"
+
+static char path_buffer[GIT_PATH_MAX];
+static int state_loc;
+static const char* names[] = {
+ "./a",
+ "./asdf",
+ "./pack-foo.pack",
+ NULL
+};
+
+static int one_entry(void *state, char *path)
+{
+ const char **c;
+
+ must_be_true(state == &state_loc);
+ must_be_true(path == path_buffer);
+ for (c = names; *c; c++) {
+ if (!strcmp(*c, path)) {
+ *c = "";
+ return 0;
+ }
+ }
+ test_die("unexpected path \"%s\"", path);
+}
+
+BEGIN_TEST(setup)
+ const char **c;
+ for (c = names; *c; c++) {
+ git_file fd = gitfo_creat(*c, 0600);
+ must_be_true(fd >= 0);
+ gitfo_close(fd);
+ }
+END_TEST
+
+BEGIN_TEST(direent_walk)
+ const char **c;
+
+ strcpy(path_buffer, ".");
+ must_pass(gitfo_dirent(path_buffer,
+ sizeof(path_buffer),
+ one_entry,
+ &state_loc));
+
+ for (c = names; *c; c++)
+ must_pass(strcmp("", *c));
+END_TEST