moved Sys_Find* code to its own file, and recoded them for platforms
lacking good glob syscall implementation
This commit is contained in:
parent
4a9ad6b6ba
commit
09d9121083
3 changed files with 214 additions and 110 deletions
62
sys_linux.c
62
sys_linux.c
|
@ -219,68 +219,6 @@ void Sys_Strtime(char *buf)
|
|||
}
|
||||
|
||||
|
||||
// directory entry list internal data
|
||||
#include <glob.h>
|
||||
|
||||
typedef struct {
|
||||
glob_t globbuf;
|
||||
size_t count;
|
||||
} uxdirdata_t;
|
||||
|
||||
|
||||
dirdata_t *Sys_Findfirst (char *dir, char *filter, dirdata_t *dirdata)
|
||||
{
|
||||
uxdirdata_t *uxdata;
|
||||
if (dirdata && filter){
|
||||
char dirfilter[MAX_OSPATH];
|
||||
uxdata=Z_Malloc (sizeof(uxdirdata_t));
|
||||
sprintf (dirfilter,"%s/%s", dir, filter);
|
||||
glob (dirfilter,0,NULL,&uxdata->globbuf);
|
||||
if (uxdata->globbuf.gl_pathc){
|
||||
dirdata->internal=uxdata;
|
||||
strncpy (dirdata->entry,uxdata->globbuf.gl_pathv[0],sizeof(dirdata->entry));
|
||||
uxdata->count=0;
|
||||
return dirdata;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dirdata_t *Sys_Findnext (dirdata_t *dirdata)
|
||||
{
|
||||
uxdirdata_t *uxdata;
|
||||
if (dirdata){
|
||||
uxdata=dirdata->internal;
|
||||
if (uxdata) {
|
||||
uxdata->count++;
|
||||
// next entry ?
|
||||
if (uxdata->count<uxdata->globbuf.gl_pathc){
|
||||
strncpy (dirdata->entry,uxdata->globbuf.gl_pathv[uxdata->count],sizeof(dirdata->entry));
|
||||
return dirdata;
|
||||
}
|
||||
// no -> close
|
||||
globfree (&uxdata->globbuf);
|
||||
Z_Free (dirdata->internal);
|
||||
dirdata->internal=NULL;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Sys_Findclose (dirdata_t *dirdata)
|
||||
{
|
||||
uxdirdata_t *uxdata;
|
||||
if (dirdata){
|
||||
uxdata=dirdata->internal;
|
||||
if (uxdata){
|
||||
globfree (&uxdata->globbuf);
|
||||
Z_Free (uxdata);
|
||||
dirdata->internal=NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int Sys_FileOpenRead (char *path, int *handle)
|
||||
{
|
||||
int h;
|
||||
|
|
48
sys_sdl.c
48
sys_sdl.c
|
@ -301,54 +301,6 @@ void Sys_Strtime(char *buf)
|
|||
|
||||
}
|
||||
|
||||
// directory entry list internal data
|
||||
// POSIX stuff...
|
||||
// FIX-ME : is there a more portable way to do that ?
|
||||
#include <glob.h>
|
||||
|
||||
typedef struct {
|
||||
glob_t globbuf;
|
||||
size_t count;
|
||||
} uxdirdata_t;
|
||||
|
||||
static uxdirdata_t uxdata;
|
||||
|
||||
|
||||
dirdata_t *Sys_Findfirst (char *dir, char *filter, dirdata_t *dirdata)
|
||||
{
|
||||
char dirfilter[MAX_OSPATH];
|
||||
if (!filter || !dirdata)
|
||||
return NULL;
|
||||
sprintf(dirfilter,"%s/%s", dir, filter);
|
||||
glob(dirfilter,0,NULL,&uxdata.globbuf);
|
||||
if (uxdata.globbuf.gl_pathc){
|
||||
dirdata->internal=&uxdata;
|
||||
strncpy(dirdata->entry,uxdata.globbuf.gl_pathv[0],sizeof(dirdata->entry));
|
||||
uxdata.count=0;
|
||||
return dirdata;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dirdata_t *Sys_Findnext (dirdata_t *dirdata)
|
||||
{
|
||||
uxdirdata_t *uxdata;
|
||||
if (dirdata){
|
||||
uxdata=dirdata->internal;
|
||||
uxdata->count++;
|
||||
// next entry ?
|
||||
if (uxdata->count<uxdata->globbuf.gl_pathc){
|
||||
strncpy(dirdata->entry,uxdata->globbuf.gl_pathv[uxdata->count],sizeof(dirdata->entry));
|
||||
return dirdata;
|
||||
}
|
||||
// no -> close
|
||||
globfree(&uxdata->globbuf);
|
||||
dirdata->internal=NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void Sys_DebugLog(char *file, char *fmt, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
|
|
214
sys_uxfindfirst.c
Normal file
214
sys_uxfindfirst.c
Normal file
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
Copyright (C) 2003 Tenebrae Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
/*
|
||||
Sys_Find* implementation for UNIX like systems
|
||||
system conformance :
|
||||
|
||||
GLIBC < 2.2 based system
|
||||
|
||||
ISO/IEC 9945-2 (fnmatch)
|
||||
BSD 4.3 (dirent syscalls)
|
||||
|
||||
OTHER :
|
||||
|
||||
POSIX.2 (glob)
|
||||
|
||||
*/
|
||||
|
||||
/* glibc < 2.3 */
|
||||
|
||||
#include "quakedef.h"
|
||||
#include <dirent.h>
|
||||
#include <fnmatch.h>
|
||||
|
||||
#if defined(__GLIBC__) && !(__GLIBC_PREREQ(2,3))
|
||||
|
||||
#define UXDATA_GRANULARITY 10
|
||||
|
||||
typedef struct {
|
||||
size_t count;
|
||||
size_t lsize;
|
||||
char **list;
|
||||
} uxdirdata_t;
|
||||
|
||||
int uxdata_free (uxdata_t *ud)
|
||||
{
|
||||
int i;
|
||||
// elements
|
||||
for (i=0;i<ud->lsize;i++)
|
||||
Z_Free (ud->list[i]);
|
||||
// table
|
||||
if (ud->lsize % UXDATA_GRANULARITY)
|
||||
ud->lsize += UXDATA_GRANULARITY - (ud->lsize % UXDATA_GRANULARITY);
|
||||
Z_Free (ud->list);
|
||||
}
|
||||
|
||||
|
||||
int direntp_compare (struct dirent **p1, struct dirent **p2)
|
||||
{
|
||||
return strncmp ((*p1)->d_name, (*p2)->d_name, sizeof ((*p1)->d_name));
|
||||
}
|
||||
|
||||
dirdata_t *Sys_Findfirst (char *dirname, char *filter, dirdata_t *dirdata)
|
||||
{
|
||||
uxdirdata_t *uxdata;
|
||||
DIR *dir;
|
||||
struct dirent *entry;
|
||||
struct dirent **list;
|
||||
char *entry;
|
||||
|
||||
if (dirdata && filter){
|
||||
uxdata = Z_Malloc (sizeof(uxdirdata_t));
|
||||
dir = opendir (dirname);
|
||||
if (dir == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
uxdata->count = 0;
|
||||
uxdata->lsize = 10;
|
||||
uxdata->list = Z_Malloc (sizeof(struct dirent *) * (uxdata->lsize));
|
||||
do {
|
||||
entry = readdir (dir);
|
||||
// realloc entry list
|
||||
if (uxdata->lsize == uxdata->count) {
|
||||
list = Z_Malloc (sizeof(struct dirent *) * (uxdata->lsize += UXDATA_GRANULARITY));
|
||||
memcpy (list, uxdata->list, uxdata->count);
|
||||
Z_Free (uxdata->list);
|
||||
uxdata->list = list;
|
||||
}
|
||||
// check name matching filter
|
||||
int code = fnmatch (filter, dir->d_name);
|
||||
switch (code){
|
||||
case 0: /* match */
|
||||
return SYS_GLOB_MATCH;
|
||||
uxdata->list[uxdata->count] = entry;
|
||||
uxdata->count++;
|
||||
break;
|
||||
case FN_NOMATCH:
|
||||
break;
|
||||
default:
|
||||
Sys_Error ("Sys_Glob_select : fnmatch call (%d)\n",errno);
|
||||
}
|
||||
} while (entry);
|
||||
uxdata->lsize = uxdata->count;
|
||||
uxdata->count = 0;
|
||||
// sort the entry list
|
||||
qsort(uxdata->list, uxdata->lsize, sizeof(struct dirent *),direntp_compare);
|
||||
strncpy (dirdata->entry,uxdata->list[0].d_name,sizeof(dirdata->entry));
|
||||
dirdata->internal = uxdata;
|
||||
return dirdata;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dirdata_t *Sys_Findnext (dirdata_t *dirdata)
|
||||
{
|
||||
uxdirdata_t *uxdata;
|
||||
if (dirdata){
|
||||
uxdata=dirdata->internal;
|
||||
if (uxdata) {
|
||||
uxdata->count++;
|
||||
// next entry ?
|
||||
if (uxdata->count<uxdata->lsize){
|
||||
strncpy (dirdata->entry,uxdata->list[uxdata->count].d_name,sizeof(dirdata->entry));
|
||||
return dirdata;
|
||||
}
|
||||
// no -> close (just in case Findclose isn't called)
|
||||
uxdata_free (dirdata->internal);
|
||||
dirdata->internal=NULL;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Sys_Findclose (dirdata_t *dirdata)
|
||||
{
|
||||
uxdirdata_t *uxdata;
|
||||
if (dirdata){
|
||||
uxdata=dirdata->internal;
|
||||
if (uxdata){
|
||||
uxdata_free (uxdata);
|
||||
dirdata->internal=NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <glob.h>
|
||||
|
||||
typedef struct {
|
||||
glob_t globbuf;
|
||||
size_t count;
|
||||
} uxdirdata_t;
|
||||
|
||||
|
||||
dirdata_t *Sys_Findfirst (char *dir, char *filter, dirdata_t *dirdata)
|
||||
{
|
||||
uxdirdata_t *uxdata;
|
||||
if (dirdata && filter){
|
||||
char dirfilter[MAX_OSPATH];
|
||||
uxdata=Z_Malloc (sizeof(uxdirdata_t));
|
||||
sprintf (dirfilter,"%s/%s", dir, filter);
|
||||
glob (dirfilter,0,NULL,&uxdata->globbuf);
|
||||
if (uxdata->globbuf.gl_pathc){
|
||||
dirdata->internal=uxdata;
|
||||
strncpy (dirdata->entry,uxdata->globbuf.gl_pathv[0],sizeof(dirdata->entry));
|
||||
uxdata->count=0;
|
||||
return dirdata;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dirdata_t *Sys_Findnext (dirdata_t *dirdata)
|
||||
{
|
||||
uxdirdata_t *uxdata;
|
||||
if (dirdata){
|
||||
uxdata=dirdata->internal;
|
||||
if (uxdata) {
|
||||
uxdata->count++;
|
||||
// next entry ?
|
||||
if (uxdata->count<uxdata->globbuf.gl_pathc){
|
||||
strncpy (dirdata->entry,uxdata->globbuf.gl_pathv[uxdata->count],sizeof(dirdata->entry));
|
||||
return dirdata;
|
||||
}
|
||||
// no -> close (just in case Findclose isn't called)
|
||||
globfree (&uxdata->globbuf);
|
||||
Z_Free (dirdata->internal);
|
||||
dirdata->internal=NULL;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Sys_Findclose (dirdata_t *dirdata)
|
||||
{
|
||||
uxdirdata_t *uxdata;
|
||||
if (dirdata){
|
||||
uxdata=dirdata->internal;
|
||||
if (uxdata){
|
||||
globfree (&uxdata->globbuf);
|
||||
Z_Free (uxdata);
|
||||
dirdata->internal=NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue