mirror of
https://git.proxmox.com/git/libgit2
synced 2025-06-20 07:52:43 +00:00
Add a dirent walker to the fileops API
Since at least MS have something like GetFirstDirEnt() and GetNextDirEnt() (presumably with superior performance), we can let MS hackers add support for a dirent walker using that API instead, while we stick with the posix-style readdir() calls. Signed-off-by: Andreas Ericsson <ae@op5.se> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
This commit is contained in:
parent
4188d28f1c
commit
ea790f337b
@ -134,3 +134,65 @@ int gitfo_close_cached(gitfo_cache *ioc)
|
|||||||
|
|
||||||
return gitfo_close(fd);
|
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)
|
||||||
|
{
|
||||||
|
char path[PATH_MAX];
|
||||||
|
size_t wd_len;
|
||||||
|
DIR *dir;
|
||||||
|
struct dirent *de;
|
||||||
|
|
||||||
|
if (!wd)
|
||||||
|
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);
|
||||||
|
if (!dir)
|
||||||
|
return GIT_ERROR;
|
||||||
|
|
||||||
|
while ((de = readdir(dir))) {
|
||||||
|
size_t de_len;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
/* always skip '.' and '..' */
|
||||||
|
if (de->d_name[0] == '.') {
|
||||||
|
if (de->d_name[1] == '\0')
|
||||||
|
continue;
|
||||||
|
if (de->d_name[1] == '.' && de->d_name[2] == '\0')
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
de_len = strlen(de->d_name);
|
||||||
|
if (sizeof(path) < wd_len + de_len + 1) {
|
||||||
|
closedir(dir);
|
||||||
|
return GIT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(path + wd_len, de->d_name);
|
||||||
|
result = fn(arg, path);
|
||||||
|
if (result < 0) {
|
||||||
|
closedir(dir);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (result > 0) {
|
||||||
|
closedir(dir);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
|
return GIT_SUCCESS;
|
||||||
|
}
|
||||||
|
@ -17,7 +17,9 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <dirent.h>
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
|
#include "git/fileops.h"
|
||||||
|
|
||||||
typedef int git_file;
|
typedef int git_file;
|
||||||
typedef struct stat gitfo_statbuf;
|
typedef struct stat gitfo_statbuf;
|
||||||
|
32
src/git/fileops.h
Normal file
32
src/git/fileops.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#ifndef INCLUDE_git_fileops_h__
|
||||||
|
#define INCLUDE_git_fileops_h__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file git/fileops.h
|
||||||
|
* @brief Git platform agnostic filesystem operations
|
||||||
|
* @defgroup Git gitfiles
|
||||||
|
* @ingroup Git
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
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__ */
|
Loading…
Reference in New Issue
Block a user