os/ossrv/genericopenlibs/openenvcore/libc/src/glob.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// glob.c
sl@0
     2
sl@0
     3
sl@0
     4
/*
sl@0
     5
 * Copyright (c) 1989, 1993
sl@0
     6
 *	The Regents of the University of California.  All rights reserved.
sl@0
     7
 *
sl@0
     8
 * This code is derived from software contributed to Berkeley by
sl@0
     9
 * Guido van Rossum.
sl@0
    10
 *
sl@0
    11
 * Redistribution and use in source and binary forms, with or without
sl@0
    12
 * modification, are permitted provided that the following conditions
sl@0
    13
 * are met:
sl@0
    14
 * 1. Redistributions of source code must retain the above copyright
sl@0
    15
 *    notice, this list of conditions and the following disclaimer.
sl@0
    16
 * 2. Redistributions in binary form must reproduce the above copyright
sl@0
    17
 *    notice, this list of conditions and the following disclaimer in the
sl@0
    18
 *    documentation and/or other materials provided with the distribution.
sl@0
    19
 * 4. Neither the name of the University nor the names of its contributors
sl@0
    20
 *    may be used to endorse or promote products derived from this software
sl@0
    21
 *    without specific prior written permission.
sl@0
    22
 *
sl@0
    23
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
sl@0
    24
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
sl@0
    25
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
sl@0
    26
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
sl@0
    27
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
sl@0
    28
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
sl@0
    29
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
sl@0
    30
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
sl@0
    31
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
sl@0
    32
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
sl@0
    33
 * SUCH DAMAGE.
sl@0
    34
 */
sl@0
    35
sl@0
    36
/* Portions Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).All rights reserved.  */
sl@0
    37
 
sl@0
    38
#if defined(LIBC_SCCS) && !defined(lint)
sl@0
    39
static char sccsid[] = "@(#)glob.c	8.3 (Berkeley) 10/13/93";
sl@0
    40
#endif /* LIBC_SCCS and not lint */
sl@0
    41
#include <sys/cdefs.h>
sl@0
    42
__FBSDID("$FreeBSD: src/lib/libc/gen/glob.c,v 1.23 2005/09/14 19:14:32 ache Exp $");
sl@0
    43
sl@0
    44
sl@0
    45
/*
sl@0
    46
 * glob(3) -- a superset of the one defined in POSIX 1003.2.
sl@0
    47
 *
sl@0
    48
 * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
sl@0
    49
 *
sl@0
    50
 * Optional extra services, controlled by flags not defined by POSIX:
sl@0
    51
 *
sl@0
    52
 * GLOB_QUOTE:
sl@0
    53
 *	Escaping convention: \ inhibits any special meaning the following
sl@0
    54
 *	character might have (except \ at end of string is retained).
sl@0
    55
 * GLOB_MAGCHAR:
sl@0
    56
 *	Set in gl_flags if pattern contained a globbing character.
sl@0
    57
 * GLOB_NOMAGIC:
sl@0
    58
 *	Same as GLOB_NOCHECK, but it will only append pattern if it did
sl@0
    59
 *	not contain any magic characters.  [Used in csh style globbing]
sl@0
    60
 * GLOB_ALTDIRFUNC:
sl@0
    61
 *	Use alternately specified directory access functions.
sl@0
    62
 * GLOB_TILDE:
sl@0
    63
 *	expand ~user/foo to the /home/dir/of/user/foo
sl@0
    64
 * GLOB_BRACE:
sl@0
    65
 *	expand {1,2}{a,b} to 1a 1b 2a 2b
sl@0
    66
 * gl_matchc:
sl@0
    67
 *	Number of matches in the current invocation of glob.
sl@0
    68
 */
sl@0
    69
sl@0
    70
/*
sl@0
    71
 * Some notes on multibyte character support:
sl@0
    72
 * 1. Patterns with illegal byte sequences match nothing - even if
sl@0
    73
 *    GLOB_NOCHECK is specified.
sl@0
    74
 * 2. Illegal byte sequences in filenames are handled by treating them as
sl@0
    75
 *    single-byte characters with a value of the first byte of the sequence
sl@0
    76
 *    cast to wchar_t.
sl@0
    77
 * 3. State-dependent encodings are not currently supported.
sl@0
    78
 */
sl@0
    79
sl@0
    80
#include <sys/param.h>
sl@0
    81
#include <sys/stat.h>
sl@0
    82
sl@0
    83
#include <ctype.h>
sl@0
    84
#include <dirent.h>
sl@0
    85
#include <errno.h>
sl@0
    86
#include <glob.h>
sl@0
    87
#include <limits.h>
sl@0
    88
#include <pwd.h>
sl@0
    89
#include <stdint.h>
sl@0
    90
#include <stdio.h>
sl@0
    91
#include <stdlib.h>
sl@0
    92
#include <string.h>
sl@0
    93
#include <unistd.h>
sl@0
    94
#include <wchar.h>
sl@0
    95
sl@0
    96
#include "libc_collate.h"
sl@0
    97
sl@0
    98
sl@0
    99
#if (defined(__SYMBIAN32__) && (defined(__WINSCW__) || defined(__WINS__)))
sl@0
   100
sl@0
   101
#include "libc_wsd_defs.h"
sl@0
   102
#include "reent.h"
sl@0
   103
sl@0
   104
#endif	//defined(__SYMBIAN32__) && (defined(__WINSCW__) || defined(__WINS__))
sl@0
   105
sl@0
   106
#ifdef __cplusplus
sl@0
   107
