Project

General

Profile

Bug #1097 » glob.c-mb.diff

Gary Mills, 2012-12-17 03:53 PM

View differences:

glob.c-mb Sun Dec 16 20:45:47 2012
94 94
#include <stdlib.h>
95 95
#include <string.h>
96 96
#include <unistd.h>
97
#include <wchar.h>
97 98

  
98 99
#include "charclass.h"
99 100

  
......
114 115
#define	RBRACE		'}'
115 116
#define	SLASH		'/'
116 117
#define	COMMA		','
118
#define	COLON		':'
117 119

  
118
#ifndef DEBUG
120
#define	M_QUOTE		0x800000
121
#define	M_PROTECT	0x400000
119 122

  
120
#define	M_QUOTE		0x8000
121
#define	M_PROTECT	0x4000
122
#define	M_MASK		0xffff
123
#define	M_ASCII		0x00ff
123
typedef struct Char_s {
124
	wchar_t wc;
125
	uint_t at;
126
} Char;
124 127

  
125
typedef ushort_t Char;
128
#define	M_ALL		'*'	/* Plus M_QUOTE */
129
#define	M_END		']'	/* Plus M_QUOTE */
130
#define	M_NOT		'!'	/* Plus M_QUOTE */
131
#define	M_ONE		'?'	/* Plus M_QUOTE */
132
#define	M_RNG		'-'	/* Plus M_QUOTE */
133
#define	M_SET		'['	/* Plus M_QUOTE */
134
#define	M_CLASS		':'	/* Plus M_QUOTE */
135
#define	ismeta(c)	(((c).at&M_QUOTE) != 0)
126 136

  
127
#else
128

  
129
#define	M_QUOTE		0x80
130
#define	M_PROTECT	0x40
131
#define	M_MASK		0xff
132
#define	M_ASCII		0x7f
133

  
134
typedef char Char;
135

  
136
#endif
137

  
138

  
139
#define	CHAR(c)		((Char)((c)&M_ASCII))
140
#define	META(c)		((Char)((c)|M_QUOTE))
141
#define	M_ALL		META('*')
142
#define	M_END		META(']')
143
#define	M_NOT		META('!')
144
#define	M_ONE		META('?')
145
#define	M_RNG		META('-')
146
#define	M_SET		META('[')
147
#define	M_CLASS		META(':')
148
#define	ismeta(c)	(((c)&M_QUOTE) != 0)
149

  
150 137
#define	GLOB_LIMIT_MALLOC	65536
151 138
#define	GLOB_LIMIT_STAT		2048
152 139
#define	GLOB_LIMIT_READDIR	16384
......
170 157
static int	 g_Ctoc(const Char *, char *, uint_t);
171 158
static int	 g_lstat(Char *, struct stat *, glob_t *);
172 159
static DIR	*g_opendir(Char *, glob_t *);
173
static Char	*g_strchr(const Char *, int);
174
static int	 g_strncmp(const Char *, const char *, size_t);
160
static Char	*g_strchr(const Char *, wchar_t);
175 161
static int	 g_stat(Char *, struct stat *, glob_t *);
176 162
static int	 glob0(const Char *, glob_t *, struct glob_lim *,
177 163
			int (*)(const char *, int));
......
200 186
glob(const char *pattern, int flags, int (*errfunc)(const char *, int),
201 187
    glob_t *pglob)
