glob.c 21 KB

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