extern "C" {
sl@0
   108
#endif
sl@0
   109
#ifdef __SYMBIAN32__
sl@0
   110
extern char LC_COLLATE_LocaleName[30];
sl@0
   111
#ifdef EMULATOR
sl@0
   112
char *GET_WSD_VAR_NAME(LC_COLLATE_LocaleName, g)();
sl@0
   113
#define LC_COLLATE_LocaleName (GET_WSD_VAR_NAME(LC_COLLATE_LocaleName, g)())
sl@0
   114
#endif 	//EMULATOR
sl@0
   115
sl@0
   116
//Declared and defined from libc_collate.h and vfscanf.c
sl@0
   117
extern int __collate_range_cmp(int , int );
sl@0
   118
#endif	//__SYMBIAN32__
sl@0
   119
sl@0
   120
 
sl@0
   121
sl@0
   122
#define	DOLLAR		'$'
sl@0
   123
#define	DOT			'.'
sl@0
   124
#define	EOS			'\0'
sl@0
   125
#define	LBRACKET	'['
sl@0
   126
#define	NOT			'!'
sl@0
   127
#define	QUESTION	'?'
sl@0
   128
#define	QUOTE		'\\'
sl@0
   129
#define	RANGE		'-'
sl@0
   130
#define	RBRACKET	']'
sl@0
   131
sl@0
   132
// For Symbian Environment the path is specified using the '\'
sl@0
   133
// unlike in the Linux where the path seprator '/' is used.
sl@0
   134
// Since '\\' as path seprator is used the escaping flag 
sl@0
   135
// 'QUOTE' cannot be used here.
sl@0
   136
// For e.g. ..\\test\\hollows\\*
sl@0
   137
sl@0
   138
#ifdef __SYMBIAN32__
sl@0
   139
	#define	SEP		'\\'
sl@0
   140
#else
sl@0
   141
	#define SEP		'/'
sl@0
   142
#endif //__SYMBIAN32__
sl@0
   143
sl@0
   144
sl@0
   145
#define	STAR		'*'
sl@0
   146
#define	TILDE		'~'
sl@0
   147
#define	UNDERSCORE	'_'
sl@0
   148
#define	LBRACE		'{'
sl@0
   149
#define	RBRACE		'}'
sl@0
   150
#define	SLASH		'/'
sl@0
   151
#define	COMMA		','
sl@0
   152
sl@0
   153
sl@0
   154
#ifndef __SYMBIAN32__
sl@0
   155
sl@0
   156
#ifndef DEBUG
sl@0
   157
sl@0
   158
#define	M_QUOTE		0x8000000000ULL
sl@0
   159
#define	M_PROTECT	0x4000000000ULL
sl@0
   160
#define	M_MASK		0xffffffffffULL
sl@0
   161
#define	M_CHAR		0x00ffffffffULL
sl@0
   162
sl@0
   163
typedef uint_fast64_t Char;
sl@0
   164
sl@0
   165
#else		//DEBUG
sl@0
   166
sl@0
   167
#define	M_QUOTE		0x80
sl@0
   168
#define	M_PROTECT	0x40
sl@0
   169
#define	M_MASK		0xff
sl@0
   170
#define	M_CHAR		0x7f
sl@0
   171
sl@0
   172
typedef char Char;
sl@0
   173
sl@0
   174
#endif 		//DEBUG
sl@0
   175
sl@0
   176
#else    	//__SYMBIAN32__
sl@0
   177
sl@0
   178
#define	M_QUOTE		0x80
sl@0
   179
#define	M_PROTECT	0x40
sl@0
   180
#define	M_MASK		0xff
sl@0
   181
#define	M_CHAR		0x7f
sl@0
   182
sl@0
   183
typedef unsigned char Char;
sl@0
   184
sl@0
   185
#endif		//__SYMBIAN32__
sl@0
   186
sl@0
   187
#define	CHAR(c)		((Char)((c)&M_CHAR))
sl@0
   188
#define	META(c)		((Char)((c)|M_QUOTE))
sl@0
   189
#define	M_ALL		META('*')
sl@0
   190
#define	M_END		META(']')
sl@0
   191
#define	M_NOT		META('!')
sl@0
   192
#define	M_ONE		META('?')
sl@0
   193
#define	M_RNG		META('-')
sl@0
   194
#define	M_SET		META('[')
sl@0
   195
#define	ismeta(c)	(((c)&M_QUOTE) != 0)
sl@0
   196
sl@0
   197
sl@0
   198
static int	 compare(const void *, const void *);
sl@0
   199
static int	 g_Ctoc(const Char *, char *, u_int);
sl@0
   200
static int	 g_lstat(Char *, struct stat *, glob_t *);
sl@0
   201
static DIR	*g_opendir(Char *, glob_t *);
sl@0
   202
static Char	*g_strchr(Char *, wchar_t);
sl@0
   203
#ifdef notdef
sl@0
   204
static Char	*g_strcat(Char *, const Char *);
sl@0
   205
#endif
sl@0
   206
static int	 g_stat(Char *, struct stat *, glob_t *);
sl@0
   207
static int	 glob0(const Char *, glob_t *, int *);
sl@0
   208
static int	 glob1(Char *, glob_t *, int *);
sl@0
   209
static int	 glob2(Char *, Char *, Char *, Char *, glob_t *, int *);
sl@0
   210
static int	 glob3(Char *, Char *, Char *, Char *, Char *, glob_t *, int *);
sl@0
   211
static int	 globextend(const Char *, glob_t *, int *);
sl@0
   212
static const Char *	
sl@0
   213
		 globtilde(const Char *, Char *, size_t, glob_t *);
sl@0
   214
static int	 globexp1(const Char *, glob_t *, int *);
sl@0
   215
static int	 globexp2(const Char *, const Char *, glob_t *, int *, int *);
sl@0
   216
static int	 match(Char *, Char *, Char *);
sl@0
   217
#ifdef DEBUG
sl@0
   218
static void	 qprintf(const char *, Char *);
sl@0
   219
#endif
sl@0
   220
sl@0
   221
// EXTERNAL FUNCTION PROTOTYPES
sl@0
   222
sl@0
   223
sl@0
   224
//--------------------------------------------------------------------------------------------
sl@0
   225
//Function Name : int glob(glob(const char *, int flags, int (*)(const char *, int), glob_t *)
sl@0
   226
//Description   : It takes pattern to be searched, flags and the structure of the type glob_t.
sl@0
   227
//				  It can optionally also take  If errfunc is not NULL, it will be called in 
sl@0
   228
//				  error with the arguments epath,  a  pointer  to  the case of an path which 
sl@0
   229
//			      failed
sl@0
   230
//				  
sl@0
   231
//Return Value  : If successful returns the pathnames of the searched pattern contained 
sl@0
   232
//				  in the glob_t structure member reference pointer gl_pathv. In case
sl@0
   233
//				  failure, gl_pathv is NULL.
sl@0
   234
//----------------------------------------------------------------------------------------------
sl@0
   235
sl@0
   236
EXPORT_C int
sl@0
   237
glob(pattern, flags, errfunc, pglob)
sl@0
   238
	const char *pattern;
sl@0
   239
	int flags, (*errfunc)(const char *, int);
sl@0
   240
	glob_t *pglob;
sl@0
   241
{
sl@0
   242
	const u_char *patnext;
sl@0
   243
	int limit;
sl@0
   244
	Char *bufnext, *bufend, patbuf[MAXPATHLEN], prot;
sl@0
   245
	mbstate_t mbs;
sl@0
   246
	wchar_t wc;
sl@0
   247
	size_t clen;
sl@0
   248
sl@0
   249
	patnext = (u_char *) pattern;
sl@0
   250
	
sl@0
   251
	// Since we are using '\\' as path seprator, this flag needs to be mentioned
sl@0
   252
	// by default in Symbian. Instead this can be hardcoded here.
sl@0
   253
	
sl@0
   254
	#ifdef __SYMBIAN32__
sl@0
   255
		flags = flags | GLOB_NOESCAPE;
sl@0
   256
	#endif
sl@0
   257
sl@0
   258
	if (!(flags & GLOB_APPEND)) {
sl@0
   259
		pglob->gl_pathc = 0;
sl@0
   260
		pglob->gl_pathv = NULL;
sl@0
   261
		if (!(flags & GLOB_DOOFFS))
sl@0
   262
			pglob->gl_offs = 0;
sl@0
   263
	}
sl@0
   264
	if (flags & GLOB_LIMIT) {
sl@0
   265
		limit = pglob->gl_matchc;
sl@0
   266
		if (limit == 0)
sl@0
   267
			limit = ARG_MAX;
sl@0
   268
	} else
sl@0
   269
		limit = 0;
sl@0
   270
	pglob->gl_flags = flags & ~GLOB_MAGCHAR;
sl@0
   271
	pglob->gl_errfunc = errfunc;
sl@0
   272
	pglob->gl_matchc = 0;
sl@0
   273
sl@0
   274
	bufnext = patbuf;
sl@0
   275
	bufend = bufnext + MAXPATHLEN - 1;
sl@0
   276
	if (flags & GLOB_NOESCAPE) {
sl@0
   277
		memset(&mbs, 0, sizeof(mbs));
sl@0
   278
		while (bufend - bufnext >= MB_CUR_MAX) {
sl@0
   279
			clen = mbrtowc(&wc,(char*)patnext, MB_LEN_MAX, &mbs);
sl@0
   280
			if (clen == (size_t)-1 || clen == (size_t)-2)
sl@0
   281
				return (GLOB_NOMATCH);
sl@0
   282
			else if (clen == 0)
sl@0
   283
				break;
sl@0
   284
			*bufnext++ = wc;
sl@0
   285
			patnext += clen;
sl@0
   286
		}
sl@0
   287
	} else {
sl@0
   288
		/* Protect the quoted characters. */
sl@0
   289
		memset(&mbs, 0, sizeof(mbs));
sl@0
   290
		while (bufend - bufnext >= MB_CUR_MAX) {
sl@0
   291
			if (*patnext == QUOTE) {
sl@0
   292
				if (*++patnext == EOS) {
sl@0
   293
					*bufnext++ = QUOTE | M_PROTECT;
sl@0
   294
					continue;
sl@0
   295
				}
sl@0
   296
				prot = M_PROTECT;
sl@0
   297
			} else
sl@0
   298
				prot = 0;
sl@0
   299
			clen = mbrtowc(&wc, (char*)patnext, MB_LEN_MAX, &mbs);
sl@0
   300
			if (clen == (size_t)-1 || clen == (size_t)-2)
sl@0
   301
				return (GLOB_NOMATCH);
sl@0
   302
			else if (clen == 0)
sl@0
   303
				break;
sl@0
   304
			*bufnext++ = wc | prot;
sl@0
   305
			patnext += clen;
sl@0
   306
		}
sl@0
   307
	}
sl@0
   308
	*bufnext = EOS;
sl@0
   309
sl@0
   310
	if (flags & GLOB_BRACE)
sl@0
   311
	    return globexp1(patbuf, pglob, &limit);
sl@0
   312
	else
sl@0
   313
	    return glob0(patbuf, pglob, &limit);
sl@0
   314
}
sl@0
   315
sl@0
   316
/*
sl@0
   317
 * Expand recursively a glob {} pattern. When there is no more expansion
sl@0
   318
 * invoke the standard globbing routine to glob the rest of the magic
sl@0
   319
 * characters
sl@0
   320
 */
sl@0
   321
static int
sl@0
   322
globexp1(pattern, pglob, limit)
sl@0
   323
	const Char *pattern;
sl@0
   324
	glob_t *pglob;
sl@0
   325
	int *limit;
sl@0
   326
{
sl@0
   327
	const Char* ptr = pattern;
sl@0
   328
	int rv;
sl@0
   329
sl@0
   330
	/* Protect a single {}, for find(1), like csh */
sl@0
   331
	if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
sl@0
   332
		return glob0(pattern, pglob, limit);
sl@0
   333
sl@0
   334
	while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL)
sl@0
   335
		if (!globexp2(ptr, pattern, pglob, &rv, limit))
sl@0
   336
			return rv;
sl@0
   337
sl@0
   338
	return glob0(pattern, pglob, limit);
sl@0
   339
}
sl@0
   340