202 188
{
203
	const uchar_t *patnext;
204
	int c;
189
	const char *patnext;
190
	size_t n;
191
	wchar_t c;
205 192
	Char *bufnext, *bufend, patbuf[MAXPATHLEN];
206 193
	struct glob_lim limit = { 0, 0, 0 };
207 194

  
208 195
	if (strnlen(pattern, PATH_MAX) == PATH_MAX)
209 196
		return (GLOB_NOMATCH);
210 197

  
211
	patnext = (uchar_t *)pattern;
198
	patnext = pattern;
212 199
	if (!(flags & GLOB_APPEND)) {
213 200
		pglob->gl_pathc = 0;
214 201
		pglob->gl_pathv = NULL;
......
227 214

  
228 215
	bufnext = patbuf;
229 216
	bufend = bufnext + MAXPATHLEN - 1;
230
	if (flags & GLOB_NOESCAPE)
231
		while (bufnext < bufend && (c = *patnext++) != EOS)
232
			*bufnext++ = c;
233
	else {
217
	if (flags & GLOB_NOESCAPE) {
218
		while (bufnext < bufend) {
219
			if ((n = mbtowc(&c, patnext, PATH_MAX)) > 0) {
220
				patnext += n;
221
				bufnext->at = 0;
222
				(bufnext++)->wc = c;
223
			} else if (n == 0) {
224
				break;
225
			} else {
226
				return (GLOB_NOMATCH);
227
			}
228
		}
229
	} else {
234 230
		/* Protect the quoted characters. */
235
		while (bufnext < bufend && (c = *patnext++) != EOS)
236
			if (c == QUOTE) {
237
				if ((c = *patnext++) == EOS) {
238
					c = QUOTE;
239
					--patnext;
231
		while (bufnext < bufend) {
232
			if ((n = mbtowc(&c, patnext, PATH_MAX)) > 0) {
233
				patnext += n;
234
				if (c == QUOTE) {
235
					n = mbtowc(&c, patnext, PATH_MAX);
236
					if (n < 0)
237
						return (GLOB_NOMATCH);
238
					if (n > 0)
239
						patnext += n;
240
					if (n == 0)
241
						c = QUOTE;
242
					bufnext->at = M_PROTECT;
243
					(bufnext++)->wc = c;
244
				} else {
245
					bufnext->at = 0;
246
					(bufnext++)->wc = c;
240 247
				}
241
				*bufnext++ = c | M_PROTECT;
242
			} else
243
				*bufnext++ = c;
248
			} else if (n == 0) {
249
				break;
250
			} else {
251
				return (GLOB_NOMATCH);
252
			}
253
		}
244 254
	}
245
	*bufnext = EOS;
255
	bufnext->at = 0;
256
	bufnext->wc = EOS;
246 257

  
247 258
	if (flags & GLOB_BRACE)
248 259
		return (globexp1(patbuf, pglob, &limit, errfunc));
......
262 273
	const Char* ptr = pattern;
263 274

  
264 275
	/* Protect a single {}, for find(1), like csh */
265
	if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
276
	if (pattern[0].wc == LBRACE && pattern[1].wc == RBRACE &&
277
	    pattern[2].wc == EOS)
266 278
		return (glob0(pattern, pglob, limitp, errfunc));
267 279

  
268 280
	if ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL)
......
289 301
	/* copy part up to the brace */
290 302
	for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
291 303
		;
292
	*lm = EOS;
304
	lm->at = 0;
305
	lm->wc = EOS;
293 306
	ls = lm;
294 307

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

  
316 330
	/* Non matching braces; just glob the pattern */
317
	if (i != 0 || *pe == EOS)
331
	if (i != 0 || pe->wc == EOS)
318 332
		return (glob0(patbuf, pglob, limitp, errfunc));
319 333

  
320 334
	for (i = 0, pl = pm = ptr; pm <= pe; pm++) {
321
		switch (*pm) {
335
		switch (pm->wc) {
322 336
		case LBRACKET:
323 337
			/* Ignore everything between [] */
324
			for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++)
338
			for (pl = pm++; pm->wc != RBRACKET && pm->wc != EOS;
339
			    pm++)
325 340
				;
326
			if (*pm == EOS) {
341
			if (pm->wc == EOS) {
327 342
				/*
328 343
				 * We could not find a matching RBRACKET.
329 344
				 * Ignore and just look for RBRACE
......
343 358
			}
344 359
			/* FALLTHROUGH */
345 360
		case COMMA:
346
			if (i && *pm == COMMA)
361
			if (i && pm->wc == COMMA)
347 362
				break;
348 363
			else {
349 364
				/* Append the current string */
......
354 369
				 * Append the rest of the pattern after the
355 370
				 * closing brace
356 371
				 */
357
				for (pl = pe + 1; (*lm++ = *pl++) != EOS; )
372
				for (pl = pe + 1;
373
				    (*lm++ = *pl++).wc != EOS; /* */)
358 374
					;
359 375

  
360 376
				/* Expand the current pattern */
361
#ifdef DEBUG
362
				qprintf("globexp2:", patbuf);
363
#endif
364 377
				rv = globexp1(patbuf, pglob, limitp, errfunc);
365 378
				if (rv && rv != GLOB_NOMATCH)
366 379
					return (rv);
......
388 401
	struct passwd *pwd;
389 402
	char *h;
390 403
	const Char *p;
391
	Char *b, *eb;
404
	Char *b, *eb, *q;
405
	size_t n;
406
	wchar_t c;
392 407

  
393
	if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
408
	if (pattern->wc != TILDE || !(pglob->gl_flags & GLOB_TILDE))
394 409
		return (pattern);
395 410

  
396 411
	/* Copy up to the end of the string or / */
397 412
	eb = &patbuf[patbuf_len - 1];
398
	for (p = pattern + 1, h = (char *)patbuf;
399
	    h < (char *)eb && *p && *p != SLASH; *h++ = *p++)
413
	for (p = pattern + 1, q = patbuf;
414
	    q < eb && p->wc != EOS && p->wc != SLASH; *q++ = *p++)
400 415
		;
401 416

  
402
	*h = EOS;
417
	q->at = 0;
418
	q->wc = EOS;
403 419

  
404
#if 0
405
	if (h == (char *)eb)
406
		return (what);
407
#endif
420
	/* What to do if patbuf is full? */
408 421

  
409
	if (((char *)patbuf)[0] == EOS) {
422
	if (patbuf[0].wc == EOS) {
410 423
		/*
411 424
		 * handle a plain ~ or ~/ by expanding $HOME
412 425
		 * first and then trying the password file
......
428 441
	}
429 442

  
430 443
	/* Copy the home directory */
431
	for (b = patbuf; b < eb && *h; *b++ = *h++)
432
		;
444
	for (b = patbuf; b < eb && *h != EOS; b++) {
445
		if ((n = mbtowc(&c, h, PATH_MAX)) > 0) {
446
			h += n;
447
			b->at = 0;
448
			b->wc = c;
449
		} else {
450
			break;
451
		}
452
	}
433 453

  
434 454
	/* Append the rest of the pattern */
435
	while (b < eb && (*b++ = *p++) != EOS)
455
	while (b < eb && (*b++ = *p++).wc != EOS)
436 456
		;
437
	*b = EOS;
457
	b->at = 0;
458
	b->wc = EOS;
438 459

  
439 460
	return (patbuf);
440 461
}
441 462

  
442 463
static int
443
g_strncmp(const Char *s1, const char *s2, size_t n)
444
{
445
	int rv = 0;
446

  
447
	while (n--) {
448
		rv = *(Char *)s1 - *(const unsigned char *)s2++;
449
		if (rv)
450
			break;
451
		if (*s1++ == '\0')
452
			break;
453
	}
454
	return (rv);
455
}
456

  
457
static int
458 464
g_charclass(const Char **patternp, Char **bufnextp)
459 465
{
460 466
	const Char *pattern = *patternp + 1;
......
463 469
	struct cclass *cc;
464 470
	size_t len;
465 471

  
466
	if ((colon = g_strchr(pattern, ':')) == NULL || colon[1] != ']')
472
	if ((colon = g_strchr(pattern, COLON)) == NULL ||
473
	    colon[1].wc != RBRACKET)
467 474
		return (1);	/* not a character class */
468 475

  
469 476
	len = (size_t)(colon - pattern);
470 477
	for (cc = cclasses; cc->name != NULL; cc++) {
471
		if (!g_strncmp(pattern, cc->name, len) && cc->name[len] == '\0')
478
		wchar_t w;
479
		const Char *s1 = pattern;
480
		const char *s2 = cc->name;
481
		size_t n = len;
482

  
483
		/* Are the strings the same? */
484
		while (n > 0 && (w = (s1++)->wc) == *s2 && w != EOS) {
485
			n--;
486
			s2++;
487
		}
488
		if (n == 0 && *s2 == EOS)
472 489
			break;
473 490
	}
474 491
	if (cc->name == NULL)
475 492
		return (-1);	/* invalid character class */
476
	*bufnext++ = M_CLASS;
477
	*bufnext++ = (Char)(cc - &cclasses[0]);
493
	bufnext->at = M_QUOTE;
494
	(bufnext++)->wc = M_CLASS;
495
	bufnext->at = (cc - &cclasses[0]);
496
	(bufnext++)->wc = COLON;
478 497
	*bufnextp = bufnext;
479 498
	*patternp += len + 3;
480 499

  
......
493 512
    int (*errfunc)(const char *, int))
494 513
{
495 514
	const Char *qpatnext;
496
	int c, err, oldpathc;
515
	int err, oldpathc;
516
	wchar_t c;
517
	int a;
497 518
	Char *bufnext, patbuf[MAXPATHLEN];
498 519

  
499 520
	qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob);
......
501 522
	bufnext = patbuf;
502 523

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

  
571 633
	if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, limitp, errfunc))
......
638 700
	Char pathbuf[MAXPATHLEN];
639 701

  
640 702
	/* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
641
	if (*pattern == EOS)
703
	if (pattern->wc == EOS)
642 704
		return (0);
643 705
	return (glob2(pathbuf, pathbuf+MAXPATHLEN-1,
644 706
	    pathbuf, pathbuf+MAXPATHLEN-1,
......
664 726
	 * segment with meta character found.
665 727
	 */
666 728
	for (anymeta = 0; ; ) {
667
		if (*pattern == EOS) {		/* End of pattern? */
668
			*pathend = EOS;
729
		if (pattern->wc == EOS) {		/* End of pattern? */
730
			pathend->at = 0;
731
			pathend->wc = EOS;
669 732

  
670 733
			if ((pglob->gl_flags & GLOB_LIMIT) &&
671 734
			    limitp->glim_stat++ >= GLOB_LIMIT_STAT) {
672 735
				errno = 0;
673
				*pathend++ = SEP;
674
				*pathend = EOS;
736
				pathend->at = 0;
737
				(pathend++)->wc = SEP;
738
				pathend->at = 0;
739
				pathend->wc = EOS;
675 740
				return (GLOB_NOSPACE);
676 741
			}
677 742
			if (g_lstat(pathbuf, &sb, pglob))
678 743
				return (0);
679 744

  
680 745
			if (((pglob->gl_flags & GLOB_MARK) &&
681
			    pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) ||
746
			    (pathend[-1].at != 0 ||
747
			    pathend[-1].wc != SEP)) &&
748
			    (S_ISDIR(sb.st_mode) ||
682 749
			    (S_ISLNK(sb.st_mode) &&
683 750
			    (g_stat(pathbuf, &sb, pglob) == 0) &&
684 751
			    S_ISDIR(sb.st_mode)))) {
685 752
				if (pathend+1 > pathend_last)
686
					return (1);
687
				*pathend++ = SEP;
688
				*pathend = EOS;
753
					return (GLOB_NOSPACE);
754
				pathend->at = 0;
755
				(pathend++)->wc = SEP;
756
				pathend->at = 0;
757
				pathend->wc = EOS;
689 758
			}
690 759
			++pglob->gl_matchc;
691 760
			return (globextend(pathbuf, pglob, limitp, &sb));
......
694 763
		/* Find end of next segment, copy tentatively to pathend. */
695 764
		q = pathend;
696 765
		p = pattern;
697
		while (*p != EOS && *p != SEP) {
766
		while (p->wc != EOS && p->wc != SEP) {
698 767
			if (ismeta(*p))
699 768
				anymeta = 1;
700 769
			if (q+1 > pathend_last)
701
				return (1);
770
				return (GLOB_NOSPACE);
702 771
			*q++ = *p++;
703 772
		}
704 773

  
705 774
		if (!anymeta) {		/* No expansion, do next segment. */
706 775
			pathend = q;
707 776
			pattern = p;
708
			while (*pattern == SEP) {
777
			while (pattern->wc == SEP) {
709 778
				if (pathend+1 > pathend_last)
710
					return (1);
779
					return (GLOB_NOSPACE);
711 780
				*pathend++ = *pattern++;
712 781
			}
713
		} else
782
		} else  {
714 783
			/* Need expansion, recurse. */
715 784
			return (glob3(pathbuf, pathbuf_last, pathend,
716 785
			    pathend_last, pattern, p, pattern_last,
717 786
			    pglob, limitp, errfunc));
787
		}
718 788
	}
719 789
	/* NOTREACHED */
720 790
}
......
738 808
	struct dirent *(*readdirfunc)(void *);
739 809

  
740 810
	if (pathend > pathend_last)
741
		return (1);
742
	*pathend = EOS;
811
		return (GLOB_NOSPACE);
812
	pathend->at = 0;
813
	pathend->wc = EOS;
743 814
	errno = 0;
744 815

  
745 816
	if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
......
762 833
	else
763 834
		readdirfunc = (struct dirent *(*)(void *))readdir;
764 835
	while ((dp = (*readdirfunc)(dirp))) {
765
		uchar_t *sc;
836
		char *sc;
766 837
		Char *dc;
838
		size_t n;
839
		wchar_t w;
767 840

  
768 841
		if ((pglob->gl_flags & GLOB_LIMIT) &&
769 842
		    limitp->glim_readdir++ >= GLOB_LIMIT_READDIR) {
770 843
			errno = 0;
771
			*pathend++ = SEP;
772
			*pathend = EOS;
844
			pathend->at = 0;
845
			(pathend++)->wc = SEP;
846
			pathend->at = 0;
847
			pathend->wc = EOS;
773 848
			err = GLOB_NOSPACE;
774 849
			break;
775 850
		}
776 851

  
777 852
		/* Initial DOT must be matched literally. */
778
		if (dp->d_name[0] == DOT && *pattern != DOT)
853
		if (dp->d_name[0] == DOT && pattern->wc != DOT)
779 854
			continue;
780 855
		dc = pathend;
781
		sc = (uchar_t *)dp->d_name;
782
		while (dc < pathend_last && (*dc++ = *sc++) != EOS)
783
			;
856
		sc = dp->d_name;
857
		while (dc < pathend_last) {
858
			if ((n = mbtowc(&w, sc, MB_LEN_MAX)) <= 0) {
859
				sc += 1;
860
				dc->at = 0;
861
				dc->wc = EOS;
862
			} else {
863
				sc += n;
864
				dc->at = 0;
865
				dc->wc = w;
866
			}
867
			dc++;
868
			if (n <= 0)
869
				break;
870
		}
784 871
		if (dc >= pathend_last) {
785
			*dc = EOS;
786
			err = 1;
872
			dc->at = 0;
873
			dc->wc = EOS;
874
			err = GLOB_NOSPACE;
787 875
			break;
788 876
		}
877
		if (n < 0) {
878
			dc->at = 0;
879
			dc->wc = EOS;
880
			continue;
881
		}
789 882

  
790 883
		if (!match(pathend, pattern, restpattern, GLOB_LIMIT_RECUR)) {
791
			*pathend = EOS;
884
			pathend->at = 0;
885
			pathend->wc = EOS;
792 886
			continue;
793 887
		}
794 888
		err = glob2(pathbuf, pathbuf_last, --dc, pathend_last,
......
830 924
	char *copy = NULL;
831 925
	const Char *p;
832 926
	struct stat **statv;
927
	char junk[MB_LEN_MAX];
928
	int n;
833 929

  
834 930
	newn = 2 + pglob->gl_pathc + pglob->gl_offs;
835 931
	if (pglob->gl_offs >= INT_MAX ||
......
897 993
		statv[pglob->gl_offs + pglob->gl_pathc + 1] = NULL;
898 994
	}
899 995

  
900
	for (p = path; *p++; )
901
		;
902
	len = (size_t)(p - path);
996
	len = MB_LEN_MAX;
997
	p = path;
998
	while ((n = wctomb(junk, p->wc)) > 0) {
999
		len += n;
1000
		if ((p++)->wc == EOS)
1001
			break;
1002
	}
1003

  
903 1004
	limitp->glim_malloc += len;
904 1005
	if ((copy = malloc(len)) != NULL) {
905 1006
		if (g_Ctoc(path, copy, len)) {
......
932 1033
	Char c, k;
933 1034

  
934 1035
	if (recur-- == 0)
935
		return (GLOB_NOSPACE);
1036
		return (1);
936 1037

  
937 1038
	while (pat < patend) {
938 1039
		c = *pat++;
939
		switch (c & M_MASK) {
1040
		switch (c.wc) {
940 1041
		case M_ALL:
941
			while (pat < patend && (*pat & M_MASK) == M_ALL)
1042
			if (c.at != M_QUOTE) {
1043
				k = *name++;
1044
				if (k.at != c.at || k.wc != c.wc)
1045
					return (0);
1046
				break;
1047
			}
1048
			while (pat < patend && pat->at == M_QUOTE &&
1049
			    pat->wc == M_ALL)
942 1050
				pat++;	/* eat consecutive '*' */
943 1051
			if (pat == patend)
944 1052
				return (1);
945 1053
			do {
946 1054
				if (match(name, pat, patend, recur))
947 1055
					return (1);
948
			} while (*name++ != EOS);
1056
			} while ((name++)->wc != EOS);
949 1057
			return (0);
950 1058
		case M_ONE:
951
			if (*name++ == EOS)
1059
			if (c.at != M_QUOTE) {
1060
				k = *name++;
1061
				if (k.at != c.at || k.wc != c.wc)
1062
					return (0);
1063
				break;
1064
			}
1065
			if ((name++)->wc == EOS)
952 1066
				return (0);
953 1067
			break;
954 1068
		case M_SET:
1069
			if (c.at != M_QUOTE) {
1070
				k = *name++;
1071
				if (k.at != c.at || k.wc != c.wc)
1072
					return (0);
1073
				break;
1074
			}
955 1075
			ok = 0;
956
			if ((k = *name++) == EOS)
1076
			if ((k = *name++).wc == EOS)
957 1077
				return (0);
958
			if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
1078
			if ((negate_range = (pat->at == M_QUOTE &&
1079
			    pat->wc == M_NOT)) != 0)
959 1080
				++pat;
960
			while (((c = *pat++) & M_MASK) != M_END) {
961
				if ((c & M_MASK) == M_CLASS) {
962
					Char idx = *pat & M_MASK;
963
					if (idx < NCCLASSES &&
964
					    cclasses[idx].isctype(k))
1081
			while (((c = *pat++).at != M_QUOTE) || c.wc != M_END) {
1082
				if (c.at == M_QUOTE && c.wc == M_CLASS) {
1083
					Char idx;
1084

  
1085
					idx.at = pat->at;
1086
					idx.wc = pat->wc;
1087
					if (idx.at < NCCLASSES &&
1088
					    cclasses[idx.at].isctype(k.wc))
965 1089
						ok = 1;
966 1090
					++pat;
967 1091
				}
968
				if ((*pat & M_MASK) == M_RNG) {
969
					if (c <= k && k <= pat[1])
1092
				if (pat->at == M_QUOTE && pat->wc == M_RNG) {
1093
					if (c.wc <= k.wc && k.wc <= pat[1].wc)
970 1094
						ok = 1;
971 1095
					pat += 2;
972
				} else if (c == k)
1096
				} else if (c.wc == k.wc)
973 1097
					ok = 1;
974 1098
			}
975 1099
			if (ok == negate_range)
976 1100
				return (0);
977 1101
			break;
978 1102
		default:
979
			if (*name++ != c)
1103
			k = *name++;
1104
			if (k.at != c.at || k.wc != c.wc)
980 1105
				return (0);
981 1106
			break;
982 1107
		}
983 1108
	}
984
	return (*name == EOS);
1109
	return (name->wc == EOS);
985 1110
}
986 1111

  
987 1112
/* Free allocated data belonging to a glob_t structure. */
......
1015 1140
{
1016 1141
	char buf[MAXPATHLEN];
1017 1142

  
1018
	if (!*str)
1143
	if (str->wc == EOS)
1019 1144
		strlcpy(buf, ".", sizeof (buf));
1020 1145
	else {
1021 1146
		if (g_Ctoc(str, buf, sizeof (buf)))
......
1053 1178
}
1054 1179

  
1055 1180
static Char *
1056
g_strchr(const Char *str, int ch)
1181
g_strchr(const Char *str, wchar_t ch)
1057 1182
{
1058 1183
	do {
1059
		if (*str == ch)
1184
		if (str->at == 0 && str->wc == ch)
1060 1185
			return ((Char *)str);
1061
	} while (*str++);
1186
	} while ((str++)->wc != EOS);
1062 1187
	return (NULL);
1063 1188
}
1064 1189

  
1065 1190
static int
1066 1191
g_Ctoc(const Char *str, char *buf, uint_t len)
1067 1192
{
1193
	int n;
1194
	wchar_t w;
1068 1195

  
1069
	while (len--) {
1070
		if ((*buf++ = *str++) == EOS)
1196
	while (len >= MB_LEN_MAX) {
1197
		w = (str++)->wc;
1198
		if ((n = wctomb(buf, w)) > 0) {
1199
			len -= n;
1200
			buf += n;
1201
		}
1202
		if (n < 0)
1203
			break;
1204
		if (w == EOS)
1071 1205
			return (0);
1072 1206
	}
1073 1207
	return (1);
......
1080 1214
	Char *p;
1081 1215

  
1082 1216
	(void) printf("%s:\n", str);
1083
	for (p = s; *p; p++)
1084
		(void) printf("%c", CHAR(*p));
1217
	for (p = s; p->wc != EOS; p++)
1218
		(void) printf("%wc", p->wc);
1085 1219
	(void) printf("\n");
1086
	for (p = s; *p; p++)
1087
		(void) printf("%c", *p & M_PROTECT ? '"' : ' ');
1220
	for (p = s; p->wc != EOS; p++)
1221
		(void) printf("%c", p->at & M_PROTECT ? '"' : ' ');
1088 1222
	(void) printf("\n");
1089
	for (p = s; *p; p++)
1223
	for (p = s; p->wc != EOS; p++)
1090 1224
		(void) printf("%c", ismeta(*p) ? '_' : ' ');
1091 1225
	(void) printf("\n");
1092 1226
}
(6-6/11)