Add 'glob' functions for file searching
This commit is contained in:
parent
c9b205fbf7
commit
99d8bdcee7
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user