sl@0
   341
sl@0
   342
/*
sl@0
   343
 * Recursive brace globbing helper. Tries to expand a single brace.
sl@0
   344
 * If it succeeds then it invokes globexp1 with the new pattern.
sl@0
   345
 * If it fails then it tries to glob the rest of the pattern and returns.
sl@0
   346
 */
sl@0
   347
static int
sl@0
   348
globexp2(ptr, pattern, pglob, rv, limit)
sl@0
   349
	const Char *ptr, *pattern;
sl@0
   350
	glob_t *pglob;
sl@0
   351
	int *rv, *limit;
sl@0
   352
{
sl@0
   353
	int     i;
sl@0
   354
	Char   *lm, *ls;
sl@0
   355
	const Char *pe, *pm, *pm1, *pl;
sl@0
   356
	Char    patbuf[MAXPATHLEN];
sl@0
   357
sl@0
   358
	/* copy part up to the brace */
sl@0
   359
	for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
sl@0
   360
		continue;
sl@0
   361
	*lm = EOS;
sl@0
   362
	ls = lm;
sl@0
   363
sl@0
   364
	/* Find the balanced brace */
sl@0
   365
	for (i = 0, pe = ++ptr; *pe; pe++)
sl@0
   366
		if (*pe == LBRACKET) {
sl@0
   367
			/* Ignore everything between [] */
sl@0
   368
			for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
sl@0
   369
				continue;
sl@0
   370
			if (*pe == EOS) {
sl@0
   371
				/*
sl@0
   372
				 * We could not find a matching RBRACKET.
sl@0
   373
				 * Ignore and just look for RBRACE
sl@0
   374
				 */
sl@0
   375
				pe = pm;
sl@0
   376
			}
sl@0
   377
		}
sl@0
   378
		else if (*pe == LBRACE)
sl@0
   379
			i++;
sl@0
   380
		else if (*pe == RBRACE) {
sl@0
   381
			if (i == 0)
sl@0
   382
				break;
sl@0
   383
			i--;
sl@0
   384
		}
sl@0
   385
sl@0
   386
	/* Non matching braces; just glob the pattern */
sl@0
   387
	if (i != 0 || *pe == EOS) {
sl@0
   388
		*rv = glob0(patbuf, pglob, limit);
sl@0
   389
		return 0;
sl@0
   390
	}
sl@0
   391
sl@0
   392
	for (i = 0, pl = pm = ptr; pm <= pe; pm++)
sl@0
   393
		switch (*pm) {
sl@0
   394
		case LBRACKET:
sl@0
   395
			/* Ignore everything between [] */
sl@0
   396
			for (pm1 = pm++; *pm != RBRACKET && *pm != EOS; pm++)
sl@0
   397
				continue;
sl@0
   398
			if (*pm == EOS) {
sl@0
   399
				/*
sl@0
   400
				 * We could not find a matching RBRACKET.
sl@0
   401
				 * Ignore and just look for RBRACE
sl@0
   402
				 */
sl@0
   403
				pm = pm1;
sl@0
   404
			}
sl@0
   405
			break;
sl@0
   406
sl@0
   407
		case LBRACE:
sl@0
   408
			i++;
sl@0
   409
			break;
sl@0
   410
sl@0
   411
		case RBRACE:
sl@0
   412
			if (i) {
sl@0
   413
			    i--;
sl@0
   414
			    break;
sl@0
   415
			}
sl@0
   416
			/* FALLTHROUGH */
sl@0
   417
		case COMMA:
sl@0
   418
			if (i && *pm == COMMA)
sl@0
   419
				break;
sl@0
   420
			else {
sl@0
   421
				/* Append the current string */
sl@0
   422
				for (lm = ls; (pl < pm); *lm++ = *pl++)
sl@0
   423
					continue;
sl@0
   424
				/*
sl@0
   425
				 * Append the rest of the pattern after the
sl@0
   426
				 * closing brace
sl@0
   427
				 */
sl@0
   428
				for (pl = pe + 1; (*lm++ = *pl++) != EOS;)
sl@0
   429
					continue;
sl@0
   430
sl@0
   431
				/* Expand the current pattern */
sl@0
   432
#ifdef DEBUG
sl@0
   433
				qprintf("globexp2:", patbuf);
sl@0
   434
#endif
sl@0
   435
				*rv = globexp1(patbuf, pglob, limit);
sl@0
   436
sl@0
   437
				/* move after the comma, to the next string */
sl@0
   438
				pl = pm + 1;
sl@0
   439
			}
sl@0
   440
			break;
sl@0
   441
sl@0
   442
		default:
sl@0
   443
			break;
sl@0
   444
		}
sl@0
   445
	*rv = 0;
sl@0
   446
	return 0;
sl@0
   447
}
sl@0
   448
