pax.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  1. /*
  2. * cpio - copy file archives in and out
  3. *
  4. * Gunnar Ritter, Freiburg i. Br., Germany, April 2003.
  5. */
  6. /*
  7. * Copyright (c) 2003 Gunnar Ritter
  8. *
  9. * This software is provided 'as-is', without any express or implied
  10. * warranty. In no event will the authors be held liable for any damages
  11. * arising from the use of this software.
  12. *
  13. * Permission is granted to anyone to use this software for any purpose,
  14. * including commercial applications, and to alter it and redistribute
  15. * it freely, subject to the following restrictions:
  16. *
  17. * 1. The origin of this software must not be misrepresented; you must not
  18. * claim that you wrote the original software. If you use this software
  19. * in a product, an acknowledgment in the product documentation would be
  20. * appreciated but is not required.
  21. *
  22. * 2. Altered source versions must be plainly marked as such, and must not be
  23. * misrepresented as being the original software.
  24. *
  25. * 3. This notice may not be removed or altered from any source distribution.
  26. */
  27. #if __GNUC__ >= 3 && __GNUC_MINOR__ >= 4 || __GNUC__ >= 4
  28. #define USED __attribute__ ((used))
  29. #elif defined __GNUC__
  30. #define USED __attribute__ ((unused))
  31. #else
  32. #define USED
  33. #endif
  34. #if defined (SU3)
  35. static const char sccsid[] USED = "@(#)pax_su3.sl 1.26 (gritter) 6/26/05";
  36. #else
  37. static const char sccsid[] USED = "@(#)pax.sl 1.26 (gritter) 6/26/05";
  38. #endif
  39. /* Sccsid @(#)pax.c 1.26 (gritter) 6/26/05 */
  40. #include <sys/types.h>
  41. #include <sys/stat.h>
  42. #include <fcntl.h>
  43. #include <unistd.h>
  44. #include <stdio.h>
  45. #include <stdarg.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48. #include <fnmatch.h>
  49. #include <dirent.h>
  50. #include <regex.h>
  51. #include <wchar.h>
  52. #include <time.h>
  53. #include <inttypes.h>
  54. #include "iblok.h"
  55. #include "cpio.h"
  56. static char **files;
  57. static int filec;
  58. static struct iblok *filinp;
  59. static char *path;
  60. static size_t pathsz;
  61. static int pax_Hflag;
  62. static void setpres(const char *);
  63. static size_t ofiles_pax(char **, size_t *);
  64. static void prtime_pax(time_t);
  65. static void parsesub(char *);
  66. void
  67. flags(int ac, char **av)
  68. {
  69. const char optstring[] = "rwab:cdf:HikKlLno:p:s:tuvx:X";
  70. int i;
  71. int illegal = 0;
  72. char *x;
  73. #if defined (SU3)
  74. pax = PAX_TYPE_PAX2001;
  75. #else
  76. pax = PAX_TYPE_PAX1992;
  77. #endif
  78. dflag = 1;
  79. uflag = 1;
  80. ofiles = ofiles_pax;
  81. prtime = prtime_pax;
  82. while ((i = getopt(ac, av, optstring)) != EOF) {
  83. switch (i) {
  84. case 'r':
  85. if (action && action != 'i')
  86. action = 'p';
  87. else
  88. action = 'i';
  89. break;
  90. case 'w':
  91. if (action && action != 'o')
  92. action = 'p';
  93. else
  94. action = 'o';
  95. break;
  96. case 'a':
  97. Aflag = 1;
  98. break;
  99. case 'b':
  100. blksiz = strtol(optarg, &x, 10);
  101. switch (*x) {
  102. case 'b':
  103. blksiz *= 512;
  104. break;
  105. case 'k':
  106. blksiz *= 1024;
  107. break;
  108. case 'm':
  109. blksiz *= 1048576;
  110. break;
  111. case 'w':
  112. blksiz *= 2;
  113. break;
  114. }
  115. if (blksiz <= 0)
  116. msg(4, -2,
  117. "Illegal size given for -b option.\n");
  118. Cflag = 1;
  119. break;
  120. case 'c':
  121. fflag = 1;
  122. break;
  123. case 'd':
  124. pax_dflag = 1;
  125. break;
  126. case 'f':
  127. Oflag = Iflag = optarg;
  128. break;
  129. case 'H':
  130. pax_Hflag = 1;
  131. break;
  132. case 'i':
  133. rflag = 1;
  134. break;
  135. case 'k':
  136. pax_kflag = 1;
  137. break;
  138. case 'K':
  139. kflag = 1;
  140. break;
  141. case 'l':
  142. lflag = 1;
  143. break;
  144. case 'L':
  145. Lflag = 1;
  146. break;
  147. case 'n':
  148. pax_nflag = 1;
  149. break;
  150. case 'o':
  151. pax_options(optarg, 1);
  152. break;
  153. case 'p':
  154. setpres(optarg);
  155. break;
  156. case 's':
  157. pax_sflag = 1;
  158. parsesub(optarg);
  159. break;
  160. case 't':
  161. aflag = 1;
  162. break;
  163. case 'u':
  164. uflag = 0;
  165. pax_uflag = 1;
  166. break;
  167. case 'v':
  168. vflag = 1;
  169. break;
  170. case 'x':
  171. if (strcmp(optarg, "cpio") == 0)
  172. fmttype = FMT_ODC;
  173. else {
  174. if (setfmt(optarg) < 0)
  175. illegal = 1;
  176. }
  177. break;
  178. case 'X':
  179. pax_Xflag = 1;
  180. break;
  181. default:
  182. illegal = 1;
  183. }
  184. }
  185. switch (action) {
  186. case 0:
  187. if (rflag || pax_kflag || pax_uflag || pax_preserve)
  188. illegal = 1;
  189. action = 'i';
  190. tflag = 1;
  191. setvbuf(stdout, NULL, _IOLBF, 0);
  192. /*FALLTHRU*/
  193. case 'i':
  194. if (aflag || pax_Xflag || lflag)
  195. illegal = 1;
  196. for (i = optind; i < ac; i++) {
  197. addg(av[i], 0);
  198. if (pax_dflag == 0) {
  199. char *da;
  200. int j;
  201. da = smalloc(strlen(av[i]) + 2);
  202. for (j = 0; av[i][j]; j++)
  203. da[j] = av[i][j];
  204. da[j++] = '/';
  205. da[j++] = '*';
  206. da[j] = 0;
  207. addg(da, 1);
  208. free(da);
  209. }
  210. }
  211. break;
  212. case 'o':
  213. if (fflag || pax_kflag || pax_nflag || kflag)
  214. illegal = 1;
  215. if (Aflag && Oflag == NULL) {
  216. msg(3, 0, "-a requires the -f option\n");
  217. illegal = 1;
  218. }
  219. if (optind != ac) {
  220. files = &av[optind];
  221. filec = ac - optind;
  222. } else
  223. filinp = ib_alloc(0, 0);
  224. if (pax_uflag)
  225. Aflag = 1;
  226. if (Aflag == 0 && fmttype == FMT_NONE)
  227. fmttype = FMT_ODC;
  228. break;
  229. case 'p':
  230. if (fflag || blksiz || Oflag || Iflag || fmttype != FMT_NONE ||
  231. kflag)
  232. illegal = 1;
  233. if (optind == ac)
  234. illegal = 1;
  235. else if (optind+1 != ac) {
  236. files = &av[optind];
  237. filec = ac - optind - 1;
  238. optind = ac - 1;
  239. } else
  240. filinp = ib_alloc(0, 0);
  241. break;
  242. }
  243. if (illegal)
  244. usage();
  245. }
  246. void
  247. usage(void)
  248. {
  249. fprintf(stderr, "USAGE:\n\
  250. \t%s [-cdnvK] [-b size] [-f file] [-s replstr] [-x hdr] [patterns]\n\
  251. \t%s -r[cdiknuvK] [-b size] [-f file] [-p priv] [-s replstr] [-x hdr] [patterns]\n\
  252. \t%s -w[adituvLX] [-b size] [-f file] [-s replstr] [-x hdr] [files]\n\
  253. \t%s -rw[diklntuvLX] [-p priv] [-s replstr] [files] directory\n",
  254. progname, progname, progname, progname);
  255. exit(1);
  256. }
  257. static void
  258. setpres(const char *s)
  259. {
  260. s--;
  261. while (*++s) {
  262. pax_preserve &= ~PAX_P_EVERY;
  263. switch (*s) {
  264. case 'a':
  265. pax_preserve |= PAX_P_ATIME;
  266. break;
  267. case 'e':
  268. pax_preserve |= PAX_P_EVERY;
  269. break;
  270. case 'm':
  271. pax_preserve |= PAX_P_MTIME;
  272. break;
  273. case 'o':
  274. pax_preserve |= PAX_P_OWNER;
  275. break;
  276. case 'p':
  277. pax_preserve |= PAX_P_MODE;
  278. break;
  279. default:
  280. msg(2, 0, "ignoring unknown option \"-p%c\"\n",
  281. *s&0377);
  282. }
  283. }
  284. if (pax_preserve & PAX_P_EVERY)
  285. pax_preserve |= PAX_P_OWNER|PAX_P_MODE;
  286. }
  287. int
  288. gmatch(const char *s, const char *p)
  289. {
  290. int val;
  291. #ifdef __GLIBC__
  292. /* avoid glibc's broken [^...] */
  293. extern char **environ;
  294. char **savenv = environ;
  295. char *newenv[] = { "POSIXLY_CORRECT=", NULL };
  296. environ = newenv;
  297. #endif /* __GLIBC__ */
  298. val = fnmatch(p, s, 0) == 0;
  299. #ifdef __GLIBC__
  300. environ = savenv;
  301. #endif /* __GLIBC__ */
  302. return val;
  303. }
  304. static const char *
  305. nextfile(void)
  306. {
  307. char *line = NULL;
  308. size_t linsiz = 0, linlen;
  309. if (filinp) {
  310. pax_Hflag = 0;
  311. if ((linlen=ib_getlin(filinp, &line, &linsiz, srealloc)) == 0) {
  312. filinp = NULL;
  313. return NULL;
  314. }
  315. if (line[linlen-1] == '\n')
  316. line[--linlen] = '\0';
  317. return line;
  318. } else if (filec > 0) {
  319. filec--;
  320. return *files++;
  321. } else
  322. return NULL;
  323. }
  324. static size_t
  325. catpath(size_t pend, const char *base)
  326. {
  327. size_t blen = strlen(base);
  328. if (pend + blen + 2 >= pathsz)
  329. path = srealloc(path, pathsz = pend + blen + 16);
  330. if (pend == 0 || path[pend-1] != '/')
  331. path[pend++] = '/';
  332. strcpy(&path[pend], base);
  333. return pend + blen;
  334. }
  335. /*
  336. * Descend the directory hierarchies given using stdin or arguments
  337. * and return file names one per one.
  338. */
  339. static size_t
  340. ofiles_pax(char **name, size_t *namsiz)
  341. {
  342. static DIR **dt;
  343. static int dti, dts;
  344. static int *pend;
  345. static dev_t *curdev;
  346. static ino_t *curino;
  347. struct stat st;
  348. struct dirent *dp;
  349. const char *nf;
  350. int i;
  351. if (dt == NULL) {
  352. dt = scalloc(dts = 1, sizeof *dt);
  353. pend = scalloc(dts, sizeof *pend);
  354. curdev = scalloc(dts, sizeof *curdev);
  355. curino = scalloc(dts, sizeof *curino);
  356. }
  357. for (;;) {
  358. if (dti >= 0 && dt[dti] != NULL) {
  359. if ((dp = readdir(dt[dti])) != NULL) {
  360. if (dp->d_name[0] == '.' &&
  361. (dp->d_name[1] == '\0' ||
  362. dp->d_name[1] == '.' &&
  363. dp->d_name[2] == '\0'))
  364. continue;
  365. if (dti+1 <= dts) {
  366. dt = srealloc(dt, sizeof *dt * ++dts);
  367. pend = srealloc(pend, sizeof *pend*dts);
  368. curdev = srealloc(curdev, sizeof *curdev
  369. * dts);
  370. curino = srealloc(curino, sizeof *curino
  371. * dts);
  372. }
  373. pend[dti+1] = catpath(pend[dti], dp->d_name);
  374. if (pax_Hflag)
  375. Lflag = dti < 0;
  376. if ((Lflag ? stat : lstat)(path, &st) < 0) {
  377. emsg(2, "Error with %s of \"%s\"",
  378. lflag? "stat" : "lstat",
  379. path);
  380. errcnt++;
  381. } else if ((st.st_mode&S_IFMT) == S_IFDIR &&
  382. (pax_Xflag == 0 ||
  383. curdev[0] == st.st_dev)) {
  384. if (Lflag) {
  385. for (i = 0; i <= dti; i++)
  386. if (st.st_dev ==
  387. curdev[i] &&
  388. st.st_ino ==
  389. curino[i]) {
  390. if (pax ==
  391. PAX_TYPE_PAX2001)
  392. msg(4, 1,
  393. "Symbolic link "
  394. "loop at "
  395. "\"%s\"\n",
  396. path);
  397. break;
  398. }
  399. if (i <= dti)
  400. break;
  401. }
  402. if ((dt[dti+1]=opendir(path)) == NULL) {
  403. emsg(2, "Cannot open directory "
  404. "\"%s\"", path);
  405. errcnt++;
  406. } else {
  407. dti++;
  408. curdev[dti] = st.st_dev;
  409. curino[dti] = st.st_ino;
  410. continue;
  411. }
  412. } else
  413. break;
  414. } else {
  415. path[pend[dti]] = '\0';
  416. closedir(dt[dti]);
  417. dt[dti--] = NULL;
  418. if (pax_Hflag)
  419. Lflag = dti < 0;
  420. break;
  421. }
  422. } else {
  423. if (pax_Hflag)
  424. Lflag = 1;
  425. while ((nf = nextfile()) != NULL &&
  426. (Lflag ? stat : lstat)(nf, &st) < 0) {
  427. emsg(2, "Error with stat of \"%s\"", nf);
  428. errcnt++;
  429. }
  430. if (nf == NULL)
  431. return 0;
  432. dti = 0;
  433. if (path)
  434. free(path);
  435. pend[dti] = strlen(nf);
  436. strcpy(path = smalloc(pathsz = pend[dti]+1), nf);
  437. if (pax_dflag || (st.st_mode&S_IFMT) != S_IFDIR) {
  438. dti = -1;
  439. break;
  440. }
  441. curdev[dti] = st.st_dev;
  442. curino[dti] = st.st_ino;
  443. if ((dt[dti] = opendir(path)) == NULL) {
  444. emsg(2, "Cannot open directory \"%s\"", path);
  445. errcnt++;
  446. }
  447. }
  448. }
  449. if (*name == NULL || *namsiz < pathsz) {
  450. free(*name);
  451. *name = smalloc(*namsiz=pathsz);
  452. }
  453. strcpy(*name, path);
  454. return pend[dti+1];
  455. }
  456. struct pax_had {
  457. struct pax_had *p_next;
  458. const char *p_name;
  459. time_t p_mtime;
  460. };
  461. static int pprime = 7919;
  462. static int
  463. phash(const char *s)
  464. {
  465. uint32_t h = 0, g;
  466. s--;
  467. while (*++s) {
  468. h = (h << 4) + (*s & 0377);
  469. if (g = h & 0xf0000000) {
  470. h = h ^ (g >> 24);
  471. h = h ^ g;
  472. }
  473. }
  474. return h % pprime;
  475. }
  476. static int
  477. plook(const char *name, struct pax_had **pp)
  478. {
  479. static struct pax_had **pt;
  480. uint32_t h, had;
  481. if (pt == NULL)
  482. pt = scalloc(pprime, sizeof *pt);
  483. (*pp) = pt[h = phash(name)];
  484. while (*pp != NULL) {
  485. if (strcmp((*pp)->p_name, name) == 0)
  486. break;
  487. *pp = (*pp)->p_next;
  488. }
  489. had = *pp != NULL;
  490. if (*pp == NULL) {
  491. *pp = scalloc(1, sizeof **pp);
  492. (*pp)->p_name = sstrdup(name);
  493. (*pp)->p_next = pt[h];
  494. pt[h] = *pp;
  495. }
  496. return had;
  497. }
  498. int
  499. pax_track(const char *name, time_t mtime)
  500. {
  501. struct pax_had *pp;
  502. struct stat st;
  503. if (pax_uflag == 0 && (pax_nflag == 0 || patterns))
  504. return 1;
  505. if (action == 'i' && pax_uflag) {
  506. if (lstat(name, &st) == 0 && mtime < st.st_mtime)
  507. return 0;
  508. }
  509. if (action != 'i' || pax_nflag) {
  510. if (plook(name, &pp) != 0) {
  511. if (action != 'i' && pax_uflag == 0)
  512. return 0;
  513. if (mtime > pp->p_mtime) {
  514. pp->p_mtime = mtime;
  515. return 1;
  516. }
  517. return 0;
  518. } else
  519. pp->p_mtime = mtime;
  520. }
  521. return 1;
  522. }
  523. static void
  524. prtime_pax(time_t t)
  525. {
  526. char b[30];
  527. time_t now;
  528. time(&now);
  529. if (t > now || t < now - (6*30*86400))
  530. strftime(b, sizeof b, "%b %e %Y", localtime(&t));
  531. else
  532. strftime(b, sizeof b, "%b %e %H:%M", localtime(&t));
  533. printf(" %s ", b);
  534. }
  535. struct replacement {
  536. regex_t r_re;
  537. const char *r_rhs;
  538. int r_nbra;
  539. enum {
  540. REPL_0 = 0,
  541. REPL_G = 1,
  542. REPL_P = 2
  543. } r_flags;
  544. } *rep;
  545. #define NBRA 9
  546. static int ren, res;
  547. static int mb_cur_max;
  548. static wchar_t
  549. nextc(char **sc, int *np)
  550. {
  551. char *p = *sc;
  552. wchar_t wcbuf;
  553. int len;
  554. if (**sc == '\0') {
  555. *np = 0;
  556. return 0;
  557. }
  558. if (mb_cur_max == 1 || (**sc&0200) == 0) {
  559. *np = 1;
  560. return *(*sc)++ & 0377;
  561. }
  562. if ((len = mbtowc(&wcbuf, p, mb_cur_max)) < 0)
  563. msg(3, -2, "Invalid multibyte character for \"-s\" option\n");
  564. *np = len;
  565. *sc += len;
  566. return wcbuf;
  567. }
  568. static void
  569. parsesub(char *s)
  570. {
  571. int len;
  572. char *ps = NULL;
  573. wchar_t seof = nextc(&s, &len);
  574. wint_t c, d;
  575. int nbra = 0;
  576. int reflags;
  577. if (seof == 0)
  578. goto unt;
  579. mb_cur_max = MB_CUR_MAX;
  580. ps = s;
  581. do {
  582. if ((c = nextc(&s, &len)) == seof)
  583. break;
  584. if (c == '\\') {
  585. if ((c = nextc(&s, &len)) == '(')
  586. nbra++;
  587. continue;
  588. } else if (c == '[') {
  589. d = WEOF;
  590. do {
  591. if ((c = nextc(&s, &len)) == '\0')
  592. continue;
  593. if (d == '[' && (c == ':' || c == '.' ||
  594. c == '=')) {
  595. d = c;
  596. do {
  597. if ((c=nextc(&s, &len)) == '\0')
  598. continue;
  599. } while (c != d || *s != ']');
  600. nextc(&s, &len);
  601. c = WEOF; /* reset d and continue */
  602. }
  603. d = c;
  604. } while (c != ']');
  605. }
  606. } while (*s != '\0');
  607. if (c != seof)
  608. unt: msg(3, -2, "Unterminated argument for \"-s\" option.\n");
  609. s[-len] = '\0';
  610. if (ren <= res)
  611. rep = srealloc(rep, ++res * sizeof *rep);
  612. reflags = REG_ANGLES;
  613. if (pax >= PAX_TYPE_PAX2001)
  614. reflags |= REG_AVOIDNULL;
  615. if (regcomp(&rep[ren].r_re, ps, reflags) != 0)
  616. msg(3, -2, "Regular expression error in \"-s\" option\n");
  617. rep[ren].r_rhs = s;
  618. rep[ren].r_nbra = nbra;
  619. while ((c = nextc(&s, &len)) != 0) {
  620. if (c == '\\')
  621. c = nextc(&s, &len);
  622. else if (c == seof)
  623. break;
  624. }
  625. rep[ren].r_flags = 0;
  626. if (c == seof) {
  627. s[-len] = '\0';
  628. while ((c = nextc(&s, &len)) != '\0') {
  629. switch (c) {
  630. case 'g':
  631. rep[ren].r_flags |= REPL_G;
  632. break;
  633. case 'p':
  634. rep[ren].r_flags |= REPL_P;
  635. break;
  636. default:
  637. msg(2, 0, "Ignoring unknown -s flag \"%c\"\n",
  638. c);
  639. }
  640. }
  641. }
  642. ren++;
  643. }
  644. #define put(c) ((new = innew+1>=newsize ? srealloc(new, newsize+=32) : new), \
  645. new[innew++] = (c))
  646. int
  647. pax_sname(char **oldp, size_t *olds)
  648. {
  649. char *new = NULL;
  650. size_t newsize = 0;
  651. regmatch_t bralist[NBRA+1];
  652. int c, i, k, l, y, z;
  653. int innew = 0, ef = 0;
  654. char *inp = *oldp;
  655. for (z = 0; z < ren; z++) {
  656. in: if (regexec(&rep[z].r_re, inp, NBRA+1, bralist, ef) != 0) {
  657. if (ef == 0)
  658. continue;
  659. goto out;
  660. }
  661. for (i = 0; i < bralist[0].rm_so; i++)
  662. put(inp[i]);
  663. k = 0;
  664. while (c = rep[z].r_rhs[k++] & 0377) {
  665. y = -1;
  666. if (c == '&')
  667. y = 0;
  668. else if (c == '\\') {
  669. c = rep[z].r_rhs[k++] & 0377;
  670. if (c >= '1' && c < rep[z].r_nbra+'1')
  671. y = c - '0';
  672. }
  673. if (y >= 0)
  674. for (l = bralist[y].rm_so; l < bralist[y].rm_eo;
  675. l++)
  676. put(inp[l]);
  677. else
  678. put(c);
  679. }
  680. k = innew;
  681. for (i = bralist[0].rm_eo; inp[i]; i++)
  682. put(inp[i]);
  683. put('\0');
  684. if (rep[z].r_flags & REPL_G) {
  685. ef = REG_NOTBOL;
  686. inp = &inp[bralist[0].rm_eo];
  687. innew = k;
  688. if (bralist[0].rm_so == bralist[0].rm_eo) {
  689. if (inp[0] && (nextc(&inp, &l), inp[0]))
  690. innew++;
  691. else
  692. goto out;
  693. }
  694. goto in;
  695. }
  696. out: if (rep[z].r_flags & REPL_P)
  697. fprintf(stderr, "%s >> %s\n", *oldp, new);
  698. free(*oldp);
  699. *oldp = new;
  700. *olds = newsize;
  701. return *new != '\0';
  702. }
  703. return 1;
  704. }
  705. void
  706. pax_onexit(void)
  707. {
  708. struct glist *gp;
  709. for (gp = patterns; gp; gp = gp->g_nxt) {
  710. if (gp->g_art)
  711. continue;
  712. if (gp->g_gotcha == 0 && (gp->g_nxt == NULL ||
  713. gp->g_nxt->g_art == 0 ||
  714. gp->g_gotcha == 0)) {
  715. msg(3, 0, "Pattern not matched: \"%s\"\n", gp->g_pat);
  716. errcnt++;
  717. }
  718. }
  719. }