You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

926 lines
21 KiB

  1. /*
  2. * Copyright (c) 1989, 1993
  3. * The Regents of the University of California. All rights reserved.
  4. *
  5. * This code is derived from software contributed to Berkeley by
  6. * Guido van Rossum.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. * 3. All advertising materials mentioning features or use of this software
  17. * must display the following acknowledgement:
  18. * This product includes software developed by the University of
  19. * California, Berkeley and its contributors.
  20. * 4. Neither the name of the University nor the names of its contributors
  21. * may be used to endorse or promote products derived from this software
  22. * without specific prior written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34. * SUCH DAMAGE.
  35. */
  36. /* $Id$ */
  37. /*
  38. * glob(3) -- a superset of the one defined in POSIX 1003.2.
  39. *
  40. * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
  41. *
  42. * Optional extra services, controlled by flags not defined by POSIX:
  43. *
  44. * GLOB_QUOTE:
  45. * Escaping convention: \ inhibits any special meaning the following
  46. * character might have (except \ at end of string is retained).
  47. * GLOB_MAGCHAR:
  48. * Set in gl_flags if pattern contained a globbing character.
  49. * GLOB_NOMAGIC:
  50. * Same as GLOB_NOCHECK, but it will only append pattern if it did
  51. * not contain any magic characters. [Used in csh style globbing]
  52. * GLOB_ALTDIRFUNC:
  53. * Use alternately specified directory access functions.
  54. * GLOB_TILDE:
  55. * expand ~user/foo to the /home/dir/of/user/foo
  56. * GLOB_BRACE:
  57. * expand {1,2}{a,b} to 1a 1b 2a 2b
  58. * gl_matchc:
  59. * Number of matches in the current invocation of glob.
  60. */
  61. #ifdef PHP_WIN32
  62. #define _POSIX_
  63. #include <limits.h>
  64. #undef _POSIX_
  65. #ifndef S_ISDIR
  66. #define S_ISDIR(m) (((m) & _S_IFDIR) == _S_IFDIR)
  67. #endif
  68. #ifndef S_ISLNK
  69. #define S_ISLNK(m) (0)
  70. #endif
  71. #endif
  72. #include "php.h"
  73. #include <sys/stat.h>
  74. #include <ctype.h>
  75. #ifndef PHP_WIN32
  76. #include <sys/param.h>
  77. #include <dirent.h>
  78. #include <pwd.h>
  79. #include <unistd.h>
  80. #endif
  81. #include <errno.h>
  82. #include "glob.h"
  83. #include <stdio.h>
  84. #include <stdlib.h>
  85. #include <string.h>
  86. #define DOLLAR '$'
  87. #define DOT '.'
  88. #define EOS '\0'
  89. #define LBRACKET '['
  90. #define NOT '!'
  91. #define QUESTION '?'
  92. #define QUOTE '\\'
  93. #define RANGE '-'
  94. #define RBRACKET ']'
  95. #define SEP DEFAULT_SLASH
  96. #define STAR '*'
  97. #define TILDE '~'
  98. #define UNDERSCORE '_'
  99. #define LBRACE '{'
  100. #define RBRACE '}'
  101. #define SLASH '/'
  102. #define COMMA ','
  103. #ifndef DEBUG
  104. #define M_QUOTE 0x8000
  105. #define M_PROTECT 0x4000
  106. #define M_MASK 0xffff
  107. #define M_ASCII 0x00ff
  108. typedef u_short Char;
  109. #else
  110. #define M_QUOTE 0x80
  111. #define M_PROTECT 0x40
  112. #define M_MASK 0xff
  113. #define M_ASCII 0x7f
  114. typedef char Char;
  115. #endif
  116. #define CHAR(c) ((Char)((c)&M_ASCII))
  117. #define META(c) ((Char)((c)|M_QUOTE))
  118. #define M_ALL META('*')
  119. #define M_END META(']')
  120. #define M_NOT META('!')
  121. #define M_ONE META('?')
  122. #define M_RNG META('-')
  123. #define M_SET META('[')
  124. #define ismeta(c) (((c)&M_QUOTE) != 0)
  125. static int compare(const void *, const void *);
  126. static int g_Ctoc(const Char *, char *, u_int);
  127. static int g_lstat(Char *, struct stat *, glob_t *);
  128. static DIR *g_opendir(Char *, glob_t *);
  129. static Char *g_strchr(Char *, int);
  130. static int g_stat(Char *, struct stat *, glob_t *);
  131. static int glob0(const Char *, glob_t *);
  132. static int glob1(Char *, Char *, glob_t *, size_t *);
  133. static int glob2(Char *, Char *, Char *, Char *, Char *, Char *,
  134. glob_t *, size_t *);
  135. static int glob3(Char *, Char *, Char *, Char *, Char *, Char *,
  136. Char *, Char *, glob_t *, size_t *);
  137. static int globextend(const Char *, glob_t *, size_t *);
  138. static const Char *
  139. globtilde(const Char *, Char *, size_t, glob_t *);
  140. static int globexp1(const Char *, glob_t *);
  141. static int globexp2(const Char *, const Char *, glob_t *, int *);
  142. static int match(Char *, Char *, Char *);
  143. #ifdef DEBUG
  144. static void qprintf(const char *, Char *);
  145. #endif
  146. int
  147. glob(pattern, flags, errfunc, pglob)
  148. const char *pattern;
  149. int flags, (*errfunc)(const char *, int);
  150. glob_t *pglob;
  151. {
  152. const u_char *patnext;
  153. int c;
  154. Char *bufnext, *bufend, patbuf[MAXPATHLEN];
  155. #ifdef PHP_WIN32
  156. /* Force skipping escape sequences on windows
  157. * due to the ambiguity with path backslashes
  158. */
  159. flags |= GLOB_NOESCAPE;
  160. #endif
  161. patnext = (u_char *) pattern;
  162. if (!(flags & GLOB_APPEND)) {
  163. pglob->gl_pathc = 0;
  164. pglob->gl_pathv = NULL;
  165. if (!(flags & GLOB_DOOFFS))
  166. pglob->gl_offs = 0;
  167. }
  168. pglob->gl_flags = flags & ~GLOB_MAGCHAR;
  169. pglob->gl_errfunc = errfunc;
  170. pglob->gl_matchc = 0;
  171. bufnext = patbuf;
  172. bufend = bufnext + MAXPATHLEN - 1;
  173. if (flags & GLOB_NOESCAPE)
  174. while (bufnext < bufend && (c = *patnext++) != EOS)
  175. *bufnext++ = c;
  176. else {
  177. /* Protect the quoted characters. */
  178. while (bufnext < bufend && (c = *patnext++) != EOS)
  179. if (c == QUOTE) {
  180. if ((c = *patnext++) == EOS) {
  181. c = QUOTE;
  182. --patnext;
  183. }
  184. *bufnext++ = c | M_PROTECT;
  185. } else
  186. *bufnext++ = c;
  187. }
  188. *bufnext = EOS;
  189. if (flags & GLOB_BRACE)
  190. return globexp1(patbuf, pglob);
  191. else
  192. return glob0(patbuf, pglob);
  193. }
  194. /*
  195. * Expand recursively a glob {} pattern. When there is no more expansion
  196. * invoke the standard globbing routine to glob the rest of the magic
  197. * characters
  198. */
  199. static int
  200. globexp1(pattern, pglob)
  201. const Char *pattern;
  202. glob_t *pglob;
  203. {
  204. const Char* ptr = pattern;
  205. int rv;
  206. /* Protect a single {}, for find(1), like csh */
  207. if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
  208. return glob0(pattern, pglob);
  209. while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL)
  210. if (!globexp2(ptr, pattern, pglob, &rv))
  211. return rv;
  212. return glob0(pattern, pglob);
  213. }
  214. /*
  215. * Recursive brace globbing helper. Tries to expand a single brace.
  216. * If it succeeds then it invokes globexp1 with the new pattern.
  217. * If it fails then it tries to glob the rest of the pattern and returns.
  218. */
  219. static int
  220. globexp2(ptr, pattern, pglob, rv)
  221. const Char *ptr, *pattern;
  222. glob_t *pglob;
  223. int *rv;
  224. {
  225. int i;
  226. Char *lm, *ls;
  227. const Char *pe, *pm, *pl;
  228. Char patbuf[MAXPATHLEN];
  229. /* copy part up to the brace */
  230. for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
  231. ;
  232. *lm = EOS;
  233. ls = lm;
  234. /* Find the balanced brace */
  235. for (i = 0, pe = ++ptr; *pe; pe++)
  236. if (*pe == LBRACKET) {
  237. /* Ignore everything between [] */
  238. for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
  239. ;
  240. if (*pe == EOS) {
  241. /*
  242. * We could not find a matching RBRACKET.
  243. * Ignore and just look for RBRACE
  244. */
  245. pe = pm;
  246. }
  247. } else if (*pe == LBRACE)
  248. i++;
  249. else if (*pe == RBRACE) {
  250. if (i == 0)
  251. break;
  252. i--;
  253. }
  254. /* Non matching braces; just glob the pattern */
  255. if (i != 0 || *pe == EOS) {
  256. *rv = glob0(patbuf, pglob);
  257. return 0;
  258. }
  259. for (i = 0, pl = pm = ptr; pm <= pe; pm++) {
  260. switch (*pm) {
  261. case LBRACKET:
  262. /* Ignore everything between [] */
  263. for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++)
  264. ;
  265. if (*pm == EOS) {
  266. /*
  267. * We could not find a matching RBRACKET.
  268. * Ignore and just look for RBRACE
  269. */
  270. pm = pl;
  271. }
  272. break;
  273. case LBRACE:
  274. i++;
  275. break;
  276. case RBRACE:
  277. if (i) {
  278. i--;
  279. break;
  280. }
  281. /* FALLTHROUGH */
  282. case COMMA:
  283. if (i && *pm == COMMA)
  284. break;
  285. else {
  286. /* Append the current string */
  287. for (lm = ls; (pl < pm); *lm++ = *pl++)
  288. ;
  289. /*
  290. * Append the rest of the pattern after the
  291. * closing brace
  292. */
  293. for (pl = pe + 1; (*lm++ = *pl++) != EOS; )
  294. ;
  295. /* Expand the current pattern */
  296. #ifdef DEBUG
  297. qprintf("globexp2:", patbuf);
  298. #endif
  299. *rv = globexp1(patbuf, pglob);
  300. /* move after the comma, to the next string */
  301. pl = pm + 1;
  302. }
  303. break;
  304. default:
  305. break;
  306. }
  307. }
  308. *rv = 0;
  309. return 0;
  310. }
  311. /*
  312. * expand tilde from the passwd file.
  313. */
  314. static const Char *
  315. globtilde(pattern, patbuf, patbuf_len, pglob)
  316. const Char *pattern;
  317. Char *patbuf;
  318. size_t patbuf_len;
  319. glob_t *pglob;
  320. {
  321. #ifndef PHP_WIN32
  322. struct passwd *pwd;
  323. #endif
  324. char *h;
  325. const Char *p;
  326. Char *b, *eb;
  327. if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
  328. return pattern;
  329. /* Copy up to the end of the string or / */
  330. eb = &patbuf[patbuf_len - 1];
  331. for (p = pattern + 1, h = (char *) patbuf;
  332. h < (char *)eb && *p && *p != SLASH; *h++ = (char) *p++)
  333. ;
  334. *h = EOS;
  335. #if 0
  336. if (h == (char *)eb)
  337. return what;
  338. #endif
  339. if (((char *) patbuf)[0] == EOS) {
  340. /*
  341. * handle a plain ~ or ~/ by expanding $HOME
  342. * first and then trying the password file
  343. */
  344. if ((h = getenv("HOME")) == NULL) {
  345. #ifndef PHP_WIN32
  346. if ((pwd = getpwuid(getuid())) == NULL)
  347. return pattern;
  348. else
  349. h = pwd->pw_dir;
  350. #else
  351. return pattern;
  352. #endif
  353. }
  354. } else {
  355. /*
  356. * Expand a ~user
  357. */
  358. #ifndef PHP_WIN32
  359. if ((pwd = getpwnam((char*) patbuf)) == NULL)
  360. return pattern;
  361. else
  362. h = pwd->pw_dir;
  363. #else
  364. return pattern;
  365. #endif
  366. }
  367. /* Copy the home directory */
  368. for (b = patbuf; b < eb && *h; *b++ = *h++)
  369. ;
  370. /* Append the rest of the pattern */
  371. while (b < eb && (*b++ = *p++) != EOS)
  372. ;
  373. *b = EOS;
  374. return patbuf;
  375. }
  376. /*
  377. * The main glob() routine: compiles the pattern (optionally processing
  378. * quotes), calls glob1() to do the real pattern matching, and finally
  379. * sorts the list (unless unsorted operation is requested). Returns 0
  380. * if things went well, nonzero if errors occurred. It is not an error
  381. * to find no matches.
  382. */
  383. static int
  384. glob0(pattern, pglob)
  385. const Char *pattern;
  386. glob_t *pglob;
  387. {
  388. const Char *qpatnext;
  389. int c, err, oldpathc;
  390. Char *bufnext, patbuf[MAXPATHLEN];
  391. size_t limit = 0;
  392. qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob);
  393. oldpathc = pglob->gl_pathc;
  394. bufnext = patbuf;
  395. /* We don't need to check for buffer overflow any more. */
  396. while ((c = *qpatnext++) != EOS) {
  397. switch (c) {
  398. case LBRACKET:
  399. c = *qpatnext;
  400. if (c == NOT)
  401. ++qpatnext;
  402. if (*qpatnext == EOS ||
  403. g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) {
  404. *bufnext++ = LBRACKET;
  405. if (c == NOT)
  406. --qpatnext;
  407. break;
  408. }
  409. *bufnext++ = M_SET;
  410. if (c == NOT)
  411. *bufnext++ = M_NOT;
  412. c = *qpatnext++;
  413. do {
  414. *bufnext++ = CHAR(c);
  415. if (*qpatnext == RANGE &&
  416. (c = qpatnext[1]) != RBRACKET) {
  417. *bufnext++ = M_RNG;
  418. *bufnext++ = CHAR(c);
  419. qpatnext += 2;
  420. }
  421. } while ((c = *qpatnext++) != RBRACKET);
  422. pglob->gl_flags |= GLOB_MAGCHAR;
  423. *bufnext++ = M_END;
  424. break;
  425. case QUESTION:
  426. pglob->gl_flags |= GLOB_MAGCHAR;
  427. *bufnext++ = M_ONE;
  428. break;
  429. case STAR:
  430. pglob->gl_flags |= GLOB_MAGCHAR;
  431. /* collapse adjacent stars to one,
  432. * to avoid exponential behavior
  433. */
  434. if (bufnext == patbuf || bufnext[-1] != M_ALL)
  435. *bufnext++ = M_ALL;
  436. break;
  437. default:
  438. *bufnext++ = CHAR(c);
  439. break;
  440. }
  441. }
  442. *bufnext = EOS;
  443. #ifdef DEBUG
  444. qprintf("glob0:", patbuf);
  445. #endif
  446. if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, &limit)) != 0)
  447. return(err);
  448. /*
  449. * If there was no match we are going to append the pattern
  450. * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
  451. * and the pattern did not contain any magic characters
  452. * GLOB_NOMAGIC is there just for compatibility with csh.
  453. */
  454. if (pglob->gl_pathc == oldpathc) {
  455. if ((pglob->gl_flags & GLOB_NOCHECK) ||
  456. ((pglob->gl_flags & GLOB_NOMAGIC) &&
  457. !(pglob->gl_flags & GLOB_MAGCHAR)))
  458. return(globextend(pattern, pglob, &limit));
  459. else
  460. return(GLOB_NOMATCH);
  461. }
  462. if (!(pglob->gl_flags & GLOB_NOSORT))
  463. qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
  464. pglob->gl_pathc - oldpathc, sizeof(char *), (const void *) compare);
  465. return(0);
  466. }
  467. static int
  468. compare(p, q)
  469. const void *p, *q;
  470. {
  471. return(strcmp(*(char **)p, *(char **)q));
  472. }
  473. static int
  474. glob1(pattern, pattern_last, pglob, limitp)
  475. Char *pattern, *pattern_last;
  476. glob_t *pglob;
  477. size_t *limitp;
  478. {
  479. Char pathbuf[MAXPATHLEN];
  480. /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
  481. if (*pattern == EOS)
  482. return(0);
  483. return(glob2(pathbuf, pathbuf+MAXPATHLEN-1,
  484. pathbuf, pathbuf+MAXPATHLEN-1,
  485. pattern, pattern_last, pglob, limitp));
  486. }
  487. /*
  488. * The functions glob2 and glob3 are mutually recursive; there is one level
  489. * of recursion for each segment in the pattern that contains one or more
  490. * meta characters.
  491. */
  492. static int
  493. glob2(pathbuf, pathbuf_last, pathend, pathend_last, pattern,
  494. pattern_last, pglob, limitp)
  495. Char *pathbuf, *pathbuf_last, *pathend, *pathend_last;
  496. Char *pattern, *pattern_last;
  497. glob_t *pglob;
  498. size_t *limitp;
  499. {
  500. struct stat sb;
  501. Char *p, *q;
  502. int anymeta;
  503. /*
  504. * Loop over pattern segments until end of pattern or until
  505. * segment with meta character found.
  506. */
  507. for (anymeta = 0;;) {
  508. if (*pattern == EOS) { /* End of pattern? */
  509. *pathend = EOS;
  510. if (g_lstat(pathbuf, &sb, pglob))
  511. return(0);
  512. if (((pglob->gl_flags & GLOB_MARK) &&
  513. !IS_SLASH(pathend[-1])) && (S_ISDIR(sb.st_mode) ||
  514. (S_ISLNK(sb.st_mode) &&
  515. (g_stat(pathbuf, &sb, pglob) == 0) &&
  516. S_ISDIR(sb.st_mode)))) {
  517. if (pathend+1 > pathend_last)
  518. return (1);
  519. *pathend++ = SEP;
  520. *pathend = EOS;
  521. }
  522. ++pglob->gl_matchc;
  523. return(globextend(pathbuf, pglob, limitp));
  524. }
  525. /* Find end of next segment, copy tentatively to pathend. */
  526. q = pathend;
  527. p = pattern;
  528. while (*p != EOS && !IS_SLASH(*p)) {
  529. if (ismeta(*p))
  530. anymeta = 1;
  531. if (q+1 > pathend_last)
  532. return (1);
  533. *q++ = *p++;
  534. }
  535. if (!anymeta) { /* No expansion, do next segment. */
  536. pathend = q;
  537. pattern = p;
  538. while (IS_SLASH(*pattern)) {
  539. if (pathend+1 > pathend_last)
  540. return (1);
  541. *pathend++ = *pattern++;
  542. }
  543. } else
  544. /* Need expansion, recurse. */
  545. return(glob3(pathbuf, pathbuf_last, pathend,
  546. pathend_last, pattern, pattern_last,
  547. p, pattern_last, pglob, limitp));
  548. }
  549. /* NOTREACHED */
  550. }
  551. static int
  552. glob3(pathbuf, pathbuf_last, pathend, pathend_last, pattern, pattern_last,
  553. restpattern, restpattern_last, pglob, limitp)
  554. Char *pathbuf, *pathbuf_last, *pathend, *pathend_last;
  555. Char *pattern, *pattern_last, *restpattern, *restpattern_last;
  556. glob_t *pglob;
  557. size_t *limitp;
  558. {
  559. register struct dirent *dp;
  560. DIR *dirp;
  561. int err;
  562. char buf[MAXPATHLEN];
  563. /*
  564. * The readdirfunc declaration can't be prototyped, because it is
  565. * assigned, below, to two functions which are prototyped in glob.h
  566. * and dirent.h as taking pointers to differently typed opaque
  567. * structures.
  568. */
  569. struct dirent *(*readdirfunc)();
  570. if (pathend > pathend_last)
  571. return (1);
  572. *pathend = EOS;
  573. errno = 0;
  574. if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
  575. /* TODO: don't call for ENOENT or ENOTDIR? */
  576. if (pglob->gl_errfunc) {
  577. if (g_Ctoc(pathbuf, buf, sizeof(buf)))
  578. return(GLOB_ABORTED);
  579. if (pglob->gl_errfunc(buf, errno) ||
  580. pglob->gl_flags & GLOB_ERR)
  581. return(GLOB_ABORTED);
  582. }
  583. return(0);
  584. }
  585. err = 0;
  586. /* Search directory for matching names. */
  587. if (pglob->gl_flags & GLOB_ALTDIRFUNC)
  588. readdirfunc = pglob->gl_readdir;
  589. else
  590. readdirfunc = readdir;
  591. while ((dp = (*readdirfunc)(dirp))) {
  592. register u_char *sc;
  593. register Char *dc;
  594. /* Initial DOT must be matched literally. */
  595. if (dp->d_name[0] == DOT && *pattern != DOT)
  596. continue;
  597. dc = pathend;
  598. sc = (u_char *) dp->d_name;
  599. while (dc < pathend_last && (*dc++ = *sc++) != EOS)
  600. ;
  601. if (dc >= pathend_last) {
  602. *dc = EOS;
  603. err = 1;
  604. break;
  605. }
  606. if (!match(pathend, pattern, restpattern)) {
  607. *pathend = EOS;
  608. continue;
  609. }
  610. err = glob2(pathbuf, pathbuf_last, --dc, pathend_last,
  611. restpattern, restpattern_last, pglob, limitp);
  612. if (err)
  613. break;
  614. }
  615. if (pglob->gl_flags & GLOB_ALTDIRFUNC)
  616. (*pglob->gl_closedir)(dirp);
  617. else
  618. closedir(dirp);
  619. return(err);
  620. }
  621. /*
  622. * Extend the gl_pathv member of a glob_t structure to accomodate a new item,
  623. * add the new item, and update gl_pathc.
  624. *
  625. * This assumes the BSD realloc, which only copies the block when its size
  626. * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
  627. * behavior.
  628. *
  629. * Return 0 if new item added, error code if memory couldn't be allocated.
  630. *
  631. * Invariant of the glob_t structure:
  632. * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
  633. * gl_pathv points to (gl_offs + gl_pathc + 1) items.
  634. */
  635. static int
  636. globextend(path, pglob, limitp)
  637. const Char *path;
  638. glob_t *pglob;
  639. size_t *limitp;
  640. {
  641. register char **pathv;
  642. register int i;
  643. u_int newsize, len;
  644. char *copy;
  645. const Char *p;
  646. newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
  647. pathv = pglob->gl_pathv ? realloc((char *)pglob->gl_pathv, newsize) :
  648. malloc(newsize);
  649. if (pathv == NULL) {
  650. if (pglob->gl_pathv) {
  651. free(pglob->gl_pathv);
  652. pglob->gl_pathv = NULL;
  653. }
  654. return(GLOB_NOSPACE);
  655. }
  656. if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
  657. /* first time around -- clear initial gl_offs items */
  658. pathv += pglob->gl_offs;
  659. for (i = pglob->gl_offs; --i >= 0; )
  660. *--pathv = NULL;
  661. }
  662. pglob->gl_pathv = pathv;
  663. for (p = path; *p++;)
  664. ;
  665. len = (size_t)(p - path);
  666. *limitp += len;
  667. if ((copy = malloc(len)) != NULL) {
  668. if (g_Ctoc(path, copy, len)) {
  669. free(copy);
  670. return(GLOB_NOSPACE);
  671. }
  672. pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
  673. }
  674. pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
  675. if ((pglob->gl_flags & GLOB_LIMIT) &&
  676. newsize + *limitp >= ARG_MAX) {
  677. errno = 0;
  678. return(GLOB_NOSPACE);
  679. }
  680. return(copy == NULL ? GLOB_NOSPACE : 0);
  681. }
  682. /*
  683. * pattern matching function for filenames. Each occurrence of the *
  684. * pattern causes a recursion level.
  685. */
  686. static int
  687. match(name, pat, patend)
  688. register Char *name, *pat, *patend;
  689. {
  690. int ok, negate_range;
  691. Char c, k;
  692. while (pat < patend) {
  693. c = *pat++;
  694. switch (c & M_MASK) {
  695. case M_ALL:
  696. if (pat == patend)
  697. return(1);
  698. do
  699. if (match(name, pat, patend))
  700. return(1);
  701. while (*name++ != EOS)
  702. ;
  703. return(0);
  704. case M_ONE:
  705. if (*name++ == EOS)
  706. return(0);
  707. break;
  708. case M_SET:
  709. ok = 0;
  710. if ((k = *name++) == EOS)
  711. return(0);
  712. if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
  713. ++pat;
  714. while (((c = *pat++) & M_MASK) != M_END)
  715. if ((*pat & M_MASK) == M_RNG) {
  716. if (c <= k && k <= pat[1])
  717. ok = 1;
  718. pat += 2;
  719. } else if (c == k)
  720. ok = 1;
  721. if (ok == negate_range)
  722. return(0);
  723. break;
  724. default:
  725. if (*name++ != c)
  726. return(0);
  727. break;
  728. }
  729. }
  730. return(*name == EOS);
  731. }
  732. /* Free allocated data belonging to a glob_t structure. */
  733. void
  734. globfree(pglob)
  735. glob_t *pglob;
  736. {
  737. register int i;
  738. register char **pp;
  739. if (pglob->gl_pathv != NULL) {
  740. pp = pglob->gl_pathv + pglob->gl_offs;
  741. for (i = pglob->gl_pathc; i--; ++pp)
  742. if (*pp)
  743. free(*pp);
  744. free(pglob->gl_pathv);
  745. pglob->gl_pathv = NULL;
  746. }
  747. }
  748. static DIR *
  749. g_opendir(str, pglob)
  750. register Char *str;
  751. glob_t *pglob;
  752. {
  753. char buf[MAXPATHLEN];
  754. if (!*str)
  755. strlcpy(buf, ".", sizeof buf);
  756. else {
  757. if (g_Ctoc(str, buf, sizeof(buf)))
  758. return(NULL);
  759. }
  760. if (pglob->gl_flags & GLOB_ALTDIRFUNC)
  761. return((*pglob->gl_opendir)(buf));
  762. return(opendir(buf));
  763. }
  764. static int
  765. g_lstat(fn, sb, pglob)
  766. register Char *fn;
  767. struct stat *sb;
  768. glob_t *pglob;
  769. {
  770. char buf[MAXPATHLEN];
  771. if (g_Ctoc(fn, buf, sizeof(buf)))
  772. return(-1);
  773. if (pglob->gl_flags & GLOB_ALTDIRFUNC)
  774. return((*pglob->gl_lstat)(buf, sb));
  775. return(lstat(buf, sb));
  776. }
  777. static int
  778. g_stat(fn, sb, pglob)
  779. register Char *fn;
  780. struct stat *sb;
  781. glob_t *pglob;
  782. {
  783. char buf[MAXPATHLEN];
  784. if (g_Ctoc(fn, buf, sizeof(buf)))
  785. return(-1);
  786. if (pglob->gl_flags & GLOB_ALTDIRFUNC)
  787. return((*pglob->gl_stat)(buf, sb));
  788. return(stat(buf, sb));
  789. }
  790. static Char *
  791. g_strchr(str, ch)
  792. Char *str;
  793. int ch;
  794. {
  795. do {
  796. if (*str == ch)
  797. return (str);
  798. } while (*str++);
  799. return (NULL);
  800. }
  801. static int
  802. g_Ctoc(str, buf, len)
  803. register const Char *str;
  804. char *buf;
  805. u_int len;
  806. {
  807. while (len--) {
  808. if ((*buf++ = (char) *str++) == EOS)
  809. return (0);
  810. }
  811. return (1);
  812. }
  813. #ifdef DEBUG
  814. static void
  815. qprintf(str, s)
  816. const char *str;
  817. register Char *s;
  818. {
  819. register Char *p;
  820. (void)printf("%s:\n", str);
  821. for (p = s; *p; p++)
  822. (void)printf("%c", CHAR(*p));
  823. (void)printf("\n");
  824. for (p = s; *p; p++)
  825. (void)printf("%c", *p & M_PROTECT ? '"' : ' ');
  826. (void)printf("\n");
  827. for (p = s; *p; p++)
  828. (void)printf("%c", ismeta(*p) ? '_' : ' ');
  829. (void)printf("\n");
  830. }
  831. #endif