sl@0
   449
sl@0
   450
/*
sl@0
   451
 * expand tilde from the passwd file.
sl@0
   452
 */
sl@0
   453
sl@0
   454
static const Char *
sl@0
   455
globtilde(pattern, patbuf, patbuf_len, pglob)
sl@0
   456
	const Char *pattern;
sl@0
   457
	Char *patbuf;
sl@0
   458
	size_t patbuf_len;
sl@0
   459
	glob_t *pglob;
sl@0
   460
{
sl@0
   461
sl@0
   462
#ifndef  __SYMBIAN32__
sl@0
   463
	struct passwd *pwd;
sl@0
   464
#endif
sl@0
   465
sl@0
   466
	char *h;
sl@0
   467
	const Char *p;
sl@0
   468
	Char *b, *eb;
sl@0
   469
	
sl@0
   470
	if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
sl@0
   471
		return pattern;
sl@0
   472
sl@0
   473
	/* 
sl@0
   474
	 * Copy up to the end of the string or / 
sl@0
   475
	 */
sl@0
   476
sl@0
   477
	eb = &patbuf[patbuf_len - 1];
sl@0
   478
	
sl@0
   479
#ifdef __SYMBIAN32__
sl@0
   480
sl@0
   481
	for (p = pattern + 1, h = (char *) patbuf;
sl@0
   482
	    h < (char *)eb && *p && *p != SEP ; *h++ = *p++)
sl@0
   483
		continue;
sl@0
   484
		
sl@0
   485
	*h = EOS;
sl@0
   486
	
sl@0
   487
	if (((char *) patbuf)[0] == EOS) {
sl@0
   488
		/*
sl@0
   489
		 * handle a plain ~ or ~\\ by getting the
sl@0
   490
		 * secure Id for this process. It shall 
sl@0
   491
		 * return the path as C:\\private\\<secureId>
sl@0
   492
		 * on emulator and Z:\\private\\<secureId>
sl@0
   493
		 * on hardware
sl@0
   494
		 */
sl@0
   495
	    if( NULL == getcwd(h, patbuf_len) )
sl@0
   496
			return pattern;
sl@0
   497
	}
sl@0
   498
	
sl@0
   499
	else{
sl@0
   500
		/*
sl@0
   501
		 * Its ~<path>\\.. This will not be handled. Returns the
sl@0
   502
		 * pattern as it is. 
sl@0
   503
		 */
sl@0
   504
		return pattern;
sl@0
   505
	}
sl@0
   506
		
sl@0
   507
#  else
sl@0
   508
sl@0
   509
	for (p = pattern + 1, h = (char *) patbuf;
sl@0
   510
	    h < (char *)eb && *p && *p != SLASH; *h++ = *p++)
sl@0
   511
		continue;
sl@0
   512
sl@0
   513
	*h = EOS;
sl@0
   514
sl@0
   515
	if (((char *) patbuf)[0] == EOS) {
sl@0
   516
		/*
sl@0
   517
		 * handle a plain ~ or ~/ by expanding $HOME first (iff
sl@0
   518
		 * we're not running setuid or setgid) and then trying
sl@0
   519
		 * the password file
sl@0
   520
		 */
sl@0
   521
		if (issetugid() != 0 ||
sl@0
   522
		    (h = getenv("HOME")) == NULL) {
sl@0
   523
			if (((h = getlogin()) != NULL &&
sl@0
   524
			     (pwd = getpwnam(h)) != NULL) ||
sl@0
   525
			    (pwd = getpwuid(getuid())) != NULL)
sl@0
   526
				h = pwd->pw_dir;
sl@0
   527
			else
sl@0
   528
				return pattern;
sl@0
   529
		}
sl@0
   530
	}
sl@0
   531
	else {
sl@0
   532
		/*
sl@0
   533
		 * Expand a ~user
sl@0
   534
		 */
sl@0
   535
		if ((pwd = getpwnam((char*) patbuf)) == NULL)
sl@0
   536
			return pattern;
sl@0
   537
		else
sl@0
   538
			h = pwd->pw_dir;
sl@0
   539
	}
sl@0
   540
sl@0
   541
#endif //__SYMBIAN32__
sl@0
   542
	
sl@0
   543
sl@0
   544
	/* Copy the home directory */
sl@0
   545
	for (b = patbuf; b < eb && *h; *b++ = *h++)
sl@0
   546
		continue;
sl@0
   547
sl@0
   548
	/* Append the rest of the pattern */
sl@0
   549
	while (b < eb && (*b++ = *p++) != EOS)
sl@0
   550
		continue;
sl@0
   551
	*b = EOS;
sl@0
   552
	
sl@0
   553
	return patbuf;
sl@0
   554
}
sl@0
   555
