/* This is part of ODS2 written by Paul Nankervis, * email address: Paulnank@au1.ibm.com * ODS2 is distributed freely for all members of the * VMS community to use. However all derived works * must maintain comments in their source to acknowledge * the contributions of the original author and * subsequent contributors. This is free software; no * warranty is offered, and while we believe it to be useful, * you use it at your own risk. */ /* Copyright (C) 2016 Timothe Litt, litt at acm dot org. */ #include #include #include #include #include "winfile.h" typedef struct globlist_ { struct globlist_ *next; char path[1]; } globlist_; /******************************************************************* addfile() */ static int addfile( int flags, glob_t *pglob, const char *path ) { size_t n, ofs; char ** nl; globlist_ *fp; ofs = pglob->gl_pathc; if( flags & GLOB_DOOFFS ) ofs += pglob->gl_offs; if( (nl = (char **)realloc( pglob->gl_pathv, (ofs + 2) * sizeof( char **) )) == NULL ) { return GLOB_NOSPACE; } pglob->gl_pathv = nl; n = offsetof( globlist_, path ) + strlen( path ) + 1; if( (fp = malloc( n )) == NULL ) return GLOB_NOSPACE; memcpy( fp->path, path, n - offsetof( globlist_, path ) ); pglob->gl_pathv[ofs++] = fp->path; pglob->gl_pathv[ofs] = NULL; ++pglob->gl_pathc; fp->next = pglob->list_; pglob->list_ = fp; return 0; } /******************************************************************* globfree() */ void globfree( glob_t *pglob ) { globlist_ *fp; while( (fp = pglob->list_) != NULL ) { pglob->list_ = fp->next; free( fp ); } free( pglob->gl_pathv ); pglob->gl_pathv = NULL; pglob->gl_pathc = 0; } /******************************************************************* cmpglb() */ static int cmpglb( const void *p1, const void *p2 ) { return _stricmp( *((const char *const *)p1), *((const char *const *)p2) ); } /******************************************************************* glob() */ int glob( const char *pattern, int flags, int (*errfunc)( const char *epath, int eerrno ), glob_t *pglob ) { HANDLE hfindfile; WIN32_FIND_DATAA finddata; int err; size_t found; if( errfunc != NULL ) abort(); found = err = 0; if( !(flags & GLOB_APPEND) ) { pglob->gl_pathc = 0; pglob->list_ = NULL; pglob->gl_pathv = NULL; } hfindfile = FindFirstFileA( pattern, &finddata ); if( hfindfile == INVALID_HANDLE_VALUE ) { if( flags & GLOB_NOCHECK ) { err = addfile( flags, pglob, pattern ); found ++; } } else { do { err = addfile( flags, pglob, finddata.cFileName ); found++; } while( !err && FindNextFile( hfindfile, &finddata ) ); FindClose( hfindfile ); } if( !found ) err = GLOB_NOMATCH; if( err ) { globfree( pglob ); errno = err; } else { if( !(flags & GLOB_NOSORT) ) { qsort( pglob->gl_pathv, pglob->gl_pathc, sizeof( char **), cmpglb ); } } return err; } /******************************************************************* strlcpy() */ static size_t strlcpy( char *dst, const char *src, size_t size ) { size_t srclen; size--; srclen = strlen( src ); if( srclen > size ) srclen = size; memcpy( dst, src, srclen ); dst[srclen] = '\0'; return (srclen); } /******************************************************************* winbasename() */ char *winbasename( char *path ) { static char buf[MAX_PATH + 1]; char *p, *d; if( path == NULL || !*path ) return "."; strlcpy( buf, path, sizeof( buf ) ); for( d = buf; *d && *d != ':' && *d != '\\'; d++ ) ; if( !*d ) return buf; if( *d == ':' ) { d++; if( !strcmp( d, "." ) ) return buf; } for( p = d + strlen( d ) - 1; p > d; p-- ) if( *p == '\\' ) *p = '\0'; else break; if( p <= d ) { if( !*++d ) return "\\"; return d; } if( (p = strrchr( d, '\\' )) == NULL ) { return d; } return ++p; }