Add 'glob' functions for file searching

This commit is contained in:
jp9000 2014-07-27 01:29:39 -07:00
parent c9b205fbf7
commit 99d8bdcee7
3 changed files with 153 additions and 8 deletions

View File

@ -21,6 +21,7 @@
#include <stdlib.h>
#include <dlfcn.h>
#include <unistd.h>
#include <glob.h>
#include <time.h>
#if !defined(__APPLE__)
@ -28,6 +29,7 @@
#include <sys/vtimes.h>
#endif
#include "darray.h"
#include "dstr.h"
#include "platform.h"
@ -194,10 +196,19 @@ os_dir_t os_opendir(const char *path)
return dir;
}
static inline bool is_dir(const char *path)
{
struct stat stat_info;
if (stat(path, &stat_info) == 0)
return !!S_ISDIR(stat_info.st_mode);
blog(LOG_DEBUG, "is_dir: stat for %s failed, errno: %d", path, errno);
return false;
}
struct os_dirent *os_readdir(os_dir_t dir)
{
struct dstr file_path = {0};
struct stat stat_info;
if (!dir) return NULL;
@ -211,11 +222,7 @@ struct os_dirent *os_readdir(os_dir_t dir)
dstr_cat(&file_path, "/");
dstr_cat(&file_path, dir->out.d_name);
if (stat(file_path.array, &stat_info) == 0)
dir->out.directory = !!S_ISDIR(stat_info.st_mode);
else
blog(LOG_DEBUG, FILE_LINE "stat for %s failed, errno: %d",
file_path.array, errno);
dir->out.directory = is_dir(file_path.array);
dstr_free(&file_path);
@ -230,6 +237,51 @@ void os_closedir(os_dir_t dir)
}
}
struct posix_glob_info {
struct os_glob_info base;
glob_t gl;
};
int os_glob(const char *pattern, int flags, os_glob_t *pglob)
{
struct posix_glob_info pgi;
int ret = glob(pattern, 0, NULL, &pgi.gl);
if (ret == 0) {
DARRAY(struct os_globent) list;
da_init(list);
for (size_t i = 0; i < pgi.gl.gl_pathc; i++) {
struct os_globent ent = {0};
ent.path = pgi.gl.gl_pathv[i];
ent.directory = is_dir(ent.path);
da_push_back(list, &ent);
}
pgi.base.gl_pathc = list.num;
pgi.base.gl_pathv = list.array;
*pglob = bmemdup(&pgi, sizeof(pgi));
} else {
*pglob = NULL;
}
UNUSED_PARAMETER(flags);
return ret;
}
void os_globfree(os_glob_t pglob)
{
if (pglob) {
struct posix_glob_info *pgi = (struct linux_glob_info*)pglob;
globfree(&pgi->gl);
bfree(pgi->base.gl_pathv);
bfree(pgi);
}
}
int os_unlink(const char *path)
{
return unlink(path);

View File

@ -21,6 +21,7 @@
#include "base.h"
#include "platform.h"
#include "darray.h"
#include "dstr.h"
#include "../../deps/w32-pthreads/pthread.h"
@ -258,6 +259,11 @@ os_dir_t os_opendir(const char *path)
return dir;
}
static inline bool is_dir(WIN32_FIND_DATA *wfd)
{
return !!(wfd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
}
struct os_dirent *os_readdir(os_dir_t dir)
{
if (!dir)
@ -273,8 +279,7 @@ struct os_dirent *os_readdir(os_dir_t dir)
os_wcs_to_utf8(dir->wfd.cFileName, 0, dir->out.d_name,
sizeof(dir->out.d_name));
dir->out.directory =
!!(dir->wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
dir->out.directory = is_dir(&dir->wfd);
return &dir->out;
}
@ -287,6 +292,77 @@ void os_closedir(os_dir_t dir)
}
}
static void make_globent(struct os_globent *ent, WIN32_FIND_DATA *wfd,
const char *pattern)
{
struct dstr name = {0};
struct dstr path = {0};
char *slash;
dstr_from_wcs(&name, wfd->cFileName);
dstr_copy(&path, pattern);
slash = strrchr(path.array, '/');
if (slash)
dstr_resize(&path, slash + 1 - path.array);
else
dstr_free(&path);
dstr_cat_dstr(&path, &name);
ent->path = path.array;
ent->directory = is_dir(wfd);
dstr_free(&name);
}
int os_glob(const char *pattern, int flags, os_glob_t *pglob)
{
DARRAY(struct os_globent) files;
HANDLE handle;
WIN32_FIND_DATA wfd;
int ret = -1;
os_glob_t out = NULL;
wchar_t *w_path;
da_init(files);
if (os_utf8_to_wcs_ptr(pattern, 0, &w_path) > 0) {
handle = FindFirstFileW(w_path, &wfd);
if (handle != INVALID_HANDLE_VALUE) {
do {
struct os_globent ent = {0};
make_globent(&ent, &wfd, pattern);
if (ent.path)
da_push_back(files, &ent);
} while (FindNextFile(handle, &wfd));
FindClose(handle);
*pglob = bmalloc(sizeof(**pglob));
(*pglob)->gl_pathc = files.num;
(*pglob)->gl_pathv = files.array;
ret = 0;
}
bfree(w_path);
}
if (ret != 0)
*pglob = NULL;
UNUSED_PARAMETER(flags);
return ret;
}
void os_globfree(os_glob_t pglob)
{
if (pglob) {
for (size_t i = 0; i < pglob->gl_pathc; i++)
bfree(pglob->gl_pathv[i].path);
bfree(pglob->gl_pathv);
bfree(pglob);
}
}
int os_unlink(const char *path)
{
wchar_t *w_path;

View File

@ -102,6 +102,23 @@ EXPORT os_dir_t os_opendir(const char *path);
EXPORT struct os_dirent *os_readdir(os_dir_t dir);
EXPORT void os_closedir(os_dir_t dir);
struct os_globent {
char *path;
bool directory;
};
struct os_glob_info {
size_t gl_pathc;
struct os_globent *gl_pathv;
};
typedef struct os_glob_info *os_glob_t;
/* currently no flags available */
EXPORT int os_glob(const char *pattern, int flags, os_glob_t *pglob);
EXPORT void os_globfree(os_glob_t pglob);
EXPORT int os_unlink(const char *path);
#define MKDIR_EXISTS 1