sl@0
   556
sl@0
   557
/*
sl@0
   558
 * The main glob() routine: compiles the pattern (optionally processing
sl@0
   559
 * quotes), calls glob1() to do the real pattern matching, and finally
sl@0
   560
 * sorts the list (unless unsorted operation is requested).  Returns 0
sl@0
   561
 * if things went well, nonzero if errors occurred.
sl@0
   562
 */
sl@0
   563
static int
sl@0
   564
glob0(pattern, pglob, limit)
sl@0
   565
	const Char *pattern;
sl@0
   566
	glob_t *pglob;
sl@0
   567
	int *limit;
sl@0
   568
{
sl@0
   569
	const Char *qpatnext;
sl@0
   570
	int c, err, oldpathc;
sl@0
   571
	Char *bufnext, patbuf[MAXPATHLEN];
sl@0
   572
sl@0
   573
	qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob);
sl@0
   574
	oldpathc = pglob->gl_pathc;
sl@0
   575
	bufnext = patbuf;
sl@0
   576
sl@0
   577
	/* We don't need to check for buffer overflow any more. */
sl@0
   578
	while ((c = *qpatnext++) != EOS) {
sl@0
   579
		switch (c) {
sl@0
   580
		case LBRACKET:
sl@0
   581
			c = *qpatnext;
sl@0
   582
			if (c == NOT)
sl@0
   583
				++qpatnext;
sl@0
   584
			if (*qpatnext == EOS ||
sl@0
   585
			    g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) {
sl@0
   586
				*bufnext++ = LBRACKET;
sl@0
   587
				if (c == NOT)
sl@0
   588
					--qpatnext;
sl@0
   589
				break;
sl@0
   590
			}
sl@0
   591
			*bufnext++ = M_SET;
sl@0
   592
			if (c == NOT)
sl@0
   593
				*bufnext++ = M_NOT;
sl@0
   594
			c = *qpatnext++;
sl@0
   595
			do {
sl@0
   596
				*bufnext++ = CHAR(c);
sl@0
   597
				if (*qpatnext == RANGE &&
sl@0
   598
				    (c = qpatnext[1]) != RBRACKET) {
sl@0
   599
					*bufnext++ = M_RNG;
sl@0
   600
					*bufnext++ = CHAR(c);
sl@0
   601
					qpatnext += 2;
sl@0
   602
				}
sl@0
   603
			} while ((c = *qpatnext++) != RBRACKET);
sl@0
   604
			pglob->gl_flags |= GLOB_MAGCHAR;
sl@0
   605
			*bufnext++ = M_END;
sl@0
   606
			break;
sl@0
   607
		case QUESTION:
sl@0
   608
			pglob->gl_flags |= GLOB_MAGCHAR;
sl@0
   609
			*bufnext++ = M_ONE;
sl@0
   610
			break;
sl@0
   611
		case STAR:
sl@0
   612
			pglob->gl_flags |= GLOB_MAGCHAR;
sl@0
   613
			/* collapse adjacent stars to one,
sl@0
   614
			 * to avoid exponential behavior
sl@0
   615
			 */
sl@0
   616
			if (bufnext == patbuf || bufnext[-1] != M_ALL)
sl@0
   617
			    *bufnext++ = M_ALL;
sl@0
   618
			break;
sl@0
   619
		default:
sl@0
   620
			*bufnext++ = CHAR(c);
sl@0
   621
			break;
sl@0
   622
		}
sl@0
   623
	}
sl@0
   624
	*bufnext = EOS;
sl@0
   625
#ifdef DEBUG
sl@0
   626
	qprintf("glob0:", patbuf);
sl@0
   627
#endif
sl@0
   628
sl@0
   629
	if ((err = glob1(patbuf, pglob, limit)) != 0)
sl@0
   630
		return(err);
sl@0
   631
sl@0
   632
	/*
sl@0
   633
	 * If there was no match we are going to append the pattern
sl@0
   634
	 * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
sl@0
   635
	 * and the pattern did not contain any magic characters
sl@0
   636
	 * GLOB_NOMAGIC is there just for compatibility with csh.
sl@0
   637
	 */
sl@0
   638
	if (pglob->gl_pathc == oldpathc) {
sl@0
   639
		if (((pglob->gl_flags & GLOB_NOCHECK) ||
sl@0
   640
		    ((pglob->gl_flags & GLOB_NOMAGIC) &&
sl@0
   641
			!(pglob->gl_flags & GLOB_MAGCHAR))))
sl@0
   642
			return(globextend(pattern, pglob, limit));
sl@0
   643
		else
sl@0
   644
			return(GLOB_NOMATCH);
sl@0
   645
	}
sl@0
   646
	if (!(pglob->gl_flags & GLOB_NOSORT))
sl@0
   647
		qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
sl@0
   648
		    pglob->gl_pathc - oldpathc, sizeof(char *), compare);
sl@0
   649
	return(0);
sl@0
   650
}
sl@0
   651
sl@0
   652
static int
sl@0
   653
compare(p, q)
sl@0
   654
	const void *p, *q;
sl@0
   655
{
sl@0
   656
	return(strcmp(*(char **)p, *(char **)q));
sl@0
   657
}
sl@0
   658
sl@0
   659
static int
sl@0
   660
glob1(pattern, pglob, limit)
sl@0
   661
	Char *pattern;
sl@0
   662
	glob_t *pglob;
sl@0
   663
	int *limit;
