Project

General

Profile

Bug #1097 » glob.c-mb.diff

Gary Mills, 2012-12-10 02:54 PM

View differences:

glob.c-mb Sun Dec 9 08:39:14 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);
160
static Char	*g_strchr(const Char *, wchar_t);
174 161
static int	 g_strncmp(const Char *, const char *, size_t);
175 162
static int	 g_stat(Char *, struct stat *, glob_t *);
176 163
static int	 glob0(const Char *, glob_t *, struct glob_lim *,
......
200 187
glob(const char *pattern, int flags, int (*errfunc)(const char *, int),
201 188
    glob_t *pglob)
202 189
{
203
	const uchar_t *patnext;
204
	int c;
190
	const char *patnext;
191
	size_t n;
192
	wchar_t c;
205 193
	Char *bufnext, *bufend, patbuf[MAXPATHLEN];
206 194
	struct glob_lim limit = { 0, 0, 0 };
207 195

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

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

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

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

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

  
268 270
	if ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL)
......
289 291
	/* copy part up to the brace */
290 292
	for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
291 293
		;
292
	*lm = EOS;
294
	lm->at = 0;
295
	lm->wc = EOS;
293 296
	ls = lm;
294 297

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

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

  
320 324
	for (i = 0, pl = pm = ptr; pm <= pe; pm++) {
321
		switch (*pm) {
325
		switch (pm->wc) {
322 326
		case LBRACKET:
323 327
			/* Ignore everything between [] */
324
			for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++)
328
			for (pl = pm++; pm->wc != RBRACKET && pm->wc != EOS;
329
			    pm++)
325 330
				;
326
			if (*pm == EOS) {
331
			if (pm->wc == EOS) {
327 332
				/*
328 333
				 * We could not find a matching RBRACKET.
329 334
				 * Ignore and just look for RBRACE
......
343 348
			}
344 349
			/* FALLTHROUGH */
345 350
		case COMMA:
346
			if (i && *pm == COMMA)
351
			if (i && pm->wc == COMMA)
347 352
				break;
348 353
			else {
349 354
				/* Append the current string */
......
354 359
				 * Append the rest of the pattern after the
355 360
				 * closing brace
356 361
				 */
357
				for (pl = pe + 1; (*lm++ = *pl++) != EOS; )
362
				for (pl = pe + 1;
363
				    (*lm++ = *pl++).wc != EOS; /* */)
358 364
					;
359 365

  
360 366
				/* Expand the current pattern */
361
#ifdef DEBUG
362
				qprintf("globexp2:", patbuf);
363
#endif
364 367
				rv = globexp1(patbuf, pglob, limitp, errfunc);
365 368
				if (rv && rv != GLOB_NOMATCH)
366 369
					return (rv);
......
388 391
	struct passwd *pwd;
389 392
	char *h;
390 393
	const Char *p;
391
	Char *b, *eb;
394
	Char *b, *eb, *q;
395
	size_t n;
396
	wchar_t c;
392 397

  
393
	if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
398
	if (pattern->wc != TILDE || !(pglob->gl_flags & GLOB_TILDE))
394 399
		return (pattern);
395 400

  
396 401
	/* Copy up to the end of the string or / */
397 402
	eb = &patbuf[patbuf_len - 1];
398
	for (p = pattern + 1, h = (char *)patbuf;
399
	    h < (char *)eb && *p && *p != SLASH; *h++ = *p++)
403
	for (p = pattern + 1, q = patbuf;
404
	    q < eb && p->wc != EOS && p->wc != SLASH; *q++ = *p++)
400 405
		;
401 406

  
402
	*h = EOS;
407
	q->at = 0;
408
	q->wc = EOS;
403 409

  
404 410
#if 0
405
	if (h == (char *)eb)
411
	if (q == eb)
406 412
		return (what);
407 413
#endif
408 414

  
409
	if (((char *)patbuf)[0] == EOS) {
415
	if (patbuf[0].wc == EOS) {
410 416
		/*
411 417
		 * handle a plain ~ or ~/ by expanding $HOME
412 418
		 * first and then trying the password file
......
428 434
	}
429 435

  
430 436
	/* Copy the home directory */
431
	for (b = patbuf; b < eb && *h; *b++ = *h++)
432
		;
437
	for (b = patbuf; b < eb && *h != EOS; b++) {
438
		if ((n = mbtowc(&c, h, PATH_MAX)) > 0) {
439
			h += n;
440
			b->at = 0;
441
			b->wc = c;
442
		} else {
443
			break;
444
		}
445
	}
433 446

  
434 447
	/* Append the rest of the pattern */
435
	while (b < eb && (*b++ = *p++) != EOS)
448
	while (b < eb && (*b++ = *p++).wc != EOS)
436 449
		;
437
	*b = EOS;
450
	b->at = 0;
451
	b->wc = EOS;
438 452

  
439 453
	return (patbuf);
440 454
}
......
443 457
g_strncmp(const Char *s1, const char *s2, size_t n)
444 458
{
445 459
	int rv = 0;
460
	int r;
461
	wchar_t c;
446 462

  
447
	while (n--) {
448
		rv = *(Char *)s1 - *(const unsigned char *)s2++;
449
		if (rv)
463
	while (n > 0) {
464
		if ((r = mbtowc(&c, s2, n)) > 0) {
465
			n -= r;
466
			s2 += r;
467
		} else {
468
			rv = s1->wc;
450 469
			break;
451
		if (*s1++ == '\0')
470
		}
471
		rv = s1->wc - c;
472
		if (rv != 0)
452 473
			break;
474
		if ((s1++)->wc == EOS)
475
			break;
453 476
	}
454 477
	return (rv);
455 478
}
......
463 486
	struct cclass *cc;
464 487
	size_t len;
465 488

  
466
	if ((colon = g_strchr(pattern, ':')) == NULL || colon[1] != ']')
489
	if ((colon = g_strchr(pattern, COLON)) == NULL ||
490
	    colon[1].wc != RBRACKET)
467 491
		return (1);	/* not a character class */
468 492

  
469 493
	len = (size_t)(colon - pattern);
470 494
	for (cc = cclasses; cc->name != NULL; cc++) {
471
		if (!g_strncmp(pattern, cc->name, len) && cc->name[len] == '\0')
495
		if (!g_strncmp(pattern, cc->name, len) && cc->name[len] == EOS)
472 496
			break;
473 497
	}
474 498
	if (cc->name == NULL)
475 499
		return (-1);	/* invalid character class */
476
	*bufnext++ = M_CLASS;
477
	*bufnext++ = (Char)(cc - &cclasses[0]);
500
	bufnext->at = M_QUOTE;
501
	(bufnext++)->wc = M_CLASS;
502
	bufnext->at = (cc - &cclasses[0]);
503
	(bufnext++)->wc = COLON;
478 504
	*bufnextp = bufnext;
479 505
	*patternp += len + 3;
480 506

  
......
493 519
    int (*errfunc)(const char *, int))
494 520
{
495 521
	const Char *qpatnext;
496
	int c, err, oldpathc;
522
	int err, oldpathc;
523
	wchar_t c;
524
	int a;
497 525
	Char *bufnext, patbuf[MAXPATHLEN];
498 526

  
499 527
	qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob);
......
501 529
	bufnext = patbuf;
502 530

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

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

  
640 709
	/* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
641
	if (*pattern == EOS)
710
	if (pattern->wc == EOS)
642 711
		return (0);
643 712
	return (glob2(pathbuf, pathbuf+MAXPATHLEN-1,
644 713
	    pathbuf, pathbuf+MAXPATHLEN-1,
......
664 733
	 * segment with meta character found.
665 734
	 */
666 735
	for (anymeta = 0; ; ) {
667
		if (*pattern == EOS) {		/* End of pattern? */
668
			*pathend = EOS;
736
		if (pattern->wc == EOS) {		/* End of pattern? */
737
			pathend->at = 0;
738
			pathend->wc = EOS;
669 739

  
670 740
			if ((pglob->gl_flags & GLOB_LIMIT) &&
671 741
			    limitp->glim_stat++ >= GLOB_LIMIT_STAT) {
672 742
				errno = 0;
673
				*pathend++ = SEP;
674
				*pathend = EOS;
743
				pathend->at = 0;
744
				(pathend++)->wc = SEP;
745
				pathend->at = 0;
746
				pathend->wc = EOS;
675 747
				return (GLOB_NOSPACE);
676 748
			}
677 749
			if (g_lstat(pathbuf, &sb, pglob))
678 750
				return (0);
679 751

  
680 752
			if (((pglob->gl_flags & GLOB_MARK) &&
681
			    pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) ||
753
			    (pathend[-1].at != 0 ||
754
			    pathend[-1].wc != SEP)) &&
755
			    (S_ISDIR(sb.st_mode) ||
682 756
			    (S_ISLNK(sb.st_mode) &&
683 757
			    (g_stat(pathbuf, &sb, pglob) == 0) &&
684 758
			    S_ISDIR(sb.st_mode)))) {
685 759
				if (pathend+1 > pathend_last)
686 760
					return (1);
687
				*pathend++ = SEP;
688
				*pathend = EOS;
761
				pathend->at = 0;
762
				(pathend++)->wc = SEP;
763
				pathend->at = 0;
764
				pathend->wc = EOS;
689 765
			}
690 766
			++pglob->gl_matchc;
691 767
			return (globextend(pathbuf, pglob, limitp, &sb));
......
694 770
		/* Find end of next segment, copy tentatively to pathend. */
695 771
		q = pathend;
696 772
		p = pattern;
697
		while (*p != EOS && *p != SEP) {
773
		while (p->wc != EOS && p->wc != SEP) {
698 774
			if (ismeta(*p))
699 775
				anymeta = 1;
700 776
			if (q+1 > pathend_last)
......
705 781
		if (!anymeta) {		/* No expansion, do next segment. */
706 782
			pathend = q;
707 783
			pattern = p;
708
			while (*pattern == SEP) {
784
			while (pattern->wc == SEP) {
709 785
				if (pathend+1 > pathend_last)
710 786
					return (1);
711 787
				*pathend++ = *pattern++;
712 788
			}
713
		} else
789
		} else  {
714 790
			/* Need expansion, recurse. */
715 791
			return (glob3(pathbuf, pathbuf_last, pathend,
716 792
			    pathend_last, pattern, p, pattern_last,
717 793
			    pglob, limitp, errfunc));
794
		}
718 795
	}
719 796
	/* NOTREACHED */
720 797
}
......
739 816

  
740 817
	if (pathend > pathend_last)
741 818
		return (1);
742
	*pathend = EOS;
819
	pathend->at = 0;
820
	pathend->wc = EOS;
743 821
	errno = 0;
744 822

  
745 823
	if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
......
762 840
	else
763 841
		readdirfunc = (struct dirent *(*)(void *))readdir;
764 842
	while ((dp = (*readdirfunc)(dirp))) {
765
		uchar_t *sc;
843
		char *sc;
766 844
		Char *dc;
845
		size_t n;
846
		wchar_t c;
767 847

  
768 848
		if ((pglob->gl_flags & GLOB_LIMIT) &&
769 849
		    limitp->glim_readdir++ >= GLOB_LIMIT_READDIR) {
770 850
			errno = 0;
771
			*pathend++ = SEP;
772
			*pathend = EOS;
851
			pathend->at = 0;
852
			(pathend++)->wc = SEP;
853
			pathend->at = 0;
854
			pathend->wc = EOS;
773 855
			err = GLOB_NOSPACE;
774 856
			break;
775 857
		}
776 858

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

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

  
834 932
	newn = 2 + pglob->gl_pathc + pglob->gl_offs;
835 933
	if (pglob->gl_offs >= INT_MAX ||
......
897 995
		statv[pglob->gl_offs + pglob->gl_pathc + 1] = NULL;
898 996
	}
899 997

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

  
903 1006
	limitp->glim_malloc += len;
904 1007
	if ((copy = malloc(len)) != NULL) {
905 1008
		if (g_Ctoc(path, copy, len)) {
......
936 1039

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

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

  
987 1114
/* Free allocated data belonging to a glob_t structure. */
......
1015 1142
{
1016 1143
	char buf[MAXPATHLEN];
1017 1144

  
1018
	if (!*str)
1145
	if (str->wc == EOS)
1019 1146
		strlcpy(buf, ".", sizeof (buf));
1020 1147
	else {
1021 1148
		if (g_Ctoc(str, buf, sizeof (buf)))
......
1053 1180
}
1054 1181

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

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

  
1069
	while (len--) {
1070
		if ((*buf++ = *str++) == EOS)
1198
	while (len >= MB_CUR_MAX) {
1199
		w = (str++)->wc;
1200
		if ((n = wctomb(buf, w)) > 0) {
1201
			len -= n;
1202
			buf += n;
1203
		}
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
}
(5-5/11)