Project

General

Profile

Bug #1097 » glob.c-rev.diff

Gary Mills, 2013-01-28 08:00 PM

View differences:

glob.c-rev Sun Jan 27 15:36:17 2013
1 1
/*
2
 * CDDL HEADER START
3
 *
4
 * The contents of this file are subject to the terms of the
5
 * Common Development and Distribution License (the "License").
6
 * You may not use this file except in compliance with the License.
7
 *
8
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9
 * or http://www.opensolaris.org/os/licensing.
10
 * See the License for the specific language governing permissions
11
 * and limitations under the License.
12
 *
13
 * When distributing Covered Code, include this CDDL HEADER in each
14
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15
 * If applicable, add the following below this CDDL HEADER, with the
16
 * fields enclosed by brackets "[]" replaced with your own identifying
17
 * information: Portions Copyright [yyyy] [name of copyright owner]
18
 *
19
 * CDDL HEADER END
20
 */
21

  
22
/*
23 2
 * Copyright (c) 2012 Gary Mills
24 3
 */
25

  
26 4
/*	$OpenBSD: glob.c,v 1.39 2012/01/20 07:09:42 tedu Exp $ */
27 5
/*
28 6
 * Copyright (c) 1989, 1993
......
119 97
#define	M_QUOTE		0x800000
120 98
#define	M_PROTECT	0x400000
121 99

  
122
typedef struct Char_s {
123
	wchar_t wc;
124
	uint_t at;
125
} Char;
100
typedef struct wcat {
101
	wchar_t w_wc;
102
	uint_t w_at;
103
} wcat_t;
126 104

  
127 105
#define	M_ALL		'*'	/* Plus M_QUOTE */
128 106
#define	M_END		']'	/* Plus M_QUOTE */
......
131 109
#define	M_RNG		'-'	/* Plus M_QUOTE */
132 110
#define	M_SET		'['	/* Plus M_QUOTE */
133 111
#define	M_CLASS		':'	/* Plus M_QUOTE */
134
#define	ismeta(c)	(((c).at&M_QUOTE) != 0)
112
#define	ismeta(c)	(((c).w_at&M_QUOTE) != 0)
135 113

  
136 114
#define	GLOB_LIMIT_MALLOC	65536
137 115
#define	GLOB_LIMIT_STAT		2048
......
153 131

  
154 132
static int	 compare(const void *, const void *);
155 133
static int	 compare_gps(const void *, const void *);
156
static int	 g_Ctoc(const Char *, char *, uint_t);
157
static int	 g_lstat(Char *, struct stat *, glob_t *);
158
static DIR	*g_opendir(Char *, glob_t *);
159
static Char	*g_strchr(const Char *, wchar_t);
160
static int	 g_stat(Char *, struct stat *, glob_t *);
161
static int	 glob0(const Char *, glob_t *, struct glob_lim *,
134
static int	 g_Ctoc(const wcat_t *, char *, uint_t);
135
static int	 g_lstat(wcat_t *, struct stat *, glob_t *);
136
static DIR	*g_opendir(wcat_t *, glob_t *);
137
static wcat_t	*g_strchr(const wcat_t *, wchar_t);
138
static int	 g_stat(wcat_t *, struct stat *, glob_t *);
139
static int	 glob0(const wcat_t *, glob_t *, struct glob_lim *,
162 140
			int (*)(const char *, int));
163
static int	 glob1(Char *, Char *, glob_t *, struct glob_lim *,
141
static int	 glob1(wcat_t *, wcat_t *, glob_t *, struct glob_lim *,
164 142
			int (*)(const char *, int));
165
static int	 glob2(Char *, Char *, Char *, Char *, Char *, Char *,
166
			glob_t *, struct glob_lim *,
143
static int	 glob2(wcat_t *, wcat_t *, wcat_t *, wcat_t *, wcat_t *,
144
			wcat_t *, glob_t *, struct glob_lim *,
167 145
			int (*)(const char *, int));
168
static int	 glob3(Char *, Char *, Char *, Char *, Char *,
169
			Char *, Char *, glob_t *, struct glob_lim *,
146
static int	 glob3(wcat_t *, wcat_t *, wcat_t *, wcat_t *, wcat_t *,
147
			wcat_t *, wcat_t *, glob_t *, struct glob_lim *,
170 148
			int (*)(const char *, int));
171
static int	 globextend(const Char *, glob_t *, struct glob_lim *,
149
static int	 globextend(const wcat_t *, glob_t *, struct glob_lim *,
172 150
		    struct stat *);
173 151
static
174
const Char	*globtilde(const Char *, Char *, size_t, glob_t *);
175
static int	 globexp1(const Char *, glob_t *, struct glob_lim *,
152
const wcat_t	*globtilde(const wcat_t *, wcat_t *, size_t, glob_t *);
153
static int	 globexp1(const wcat_t *, glob_t *, struct glob_lim *,
176 154
		    int (*)(const char *, int));
177
static int	 globexp2(const Char *, const Char *, glob_t *,
155
static int	 globexp2(const wcat_t *, const wcat_t *, glob_t *,
178 156
		    struct glob_lim *, int (*)(const char *, int));
179
static int	 match(Char *, Char *, Char *, int);
157
static int	 match(wcat_t *, wcat_t *, wcat_t *, int);
180 158
#ifdef DEBUG
181
static void	 qprintf(const char *, Char *);
159
static void	 qprintf(const char *, wcat_t *);
182 160
#endif
183 161

  
184 162
int
......
188 166
	const char *patnext;
189 167
	size_t n;
190 168
	wchar_t c;
191
	Char *bufnext, *bufend, patbuf[MAXPATHLEN];
169
	wcat_t *bufnext, *bufend, patbuf[MAXPATHLEN];
192 170
	struct glob_lim limit = { 0, 0, 0 };
193 171

  
194 172
	if (strnlen(pattern, PATH_MAX) == PATH_MAX)
......
215 193
	bufend = bufnext + MAXPATHLEN - 1;
216 194
	if (flags & GLOB_NOESCAPE) {
217 195
		while (bufnext < bufend) {
218
			if ((n = mbtowc(&c, patnext, PATH_MAX)) > 0) {
196
			if ((n = mbtowc(&c, patnext, MB_LEN_MAX)) > 0) {
219 197
				patnext += n;
220
				bufnext->at = 0;
221
				(bufnext++)->wc = c;
198
				bufnext->w_at = 0;
199
				(bufnext++)->w_wc = c;
222 200
			} else if (n == 0) {
223 201
				break;
224 202
			} else {
......
228 206
	} else {
229 207
		/* Protect the quoted characters. */
230 208
		while (bufnext < bufend) {
231
			if ((n = mbtowc(&c, patnext, PATH_MAX)) > 0) {
209
			if ((n = mbtowc(&c, patnext, MB_LEN_MAX)) > 0) {
232 210
				patnext += n;
233 211
				if (c == QUOTE) {
234
					n = mbtowc(&c, patnext, PATH_MAX);
212
					n = mbtowc(&c, patnext, MB_LEN_MAX);
235 213
					if (n < 0)
236 214
						return (GLOB_NOMATCH);
237 215
					if (n > 0)
238 216
						patnext += n;
239 217
					if (n == 0)
240 218
						c = QUOTE;
241
					bufnext->at = M_PROTECT;
242
					(bufnext++)->wc = c;
219
					bufnext->w_at = M_PROTECT;
220
					(bufnext++)->w_wc = c;
243 221
				} else {
244
					bufnext->at = 0;
245
					(bufnext++)->wc = c;
222
					bufnext->w_at = 0;
223
					(bufnext++)->w_wc = c;
246 224
				}
247 225
			} else if (n == 0) {
248 226
				break;
......
251 229
			}
252 230
		}
253 231
	}
254
	bufnext->at = 0;
255
	bufnext->wc = EOS;
232
	bufnext->w_at = 0;
233
	bufnext->w_wc = EOS;
256 234

  
257 235
	if (flags & GLOB_BRACE)
258 236
		return (globexp1(patbuf, pglob, &limit, errfunc));
......
266 244
 * characters
267 245
 */
268 246
static int
269
globexp1(const Char *pattern, glob_t *pglob, struct glob_lim *limitp,
247
globexp1(const wcat_t *pattern, glob_t *pglob, struct glob_lim *limitp,
270 248
    int (*errfunc)(const char *, int))
271 249
{
272
	const Char* ptr = pattern;
250
	const wcat_t *ptr = pattern;
273 251

  
274 252
	/* Protect a single {}, for find(1), like csh */
275
	if (pattern[0].wc == LBRACE && pattern[1].wc == RBRACE &&
276
	    pattern[2].wc == EOS)
253
	if (pattern[0].w_wc == LBRACE && pattern[1].w_wc == RBRACE &&
254
	    pattern[2].w_wc == EOS)
277 255
		return (glob0(pattern, pglob, limitp, errfunc));
278 256

  
279
	if ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL)
257
	if ((ptr = (const wcat_t *) g_strchr(ptr, LBRACE)) != NULL)
280 258
		return (globexp2(ptr, pattern, pglob, limitp, errfunc));
281 259

  
282 260
	return (glob0(pattern, pglob, limitp, errfunc));
......
289 267
 * If it fails then it tries to glob the rest of the pattern and returns.
290 268
 */
291 269
static int
292
globexp2(const Char *ptr, const Char *pattern, glob_t *pglob,
270
globexp2(const wcat_t *ptr, const wcat_t *pattern, glob_t *pglob,
293 271
    struct glob_lim *limitp, int (*errfunc)(const char *, int))
294 272
{
295 273
	int	i, rv;
296
	Char   *lm, *ls;
297
	const Char *pe, *pm, *pl;
298
	Char    patbuf[MAXPATHLEN];
274
	wcat_t   *lm, *ls;
275
	const wcat_t *pe, *pm, *pl;
276
	wcat_t    patbuf[MAXPATHLEN];
299 277

  
300 278
	/* copy part up to the brace */
301 279
	for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
302 280
		;
303
	lm->at = 0;
304
	lm->wc = EOS;
281
	lm->w_at = 0;
282
	lm->w_wc = EOS;
305 283
	ls = lm;
306 284

  
307 285
	/* Find the balanced brace */
308
	for (i = 0, pe = ++ptr; pe->wc != EOS; pe++)
309
		if (pe->wc == LBRACKET) {
286
	for (i = 0, pe = ++ptr; pe->w_wc != EOS; pe++)
287
		if (pe->w_wc == LBRACKET) {
310 288
			/* Ignore everything between [] */
311
			for (pm = pe++; pe->wc != RBRACKET &&
312
			    pe->wc != EOS; pe++)
289
			for (pm = pe++; pe->w_wc != RBRACKET &&
290
			    pe->w_wc != EOS; pe++)
313 291
				;
314
			if (pe->wc == EOS) {
292
			if (pe->w_wc == EOS) {
315 293
				/*
316 294
				 * We could not find a matching RBRACKET.
317 295
				 * Ignore and just look for RBRACE
318 296
				 */
319 297
				pe = pm;
320 298
			}
321
		} else if (pe->wc == LBRACE) {
299
		} else if (pe->w_wc == LBRACE) {
322 300
			i++;
323
		} else if (pe->wc == RBRACE) {
301
		} else if (pe->w_wc == RBRACE) {
324 302
			if (i == 0)
325 303
				break;
326 304
			i--;
327 305
		}
328 306

  
329 307
	/* Non matching braces; just glob the pattern */
330
	if (i != 0 || pe->wc == EOS)
308
	if (i != 0 || pe->w_wc == EOS)
331 309
		return (glob0(patbuf, pglob, limitp, errfunc));
332 310

  
333 311
	for (i = 0, pl = pm = ptr; pm <= pe; pm++) {
334
		switch (pm->wc) {
312
		switch (pm->w_wc) {
335 313
		case LBRACKET:
336 314
			/* Ignore everything between [] */
337
			for (pl = pm++; pm->wc != RBRACKET && pm->wc != EOS;
315
			for (pl = pm++; pm->w_wc != RBRACKET && pm->w_wc != EOS;
338 316
			    pm++)
339 317
				;
340
			if (pm->wc == EOS) {
318
			if (pm->w_wc == EOS) {
341 319
				/*
342 320
				 * We could not find a matching RBRACKET.
343 321
				 * Ignore and just look for RBRACE
......
357 335
			}
358 336
			/* FALLTHROUGH */
359 337
		case COMMA:
360
			if (i && pm->wc == COMMA)
338
			if (i && pm->w_wc == COMMA)
361 339
				break;
362 340
			else {
363 341
				/* Append the current string */
......
369 347
				 * closing brace
370 348
				 */
371 349
				for (pl = pe + 1;
372
				    (*lm++ = *pl++).wc != EOS; /* */)
350
				    (*lm++ = *pl++).w_wc != EOS; /* */)
373 351
					;
374 352

  
375 353
				/* Expand the current pattern */
......
394 372
/*
395 373
 * expand tilde from the passwd file.
396 374
 */
397
static const Char *
398
globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob)
375
static const wcat_t *
376
globtilde(const wcat_t *pattern, wcat_t *patbuf, size_t patbuf_len,
377
    glob_t *pglob)
399 378
{
400 379
	struct passwd *pwd;
401 380
	char *h;
402
	const Char *p;
403
	Char *b, *eb, *q;
381
	const wcat_t *p;
382
	wcat_t *b, *eb, *q;
404 383
	size_t n;
405 384
	wchar_t c;
406 385

  
407
	if (pattern->wc != TILDE || !(pglob->gl_flags & GLOB_TILDE))
386
	if (pattern->w_wc != TILDE || !(pglob->gl_flags & GLOB_TILDE))
408 387
		return (pattern);
409 388

  
410 389
	/* Copy up to the end of the string or / */
411 390
	eb = &patbuf[patbuf_len - 1];
412 391
	for (p = pattern + 1, q = patbuf;
413
	    q < eb && p->wc != EOS && p->wc != SLASH; *q++ = *p++)
392
	    q < eb && p->w_wc != EOS && p->w_wc != SLASH; *q++ = *p++)
414 393
		;
415 394

  
416
	q->at = 0;
417
	q->wc = EOS;
395
	q->w_at = 0;
396
	q->w_wc = EOS;
418 397

  
419 398
	/* What to do if patbuf is full? */
420 399

  
421
	if (patbuf[0].wc == EOS) {
400
	if (patbuf[0].w_wc == EOS) {
422 401
		/*
423 402
		 * handle a plain ~ or ~/ by expanding $HOME
424 403
		 * first and then trying the password file
425 404
		 */
426
		if (issetugid() != 0 || (h = getenv("HOME")) == NULL) {
405
		if (issetugid() != 0)
406
			return (pattern);
407
		if ((h = getenv("HOME")) == NULL) {
427 408
			if ((pwd = getpwuid(getuid())) == NULL)
428 409
				return (pattern);
429 410
			else
......
441 422

  
442 423
	/* Copy the home directory */
443 424
	for (b = patbuf; b < eb && *h != EOS; b++) {
444
		if ((n = mbtowc(&c, h, PATH_MAX)) > 0) {
425
		if ((n = mbtowc(&c, h, MB_LEN_MAX)) > 0) {
445 426
			h += n;
446
			b->at = 0;
447
			b->wc = c;
427
			b->w_at = 0;
428
			b->w_wc = c;
429
		} else if (n < 0) {
430
			return (pattern);
448 431
		} else {
449 432
			break;
450 433
		}
451 434
	}
452 435

  
453 436
	/* Append the rest of the pattern */
454
	while (b < eb && (*b++ = *p++).wc != EOS)
437
	while (b < eb && (*b++ = *p++).w_wc != EOS)
455 438
		;
456
	b->at = 0;
457
	b->wc = EOS;
439
	b->w_at = 0;
440
	b->w_wc = EOS;
458 441

  
459 442
	return (patbuf);
460 443
}
461 444

  
462 445
static int
463
g_charclass(const Char **patternp, Char **bufnextp)
446
g_charclass(const wcat_t **patternp, wcat_t **bufnextp)
464 447
{
465
	const Char *pattern = *patternp + 1;
466
	Char *bufnext = *bufnextp;
467
	const Char *colon;
448
	const wcat_t *pattern = *patternp + 1;
449
	wcat_t *bufnext = *bufnextp;
450
	const wcat_t *colon;
468 451
	char cbuf[MB_LEN_MAX + 32];
469 452
	wctype_t cc;
470 453
	size_t len;
471 454

  
472 455
	if ((colon = g_strchr(pattern, COLON)) == NULL ||
473
	    colon[1].wc != RBRACKET)
456
	    colon[1].w_wc != RBRACKET)
474 457
		return (1);	/* not a character class */
475 458

  
476 459
	len = (size_t)(colon - pattern);
......
478 461
		return (-1);	/* invalid character class */
479 462
	{
480 463
		wchar_t w;
481
		const Char *s1 = pattern;
464
		const wcat_t *s1 = pattern;
482 465
		char *s2 = cbuf;
483 466
		size_t n = len;
484 467

  
485 468
		/* Copy the string. */
486 469
		while (n > 0) {
487
			w = (s1++)->wc;
470
			w = (s1++)->w_wc;
488 471
			/* Character class names must be ASCII. */
489 472
			if (iswascii(w)) {
490 473
				n--;
......
497 480
	}
498 481
	if ((cc = wctype(cbuf)) == 0)
499 482
		return (-1);	/* invalid character class */
500
	bufnext->at = M_QUOTE;
501
	(bufnext++)->wc = M_CLASS;
502
	bufnext->at = 0;
503
	(bufnext++)->wc = cc;
483
	bufnext->w_at = M_QUOTE;
484
	(bufnext++)->w_wc = M_CLASS;
485
	bufnext->w_at = 0;
486
	(bufnext++)->w_wc = cc;
504 487
	*bufnextp = bufnext;
505 488
	*patternp += len + 3;
506 489

  
......
515 498
 * to find no matches.
516 499
 */
517 500
static int
518
glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp,
501
glob0(const wcat_t *pattern, glob_t *pglob, struct glob_lim *limitp,
519 502
    int (*errfunc)(const char *, int))
520 503
{
521
	const Char *qpatnext;
504
	const wcat_t *qpatnext;
522 505
	int err, oldpathc;
523 506
	wchar_t c;
524 507
	int a;
525
	Char *bufnext, patbuf[MAXPATHLEN];
508
	wcat_t *bufnext, patbuf[MAXPATHLEN];
526 509

  
527 510
	qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob);
528 511
	oldpathc = pglob->gl_pathc;
529 512
	bufnext = patbuf;
530 513

  
531
	/* We don't need to check for buffer overflow any more. */
532
	while ((a = qpatnext->at), (c = (qpatnext++)->wc) != EOS) {
514
	/*
515
	 * We don't need to check for buffer overflow any more.
516
	 * The pattern has already been copied to an internal buffer.
517
	 */
518
	while ((a = qpatnext->w_at), (c = (qpatnext++)->w_wc) != EOS) {
533 519
		switch (c) {
534 520
		case LBRACKET:
535 521
			if (a != 0) {
536
				bufnext->at = a;
537
				(bufnext++)->wc = c;
522
				bufnext->w_at = a;
523
				(bufnext++)->w_wc = c;
538 524
				break;
539 525
			}
540
			a = qpatnext->at;
541
			c = qpatnext->wc;
526
			a = qpatnext->w_at;
527
			c = qpatnext->w_wc;
542 528
			if (a == 0 && c == NOT)
543 529
				++qpatnext;
544
			if (qpatnext->wc == EOS ||
530
			if (qpatnext->w_wc == EOS ||
545 531
			    g_strchr(qpatnext+1, RBRACKET) == NULL) {
546
				bufnext->at = 0;
547
				(bufnext++)->wc = LBRACKET;
532
				bufnext->w_at = 0;
533
				(bufnext++)->w_wc = LBRACKET;
548 534
				if (a == 0 && c == NOT)
549 535
					--qpatnext;
550 536
				break;
551 537
			}
552
			bufnext->at = M_QUOTE;
553
			(bufnext++)->wc = M_SET;
538
			bufnext->w_at = M_QUOTE;
539
			(bufnext++)->w_wc = M_SET;
554 540
			if (a == 0 && c == NOT) {
555
				bufnext->at = M_QUOTE;
556
				(bufnext++)->wc = M_NOT;
541
				bufnext->w_at = M_QUOTE;
542
				(bufnext++)->w_wc = M_NOT;
557 543
			}
558
			a = qpatnext->at;
559
			c = (qpatnext++)->wc;
544
			a = qpatnext->w_at;
545
			c = (qpatnext++)->w_wc;
560 546
			do {
561 547
				if (a == 0 && c == LBRACKET &&
562
				    qpatnext->wc == COLON) {
548
				    qpatnext->w_wc == COLON) {
563 549
					do {
564 550
						err = g_charclass(&qpatnext,
565 551
						    &bufnext);
566 552
						if (err)
567 553
							break;
568
						a = qpatnext->at;
569
						c = (qpatnext++)->wc;
554
						a = qpatnext->w_at;
555
						c = (qpatnext++)->w_wc;
570 556
					} while (a == 0 && c == LBRACKET &&
571
					    qpatnext->wc == COLON);
557
					    qpatnext->w_wc == COLON);
572 558
					if (err == -1 &&
573 559
					    !(pglob->gl_flags & GLOB_NOCHECK))
574 560
						return (GLOB_NOMATCH);
575 561
					if (a == 0 && c == RBRACKET)
576 562
						break;
577 563
				}
578
				bufnext->at = a;
579
				(bufnext++)->wc = c;
580
				if (qpatnext->at == 0 &&
581
				    qpatnext->wc == RANGE) {
582
					a = qpatnext[1].at;
583
					c = qpatnext[1].wc;
584
					if (qpatnext[1].at != 0 ||
585
					    qpatnext[1].wc != RBRACKET) {
586
						bufnext->at = M_QUOTE;
587
						(bufnext++)->wc = M_RNG;
588
						bufnext->at = a;
589
						(bufnext++)->wc = c;
564
				bufnext->w_at = a;
565
				(bufnext++)->w_wc = c;
566
				if (qpatnext->w_at == 0 &&
567
				    qpatnext->w_wc == RANGE) {
568
					a = qpatnext[1].w_at;
569
					c = qpatnext[1].w_wc;
570
					if (qpatnext[1].w_at != 0 ||
571
					    qpatnext[1].w_wc != RBRACKET) {
572
						bufnext->w_at = M_QUOTE;
573
						(bufnext++)->w_wc = M_RNG;
574
						bufnext->w_at = a;
575
						(bufnext++)->w_wc = c;
590 576
						qpatnext += 2;
591 577
					}
592 578
				}
593
				a = qpatnext->at;
594
				c = (qpatnext++)->wc;
579
				a = qpatnext->w_at;
580
				c = (qpatnext++)->w_wc;
595 581
			} while (a != 0 || c != RBRACKET);
596 582
			pglob->gl_flags |= GLOB_MAGCHAR;
597
			bufnext->at = M_QUOTE;
598
			(bufnext++)->wc = M_END;
583
			bufnext->w_at = M_QUOTE;
584
			(bufnext++)->w_wc = M_END;
599 585
			break;
600 586
		case QUESTION:
601 587
			if (a != 0) {
602
				bufnext->at = a;
603
				(bufnext++)->wc = c;
588
				bufnext->w_at = a;
589
				(bufnext++)->w_wc = c;
604 590
				break;
605 591
			}
606 592
			pglob->gl_flags |= GLOB_MAGCHAR;
607
			bufnext->at = M_QUOTE;
608
			(bufnext++)->wc = M_ONE;
593
			bufnext->w_at = M_QUOTE;
594
			(bufnext++)->w_wc = M_ONE;
609 595
			break;
610 596
		case STAR:
611 597
			if (a != 0) {
612
				bufnext->at = a;
613
				(bufnext++)->wc = c;
598
				bufnext->w_at = a;
599
				(bufnext++)->w_wc = c;
614 600
				break;
615 601
			}
616 602
			pglob->gl_flags |= GLOB_MAGCHAR;
......
619 605
			 * to avoid exponential behavior
620 606
			 */
621 607
			if (bufnext == patbuf ||
622
			    bufnext[-1].at != M_QUOTE ||
623
			    bufnext[-1].wc != M_ALL) {
624
				bufnext->at = M_QUOTE;
625
				(bufnext++)->wc = M_ALL;
608
			    bufnext[-1].w_at != M_QUOTE ||
609
			    bufnext[-1].w_wc != M_ALL) {
610
				bufnext->w_at = M_QUOTE;
611
				(bufnext++)->w_wc = M_ALL;
626 612
			}
627 613
			break;
628 614
		default:
629
			bufnext->at = a;
630
			(bufnext++)->wc = c;
615
			bufnext->w_at = a;
616
			(bufnext++)->w_wc = c;
631 617
			break;
632 618
		}
633 619
	}
634
	bufnext->at = 0;
635
	bufnext->wc = EOS;
620
	bufnext->w_at = 0;
621
	bufnext->w_wc = EOS;
636 622
#ifdef DEBUG
637 623
	qprintf("glob0:glob1:patbuf", patbuf);
638 624
#endif
......
701 687
}
702 688

  
703 689
static int
704
glob1(Char *pattern, Char *pattern_last, glob_t *pglob,
690
glob1(wcat_t *pattern, wcat_t *pattern_last, glob_t *pglob,
705 691
    struct glob_lim *limitp, int (*errfunc)(const char *, int))
706 692
{
707
	Char pathbuf[MAXPATHLEN];
693
	wcat_t pathbuf[MAXPATHLEN];
708 694

  
709 695
	/* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
710
	if (pattern->wc == EOS)
696
	if (pattern->w_wc == EOS)
711 697
		return (0);
712 698
	return (glob2(pathbuf, pathbuf+MAXPATHLEN-1,
713 699
	    pathbuf, pathbuf+MAXPATHLEN-1,
......
720 706
 * meta characters.
721 707
 */
722 708
static int
723
glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
724
    Char *pattern, Char *pattern_last, glob_t *pglob,
725
    struct glob_lim *limitp, int (*errfunc)(const char *, int))
709
glob2(wcat_t *pathbuf, wcat_t *pathbuf_last, wcat_t *pathend,
710
    wcat_t *pathend_last, wcat_t *pattern, wcat_t *pattern_last,
711
    glob_t *pglob, struct glob_lim *limitp, int (*errfunc)(const char *, int))
726 712
{
727 713
	struct stat sb;
728
	Char *p, *q;
714
	wcat_t *p, *q;
729 715
	int anymeta;
730 716

  
731 717
	/*
......
733 719
	 * segment with meta character found.
734 720
	 */
735 721
	for (anymeta = 0; ; ) {
736
		if (pattern->wc == EOS) {		/* End of pattern? */
737
			pathend->at = 0;
738
			pathend->wc = EOS;
722
		if (pattern->w_wc == EOS) {		/* End of pattern? */
723
			pathend->w_at = 0;
724
			pathend->w_wc = EOS;
739 725

  
740 726
			if ((pglob->gl_flags & GLOB_LIMIT) &&
741 727
			    limitp->glim_stat++ >= GLOB_LIMIT_STAT) {
742 728
				errno = 0;
743
				pathend->at = 0;
744
				(pathend++)->wc = SEP;
745
				pathend->at = 0;
746
				pathend->wc = EOS;
729
				pathend->w_at = 0;
730
				(pathend++)->w_wc = SEP;
731
				pathend->w_at = 0;
732
				pathend->w_wc = EOS;
747 733
				return (GLOB_NOSPACE);
748 734
			}
749 735
			if (g_lstat(pathbuf, &sb, pglob))
750 736
				return (0);
751 737

  
752 738
			if (((pglob->gl_flags & GLOB_MARK) &&
753
			    (pathend[-1].at != 0 ||
754
			    pathend[-1].wc != SEP)) &&
739
			    (pathend[-1].w_at != 0 ||
740
			    pathend[-1].w_wc != SEP)) &&
755 741
			    (S_ISDIR(sb.st_mode) ||
756 742
			    (S_ISLNK(sb.st_mode) &&
757 743
			    (g_stat(pathbuf, &sb, pglob) == 0) &&
758 744
			    S_ISDIR(sb.st_mode)))) {
759 745
				if (pathend+1 > pathend_last)
760 746
					return (GLOB_NOSPACE);
761
				pathend->at = 0;
762
				(pathend++)->wc = SEP;
763
				pathend->at = 0;
764
				pathend->wc = EOS;
747
				pathend->w_at = 0;
748
				(pathend++)->w_wc = SEP;
749
				pathend->w_at = 0;
750
				pathend->w_wc = EOS;
765 751
			}
766 752
			++pglob->gl_matchc;
767 753
			return (globextend(pathbuf, pglob, limitp, &sb));
......
770 756
		/* Find end of next segment, copy tentatively to pathend. */
771 757
		q = pathend;
772 758
		p = pattern;
773
		while (p->wc != EOS && p->wc != SEP) {
759
		while (p->w_wc != EOS && p->w_wc != SEP) {
774 760
			if (ismeta(*p))
775 761
				anymeta = 1;
776 762
			if (q+1 > pathend_last)
......
781 767
		if (!anymeta) {		/* No expansion, do next segment. */
782 768
			pathend = q;
783 769
			pattern = p;
784
			while (pattern->wc == SEP) {
770
			while (pattern->w_wc == SEP) {
785 771
				if (pathend+1 > pathend_last)
786 772
					return (GLOB_NOSPACE);
787 773
				*pathend++ = *pattern++;
......
797 783
}
798 784

  
799 785
static int
800
glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
801
    Char *pattern, Char *restpattern, Char *restpattern_last, glob_t *pglob,
802
    struct glob_lim *limitp, int (*errfunc)(const char *, int))
786
glob3(wcat_t *pathbuf, wcat_t *pathbuf_last, wcat_t *pathend,
787
    wcat_t *pathend_last, wcat_t *pattern, wcat_t *restpattern,
788
    wcat_t *restpattern_last, glob_t *pglob, struct glob_lim *limitp,
789
    int (*errfunc)(const char *, int))
803 790
{
804 791
	struct dirent *dp;
805 792
	DIR *dirp;
......
816 803

  
817 804
	if (pathend > pathend_last)
818 805
		return (GLOB_NOSPACE);
819
	pathend->at = 0;
820
	pathend->wc = EOS;
806
	pathend->w_at = 0;
807
	pathend->w_wc = EOS;
821 808
	errno = 0;
822 809

  
823 810
	if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
......
841 828
		readdirfunc = (struct dirent *(*)(void *))readdir;
842 829
	while ((dp = (*readdirfunc)(dirp))) {
843 830
		char *sc;
844
		Char *dc;
831
		wcat_t *dc;
845 832
		size_t n;
846 833
		wchar_t w;
847 834

  
848 835
		if ((pglob->gl_flags & GLOB_LIMIT) &&
849 836
		    limitp->glim_readdir++ >= GLOB_LIMIT_READDIR) {
850 837
			errno = 0;
851
			pathend->at = 0;
852
			(pathend++)->wc = SEP;
853
			pathend->at = 0;
854
			pathend->wc = EOS;
838
			pathend->w_at = 0;
839
			(pathend++)->w_wc = SEP;
840
			pathend->w_at = 0;
841
			pathend->w_wc = EOS;
855 842
			err = GLOB_NOSPACE;
856 843
			break;
857 844
		}
858 845

  
859 846
		/* Initial DOT must be matched literally. */
860
		if (dp->d_name[0] == DOT && pattern->wc != DOT)
847
		if (dp->d_name[0] == DOT && pattern->w_wc != DOT)
861 848
			continue;
862 849
		dc = pathend;
863 850
		sc = dp->d_name;
864 851
		while (dc < pathend_last) {
865 852
			if ((n = mbtowc(&w, sc, MB_LEN_MAX)) <= 0) {
866 853
				sc += 1;
867
				dc->at = 0;
868
				dc->wc = EOS;
854
				dc->w_at = 0;
855
				dc->w_wc = EOS;
869 856
			} else {
870 857
				sc += n;
871
				dc->at = 0;
872
				dc->wc = w;
858
				dc->w_at = 0;
859
				dc->w_wc = w;
873 860
			}
874 861
			dc++;
875 862
			if (n <= 0)
876 863
				break;
877 864
		}
878 865
		if (dc >= pathend_last) {
879
			dc->at = 0;
880
			dc->wc = EOS;
866
			dc->w_at = 0;
867
			dc->w_wc = EOS;
881 868
			err = GLOB_NOSPACE;
882 869
			break;
883 870
		}
884 871
		if (n < 0) {
885
			dc->at = 0;
886
			dc->wc = EOS;
887
			continue;
872
			err = GLOB_NOMATCH;
873
			break;
888 874
		}
889 875

  
890 876
		if (!match(pathend, pattern, restpattern, GLOB_LIMIT_RECUR)) {
891
			pathend->at = 0;
892
			pathend->wc = EOS;
877
			pathend->w_at = 0;
878
			pathend->w_wc = EOS;
893 879
			continue;
894 880
		}
895 881
		err = glob2(pathbuf, pathbuf_last, --dc, pathend_last,
......
922 908
 *	gl_pathv points to (gl_offs + gl_pathc + 1) items.
923 909
 */
924 910
static int
925
globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp,
911
globextend(const wcat_t *path, glob_t *pglob, struct glob_lim *limitp,
926 912
    struct stat *sb)
927 913
{
928 914
	char **pathv;
929 915
	ssize_t i;
930 916
	size_t newn, len;
931 917
	char *copy = NULL;
932
	const Char *p;
918
	const wcat_t *p;
933 919
	struct stat **statv;
934 920
	char junk[MB_LEN_MAX];
935 921
	int n;
......
945 931
			if (pglob->gl_pathv && pglob->gl_pathv[i])
946 932
				free(pglob->gl_pathv[i]);
947 933
			if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0 &&
948
			    pglob->gl_pathv && pglob->gl_pathv[i])
934
			    pglob->gl_statv && pglob->gl_statv[i])
949 935
				free(pglob->gl_statv[i]);
950 936
		}
951 937
		if (pglob->gl_pathv) {
......
1002 988

  
1003 989
	len = MB_LEN_MAX;
1004 990
	p = path;
1005
	while ((n = wctomb(junk, p->wc)) > 0) {
991
	while ((n = wctomb(junk, p->w_wc)) > 0) {
1006 992
		len += n;
1007
		if ((p++)->wc == EOS)
993
		if ((p++)->w_wc == EOS)
1008 994
			break;
1009 995
	}
996
	if (n < 0)
997
		return (GLOB_NOMATCH);
1010 998

  
1011 999
	limitp->glim_malloc += len;
1012 1000
	if ((copy = malloc(len)) != NULL) {
......
1034 1022
 * pattern causes a recursion level.
1035 1023
 */
1036 1024
static int
1037
match(Char *name, Char *pat, Char *patend, int recur)
1025
match(wcat_t *name, wcat_t *pat, wcat_t *patend, int recur)
1038 1026
{
1039 1027
	int ok, negate_range;
1040
	Char c, k;
1028
	wcat_t c, k;
1041 1029

  
1042 1030
	if (recur-- == 0)
1043 1031
		return (1);
1044 1032

  
1045 1033
	while (pat < patend) {
1046 1034
		c = *pat++;
1047
		switch (c.wc) {
1035
		switch (c.w_wc) {
1048 1036
		case M_ALL:
1049
			if (c.at != M_QUOTE) {
1037
			if (c.w_at != M_QUOTE) {
1050 1038
				k = *name++;
1051
				if (k.at != c.at || k.wc != c.wc)
1039
				if (k.w_at != c.w_at || k.w_wc != c.w_wc)
1052 1040
					return (0);
1053 1041
				break;
1054 1042
			}
1055
			while (pat < patend && pat->at == M_QUOTE &&
1056
			    pat->wc == M_ALL)
1043
			while (pat < patend && pat->w_at == M_QUOTE &&
1044
			    pat->w_wc == M_ALL)
1057 1045
				pat++;	/* eat consecutive '*' */
1058 1046
			if (pat == patend)
1059 1047
				return (1);
1060 1048
			do {
1061 1049
				if (match(name, pat, patend, recur))
1062 1050
					return (1);
1063
			} while ((name++)->wc != EOS);
1051
			} while ((name++)->w_wc != EOS);
1064 1052
			return (0);
1065 1053
		case M_ONE:
1066
			if (c.at != M_QUOTE) {
1054
			if (c.w_at != M_QUOTE) {
1067 1055
				k = *name++;
1068
				if (k.at != c.at || k.wc != c.wc)
1056
				if (k.w_at != c.w_at || k.w_wc != c.w_wc)
1069 1057
					return (0);
1070 1058
				break;
1071 1059
			}
1072
			if ((name++)->wc == EOS)
1060
			if ((name++)->w_wc == EOS)
1073 1061
				return (0);
1074 1062
			break;
1075 1063
		case M_SET:
1076
			if (c.at != M_QUOTE) {
1064
			if (c.w_at != M_QUOTE) {
1077 1065
				k = *name++;
1078
				if (k.at != c.at || k.wc != c.wc)
1066
				if (k.w_at != c.w_at || k.w_wc != c.w_wc)
1079 1067
					return (0);
1080 1068
				break;
1081 1069
			}
1082 1070
			ok = 0;
1083
			if ((k = *name++).wc == EOS)
1071
			if ((k = *name++).w_wc == EOS)
1084 1072
				return (0);
1085
			if ((negate_range = (pat->at == M_QUOTE &&
1086
			    pat->wc == M_NOT)) != 0)
1073
			if ((negate_range = (pat->w_at == M_QUOTE &&
1074
			    pat->w_wc == M_NOT)) != 0)
1087 1075
				++pat;
1088
			while (((c = *pat++).at != M_QUOTE) || c.wc != M_END) {
1089
				if (c.at == M_QUOTE && c.wc == M_CLASS) {
1090
					Char cc;
1076
			while (((c = *pat++).w_at != M_QUOTE) ||
1077
			    c.w_wc != M_END) {
1078
				if (c.w_at == M_QUOTE && c.w_wc == M_CLASS) {
1079
					wcat_t cc;
1091 1080

  
1092
					cc.at = pat->at;
1093
					cc.wc = pat->wc;
1094
					if (iswctype(k.wc, cc.wc))
1081
					cc.w_at = pat->w_at;
1082
					cc.w_wc = pat->w_wc;
1083
					if (iswctype(k.w_wc, cc.w_wc))
1095 1084
						ok = 1;
1096 1085
					++pat;
1097 1086
				}
1098
				if (pat->at == M_QUOTE && pat->wc == M_RNG) {
1099
					if (c.wc <= k.wc && k.wc <= pat[1].wc)
1087
				if (pat->w_at == M_QUOTE &&
1088
				    pat->w_wc == M_RNG) {
1089
					if (c.w_wc <= k.w_wc &&
1090
					    k.w_wc <= pat[1].w_wc)
1100 1091
						ok = 1;
1101 1092
					pat += 2;
1102
				} else if (c.wc == k.wc)
1093
				} else if (c.w_wc == k.w_wc)
1103 1094
					ok = 1;
1104 1095
			}
1105 1096
			if (ok == negate_range)
......
1107 1098
			break;
1108 1099
		default:
1109 1100
			k = *name++;
1110
			if (k.at != c.at || k.wc != c.wc)
1101
			if (k.w_at != c.w_at || k.w_wc != c.w_wc)
1111 1102
				return (0);
1112 1103
			break;
1113 1104
		}
1114 1105
	}
1115
	return (name->wc == EOS);
1106
	return (name->w_wc == EOS);
1116 1107
}
1117 1108

  
1118 1109
/* Free allocated data belonging to a glob_t structure. */
......
1142 1133
}
1143 1134

  
1144 1135
static DIR *
1145
g_opendir(Char *str, glob_t *pglob)
1136
g_opendir(wcat_t *str, glob_t *pglob)
1146 1137
{
1147 1138
	char buf[MAXPATHLEN];
1148 1139

  
1149
	if (str->wc == EOS)
1140
	if (str->w_wc == EOS)
1150 1141
		strlcpy(buf, ".", sizeof (buf));
1151 1142
	else {
1152 1143
		if (g_Ctoc(str, buf, sizeof (buf)))
......
1160 1151
}
1161 1152

  
1162 1153
static int
1163
g_lstat(Char *fn, struct stat *sb, glob_t *pglob)
1154
g_lstat(wcat_t *fn, struct stat *sb, glob_t *pglob)
1164 1155
{
1165 1156
	char buf[MAXPATHLEN];
1166 1157

  
......
1172 1163
}
1173 1164

  
1174 1165
static int
1175
g_stat(Char *fn, struct stat *sb, glob_t *pglob)
1166
g_stat(wcat_t *fn, struct stat *sb, glob_t *pglob)
1176 1167
{
1177 1168
	char buf[MAXPATHLEN];
1178 1169

  
......
1183 1174
	return (stat(buf, sb));
1184 1175
}
1185 1176

  
1186
static Char *
1187
g_strchr(const Char *str, wchar_t ch)
1177
static wcat_t *
1178
g_strchr(const wcat_t *str, wchar_t ch)
1188 1179
{
1189 1180
	do {
1190
		if (str->at == 0 && str->wc == ch)
1191
			return ((Char *)str);
1192
	} while ((str++)->wc != EOS);
1181
		if (str->w_at == 0 && str->w_wc == ch)
1182
			return ((wcat_t *)str);
1183
	} while ((str++)->w_wc != EOS);
1193 1184
	return (NULL);
1194 1185
}
1195 1186

  
1196 1187
static int
1197
g_Ctoc(const Char *str, char *buf, uint_t len)
1188
g_Ctoc(const wcat_t *str, char *buf, uint_t len)
1198 1189
{
1199 1190
	int n;
1200 1191
	wchar_t w;
1201 1192

  
1202 1193
	while (len >= MB_LEN_MAX) {
1203
		w = (str++)->wc;
1194
		w = (str++)->w_wc;
1204 1195
		if ((n = wctomb(buf, w)) > 0) {
1205 1196
			len -= n;
1206 1197
			buf += n;
......
1215 1206

  
1216 1207
#ifdef DEBUG
1217 1208
static void
1218
qprintf(const char *str, Char *s)
1209
qprintf(const char *str, wcat_t *s)
1219 1210
{
1220
	Char *p;
1211
	wcat_t *p;
1221 1212

  
1222 1213
	(void) printf("%s:\n", str);
1223
	for (p = s; p->wc != EOS; p++)
1224
		(void) printf("%wc", p->wc);
1214
	for (p = s; p->w_wc != EOS; p++)
1215
		(void) printf("%wc", p->w_wc);
1225 1216
	(void) printf("\n");
1226
	for (p = s; p->wc != EOS; p++)
1227
		(void) printf("%c", p->at & M_PROTECT ? '"' : ' ');
1217
	for (p = s; p->w_wc != EOS; p++)
1218
		(void) printf("%c", p->w_at & M_PROTECT ? '"' : ' ');
1228 1219
	(void) printf("\n");
1229
	for (p = s; p->wc != EOS; p++)
1220
	for (p = s; p->w_wc != EOS; p++)
1230 1221
		(void) printf("%c", ismeta(*p) ? '_' : ' ');
1231 1222
	(void) printf("\n");
1232 1223
}
(9-9/11)