sl@0
   664
{
sl@0
   665
	Char pathbuf[MAXPATHLEN];
sl@0
   666
sl@0
   667
	/* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
sl@0
   668
	if (*pattern == EOS)
sl@0
   669
		return(0);
sl@0
   670
	return(glob2(pathbuf, pathbuf, pathbuf + MAXPATHLEN - 1,
sl@0
   671
	    pattern, pglob, limit));
sl@0
   672
}
sl@0
   673
sl@0
   674
/*
sl@0
   675
 * The functions glob2 and glob3 are mutually recursive; there is one level
sl@0
   676
 * of recursion for each segment in the pattern that contains one or more
sl@0
   677
 * meta characters.
sl@0
   678
 */
sl@0
   679
static int
sl@0
   680
glob2(pathbuf, pathend, pathend_last, pattern, pglob, limit)
sl@0
   681
	Char *pathbuf, *pathend, *pathend_last, *pattern;
sl@0
   682
	glob_t *pglob;
sl@0
   683
	int *limit;
sl@0
   684
{
sl@0
   685
	struct stat sb;
sl@0
   686
	Char *p, *q;
sl@0
   687
	int anymeta;
sl@0
   688
sl@0
   689
	/*
sl@0
   690
	 * Loop over pattern segments until end of pattern or until
sl@0
   691
	 * segment with meta character found.
sl@0
   692
	 */
sl@0
   693
	for (anymeta = 0;;) {
sl@0
   694
		if (*pattern == EOS) {		/* End of pattern? */
sl@0
   695
			*pathend = EOS;
sl@0
   696
			if (g_lstat(pathbuf, &sb, pglob))
sl@0
   697
				return(0);
sl@0
   698
sl@0
   699
			if (((pglob->gl_flags & GLOB_MARK) &&
sl@0
   700
			    pathend[-1] != SEP) && (S_ISDIR(sb.st_mode)
sl@0
   701
			    || (S_ISLNK(sb.st_mode) &&
sl@0
   702
			    (g_stat(pathbuf, &sb, pglob) == 0) &&
sl@0
   703
			    S_ISDIR(sb.st_mode)))) {
sl@0
   704
				if (pathend + 1 > pathend_last)
sl@0
   705
					return (GLOB_ABORTED);
sl@0
   706
				*pathend++ = SEP;
sl@0
   707
				*pathend = EOS;
sl@0
   708
			}
sl@0
   709
			++pglob->gl_matchc;
sl@0
   710
			return(globextend(pathbuf, pglob, limit));
sl@0
   711
		}
sl@0
   712
sl@0
   713
		/* Find end of next segment, copy tentatively to pathend. */
sl@0
   714
		q = pathend;
sl@0
   715
		p = pattern;
sl@0
   716
		while (*p != EOS && *p != SEP) {
sl@0
   717
			if (ismeta(*p))
sl@0
   718
				anymeta = 1;
sl@0
   719
			if (q + 1 > pathend_last)
sl@0
   720
				return (GLOB_ABORTED);
sl@0
   721
			*q++ = *p++;
sl@0
   722
		}
sl@0
   723
sl@0
   724
		if (!anymeta) {		/* No expansion, do next segment. */
sl@0
   725
			pathend = q;
sl@0
   726
			pattern = p;
sl@0
   727
			while (*pattern == SEP) {
sl@0
   728
				if (pathend + 1 > pathend_last)
sl@0
   729
					return (GLOB_ABORTED);
sl@0
   730
				*pathend++ = *pattern++;
sl@0
   731
			}
sl@0
   732
		} else			/* Need expansion, recurse. */
sl@0
   733
			return(glob3(pathbuf, pathend, pathend_last, pattern, p,
sl@0
   734
			    pglob, limit));
sl@0
   735
	}
sl@0
   736
	/* NOTREACHED */
sl@0
   737
}
sl@0
   738
sl@0
   739
static int
sl@0
   740
glob3(pathbuf, pathend, pathend_last, pattern, restpattern, pglob, limit)
sl@0
   741
	Char *pathbuf, *pathend, *pathend_last, *pattern, *restpattern;
sl@0
   742
	glob_t *pglob;
sl@0
   743
	int *limit;
sl@0
   744
{
sl@0
   745
	struct dirent *dp;
sl@0
   746
	DIR *dirp;
sl@0
   747
	int err;
sl@0
   748
	char buf[MAXPATHLEN];
sl@0
   749
sl@0
   750
	/*
sl@0
   751
	 * The readdirfunc declaration can't be prototyped, because it is
sl@0
   752
	 * assigned, below, to two functions which are prototyped in glob.h
sl@0
   753
	 * and dirent.h as taking pointers to differently typed opaque
sl@0
   754
	 * structures.
sl@0
   755
	 */
sl@0
   756
	struct dirent *(*readdirfunc)();
sl@0
   757
sl@0
   758
	if (pathend > pathend_last)
sl@0
   759
		return (GLOB_ABORTED);
sl@0
   760
	*pathend = EOS;
sl@0
   761
	errno = 0;
sl@0
   762
sl@0
   763
	if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
sl@0
   764
		/* TODO: don't call for ENOENT or ENOTDIR? */
sl@0
   765
		if (pglob->gl_errfunc) {
sl@0
   766
			if (g_Ctoc(pathbuf, buf, sizeof(buf)))
sl@0
   767
				return (GLOB_ABORTED);
sl@0
   768
			if (pglob->gl_errfunc(buf, errno) ||
sl@0
   769
			    pglob->gl_flags & GLOB_ERR)
sl@0
   770
				return (GLOB_ABORTED);
sl@0
   771
		}
sl@0
   772
		return(0);
sl@0
   773
	}
sl@0
   774
sl@0
   775
	err = 0;
sl@0
   776
sl@0
   777
	/* Search directory for matching names. */
sl@0
   778
	if (pglob->gl_flags & GLOB_ALTDIRFUNC)
sl@0
   779
		readdirfunc = pglob->gl_readdir;
sl@0
   780
	else
sl@0
   781
		readdirfunc = readdir;
sl@0
   782
		while (NULL != (dp = (*readdirfunc)(dirp))) {
sl@0
   783
		u_char *sc;
sl@0
   784
		Char *dc;
sl@0
   785
		wchar_t wc;
sl@0
   786
		size_t clen;
sl@0
   787
		mbstate_t mbs;
sl@0
   788
sl@0
   789
		/* Initial DOT must be matched literally. */
sl@0
   790
		if (dp->d_name[0] == DOT && *pattern != DOT)
sl@0
   791
			continue;
sl@0
   792
		memset(&mbs, 0, sizeof(mbs));
sl@0
   793
		dc = pathend;
sl@0
   794
		sc = (u_char *) dp->d_name;
sl@0
   795
		while (dc < pathend_last) {
sl@0
   796
			clen = mbrtowc(&wc,(char*)sc, MB_LEN_MAX, &mbs);
sl@0
   797
			if (clen == (size_t)-1 || clen == (size_t)-2) {
sl@0
   798
				wc = *sc;
sl@0
   799
				clen = 1;
sl@0
   800
				memset(&mbs, 0, sizeof(mbs));
sl@0
   801
			}
sl@0
   802
			if ((*dc++ = wc) == EOS)
sl@0
   803
				break;
sl@0
   804
			sc += clen;
sl@0
   805
		}
sl@0
   806
		if (!match(pathend, pattern, restpattern)) {
sl@0
   807
			*pathend = EOS;
sl@0
   808
			continue;
sl@0
   809
		}
sl@0
   810
		err = glob2(pathbuf, --dc, pathend_last, restpattern,
sl@0
   811
		    pglob, limit);
sl@0
   812
		if (err)
sl@0
   813
			break;
sl@0
   814
	}
sl@0
   815
sl@0
   816
	if (pglob->gl_flags & GLOB_ALTDIRFUNC)
sl@0
   817
		(*pglob->gl_closedir)(dirp);
sl@0
   818
	else
sl@0
   819
		closedir(dirp);
sl@0
   820
	return(err);
sl@0
   821
}
sl@0
   822
