os/ossrv/genericopenlibs/openenvcore/libc/src/glob.c
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/ossrv/genericopenlibs/openenvcore/libc/src/glob.c	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1092 @@
     1.4 +// glob.c
     1.5 +
     1.6 +
     1.7 +/*
     1.8 + * Copyright (c) 1989, 1993
     1.9 + *	The Regents of the University of California.  All rights reserved.
    1.10 + *
    1.11 + * This code is derived from software contributed to Berkeley by
    1.12 + * Guido van Rossum.
    1.13 + *
    1.14 + * Redistribution and use in source and binary forms, with or without
    1.15 + * modification, are permitted provided that the following conditions
    1.16 + * are met:
    1.17 + * 1. Redistributions of source code must retain the above copyright
    1.18 + *    notice, this list of conditions and the following disclaimer.
    1.19 + * 2. Redistributions in binary form must reproduce the above copyright
    1.20 + *    notice, this list of conditions and the following disclaimer in the
    1.21 + *    documentation and/or other materials provided with the distribution.
    1.22 + * 4. Neither the name of the University nor the names of its contributors
    1.23 + *    may be used to endorse or promote products derived from this software
    1.24 + *    without specific prior written permission.
    1.25 + *
    1.26 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    1.27 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    1.28 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    1.29 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    1.30 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    1.31 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    1.32 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    1.33 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    1.34 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    1.35 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    1.36 + * SUCH DAMAGE.
    1.37 + */
    1.38 +
    1.39 +/* Portions Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).All rights reserved.  */
    1.40 + 
    1.41 +#if defined(LIBC_SCCS) && !defined(lint)
    1.42 +static char sccsid[] = "@(#)glob.c	8.3 (Berkeley) 10/13/93";
    1.43 +#endif /* LIBC_SCCS and not lint */
    1.44 +#include <sys/cdefs.h>
    1.45 +__FBSDID("$FreeBSD: src/lib/libc/gen/glob.c,v 1.23 2005/09/14 19:14:32 ache Exp $");
    1.46 +
    1.47 +
    1.48 +/*
    1.49 + * glob(3) -- a superset of the one defined in POSIX 1003.2.
    1.50 + *
    1.51 + * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
    1.52 + *
    1.53 + * Optional extra services, controlled by flags not defined by POSIX:
    1.54 + *
    1.55 + * GLOB_QUOTE:
    1.56 + *	Escaping convention: \ inhibits any special meaning the following
    1.57 + *	character might have (except \ at end of string is retained).
    1.58 + * GLOB_MAGCHAR:
    1.59 + *	Set in gl_flags if pattern contained a globbing character.
    1.60 + * GLOB_NOMAGIC:
    1.61 + *	Same as GLOB_NOCHECK, but it will only append pattern if it did
    1.62 + *	not contain any magic characters.  [Used in csh style globbing]
    1.63 + * GLOB_ALTDIRFUNC:
    1.64 + *	Use alternately specified directory access functions.
    1.65 + * GLOB_TILDE:
    1.66 + *	expand ~user/foo to the /home/dir/of/user/foo
    1.67 + * GLOB_BRACE:
    1.68 + *	expand {1,2}{a,b} to 1a 1b 2a 2b
    1.69 + * gl_matchc:
    1.70 + *	Number of matches in the current invocation of glob.
    1.71 + */
    1.72 +
    1.73 +/*
    1.74 + * Some notes on multibyte character support:
    1.75 + * 1. Patterns with illegal byte sequences match nothing - even if
    1.76 + *    GLOB_NOCHECK is specified.
    1.77 + * 2. Illegal byte sequences in filenames are handled by treating them as
    1.78 + *    single-byte characters with a value of the first byte of the sequence
    1.79 + *    cast to wchar_t.
    1.80 + * 3. State-dependent encodings are not currently supported.
    1.81 + */
    1.82 +
    1.83 +#include <sys/param.h>
    1.84 +#include <sys/stat.h>
    1.85 +
    1.86 +#include <ctype.h>
    1.87 +#include <dirent.h>
    1.88 +#include <errno.h>
    1.89 +#include <glob.h>
    1.90 +#include <limits.h>
    1.91 +#include <pwd.h>
    1.92 +#include <stdint.h>
    1.93 +#include <stdio.h>
    1.94 +#include <stdlib.h>
    1.95 +#include <string.h>
    1.96 +#include <unistd.h>
    1.97 +#include <wchar.h>
    1.98 +
    1.99 +#include "libc_collate.h"
   1.100 +
   1.101 +
   1.102 +#if (defined(__SYMBIAN32__) && (defined(__WINSCW__) || defined(__WINS__)))
   1.103 +
   1.104 +#include "libc_wsd_defs.h"
   1.105 +#include "reent.h"
   1.106 +
   1.107 +#endif	//defined(__SYMBIAN32__) && (defined(__WINSCW__) || defined(__WINS__))
   1.108 +
   1.109 +#ifdef __cplusplus
   1.110 +extern "C" {
   1.111 +#endif
   1.112 +#ifdef __SYMBIAN32__
   1.113 +extern char LC_COLLATE_LocaleName[30];
   1.114 +#ifdef EMULATOR
   1.115 +char *GET_WSD_VAR_NAME(LC_COLLATE_LocaleName, g)();
   1.116 +#define LC_COLLATE_LocaleName (GET_WSD_VAR_NAME(LC_COLLATE_LocaleName, g)())
   1.117 +#endif 	//EMULATOR
   1.118 +
   1.119 +//Declared and defined from libc_collate.h and vfscanf.c
   1.120 +extern int __collate_range_cmp(int , int );
   1.121 +#endif	//__SYMBIAN32__
   1.122 +
   1.123 + 
   1.124 +
   1.125 +#define	DOLLAR		'$'
   1.126 +#define	DOT			'.'
   1.127 +#define	EOS			'\0'
   1.128 +#define	LBRACKET	'['
   1.129 +#define	NOT			'!'
   1.130 +#define	QUESTION	'?'
   1.131 +#define	QUOTE		'\\'
   1.132 +#define	RANGE		'-'
   1.133 +#define	RBRACKET	']'
   1.134 +
   1.135 +// For Symbian Environment the path is specified using the '\'
   1.136 +// unlike in the Linux where the path seprator '/' is used.
   1.137 +// Since '\\' as path seprator is used the escaping flag 
   1.138 +// 'QUOTE' cannot be used here.
   1.139 +// For e.g. ..\\test\\hollows\\*
   1.140 +
   1.141 +#ifdef __SYMBIAN32__
   1.142 +	#define	SEP		'\\'
   1.143 +#else
   1.144 +	#define SEP		'/'
   1.145 +#endif //__SYMBIAN32__
   1.146 +
   1.147 +
   1.148 +#define	STAR		'*'
   1.149 +#define	TILDE		'~'
   1.150 +#define	UNDERSCORE	'_'
   1.151 +#define	LBRACE		'{'
   1.152 +#define	RBRACE		'}'
   1.153 +#define	SLASH		'/'
   1.154 +#define	COMMA		','
   1.155 +
   1.156 +
   1.157 +#ifndef __SYMBIAN32__
   1.158 +
   1.159 +#ifndef DEBUG
   1.160 +
   1.161 +#define	M_QUOTE		0x8000000000ULL
   1.162 +#define	M_PROTECT	0x4000000000ULL
   1.163 +#define	M_MASK		0xffffffffffULL
   1.164 +#define	M_CHAR		0x00ffffffffULL
   1.165 +
   1.166 +typedef uint_fast64_t Char;
   1.167 +
   1.168 +#else		//DEBUG
   1.169 +
   1.170 +#define	M_QUOTE		0x80
   1.171 +#define	M_PROTECT	0x40
   1.172 +#define	M_MASK		0xff
   1.173 +#define	M_CHAR		0x7f
   1.174 +
   1.175 +typedef char Char;
   1.176 +
   1.177 +#endif 		//DEBUG
   1.178 +
   1.179 +#else    	//__SYMBIAN32__
   1.180 +
   1.181 +#define	M_QUOTE		0x80
   1.182 +#define	M_PROTECT	0x40
   1.183 +#define	M_MASK		0xff
   1.184 +#define	M_CHAR		0x7f
   1.185 +
   1.186 +typedef unsigned char Char;
   1.187 +
   1.188 +#endif		//__SYMBIAN32__
   1.189 +
   1.190 +#define	CHAR(c)		((Char)((c)&M_CHAR))
   1.191 +#define	META(c)		((Char)((c)|M_QUOTE))
   1.192 +#define	M_ALL		META('*')
   1.193 +#define	M_END		META(']')
   1.194 +#define	M_NOT		META('!')
   1.195 +#define	M_ONE		META('?')
   1.196 +#define	M_RNG		META('-')
   1.197 +#define	M_SET		META('[')
   1.198 +#define	ismeta(c)	(((c)&M_QUOTE) != 0)
   1.199 +
   1.200 +
   1.201 +static int	 compare(const void *, const void *);
   1.202 +static int	 g_Ctoc(const Char *, char *, u_int);
   1.203 +static int	 g_lstat(Char *, struct stat *, glob_t *);
   1.204 +static DIR	*g_opendir(Char *, glob_t *);
   1.205 +static Char	*g_strchr(Char *, wchar_t);
   1.206 +#ifdef notdef
   1.207 +static Char	*g_strcat(Char *, const Char *);
   1.208 +#endif
   1.209 +static int	 g_stat(Char *, struct stat *, glob_t *);
   1.210 +static int	 glob0(const Char *, glob_t *, int *);
   1.211 +static int	 glob1(Char *, glob_t *, int *);
   1.212 +static int	 glob2(Char *, Char *, Char *, Char *, glob_t *, int *);
   1.213 +static int	 glob3(Char *, Char *, Char *, Char *, Char *, glob_t *, int *);
   1.214 +static int	 globextend(const Char *, glob_t *, int *);
   1.215 +static const Char *	
   1.216 +		 globtilde(const Char *, Char *, size_t, glob_t *);
   1.217 +static int	 globexp1(const Char *, glob_t *, int *);
   1.218 +static int	 globexp2(const Char *, const Char *, glob_t *, int *, int *);
   1.219 +static int	 match(Char *, Char *, Char *);
   1.220 +#ifdef DEBUG
   1.221 +static void	 qprintf(const char *, Char *);
   1.222 +#endif
   1.223 +
   1.224 +// EXTERNAL FUNCTION PROTOTYPES
   1.225 +
   1.226 +
   1.227 +//--------------------------------------------------------------------------------------------
   1.228 +//Function Name : int glob(glob(const char *, int flags, int (*)(const char *, int), glob_t *)
   1.229 +//Description   : It takes pattern to be searched, flags and the structure of the type glob_t.
   1.230 +//				  It can optionally also take  If errfunc is not NULL, it will be called in 
   1.231 +//				  error with the arguments epath,  a  pointer  to  the case of an path which 
   1.232 +//			      failed
   1.233 +//				  
   1.234 +//Return Value  : If successful returns the pathnames of the searched pattern contained 
   1.235 +//				  in the glob_t structure member reference pointer gl_pathv. In case
   1.236 +//				  failure, gl_pathv is NULL.
   1.237 +//----------------------------------------------------------------------------------------------
   1.238 +
   1.239 +EXPORT_C int
   1.240 +glob(pattern, flags, errfunc, pglob)
   1.241 +	const char *pattern;
   1.242 +	int flags, (*errfunc)(const char *, int);
   1.243 +	glob_t *pglob;
   1.244 +{
   1.245 +	const u_char *patnext;
   1.246 +	int limit;
   1.247 +	Char *bufnext, *bufend, patbuf[MAXPATHLEN], prot;
   1.248 +	mbstate_t mbs;
   1.249 +	wchar_t wc;
   1.250 +	size_t clen;
   1.251 +
   1.252 +	patnext = (u_char *) pattern;
   1.253 +	
   1.254 +	// Since we are using '\\' as path seprator, this flag needs to be mentioned
   1.255 +	// by default in Symbian. Instead this can be hardcoded here.
   1.256 +	
   1.257 +	#ifdef __SYMBIAN32__
   1.258 +		flags = flags | GLOB_NOESCAPE;
   1.259 +	#endif
   1.260 +
   1.261 +	if (!(flags & GLOB_APPEND)) {
   1.262 +		pglob->gl_pathc = 0;
   1.263 +		pglob->gl_pathv = NULL;
   1.264 +		if (!(flags & GLOB_DOOFFS))
   1.265 +			pglob->gl_offs = 0;
   1.266 +	}
   1.267 +	if (flags & GLOB_LIMIT) {
   1.268 +		limit = pglob->gl_matchc;
   1.269 +		if (limit == 0)
   1.270 +			limit = ARG_MAX;
   1.271 +	} else
   1.272 +		limit = 0;
   1.273 +	pglob->gl_flags = flags & ~GLOB_MAGCHAR;
   1.274 +	pglob->gl_errfunc = errfunc;
   1.275 +	pglob->gl_matchc = 0;
   1.276 +
   1.277 +	bufnext = patbuf;
   1.278 +	bufend = bufnext + MAXPATHLEN - 1;
   1.279 +	if (flags & GLOB_NOESCAPE) {
   1.280 +		memset(&mbs, 0, sizeof(mbs));
   1.281 +		while (bufend - bufnext >= MB_CUR_MAX) {
   1.282 +			clen = mbrtowc(&wc,(char*)patnext, MB_LEN_MAX, &mbs);
   1.283 +			if (clen == (size_t)-1 || clen == (size_t)-2)
   1.284 +				return (GLOB_NOMATCH);
   1.285 +			else if (clen == 0)
   1.286 +				break;
   1.287 +			*bufnext++ = wc;
   1.288 +			patnext += clen;
   1.289 +		}
   1.290 +	} else {
   1.291 +		/* Protect the quoted characters. */
   1.292 +		memset(&mbs, 0, sizeof(mbs));
   1.293 +		while (bufend - bufnext >= MB_CUR_MAX) {
   1.294 +			if (*patnext == QUOTE) {
   1.295 +				if (*++patnext == EOS) {
   1.296 +					*bufnext++ = QUOTE | M_PROTECT;
   1.297 +					continue;
   1.298 +				}
   1.299 +				prot = M_PROTECT;
   1.300 +			} else
   1.301 +				prot = 0;
   1.302 +			clen = mbrtowc(&wc, (char*)patnext, MB_LEN_MAX, &mbs);
   1.303 +			if (clen == (size_t)-1 || clen == (size_t)-2)
   1.304 +				return (GLOB_NOMATCH);
   1.305 +			else if (clen == 0)
   1.306 +				break;
   1.307 +			*bufnext++ = wc | prot;
   1.308 +			patnext += clen;
   1.309 +		}
   1.310 +	}
   1.311 +	*bufnext = EOS;
   1.312 +
   1.313 +	if (flags & GLOB_BRACE)
   1.314 +	    return globexp1(patbuf, pglob, &limit);
   1.315 +	else
   1.316 +	    return glob0(patbuf, pglob, &limit);
   1.317 +}
   1.318 +
   1.319 +/*
   1.320 + * Expand recursively a glob {} pattern. When there is no more expansion
   1.321 + * invoke the standard globbing routine to glob the rest of the magic
   1.322 + * characters
   1.323 + */
   1.324 +static int
   1.325 +globexp1(pattern, pglob, limit)
   1.326 +	const Char *pattern;
   1.327 +	glob_t *pglob;
   1.328 +	int *limit;
   1.329 +{
   1.330 +	const Char* ptr = pattern;
   1.331 +	int rv;
   1.332 +
   1.333 +	/* Protect a single {}, for find(1), like csh */
   1.334 +	if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
   1.335 +		return glob0(pattern, pglob, limit);
   1.336 +
   1.337 +	while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL)
   1.338 +		if (!globexp2(ptr, pattern, pglob, &rv, limit))
   1.339 +			return rv;
   1.340 +
   1.341 +	return glob0(pattern, pglob, limit);
   1.342 +}
   1.343 +
   1.344 +
   1.345 +/*
   1.346 + * Recursive brace globbing helper. Tries to expand a single brace.
   1.347 + * If it succeeds then it invokes globexp1 with the new pattern.
   1.348 + * If it fails then it tries to glob the rest of the pattern and returns.
   1.349 + */
   1.350 +static int
   1.351 +globexp2(ptr, pattern, pglob, rv, limit)
   1.352 +	const Char *ptr, *pattern;
   1.353 +	glob_t *pglob;
   1.354 +	int *rv, *limit;
   1.355 +{
   1.356 +	int     i;
   1.357 +	Char   *lm, *ls;
   1.358 +	const Char *pe, *pm, *pm1, *pl;
   1.359 +	Char    patbuf[MAXPATHLEN];
   1.360 +
   1.361 +	/* copy part up to the brace */
   1.362 +	for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
   1.363 +		continue;
   1.364 +	*lm = EOS;
   1.365 +	ls = lm;
   1.366 +
   1.367 +	/* Find the balanced brace */
   1.368 +	for (i = 0, pe = ++ptr; *pe; pe++)
   1.369 +		if (*pe == LBRACKET) {
   1.370 +			/* Ignore everything between [] */
   1.371 +			for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
   1.372 +				continue;
   1.373 +			if (*pe == EOS) {
   1.374 +				/*
   1.375 +				 * We could not find a matching RBRACKET.
   1.376 +				 * Ignore and just look for RBRACE
   1.377 +				 */
   1.378 +				pe = pm;
   1.379 +			}
   1.380 +		}
   1.381 +		else if (*pe == LBRACE)
   1.382 +			i++;
   1.383 +		else if (*pe == RBRACE) {
   1.384 +			if (i == 0)
   1.385 +				break;
   1.386 +			i--;
   1.387 +		}
   1.388 +
   1.389 +	/* Non matching braces; just glob the pattern */
   1.390 +	if (i != 0 || *pe == EOS) {
   1.391 +		*rv = glob0(patbuf, pglob, limit);
   1.392 +		return 0;
   1.393 +	}
   1.394 +
   1.395 +	for (i = 0, pl = pm = ptr; pm <= pe; pm++)
   1.396 +		switch (*pm) {
   1.397 +		case LBRACKET:
   1.398 +			/* Ignore everything between [] */
   1.399 +			for (pm1 = pm++; *pm != RBRACKET && *pm != EOS; pm++)
   1.400 +				continue;
   1.401 +			if (*pm == EOS) {
   1.402 +				/*
   1.403 +				 * We could not find a matching RBRACKET.
   1.404 +				 * Ignore and just look for RBRACE
   1.405 +				 */
   1.406 +				pm = pm1;
   1.407 +			}
   1.408 +			break;
   1.409 +
   1.410 +		case LBRACE:
   1.411 +			i++;
   1.412 +			break;
   1.413 +
   1.414 +		case RBRACE:
   1.415 +			if (i) {
   1.416 +			    i--;
   1.417 +			    break;
   1.418 +			}
   1.419 +			/* FALLTHROUGH */
   1.420 +		case COMMA:
   1.421 +			if (i && *pm == COMMA)
   1.422 +				break;
   1.423 +			else {
   1.424 +				/* Append the current string */
   1.425 +				for (lm = ls; (pl < pm); *lm++ = *pl++)
   1.426 +					continue;
   1.427 +				/*
   1.428 +				 * Append the rest of the pattern after the
   1.429 +				 * closing brace
   1.430 +				 */
   1.431 +				for (pl = pe + 1; (*lm++ = *pl++) != EOS;)
   1.432 +					continue;
   1.433 +
   1.434 +				/* Expand the current pattern */
   1.435 +#ifdef DEBUG
   1.436 +				qprintf("globexp2:", patbuf);
   1.437 +#endif
   1.438 +				*rv = globexp1(patbuf, pglob, limit);
   1.439 +
   1.440 +				/* move after the comma, to the next string */
   1.441 +				pl = pm + 1;
   1.442 +			}
   1.443 +			break;
   1.444 +
   1.445 +		default:
   1.446 +			break;
   1.447 +		}
   1.448 +	*rv = 0;
   1.449 +	return 0;
   1.450 +}
   1.451 +
   1.452 +
   1.453 +/*
   1.454 + * expand tilde from the passwd file.
   1.455 + */
   1.456 +
   1.457 +static const Char *
   1.458 +globtilde(pattern, patbuf, patbuf_len, pglob)
   1.459 +	const Char *pattern;
   1.460 +	Char *patbuf;
   1.461 +	size_t patbuf_len;
   1.462 +	glob_t *pglob;
   1.463 +{
   1.464 +
   1.465 +#ifndef  __SYMBIAN32__
   1.466 +	struct passwd *pwd;
   1.467 +#endif
   1.468 +
   1.469 +	char *h;
   1.470 +	const Char *p;
   1.471 +	Char *b, *eb;
   1.472 +	
   1.473 +	if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
   1.474 +		return pattern;
   1.475 +
   1.476 +	/* 
   1.477 +	 * Copy up to the end of the string or / 
   1.478 +	 */
   1.479 +
   1.480 +	eb = &patbuf[patbuf_len - 1];
   1.481 +	
   1.482 +#ifdef __SYMBIAN32__
   1.483 +
   1.484 +	for (p = pattern + 1, h = (char *) patbuf;
   1.485 +	    h < (char *)eb && *p && *p != SEP ; *h++ = *p++)
   1.486 +		continue;
   1.487 +		
   1.488 +	*h = EOS;
   1.489 +	
   1.490 +	if (((char *) patbuf)[0] == EOS) {
   1.491 +		/*
   1.492 +		 * handle a plain ~ or ~\\ by getting the
   1.493 +		 * secure Id for this process. It shall 
   1.494 +		 * return the path as C:\\private\\<secureId>
   1.495 +		 * on emulator and Z:\\private\\<secureId>
   1.496 +		 * on hardware
   1.497 +		 */
   1.498 +	    if( NULL == getcwd(h, patbuf_len) )
   1.499 +			return pattern;
   1.500 +	}
   1.501 +	
   1.502 +	else{
   1.503 +		/*
   1.504 +		 * Its ~<path>\\.. This will not be handled. Returns the
   1.505 +		 * pattern as it is. 
   1.506 +		 */
   1.507 +		return pattern;
   1.508 +	}
   1.509 +		
   1.510 +#  else
   1.511 +
   1.512 +	for (p = pattern + 1, h = (char *) patbuf;
   1.513 +	    h < (char *)eb && *p && *p != SLASH; *h++ = *p++)
   1.514 +		continue;
   1.515 +
   1.516 +	*h = EOS;
   1.517 +
   1.518 +	if (((char *) patbuf)[0] == EOS) {
   1.519 +		/*
   1.520 +		 * handle a plain ~ or ~/ by expanding $HOME first (iff
   1.521 +		 * we're not running setuid or setgid) and then trying
   1.522 +		 * the password file
   1.523 +		 */
   1.524 +		if (issetugid() != 0 ||
   1.525 +		    (h = getenv("HOME")) == NULL) {
   1.526 +			if (((h = getlogin()) != NULL &&
   1.527 +			     (pwd = getpwnam(h)) != NULL) ||
   1.528 +			    (pwd = getpwuid(getuid())) != NULL)
   1.529 +				h = pwd->pw_dir;
   1.530 +			else
   1.531 +				return pattern;
   1.532 +		}
   1.533 +	}
   1.534 +	else {
   1.535 +		/*
   1.536 +		 * Expand a ~user
   1.537 +		 */
   1.538 +		if ((pwd = getpwnam((char*) patbuf)) == NULL)
   1.539 +			return pattern;
   1.540 +		else
   1.541 +			h = pwd->pw_dir;
   1.542 +	}
   1.543 +
   1.544 +#endif //__SYMBIAN32__
   1.545 +	
   1.546 +
   1.547 +	/* Copy the home directory */
   1.548 +	for (b = patbuf; b < eb && *h; *b++ = *h++)
   1.549 +		continue;
   1.550 +
   1.551 +	/* Append the rest of the pattern */
   1.552 +	while (b < eb && (*b++ = *p++) != EOS)
   1.553 +		continue;
   1.554 +	*b = EOS;
   1.555 +	
   1.556 +	return patbuf;
   1.557 +}
   1.558 +
   1.559 +
   1.560 +/*
   1.561 + * The main glob() routine: compiles the pattern (optionally processing
   1.562 + * quotes), calls glob1() to do the real pattern matching, and finally
   1.563 + * sorts the list (unless unsorted operation is requested).  Returns 0
   1.564 + * if things went well, nonzero if errors occurred.
   1.565 + */
   1.566 +static int
   1.567 +glob0(pattern, pglob, limit)
   1.568 +	const Char *pattern;
   1.569 +	glob_t *pglob;
   1.570 +	int *limit;
   1.571 +{
   1.572 +	const Char *qpatnext;
   1.573 +	int c, err, oldpathc;
   1.574 +	Char *bufnext, patbuf[MAXPATHLEN];
   1.575 +
   1.576 +	qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob);
   1.577 +	oldpathc = pglob->gl_pathc;
   1.578 +	bufnext = patbuf;
   1.579 +
   1.580 +	/* We don't need to check for buffer overflow any more. */
   1.581 +	while ((c = *qpatnext++) != EOS) {
   1.582 +		switch (c) {
   1.583 +		case LBRACKET:
   1.584 +			c = *qpatnext;
   1.585 +			if (c == NOT)
   1.586 +				++qpatnext;
   1.587 +			if (*qpatnext == EOS ||
   1.588 +			    g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) {
   1.589 +				*bufnext++ = LBRACKET;
   1.590 +				if (c == NOT)
   1.591 +					--qpatnext;
   1.592 +				break;
   1.593 +			}
   1.594 +			*bufnext++ = M_SET;
   1.595 +			if (c == NOT)
   1.596 +				*bufnext++ = M_NOT;
   1.597 +			c = *qpatnext++;
   1.598 +			do {
   1.599 +				*bufnext++ = CHAR(c);
   1.600 +				if (*qpatnext == RANGE &&
   1.601 +				    (c = qpatnext[1]) != RBRACKET) {
   1.602 +					*bufnext++ = M_RNG;
   1.603 +					*bufnext++ = CHAR(c);
   1.604 +					qpatnext += 2;
   1.605 +				}
   1.606 +			} while ((c = *qpatnext++) != RBRACKET);
   1.607 +			pglob->gl_flags |= GLOB_MAGCHAR;
   1.608 +			*bufnext++ = M_END;
   1.609 +			break;
   1.610 +		case QUESTION:
   1.611 +			pglob->gl_flags |= GLOB_MAGCHAR;
   1.612 +			*bufnext++ = M_ONE;
   1.613 +			break;
   1.614 +		case STAR:
   1.615 +			pglob->gl_flags |= GLOB_MAGCHAR;
   1.616 +			/* collapse adjacent stars to one,
   1.617 +			 * to avoid exponential behavior
   1.618 +			 */
   1.619 +			if (bufnext == patbuf || bufnext[-1] != M_ALL)
   1.620 +			    *bufnext++ = M_ALL;
   1.621 +			break;
   1.622 +		default:
   1.623 +			*bufnext++ = CHAR(c);
   1.624 +			break;
   1.625 +		}
   1.626 +	}
   1.627 +	*bufnext = EOS;
   1.628 +#ifdef DEBUG
   1.629 +	qprintf("glob0:", patbuf);
   1.630 +#endif
   1.631 +
   1.632 +	if ((err = glob1(patbuf, pglob, limit)) != 0)
   1.633 +		return(err);
   1.634 +
   1.635 +	/*
   1.636 +	 * If there was no match we are going to append the pattern
   1.637 +	 * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
   1.638 +	 * and the pattern did not contain any magic characters
   1.639 +	 * GLOB_NOMAGIC is there just for compatibility with csh.
   1.640 +	 */
   1.641 +	if (pglob->gl_pathc == oldpathc) {
   1.642 +		if (((pglob->gl_flags & GLOB_NOCHECK) ||
   1.643 +		    ((pglob->gl_flags & GLOB_NOMAGIC) &&
   1.644 +			!(pglob->gl_flags & GLOB_MAGCHAR))))
   1.645 +			return(globextend(pattern, pglob, limit));
   1.646 +		else
   1.647 +			return(GLOB_NOMATCH);
   1.648 +	}
   1.649 +	if (!(pglob->gl_flags & GLOB_NOSORT))
   1.650 +		qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
   1.651 +		    pglob->gl_pathc - oldpathc, sizeof(char *), compare);
   1.652 +	return(0);
   1.653 +}
   1.654 +
   1.655 +static int
   1.656 +compare(p, q)
   1.657 +	const void *p, *q;
   1.658 +{
   1.659 +	return(strcmp(*(char **)p, *(char **)q));
   1.660 +}
   1.661 +
   1.662 +static int
   1.663 +glob1(pattern, pglob, limit)
   1.664 +	Char *pattern;
   1.665 +	glob_t *pglob;
   1.666 +	int *limit;
   1.667 +{
   1.668 +	Char pathbuf[MAXPATHLEN];
   1.669 +
   1.670 +	/* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
   1.671 +	if (*pattern == EOS)
   1.672 +		return(0);
   1.673 +	return(glob2(pathbuf, pathbuf, pathbuf + MAXPATHLEN - 1,
   1.674 +	    pattern, pglob, limit));
   1.675 +}
   1.676 +
   1.677 +/*
   1.678 + * The functions glob2 and glob3 are mutually recursive; there is one level
   1.679 + * of recursion for each segment in the pattern that contains one or more
   1.680 + * meta characters.
   1.681 + */
   1.682 +static int
   1.683 +glob2(pathbuf, pathend, pathend_last, pattern, pglob, limit)
   1.684 +	Char *pathbuf, *pathend, *pathend_last, *pattern;
   1.685 +	glob_t *pglob;
   1.686 +	int *limit;
   1.687 +{
   1.688 +	struct stat sb;
   1.689 +	Char *p, *q;
   1.690 +	int anymeta;
   1.691 +
   1.692 +	/*
   1.693 +	 * Loop over pattern segments until end of pattern or until
   1.694 +	 * segment with meta character found.
   1.695 +	 */
   1.696 +	for (anymeta = 0;;) {
   1.697 +		if (*pattern == EOS) {		/* End of pattern? */
   1.698 +			*pathend = EOS;
   1.699 +			if (g_lstat(pathbuf, &sb, pglob))
   1.700 +				return(0);
   1.701 +
   1.702 +			if (((pglob->gl_flags & GLOB_MARK) &&
   1.703 +			    pathend[-1] != SEP) && (S_ISDIR(sb.st_mode)
   1.704 +			    || (S_ISLNK(sb.st_mode) &&
   1.705 +			    (g_stat(pathbuf, &sb, pglob) == 0) &&
   1.706 +			    S_ISDIR(sb.st_mode)))) {
   1.707 +				if (pathend + 1 > pathend_last)
   1.708 +					return (GLOB_ABORTED);
   1.709 +				*pathend++ = SEP;
   1.710 +				*pathend = EOS;
   1.711 +			}
   1.712 +			++pglob->gl_matchc;
   1.713 +			return(globextend(pathbuf, pglob, limit));
   1.714 +		}
   1.715 +
   1.716 +		/* Find end of next segment, copy tentatively to pathend. */
   1.717 +		q = pathend;
   1.718 +		p = pattern;
   1.719 +		while (*p != EOS && *p != SEP) {
   1.720 +			if (ismeta(*p))
   1.721 +				anymeta = 1;
   1.722 +			if (q + 1 > pathend_last)
   1.723 +				return (GLOB_ABORTED);
   1.724 +			*q++ = *p++;
   1.725 +		}
   1.726 +
   1.727 +		if (!anymeta) {		/* No expansion, do next segment. */
   1.728 +			pathend = q;
   1.729 +			pattern = p;
   1.730 +			while (*pattern == SEP) {
   1.731 +				if (pathend + 1 > pathend_last)
   1.732 +					return (GLOB_ABORTED);
   1.733 +				*pathend++ = *pattern++;
   1.734 +			}
   1.735 +		} else			/* Need expansion, recurse. */
   1.736 +			return(glob3(pathbuf, pathend, pathend_last, pattern, p,
   1.737 +			    pglob, limit));
   1.738 +	}
   1.739 +	/* NOTREACHED */
   1.740 +}
   1.741 +
   1.742 +static int
   1.743 +glob3(pathbuf, pathend, pathend_last, pattern, restpattern, pglob, limit)
   1.744 +	Char *pathbuf, *pathend, *pathend_last, *pattern, *restpattern;
   1.745 +	glob_t *pglob;
   1.746 +	int *limit;
   1.747 +{
   1.748 +	struct dirent *dp;
   1.749 +	DIR *dirp;
   1.750 +	int err;
   1.751 +	char buf[MAXPATHLEN];
   1.752 +
   1.753 +	/*
   1.754 +	 * The readdirfunc declaration can't be prototyped, because it is
   1.755 +	 * assigned, below, to two functions which are prototyped in glob.h
   1.756 +	 * and dirent.h as taking pointers to differently typed opaque
   1.757 +	 * structures.
   1.758 +	 */
   1.759 +	struct dirent *(*readdirfunc)();
   1.760 +
   1.761 +	if (pathend > pathend_last)
   1.762 +		return (GLOB_ABORTED);
   1.763 +	*pathend = EOS;
   1.764 +	errno = 0;
   1.765 +
   1.766 +	if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
   1.767 +		/* TODO: don't call for ENOENT or ENOTDIR? */
   1.768 +		if (pglob->gl_errfunc) {
   1.769 +			if (g_Ctoc(pathbuf, buf, sizeof(buf)))
   1.770 +				return (GLOB_ABORTED);
   1.771 +			if (pglob->gl_errfunc(buf, errno) ||
   1.772 +			    pglob->gl_flags & GLOB_ERR)
   1.773 +				return (GLOB_ABORTED);
   1.774 +		}
   1.775 +		return(0);
   1.776 +	}
   1.777 +
   1.778 +	err = 0;
   1.779 +
   1.780 +	/* Search directory for matching names. */
   1.781 +	if (pglob->gl_flags & GLOB_ALTDIRFUNC)
   1.782 +		readdirfunc = pglob->gl_readdir;
   1.783 +	else
   1.784 +		readdirfunc = readdir;
   1.785 +		while (NULL != (dp = (*readdirfunc)(dirp))) {
   1.786 +		u_char *sc;
   1.787 +		Char *dc;
   1.788 +		wchar_t wc;
   1.789 +		size_t clen;
   1.790 +		mbstate_t mbs;
   1.791 +
   1.792 +		/* Initial DOT must be matched literally. */
   1.793 +		if (dp->d_name[0] == DOT && *pattern != DOT)
   1.794 +			continue;
   1.795 +		memset(&mbs, 0, sizeof(mbs));
   1.796 +		dc = pathend;
   1.797 +		sc = (u_char *) dp->d_name;
   1.798 +		while (dc < pathend_last) {
   1.799 +			clen = mbrtowc(&wc,(char*)sc, MB_LEN_MAX, &mbs);
   1.800 +			if (clen == (size_t)-1 || clen == (size_t)-2) {
   1.801 +				wc = *sc;
   1.802 +				clen = 1;
   1.803 +				memset(&mbs, 0, sizeof(mbs));
   1.804 +			}
   1.805 +			if ((*dc++ = wc) == EOS)
   1.806 +				break;
   1.807 +			sc += clen;
   1.808 +		}
   1.809 +		if (!match(pathend, pattern, restpattern)) {
   1.810 +			*pathend = EOS;
   1.811 +			continue;
   1.812 +		}
   1.813 +		err = glob2(pathbuf, --dc, pathend_last, restpattern,
   1.814 +		    pglob, limit);
   1.815 +		if (err)
   1.816 +			break;
   1.817 +	}
   1.818 +
   1.819 +	if (pglob->gl_flags & GLOB_ALTDIRFUNC)
   1.820 +		(*pglob->gl_closedir)(dirp);
   1.821 +	else
   1.822 +		closedir(dirp);
   1.823 +	return(err);
   1.824 +}
   1.825 +
   1.826 +
   1.827 +/*
   1.828 + * Extend the gl_pathv member of a glob_t structure to accomodate a new item,
   1.829 + * add the new item, and update gl_pathc.
   1.830 + *
   1.831 + * This assumes the BSD realloc, which only copies the block when its size
   1.832 + * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
   1.833 + * behavior.
   1.834 + *
   1.835 + * Return 0 if new item added, error code if memory couldn't be allocated.
   1.836 + *
   1.837 + * Invariant of the glob_t structure:
   1.838 + *	Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
   1.839 + *	gl_pathv points to (gl_offs + gl_pathc + 1) items.
   1.840 + */
   1.841 +static int
   1.842 +globextend(path, pglob, limit)
   1.843 +	const Char *path;
   1.844 +	glob_t *pglob;
   1.845 +	int *limit;
   1.846 +{
   1.847 +	char **pathv;
   1.848 +	int i;
   1.849 +	u_int newsize, len;
   1.850 +	char *copy;
   1.851 +	const Char *p;
   1.852 +
   1.853 +	if (*limit && pglob->gl_pathc > *limit) {
   1.854 +		errno = 0;
   1.855 +		return (GLOB_NOSPACE);
   1.856 +	}
   1.857 +
   1.858 +	newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
   1.859 +	pathv = pglob->gl_pathv ?
   1.860 +		    realloc((char *)pglob->gl_pathv, newsize) :
   1.861 +		    malloc(newsize);
   1.862 +	if (pathv == NULL) {
   1.863 +		if (pglob->gl_pathv) {
   1.864 +			free(pglob->gl_pathv);
   1.865 +			pglob->gl_pathv = NULL;
   1.866 +		}
   1.867 +		return(GLOB_NOSPACE);
   1.868 +	}
   1.869 +
   1.870 +	if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
   1.871 +		/* first time around -- clear initial gl_offs items */
   1.872 +		pathv += pglob->gl_offs;
   1.873 +		for (i = pglob->gl_offs; --i >= 0; )
   1.874 +			*--pathv = NULL;
   1.875 +	}
   1.876 +	pglob->gl_pathv = pathv;
   1.877 +
   1.878 +	for (p = path; *p++;)
   1.879 +		continue;
   1.880 +	len = MB_CUR_MAX * (size_t)(p - path);	/* XXX overallocation */
   1.881 +	if ((copy = malloc(len)) != NULL) {
   1.882 +		if (g_Ctoc(path, copy, len)) {
   1.883 +			free(copy);
   1.884 +			return (GLOB_NOSPACE);
   1.885 +		}
   1.886 +		pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
   1.887 +	}
   1.888 +	pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
   1.889 +	return(copy == NULL ? GLOB_NOSPACE : 0);
   1.890 +}
   1.891 +
   1.892 +/*
   1.893 + * pattern matching function for filenames.  Each occurrence of the *
   1.894 + * pattern causes a recursion level.
   1.895 + */
   1.896 +static int
   1.897 +match(name, pat, patend)
   1.898 +	Char *name, *pat, *patend;
   1.899 +{
   1.900 +	int ok, negate_range;
   1.901 +	Char c, k;
   1.902 +
   1.903 +	while (pat < patend) {
   1.904 +		c = *pat++;
   1.905 +		switch (c & M_MASK) {
   1.906 +		case M_ALL:
   1.907 +			if (pat == patend)
   1.908 +				return(1);
   1.909 +			do
   1.910 +			    if (match(name, pat, patend))
   1.911 +				    return(1);
   1.912 +			while (*name++ != EOS);
   1.913 +			return(0);
   1.914 +		case M_ONE:
   1.915 +			if (*name++ == EOS)
   1.916 +				return(0);
   1.917 +			break;
   1.918 +		case M_SET:
   1.919 +			ok = 0;
   1.920 +			if ((k = *name++) == EOS)
   1.921 +				return(0);
   1.922 +			if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
   1.923 +				++pat;
   1.924 +			while (((c = *pat++) & M_MASK) != M_END)
   1.925 +				if ((*pat & M_MASK) == M_RNG) {
   1.926 +					if (
   1.927 +					// As used in vfscanf.c 
   1.928 +					#ifndef __SYMBIAN32__		
   1.929 +						__collate_load_error ?
   1.930 +					#else
   1.931 +						((strcmp("C",(const char*) LC_COLLATE_LocaleName)==0) ||(strcmp("POSIX", (const char*) LC_COLLATE_LocaleName)==0 )) ?
   1.932 +					#endif	
   1.933 +					    CHAR(c) <= CHAR(k) && CHAR(k) <= CHAR(pat[1]) :
   1.934 +					       __collate_range_cmp(CHAR(c), CHAR(k)) <= 0
   1.935 +					    && __collate_range_cmp(CHAR(k), CHAR(pat[1])) <= 0
   1.936 +					   )
   1.937 +						ok = 1;
   1.938 +					pat += 2;
   1.939 +				} else if (c == k)
   1.940 +					ok = 1;
   1.941 +			if (ok == negate_range)
   1.942 +				return(0);
   1.943 +			break;
   1.944 +		default:
   1.945 +			if (*name++ != c)
   1.946 +				return(0);
   1.947 +			break;
   1.948 +		}
   1.949 +	}
   1.950 +	return(*name == EOS);
   1.951 +}
   1.952 +
   1.953 +
   1.954 + 
   1.955 +
   1.956 +// EXTERNAL FUNCTION PROTOTYPES
   1.957 +//-----------------------------------------------------------------------------
   1.958 +//Function Name : void globfree(struct glob_t*)
   1.959 +//
   1.960 +//Description   : Free allocated data belonging to a glob_t structure. Memory 
   1.961 +//				  which was dynamically allocated storage from an earlier call to glob()
   1.962 +//				 
   1.963 +//Return Value  : None
   1.964 +//				  
   1.965 +//-----------------------------------------------------------------------------
   1.966 +
   1.967 +
   1.968 +EXPORT_C void
   1.969 +globfree(pglob)
   1.970 +	glob_t *pglob;
   1.971 +{
   1.972 +	int i;
   1.973 +	char **pp;
   1.974 +
   1.975 +	if (pglob->gl_pathv != NULL) {
   1.976 +		pp = pglob->gl_pathv + pglob->gl_offs;
   1.977 +		for (i = pglob->gl_pathc; i--; ++pp)
   1.978 +			if (*pp)
   1.979 +				free(*pp);
   1.980 +		free(pglob->gl_pathv);
   1.981 +		pglob->gl_pathv = NULL;
   1.982 +	}
   1.983 +}
   1.984 +
   1.985 +static DIR *
   1.986 +g_opendir(str, pglob)
   1.987 +	Char *str;
   1.988 +	glob_t *pglob;
   1.989 +{
   1.990 +	char buf[MAXPATHLEN];
   1.991 +
   1.992 +	if (!*str)
   1.993 +		strcpy(buf, ".");
   1.994 +	else {
   1.995 +		if (g_Ctoc(str, buf, sizeof(buf)))
   1.996 +			return (NULL);
   1.997 +	}
   1.998 +
   1.999 +	if (pglob->gl_flags & GLOB_ALTDIRFUNC)
  1.1000 +		return((*pglob->gl_opendir)(buf));
  1.1001 +
  1.1002 +	return(opendir(buf));
  1.1003 +}
  1.1004 +
  1.1005 +static int
  1.1006 +g_lstat(fn, sb, pglob)
  1.1007 +	Char *fn;
  1.1008 +	struct stat *sb;
  1.1009 +	glob_t *pglob;
  1.1010 +{
  1.1011 +	char buf[MAXPATHLEN];
  1.1012 +
  1.1013 +	if (g_Ctoc(fn, buf, sizeof(buf))) {
  1.1014 +		errno = ENAMETOOLONG;
  1.1015 +		return (-1);
  1.1016 +	}
  1.1017 +	if (pglob->gl_flags & GLOB_ALTDIRFUNC)
  1.1018 +		return((*pglob->gl_lstat)(buf, sb));
  1.1019 +	return(lstat(buf, sb));
  1.1020 +}
  1.1021 +
  1.1022 +static int
  1.1023 +g_stat(fn, sb, pglob)
  1.1024 +	Char *fn;
  1.1025 +	struct stat *sb;
  1.1026 +	glob_t *pglob;
  1.1027 +{
  1.1028 +	char buf[MAXPATHLEN];
  1.1029 +
  1.1030 +	if (g_Ctoc(fn, buf, sizeof(buf))) {
  1.1031 +		errno = ENAMETOOLONG;
  1.1032 +		return (-1);
  1.1033 +	}
  1.1034 +	if (pglob->gl_flags & GLOB_ALTDIRFUNC)
  1.1035 +		return((*pglob->gl_stat)(buf, sb));
  1.1036 +	return(stat(buf, sb));
  1.1037 +}
  1.1038 +
  1.1039 +static Char *
  1.1040 +g_strchr(Char *str, wchar_t ch)
  1.1041 +{
  1.1042 +	do {
  1.1043 +		if (*str == ch)
  1.1044 +			return (str);
  1.1045 +	} while (*str++);
  1.1046 +	return (NULL);
  1.1047 +}
  1.1048 +
  1.1049 +static int
  1.1050 +g_Ctoc(str, buf, len)
  1.1051 +	const Char *str;
  1.1052 +	char *buf;
  1.1053 +	u_int len;
  1.1054 +{
  1.1055 +	mbstate_t mbs;
  1.1056 +	size_t clen;
  1.1057 +
  1.1058 +	memset(&mbs, 0, sizeof(mbs));
  1.1059 +	while (len >= MB_CUR_MAX) {
  1.1060 +		clen = wcrtomb(buf, *str, &mbs);
  1.1061 +		if (clen == (size_t)-1)
  1.1062 +			return (1);
  1.1063 +		if (*str == L'\0')
  1.1064 +			return (0);
  1.1065 +		str++;
  1.1066 +		buf += clen;
  1.1067 +		len -= clen;
  1.1068 +	}
  1.1069 +	return (1);
  1.1070 +}
  1.1071 +
  1.1072 +#ifdef DEBUG
  1.1073 +static void
  1.1074 +qprintf(str, s)
  1.1075 +	const char *str;
  1.1076 +	Char *s;
  1.1077 +{
  1.1078 +	Char *p;
  1.1079 +
  1.1080 +	(void)printf("%s:\n", str);
  1.1081 +	for (p = s; *p; p++)
  1.1082 +		(void)printf("%c", CHAR(*p));
  1.1083 +	(void)printf("\n");
  1.1084 +	for (p = s; *p; p++)
  1.1085 +		(void)printf("%c", *p & M_PROTECT ? '"' : ' ');
  1.1086 +	(void)printf("\n");
  1.1087 +	for (p = s; *p; p++)
  1.1088 +		(void)printf("%c", ismeta(*p) ? '_' : ' ');
  1.1089 +	(void)printf("\n");
  1.1090 +}
  1.1091 +#endif
  1.1092 +
  1.1093 +#ifdef __cplusplus
  1.1094 +} // extern "C"
  1.1095 +#endif