sl@0
   823
sl@0
   824
/*
sl@0
   825
 * Extend the gl_pathv member of a glob_t structure to accomodate a new item,
sl@0
   826
 * add the new item, and update gl_pathc.
sl@0
   827
 *
sl@0
   828
 * This assumes the BSD realloc, which only copies the block when its size
sl@0
   829
 * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
sl@0
   830
 * behavior.
sl@0
   831
 *
sl@0
   832
 * Return 0 if new item added, error code if memory couldn't be allocated.
sl@0
   833
 *
sl@0
   834
 * Invariant of the glob_t structure:
sl@0
   835
 *	Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
sl@0
   836
 *	gl_pathv points to (gl_offs + gl_pathc + 1) items.
sl@0
   837
 */
sl@0
   838
static int
sl@0
   839
globextend(path, pglob, limit)
sl@0
   840
	const Char *path;
sl@0
   841
	glob_t *pglob;
sl@0
   842
	int *limit;
sl@0
   843
{
sl@0
   844
	char **pathv;
sl@0
   845
	int i;
sl@0
   846
	u_int newsize, len;
sl@0
   847
	char *copy;
sl@0
   848
	const Char *p;
sl@0
   849
sl@0
   850
	if (*limit && pglob->gl_pathc > *limit) {
sl@0
   851
		errno = 0;
sl@0
   852
		return (GLOB_NOSPACE);
sl@0
   853
	}
sl@0
   854
sl@0
   855
	newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
sl@0
   856
	pathv = pglob->gl_pathv ?
sl@0
   857
		    realloc((char *)pglob->gl_pathv, newsize) :
sl@0
   858
		    malloc(newsize);
sl@0
   859
	if (pathv == NULL) {
sl@0
   860
		if (pglob->gl_pathv) {
sl@0
   861
			free(pglob->gl_pathv);
sl@0
   862
			pglob->gl_pathv = NULL;
sl@0
   863
		}
sl@0
   864
		return(GLOB_NOSPACE);
sl@0
   865
	}
sl@0
   866
sl@0
   867
	if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
sl@0
   868
		/* first time around -- clear initial gl_offs items */
sl@0
   869
		pathv += pglob->gl_offs;
sl@0
   870
		for (i = pglob->gl_offs; --i >= 0; )
sl@0
   871
			*--pathv = NULL;
sl@0
   872
	}
sl@0
   873
	pglob->gl_pathv = pathv;
sl@0
   874
sl@0
   875
	for (p = path; *p++;)
sl@0
   876
		continue;
sl@0
   877
	len = MB_CUR_MAX * (size_t)(p - path);	/* XXX overallocation */
sl@0
   878
	if ((copy = malloc(len)) != NULL) {
sl@0
   879
		if (g_Ctoc(path, copy, len)) {
sl@0
   880
			free(copy);
sl@0
   881
			return (GLOB_NOSPACE);
sl@0
   882
		}
sl@0
   883
		pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
sl@0
   884
	}
sl@0
   885
	pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
sl@0
   886
	return(copy == NULL ? GLOB_NOSPACE : 0);
sl@0
   887
}
sl@0
   888
sl@0
   889
/*
sl@0
   890
 * pattern matching function for filenames.  Each occurrence of the *
sl@0
   891
 * pattern causes a recursion level.
sl@0
   892
 */
sl@0
   893
static int
sl@0
   894
match(name, pat, patend)
sl@0
   895
	Char *name, *pat, *patend;
sl@0
   896
{
sl@0
   897
	int ok, negate_range;
sl@0
   898
	Char c, k;
sl@0
   899
sl@0
   900
	while (pat < patend) {
sl@0
   901
		c = *pat++;
sl@0
   902
		switch (c & M_MASK) {
sl@0
   903
		case M_ALL:
sl@0
   904
			if (pat == patend)
sl@0
   905
				return(1);
sl@0
   906
			do
sl@0
   907
			    if (match(name, pat, patend))
sl@0
   908
				    return(1);
sl@0
   909
			while (*name++ != EOS);
sl@0
   910
			return(0);
sl@0
   911
		case M_ONE:
sl@0
   912
			if (*name++ == EOS)
sl@0
   913
				return(0);
sl@0
   914
			break;
sl@0
   915
		case M_SET:
sl@0
   916
			ok = 0;
sl@0
   917
			if ((k = *name++) == EOS)
sl@0
   918
				return(0);
sl@0
   919
			if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
sl@0
   920
				++pat;
sl@0
   921
			while (((c = *pat++) & M_MASK) != M_END)
sl@0
   922
				if ((*pat & M_MASK) == M_RNG) {
sl@0
   923
					if (
sl@0
   924
					// As used in vfscanf.c 
sl@0
   925
					#ifndef __SYMBIAN32__		
sl@0
   926
						__collate_load_error ?
sl@0
   927
					#else
sl@0
   928
						((strcmp("C",(const char*) LC_COLLATE_LocaleName)==0) ||(strcmp("POSIX", (const char*) LC_COLLATE_LocaleName)==0 )) ?
sl@0
   929
					#endif	
sl@0
   930
					    CHAR(c) <= CHAR(k) && CHAR(k) <= CHAR(pat[1]) :
sl@0
   931
					       __collate_range_cmp(CHAR(c), CHAR(k)) <= 0
sl@0
   932
					    && __collate_range_cmp(CHAR(k), CHAR(pat[1])) <= 0
sl@0
   933
					   )
sl@0
   934
						ok = 1;
sl@0
   935
					pat += 2;
sl@0
   936
				} else if (c == k)
sl@0
   937
					ok = 1;
sl@0
   938
			if (ok == negate_range)
sl@0
   939
				return(0);
sl@0
   940
			break;
sl@0
   941
		default:
sl@0
   942
			if (*name++ != c)
sl@0
   943
				return(0);
sl@0
   944
			break;
sl@0
   945
		}
sl@0
   946
	}
sl@0
   947
	return(*name == EOS);
sl@0
   948
}
sl@0
   949
sl@0
   950
sl@0
   951
 
sl@0
   952
sl@0
   953
// EXTERNAL FUNCTION PROTOTYPES
sl@0
   954
//-----------------------------------------------------------------------------
sl@0
   955
//Function Name : void globfree(struct glob_t*)
sl@0
   956
//
sl@0
   957
//Description   : Free allocated data belonging to a glob_t structure. Memory 
sl@0
   958
//				  which was dynamically allocated storage from an earlier call to glob()
sl@0
   959
//				 
sl@0
   960
//Return Value  : None
sl@0
   961
//				  
sl@0
   962
//-----------------------------------------------------------------------------
sl@0
   963
sl@0
   964
sl@0
   965
EXPORT_C void
sl@0
   966
globfree(pglob)
sl@0
   967
	glob_t *pglob;
sl@0
   968
{
sl@0
   969
	int i;
sl@0
   970
	char **pp;
sl@0
   971
sl@0
   972
	if (pglob->gl_pathv != NULL) {
sl@0
   973
		pp = pglob->gl_pathv + pglob->gl_offs;
sl@0
   974
		for (i = pglob->gl_pathc; i--; ++pp)
sl@0
   975
			if (*pp)
sl@0
   976
				free(*pp);
sl@0
   977
		free(pglob->gl_pathv);
sl@0
   978
		pglob->gl_pathv = NULL;
sl@0
   979
	}
sl@0
   980
}
sl@0
   981
sl@0
   982
static DIR *
sl@0
   983
g_opendir(str, pglob)
sl@0
   984
	Char *str;
sl@0
   985
	glob_t *pglob;
sl@0
   986
{
sl@0
   987
	char buf[MAXPATHLEN];
sl@0
   988
sl@0
   989
	if (!*str)
sl@0
   990
		strcpy(buf, ".");
sl@0
   991
	else {
sl@0
   992
		if (g_Ctoc(str, buf, sizeof(buf)))
sl@0
   993
			return (NULL);
sl@0
   994
	}
sl@0
   995
sl@0
   996
	if (pglob->gl_flags & GLOB_ALTDIRFUNC)
sl@0
   997
		return((*pglob->gl_opendir)(buf));
sl@0
   998
sl@0
   999
	return(opendir(buf));
sl@0
  1000
}
sl@0
  1001
sl@0
  1002
static int
sl@0
  1003
g_lstat(fn, sb, pglob)
sl@0
  1004
	Char *fn;
sl@0
  1005
	struct stat *sb;
sl@0
  1006
	glob_t *pglob;
sl@0
  1007
{
sl@0
  1008
	char buf[MAXPATHLEN];
sl@0
  1009
sl@0
  1010
	if (g_Ctoc(fn, buf, sizeof(buf))) {
sl@0
  1011
		errno = ENAMETOOLONG;
sl@0
  1012
		return (-1);
sl@0
  1013
	}
sl@0
  1014
	if (pglob->gl_flags & GLOB_ALTDIRFUNC)
sl@0
  1015
		return((*pglob->gl_lstat)(buf, sb));
sl@0
  1016
	return(lstat(buf, sb));
sl@0
  1017
}
sl@0
  1018
sl@0
  1019
static int
sl@0
  1020
g_stat(fn, sb, pglob)
sl@0
  1021
	Char *fn;
sl@0
  1022
	struct stat *sb;
sl@0
  1023
	glob_t *pglob;
sl@0
  1024
{
sl@0
  1025
	char buf[MAXPATHLEN];
sl@0
  1026
sl@0
  1027
	if (g_Ctoc(fn, buf, sizeof(buf))) {
sl@0
  1028
		errno = ENAMETOOLONG;
sl@0
  1029
		return (-1);
sl@0
  1030
	}
sl@0
  1031
	if (pglob->gl_flags & GLOB_ALTDIRFUNC)
sl@0
  1032
		return((*pglob->gl_stat)(buf, sb));
sl@0
  1033
	return(stat(buf, sb));
sl@0
  1034
}
sl@0
  1035
sl@0
  1036
static Char *
sl@0
  1037
g_strchr(Char *str, wchar_t ch)
sl@0
  1038
{
sl@0
  1039
	do {
sl@0
  1040
		if (*str == ch)
sl@0
  1041
			return (str);
sl@0
  1042
	} while (*str++);
sl@0
  1043
	return (NULL);
sl@0
  1044
}
sl@0
  1045
sl@0
  1046
static int
sl@0
  1047
g_Ctoc(str, buf, len)
sl@0
  1048
	const Char *str;
sl@0
  1049
	char *buf;
sl@0
  1050
	u_int len;
sl@0
  1051
{
sl@0
  1052
	mbstate_t mbs;
sl@0
  1053
	size_t clen;
sl@0
  1054
sl@0
  1055
	memset(&mbs, 0, sizeof(mbs));
sl@0
  1056
	while (len >= MB_CUR_MAX) {
sl@0
  1057
		clen = wcrtomb(buf, *str, &mbs);
sl@0
  1058
		if (clen == (size_t)-1)
sl@0
  1059
			return (1);
sl@0
  1060
		if (*str == L'\0')
sl@0
  1061
			return (0);
sl@0
  1062
		str++;
sl@0
  1063
		buf += clen;
sl@0
  1064
		len -= clen;
sl@0
  1065
	}
sl@0
  1066
	return (1);
sl@0
  1067
}
sl@0
  1068
sl@0
  1069
#ifdef DEBUG
sl@0
  1070
static void
sl@0
  1071
qprintf(str, s)
sl@0
  1072
	const char *str;
sl@0
  1073
	Char *s;
sl@0
  1074
{
sl@0
  1075
	Char *p;
sl@0
  1076
sl@0
  1077
	(void)printf("%s:\n", str);
sl@0
  1078
	for (p = s; *p; p++)
sl@0
  1079
		(void)printf("%c", CHAR(*p));
sl@0
  1080
	(void)printf("\n");
sl@0
  1081
	for (p = s; *p; p++)
sl@0
  1082
		(void)printf("%c", *p & M_PROTECT ? '"' : ' ');
sl@0
  1083
	(void)printf("\n");
sl@0
  1084
	for (p = s; *p; p++)
sl@0
  1085
		(void)printf("%c", ismeta(*p) ? '_' : ' ');
sl@0
  1086
	(void)printf("\n");
sl@0
  1087
}
sl@0
  1088
#endif
sl@0
  1089
sl@0
  1090
#ifdef __cplusplus
sl@0
  1091
} // extern "C"
sl@0
  1092
#endif