archive_match.c 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875
  1. /*-
  2. * Copyright (c) 2003-2007 Tim Kientzle
  3. * Copyright (c) 2012 Michihiro NAKAJIMA
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
  16. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  17. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  18. * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
  19. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  20. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  21. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  22. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  24. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include "archive_platform.h"
  27. __FBSDID("$FreeBSD$");
  28. #ifdef HAVE_ERRNO_H
  29. #include <errno.h>
  30. #endif
  31. #ifdef HAVE_STDLIB_H
  32. #include <stdlib.h>
  33. #endif
  34. #ifdef HAVE_STRING_H
  35. #include <string.h>
  36. #endif
  37. #include "archive.h"
  38. #include "archive_private.h"
  39. #include "archive_entry.h"
  40. #include "archive_getdate.h"
  41. #include "archive_pathmatch.h"
  42. #include "archive_rb.h"
  43. #include "archive_string.h"
  44. struct match {
  45. struct match *next;
  46. int matches;
  47. struct archive_mstring pattern;
  48. };
  49. struct match_list {
  50. struct match *first;
  51. struct match **last;
  52. int count;
  53. int unmatched_count;
  54. struct match *unmatched_next;
  55. int unmatched_eof;
  56. };
  57. struct match_file {
  58. struct archive_rb_node node;
  59. struct match_file *next;
  60. struct archive_mstring pathname;
  61. int flag;
  62. time_t mtime_sec;
  63. long mtime_nsec;
  64. time_t ctime_sec;
  65. long ctime_nsec;
  66. };
  67. struct entry_list {
  68. struct match_file *first;
  69. struct match_file **last;
  70. int count;
  71. };
  72. struct id_array {
  73. size_t size;/* Allocated size */
  74. size_t count;
  75. int64_t *ids;
  76. };
  77. #define PATTERN_IS_SET 1
  78. #define TIME_IS_SET 2
  79. #define ID_IS_SET 4
  80. struct archive_match {
  81. struct archive archive;
  82. /* exclusion/inclusion set flag. */
  83. int setflag;
  84. /* Recursively include directory content? */
  85. int recursive_include;
  86. /*
  87. * Matching filename patterns.
  88. */
  89. struct match_list exclusions;
  90. struct match_list inclusions;
  91. /*
  92. * Matching time stamps.
  93. */
  94. time_t now;
  95. int newer_mtime_filter;
  96. time_t newer_mtime_sec;
  97. long newer_mtime_nsec;
  98. int newer_ctime_filter;
  99. time_t newer_ctime_sec;
  100. long newer_ctime_nsec;
  101. int older_mtime_filter;
  102. time_t older_mtime_sec;
  103. long older_mtime_nsec;
  104. int older_ctime_filter;
  105. time_t older_ctime_sec;
  106. long older_ctime_nsec;
  107. /*
  108. * Matching time stamps with its filename.
  109. */
  110. struct archive_rb_tree exclusion_tree;
  111. struct entry_list exclusion_entry_list;
  112. /*
  113. * Matching file owners.
  114. */
  115. struct id_array inclusion_uids;
  116. struct id_array inclusion_gids;
  117. struct match_list inclusion_unames;
  118. struct match_list inclusion_gnames;
  119. };
  120. static int add_pattern_from_file(struct archive_match *,
  121. struct match_list *, int, const void *, int);
  122. static int add_entry(struct archive_match *, int,
  123. struct archive_entry *);
  124. static int add_owner_id(struct archive_match *, struct id_array *,
  125. int64_t);
  126. static int add_owner_name(struct archive_match *, struct match_list *,
  127. int, const void *);
  128. static int add_pattern_mbs(struct archive_match *, struct match_list *,
  129. const char *);
  130. static int add_pattern_wcs(struct archive_match *, struct match_list *,
  131. const wchar_t *);
  132. static int cmp_key_mbs(const struct archive_rb_node *, const void *);
  133. static int cmp_key_wcs(const struct archive_rb_node *, const void *);
  134. static int cmp_node_mbs(const struct archive_rb_node *,
  135. const struct archive_rb_node *);
  136. static int cmp_node_wcs(const struct archive_rb_node *,
  137. const struct archive_rb_node *);
  138. static void entry_list_add(struct entry_list *, struct match_file *);
  139. static void entry_list_free(struct entry_list *);
  140. static void entry_list_init(struct entry_list *);
  141. static int error_nomem(struct archive_match *);
  142. static void match_list_add(struct match_list *, struct match *);
  143. static void match_list_free(struct match_list *);
  144. static void match_list_init(struct match_list *);
  145. static int match_list_unmatched_inclusions_next(struct archive_match *,
  146. struct match_list *, int, const void **);
  147. static int match_owner_id(struct id_array *, int64_t);
  148. #if !defined(_WIN32) || defined(__CYGWIN__)
  149. static int match_owner_name_mbs(struct archive_match *,
  150. struct match_list *, const char *);
  151. #else
  152. static int match_owner_name_wcs(struct archive_match *,
  153. struct match_list *, const wchar_t *);
  154. #endif
  155. static int match_path_exclusion(struct archive_match *,
  156. struct match *, int, const void *);
  157. static int match_path_inclusion(struct archive_match *,
  158. struct match *, int, const void *);
  159. static int owner_excluded(struct archive_match *,
  160. struct archive_entry *);
  161. static int path_excluded(struct archive_match *, int, const void *);
  162. static int set_timefilter(struct archive_match *, int, time_t, long,
  163. time_t, long);
  164. static int set_timefilter_pathname_mbs(struct archive_match *,
  165. int, const char *);
  166. static int set_timefilter_pathname_wcs(struct archive_match *,
  167. int, const wchar_t *);
  168. static int set_timefilter_date(struct archive_match *, int, const char *);
  169. static int set_timefilter_date_w(struct archive_match *, int,
  170. const wchar_t *);
  171. static int time_excluded(struct archive_match *,
  172. struct archive_entry *);
  173. static int validate_time_flag(struct archive *, int, const char *);
  174. #define get_date __archive_get_date
  175. static const struct archive_rb_tree_ops rb_ops_mbs = {
  176. cmp_node_mbs, cmp_key_mbs
  177. };
  178. static const struct archive_rb_tree_ops rb_ops_wcs = {
  179. cmp_node_wcs, cmp_key_wcs
  180. };
  181. /*
  182. * The matching logic here needs to be re-thought. I started out to
  183. * try to mimic gtar's matching logic, but it's not entirely
  184. * consistent. In particular 'tar -t' and 'tar -x' interpret patterns
  185. * on the command line as anchored, but --exclude doesn't.
  186. */
  187. static int
  188. error_nomem(struct archive_match *a)
  189. {
  190. archive_set_error(&(a->archive), ENOMEM, "No memory");
  191. a->archive.state = ARCHIVE_STATE_FATAL;
  192. return (ARCHIVE_FATAL);
  193. }
  194. /*
  195. * Create an ARCHIVE_MATCH object.
  196. */
  197. struct archive *
  198. archive_match_new(void)
  199. {
  200. struct archive_match *a;
  201. a = (struct archive_match *)calloc(1, sizeof(*a));
  202. if (a == NULL)
  203. return (NULL);
  204. a->archive.magic = ARCHIVE_MATCH_MAGIC;
  205. a->archive.state = ARCHIVE_STATE_NEW;
  206. a->recursive_include = 1;
  207. match_list_init(&(a->inclusions));
  208. match_list_init(&(a->exclusions));
  209. __archive_rb_tree_init(&(a->exclusion_tree), &rb_ops_mbs);
  210. entry_list_init(&(a->exclusion_entry_list));
  211. match_list_init(&(a->inclusion_unames));
  212. match_list_init(&(a->inclusion_gnames));
  213. time(&a->now);
  214. return (&(a->archive));
  215. }
  216. /*
  217. * Free an ARCHIVE_MATCH object.
  218. */
  219. int
  220. archive_match_free(struct archive *_a)
  221. {
  222. struct archive_match *a;
  223. if (_a == NULL)
  224. return (ARCHIVE_OK);
  225. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  226. ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_match_free");
  227. a = (struct archive_match *)_a;
  228. match_list_free(&(a->inclusions));
  229. match_list_free(&(a->exclusions));
  230. entry_list_free(&(a->exclusion_entry_list));
  231. free(a->inclusion_uids.ids);
  232. free(a->inclusion_gids.ids);
  233. match_list_free(&(a->inclusion_unames));
  234. match_list_free(&(a->inclusion_gnames));
  235. free(a);
  236. return (ARCHIVE_OK);
  237. }
  238. /*
  239. * Convenience function to perform all exclusion tests.
  240. *
  241. * Returns 1 if archive entry is excluded.
  242. * Returns 0 if archive entry is not excluded.
  243. * Returns <0 if something error happened.
  244. */
  245. int
  246. archive_match_excluded(struct archive *_a, struct archive_entry *entry)
  247. {
  248. struct archive_match *a;
  249. int r;
  250. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  251. ARCHIVE_STATE_NEW, "archive_match_excluded_ae");
  252. a = (struct archive_match *)_a;
  253. if (entry == NULL) {
  254. archive_set_error(&(a->archive), EINVAL, "entry is NULL");
  255. return (ARCHIVE_FAILED);
  256. }
  257. r = 0;
  258. if (a->setflag & PATTERN_IS_SET) {
  259. #if defined(_WIN32) && !defined(__CYGWIN__)
  260. r = path_excluded(a, 0, archive_entry_pathname_w(entry));
  261. #else
  262. r = path_excluded(a, 1, archive_entry_pathname(entry));
  263. #endif
  264. if (r != 0)
  265. return (r);
  266. }
  267. if (a->setflag & TIME_IS_SET) {
  268. r = time_excluded(a, entry);
  269. if (r != 0)
  270. return (r);
  271. }
  272. if (a->setflag & ID_IS_SET)
  273. r = owner_excluded(a, entry);
  274. return (r);
  275. }
  276. /*
  277. * Utility functions to manage exclusion/inclusion patterns
  278. */
  279. int
  280. archive_match_exclude_pattern(struct archive *_a, const char *pattern)
  281. {
  282. struct archive_match *a;
  283. int r;
  284. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  285. ARCHIVE_STATE_NEW, "archive_match_exclude_pattern");
  286. a = (struct archive_match *)_a;
  287. if (pattern == NULL || *pattern == '\0') {
  288. archive_set_error(&(a->archive), EINVAL, "pattern is empty");
  289. return (ARCHIVE_FAILED);
  290. }
  291. if ((r = add_pattern_mbs(a, &(a->exclusions), pattern)) != ARCHIVE_OK)
  292. return (r);
  293. return (ARCHIVE_OK);
  294. }
  295. int
  296. archive_match_exclude_pattern_w(struct archive *_a, const wchar_t *pattern)
  297. {
  298. struct archive_match *a;
  299. int r;
  300. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  301. ARCHIVE_STATE_NEW, "archive_match_exclude_pattern_w");
  302. a = (struct archive_match *)_a;
  303. if (pattern == NULL || *pattern == L'\0') {
  304. archive_set_error(&(a->archive), EINVAL, "pattern is empty");
  305. return (ARCHIVE_FAILED);
  306. }
  307. if ((r = add_pattern_wcs(a, &(a->exclusions), pattern)) != ARCHIVE_OK)
  308. return (r);
  309. return (ARCHIVE_OK);
  310. }
  311. int
  312. archive_match_exclude_pattern_from_file(struct archive *_a,
  313. const char *pathname, int nullSeparator)
  314. {
  315. struct archive_match *a;
  316. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  317. ARCHIVE_STATE_NEW, "archive_match_exclude_pattern_from_file");
  318. a = (struct archive_match *)_a;
  319. return add_pattern_from_file(a, &(a->exclusions), 1, pathname,
  320. nullSeparator);
  321. }
  322. int
  323. archive_match_exclude_pattern_from_file_w(struct archive *_a,
  324. const wchar_t *pathname, int nullSeparator)
  325. {
  326. struct archive_match *a;
  327. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  328. ARCHIVE_STATE_NEW, "archive_match_exclude_pattern_from_file_w");
  329. a = (struct archive_match *)_a;
  330. return add_pattern_from_file(a, &(a->exclusions), 0, pathname,
  331. nullSeparator);
  332. }
  333. int
  334. archive_match_include_pattern(struct archive *_a, const char *pattern)
  335. {
  336. struct archive_match *a;
  337. int r;
  338. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  339. ARCHIVE_STATE_NEW, "archive_match_include_pattern");
  340. a = (struct archive_match *)_a;
  341. if (pattern == NULL || *pattern == '\0') {
  342. archive_set_error(&(a->archive), EINVAL, "pattern is empty");
  343. return (ARCHIVE_FAILED);
  344. }
  345. if ((r = add_pattern_mbs(a, &(a->inclusions), pattern)) != ARCHIVE_OK)
  346. return (r);
  347. return (ARCHIVE_OK);
  348. }
  349. int
  350. archive_match_include_pattern_w(struct archive *_a, const wchar_t *pattern)
  351. {
  352. struct archive_match *a;
  353. int r;
  354. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  355. ARCHIVE_STATE_NEW, "archive_match_include_pattern_w");
  356. a = (struct archive_match *)_a;
  357. if (pattern == NULL || *pattern == L'\0') {
  358. archive_set_error(&(a->archive), EINVAL, "pattern is empty");
  359. return (ARCHIVE_FAILED);
  360. }
  361. if ((r = add_pattern_wcs(a, &(a->inclusions), pattern)) != ARCHIVE_OK)
  362. return (r);
  363. return (ARCHIVE_OK);
  364. }
  365. int
  366. archive_match_include_pattern_from_file(struct archive *_a,
  367. const char *pathname, int nullSeparator)
  368. {
  369. struct archive_match *a;
  370. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  371. ARCHIVE_STATE_NEW, "archive_match_include_pattern_from_file");
  372. a = (struct archive_match *)_a;
  373. return add_pattern_from_file(a, &(a->inclusions), 1, pathname,
  374. nullSeparator);
  375. }
  376. int
  377. archive_match_include_pattern_from_file_w(struct archive *_a,
  378. const wchar_t *pathname, int nullSeparator)
  379. {
  380. struct archive_match *a;
  381. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  382. ARCHIVE_STATE_NEW, "archive_match_include_pattern_from_file_w");
  383. a = (struct archive_match *)_a;
  384. return add_pattern_from_file(a, &(a->inclusions), 0, pathname,
  385. nullSeparator);
  386. }
  387. /*
  388. * Test functions for pathname patterns.
  389. *
  390. * Returns 1 if archive entry is excluded.
  391. * Returns 0 if archive entry is not excluded.
  392. * Returns <0 if something error happened.
  393. */
  394. int
  395. archive_match_path_excluded(struct archive *_a,
  396. struct archive_entry *entry)
  397. {
  398. struct archive_match *a;
  399. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  400. ARCHIVE_STATE_NEW, "archive_match_path_excluded");
  401. a = (struct archive_match *)_a;
  402. if (entry == NULL) {
  403. archive_set_error(&(a->archive), EINVAL, "entry is NULL");
  404. return (ARCHIVE_FAILED);
  405. }
  406. /* If we don't have exclusion/inclusion pattern set at all,
  407. * the entry is always not excluded. */
  408. if ((a->setflag & PATTERN_IS_SET) == 0)
  409. return (0);
  410. #if defined(_WIN32) && !defined(__CYGWIN__)
  411. return (path_excluded(a, 0, archive_entry_pathname_w(entry)));
  412. #else
  413. return (path_excluded(a, 1, archive_entry_pathname(entry)));
  414. #endif
  415. }
  416. /*
  417. * When recursive inclusion of directory content is enabled,
  418. * an inclusion pattern that matches a directory will also
  419. * include everything beneath that directory. Enabled by default.
  420. *
  421. * For compatibility with GNU tar, exclusion patterns always
  422. * match if a subset of the full patch matches (i.e., they are
  423. * are not rooted at the beginning of the path) and thus there
  424. * is no corresponding non-recursive exclusion mode.
  425. */
  426. int
  427. archive_match_set_inclusion_recursion(struct archive *_a, int enabled)
  428. {
  429. struct archive_match *a;
  430. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  431. ARCHIVE_STATE_NEW, "archive_match_set_inclusion_recursion");
  432. a = (struct archive_match *)_a;
  433. a->recursive_include = enabled;
  434. return (ARCHIVE_OK);
  435. }
  436. /*
  437. * Utility functions to get statistic information for inclusion patterns.
  438. */
  439. int
  440. archive_match_path_unmatched_inclusions(struct archive *_a)
  441. {
  442. struct archive_match *a;
  443. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  444. ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions");
  445. a = (struct archive_match *)_a;
  446. return (a->inclusions.unmatched_count);
  447. }
  448. int
  449. archive_match_path_unmatched_inclusions_next(struct archive *_a,
  450. const char **_p)
  451. {
  452. struct archive_match *a;
  453. const void *v;
  454. int r;
  455. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  456. ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions_next");
  457. a = (struct archive_match *)_a;
  458. r = match_list_unmatched_inclusions_next(a, &(a->inclusions), 1, &v);
  459. *_p = (const char *)v;
  460. return (r);
  461. }
  462. int
  463. archive_match_path_unmatched_inclusions_next_w(struct archive *_a,
  464. const wchar_t **_p)
  465. {
  466. struct archive_match *a;
  467. const void *v;
  468. int r;
  469. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  470. ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions_next_w");
  471. a = (struct archive_match *)_a;
  472. r = match_list_unmatched_inclusions_next(a, &(a->inclusions), 0, &v);
  473. *_p = (const wchar_t *)v;
  474. return (r);
  475. }
  476. /*
  477. * Add inclusion/exclusion patterns.
  478. */
  479. static int
  480. add_pattern_mbs(struct archive_match *a, struct match_list *list,
  481. const char *pattern)
  482. {
  483. struct match *match;
  484. size_t len;
  485. match = calloc(1, sizeof(*match));
  486. if (match == NULL)
  487. return (error_nomem(a));
  488. /* Both "foo/" and "foo" should match "foo/bar". */
  489. len = strlen(pattern);
  490. if (len && pattern[len - 1] == '/')
  491. --len;
  492. archive_mstring_copy_mbs_len(&(match->pattern), pattern, len);
  493. match_list_add(list, match);
  494. a->setflag |= PATTERN_IS_SET;
  495. return (ARCHIVE_OK);
  496. }
  497. static int
  498. add_pattern_wcs(struct archive_match *a, struct match_list *list,
  499. const wchar_t *pattern)
  500. {
  501. struct match *match;
  502. size_t len;
  503. match = calloc(1, sizeof(*match));
  504. if (match == NULL)
  505. return (error_nomem(a));
  506. /* Both "foo/" and "foo" should match "foo/bar". */
  507. len = wcslen(pattern);
  508. if (len && pattern[len - 1] == L'/')
  509. --len;
  510. archive_mstring_copy_wcs_len(&(match->pattern), pattern, len);
  511. match_list_add(list, match);
  512. a->setflag |= PATTERN_IS_SET;
  513. return (ARCHIVE_OK);
  514. }
  515. static int
  516. add_pattern_from_file(struct archive_match *a, struct match_list *mlist,
  517. int mbs, const void *pathname, int nullSeparator)
  518. {
  519. struct archive *ar;
  520. struct archive_entry *ae;
  521. struct archive_string as;
  522. const void *buff;
  523. size_t size;
  524. int64_t offset;
  525. int r;
  526. ar = archive_read_new();
  527. if (ar == NULL) {
  528. archive_set_error(&(a->archive), ENOMEM, "No memory");
  529. return (ARCHIVE_FATAL);
  530. }
  531. r = archive_read_support_format_raw(ar);
  532. r = archive_read_support_format_empty(ar);
  533. if (r != ARCHIVE_OK) {
  534. archive_copy_error(&(a->archive), ar);
  535. archive_read_free(ar);
  536. return (r);
  537. }
  538. if (mbs)
  539. r = archive_read_open_filename(ar, pathname, 512*20);
  540. else
  541. r = archive_read_open_filename_w(ar, pathname, 512*20);
  542. if (r != ARCHIVE_OK) {
  543. archive_copy_error(&(a->archive), ar);
  544. archive_read_free(ar);
  545. return (r);
  546. }
  547. r = archive_read_next_header(ar, &ae);
  548. if (r != ARCHIVE_OK) {
  549. archive_read_free(ar);
  550. if (r == ARCHIVE_EOF) {
  551. return (ARCHIVE_OK);
  552. } else {
  553. archive_copy_error(&(a->archive), ar);
  554. return (r);
  555. }
  556. }
  557. archive_string_init(&as);
  558. while ((r = archive_read_data_block(ar, &buff, &size, &offset))
  559. == ARCHIVE_OK) {
  560. const char *b = (const char *)buff;
  561. while (size) {
  562. const char *s = (const char *)b;
  563. size_t length = 0;
  564. int found_separator = 0;
  565. while (length < size) {
  566. if (nullSeparator) {
  567. if (*b == '\0') {
  568. found_separator = 1;
  569. break;
  570. }
  571. } else {
  572. if (*b == 0x0d || *b == 0x0a) {
  573. found_separator = 1;
  574. break;
  575. }
  576. }
  577. b++;
  578. length++;
  579. }
  580. if (!found_separator) {
  581. archive_strncat(&as, s, length);
  582. /* Read next data block. */
  583. break;
  584. }
  585. b++;
  586. size -= length + 1;
  587. archive_strncat(&as, s, length);
  588. /* If the line is not empty, add the pattern. */
  589. if (archive_strlen(&as) > 0) {
  590. /* Add pattern. */
  591. r = add_pattern_mbs(a, mlist, as.s);
  592. if (r != ARCHIVE_OK) {
  593. archive_read_free(ar);
  594. archive_string_free(&as);
  595. return (r);
  596. }
  597. archive_string_empty(&as);
  598. }
  599. }
  600. }
  601. /* If an error occurred, report it immediately. */
  602. if (r < ARCHIVE_OK) {
  603. archive_copy_error(&(a->archive), ar);
  604. archive_read_free(ar);
  605. archive_string_free(&as);
  606. return (r);
  607. }
  608. /* If the line is not empty, add the pattern. */
  609. if (r == ARCHIVE_EOF && archive_strlen(&as) > 0) {
  610. /* Add pattern. */
  611. r = add_pattern_mbs(a, mlist, as.s);
  612. if (r != ARCHIVE_OK) {
  613. archive_read_free(ar);
  614. archive_string_free(&as);
  615. return (r);
  616. }
  617. }
  618. archive_read_free(ar);
  619. archive_string_free(&as);
  620. return (ARCHIVE_OK);
  621. }
  622. /*
  623. * Test if pathname is excluded by inclusion/exclusion patterns.
  624. */
  625. static int
  626. path_excluded(struct archive_match *a, int mbs, const void *pathname)
  627. {
  628. struct match *match;
  629. struct match *matched;
  630. int r;
  631. if (a == NULL)
  632. return (0);
  633. /* Mark off any unmatched inclusions. */
  634. /* In particular, if a filename does appear in the archive and
  635. * is explicitly included and excluded, then we don't report
  636. * it as missing even though we don't extract it.
  637. */
  638. matched = NULL;
  639. for (match = a->inclusions.first; match != NULL;
  640. match = match->next){
  641. if (match->matches == 0 &&
  642. (r = match_path_inclusion(a, match, mbs, pathname)) != 0) {
  643. if (r < 0)
  644. return (r);
  645. a->inclusions.unmatched_count--;
  646. match->matches++;
  647. matched = match;
  648. }
  649. }
  650. /* Exclusions take priority */
  651. for (match = a->exclusions.first; match != NULL;
  652. match = match->next){
  653. r = match_path_exclusion(a, match, mbs, pathname);
  654. if (r)
  655. return (r);
  656. }
  657. /* It's not excluded and we found an inclusion above, so it's
  658. * included. */
  659. if (matched != NULL)
  660. return (0);
  661. /* We didn't find an unmatched inclusion, check the remaining ones. */
  662. for (match = a->inclusions.first; match != NULL;
  663. match = match->next){
  664. /* We looked at previously-unmatched inclusions already. */
  665. if (match->matches > 0 &&
  666. (r = match_path_inclusion(a, match, mbs, pathname)) != 0) {
  667. if (r < 0)
  668. return (r);
  669. match->matches++;
  670. return (0);
  671. }
  672. }
  673. /* If there were inclusions, default is to exclude. */
  674. if (a->inclusions.first != NULL)
  675. return (1);
  676. /* No explicit inclusions, default is to match. */
  677. return (0);
  678. }
  679. /*
  680. * This is a little odd, but it matches the default behavior of
  681. * gtar. In particular, 'a*b' will match 'foo/a1111/222b/bar'
  682. *
  683. */
  684. static int
  685. match_path_exclusion(struct archive_match *a, struct match *m,
  686. int mbs, const void *pn)
  687. {
  688. int flag = PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END;
  689. int r;
  690. if (mbs) {
  691. const char *p;
  692. r = archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p);
  693. if (r == 0)
  694. return (archive_pathmatch(p, (const char *)pn, flag));
  695. } else {
  696. const wchar_t *p;
  697. r = archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p);
  698. if (r == 0)
  699. return (archive_pathmatch_w(p, (const wchar_t *)pn,
  700. flag));
  701. }
  702. if (errno == ENOMEM)
  703. return (error_nomem(a));
  704. return (0);
  705. }
  706. /*
  707. * Again, mimic gtar: inclusions are always anchored (have to match
  708. * the beginning of the path) even though exclusions are not anchored.
  709. */
  710. static int
  711. match_path_inclusion(struct archive_match *a, struct match *m,
  712. int mbs, const void *pn)
  713. {
  714. /* Recursive operation requires only a prefix match. */
  715. int flag = a->recursive_include ?
  716. PATHMATCH_NO_ANCHOR_END :
  717. 0;
  718. int r;
  719. if (mbs) {
  720. const char *p;
  721. r = archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p);
  722. if (r == 0)
  723. return (archive_pathmatch(p, (const char *)pn, flag));
  724. } else {
  725. const wchar_t *p;
  726. r = archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p);
  727. if (r == 0)
  728. return (archive_pathmatch_w(p, (const wchar_t *)pn,
  729. flag));
  730. }
  731. if (errno == ENOMEM)
  732. return (error_nomem(a));
  733. return (0);
  734. }
  735. static void
  736. match_list_init(struct match_list *list)
  737. {
  738. list->first = NULL;
  739. list->last = &(list->first);
  740. list->count = 0;
  741. }
  742. static void
  743. match_list_free(struct match_list *list)
  744. {
  745. struct match *p, *q;
  746. for (p = list->first; p != NULL; ) {
  747. q = p;
  748. p = p->next;
  749. archive_mstring_clean(&(q->pattern));
  750. free(q);
  751. }
  752. }
  753. static void
  754. match_list_add(struct match_list *list, struct match *m)
  755. {
  756. *list->last = m;
  757. list->last = &(m->next);
  758. list->count++;
  759. list->unmatched_count++;
  760. }
  761. static int
  762. match_list_unmatched_inclusions_next(struct archive_match *a,
  763. struct match_list *list, int mbs, const void **vp)
  764. {
  765. struct match *m;
  766. *vp = NULL;
  767. if (list->unmatched_eof) {
  768. list->unmatched_eof = 0;
  769. return (ARCHIVE_EOF);
  770. }
  771. if (list->unmatched_next == NULL) {
  772. if (list->unmatched_count == 0)
  773. return (ARCHIVE_EOF);
  774. list->unmatched_next = list->first;
  775. }
  776. for (m = list->unmatched_next; m != NULL; m = m->next) {
  777. int r;
  778. if (m->matches)
  779. continue;
  780. if (mbs) {
  781. const char *p;
  782. r = archive_mstring_get_mbs(&(a->archive),
  783. &(m->pattern), &p);
  784. if (r < 0 && errno == ENOMEM)
  785. return (error_nomem(a));
  786. if (p == NULL)
  787. p = "";
  788. *vp = p;
  789. } else {
  790. const wchar_t *p;
  791. r = archive_mstring_get_wcs(&(a->archive),
  792. &(m->pattern), &p);
  793. if (r < 0 && errno == ENOMEM)
  794. return (error_nomem(a));
  795. if (p == NULL)
  796. p = L"";
  797. *vp = p;
  798. }
  799. list->unmatched_next = m->next;
  800. if (list->unmatched_next == NULL)
  801. /* To return EOF next time. */
  802. list->unmatched_eof = 1;
  803. return (ARCHIVE_OK);
  804. }
  805. list->unmatched_next = NULL;
  806. return (ARCHIVE_EOF);
  807. }
  808. /*
  809. * Utility functions to manage inclusion timestamps.
  810. */
  811. int
  812. archive_match_include_time(struct archive *_a, int flag, time_t sec,
  813. long nsec)
  814. {
  815. int r;
  816. r = validate_time_flag(_a, flag, "archive_match_include_time");
  817. if (r != ARCHIVE_OK)
  818. return (r);
  819. return set_timefilter((struct archive_match *)_a, flag,
  820. sec, nsec, sec, nsec);
  821. }
  822. int
  823. archive_match_include_date(struct archive *_a, int flag,
  824. const char *datestr)
  825. {
  826. int r;
  827. r = validate_time_flag(_a, flag, "archive_match_include_date");
  828. if (r != ARCHIVE_OK)
  829. return (r);
  830. return set_timefilter_date((struct archive_match *)_a, flag, datestr);
  831. }
  832. int
  833. archive_match_include_date_w(struct archive *_a, int flag,
  834. const wchar_t *datestr)
  835. {
  836. int r;
  837. r = validate_time_flag(_a, flag, "archive_match_include_date_w");
  838. if (r != ARCHIVE_OK)
  839. return (r);
  840. return set_timefilter_date_w((struct archive_match *)_a, flag, datestr);
  841. }
  842. int
  843. archive_match_include_file_time(struct archive *_a, int flag,
  844. const char *pathname)
  845. {
  846. int r;
  847. r = validate_time_flag(_a, flag, "archive_match_include_file_time");
  848. if (r != ARCHIVE_OK)
  849. return (r);
  850. return set_timefilter_pathname_mbs((struct archive_match *)_a,
  851. flag, pathname);
  852. }
  853. int
  854. archive_match_include_file_time_w(struct archive *_a, int flag,
  855. const wchar_t *pathname)
  856. {
  857. int r;
  858. r = validate_time_flag(_a, flag, "archive_match_include_file_time_w");
  859. if (r != ARCHIVE_OK)
  860. return (r);
  861. return set_timefilter_pathname_wcs((struct archive_match *)_a,
  862. flag, pathname);
  863. }
  864. int
  865. archive_match_exclude_entry(struct archive *_a, int flag,
  866. struct archive_entry *entry)
  867. {
  868. struct archive_match *a;
  869. int r;
  870. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  871. ARCHIVE_STATE_NEW, "archive_match_time_include_entry");
  872. a = (struct archive_match *)_a;
  873. if (entry == NULL) {
  874. archive_set_error(&(a->archive), EINVAL, "entry is NULL");
  875. return (ARCHIVE_FAILED);
  876. }
  877. r = validate_time_flag(_a, flag, "archive_match_exclude_entry");
  878. if (r != ARCHIVE_OK)
  879. return (r);
  880. return (add_entry(a, flag, entry));
  881. }
  882. /*
  883. * Test function for time stamps.
  884. *
  885. * Returns 1 if archive entry is excluded.
  886. * Returns 0 if archive entry is not excluded.
  887. * Returns <0 if something error happened.
  888. */
  889. int
  890. archive_match_time_excluded(struct archive *_a,
  891. struct archive_entry *entry)
  892. {
  893. struct archive_match *a;
  894. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  895. ARCHIVE_STATE_NEW, "archive_match_time_excluded_ae");
  896. a = (struct archive_match *)_a;
  897. if (entry == NULL) {
  898. archive_set_error(&(a->archive), EINVAL, "entry is NULL");
  899. return (ARCHIVE_FAILED);
  900. }
  901. /* If we don't have inclusion time set at all, the entry is always
  902. * not excluded. */
  903. if ((a->setflag & TIME_IS_SET) == 0)
  904. return (0);
  905. return (time_excluded(a, entry));
  906. }
  907. static int
  908. validate_time_flag(struct archive *_a, int flag, const char *_fn)
  909. {
  910. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  911. ARCHIVE_STATE_NEW, _fn);
  912. /* Check a type of time. */
  913. if (flag &
  914. ((~(ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME)) & 0xff00)) {
  915. archive_set_error(_a, EINVAL, "Invalid time flag");
  916. return (ARCHIVE_FAILED);
  917. }
  918. if ((flag & (ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME)) == 0) {
  919. archive_set_error(_a, EINVAL, "No time flag");
  920. return (ARCHIVE_FAILED);
  921. }
  922. /* Check a type of comparison. */
  923. if (flag &
  924. ((~(ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER
  925. | ARCHIVE_MATCH_EQUAL)) & 0x00ff)) {
  926. archive_set_error(_a, EINVAL, "Invalid comparison flag");
  927. return (ARCHIVE_FAILED);
  928. }
  929. if ((flag & (ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER
  930. | ARCHIVE_MATCH_EQUAL)) == 0) {
  931. archive_set_error(_a, EINVAL, "No comparison flag");
  932. return (ARCHIVE_FAILED);
  933. }
  934. return (ARCHIVE_OK);
  935. }
  936. #define JUST_EQUAL(t) (((t) & (ARCHIVE_MATCH_EQUAL |\
  937. ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER)) == ARCHIVE_MATCH_EQUAL)
  938. static int
  939. set_timefilter(struct archive_match *a, int timetype,
  940. time_t mtime_sec, long mtime_nsec, time_t ctime_sec, long ctime_nsec)
  941. {
  942. if (timetype & ARCHIVE_MATCH_MTIME) {
  943. if ((timetype & ARCHIVE_MATCH_NEWER) || JUST_EQUAL(timetype)) {
  944. a->newer_mtime_filter = timetype;
  945. a->newer_mtime_sec = mtime_sec;
  946. a->newer_mtime_nsec = mtime_nsec;
  947. a->setflag |= TIME_IS_SET;
  948. }
  949. if ((timetype & ARCHIVE_MATCH_OLDER) || JUST_EQUAL(timetype)) {
  950. a->older_mtime_filter = timetype;
  951. a->older_mtime_sec = mtime_sec;
  952. a->older_mtime_nsec = mtime_nsec;
  953. a->setflag |= TIME_IS_SET;
  954. }
  955. }
  956. if (timetype & ARCHIVE_MATCH_CTIME) {
  957. if ((timetype & ARCHIVE_MATCH_NEWER) || JUST_EQUAL(timetype)) {
  958. a->newer_ctime_filter = timetype;
  959. a->newer_ctime_sec = ctime_sec;
  960. a->newer_ctime_nsec = ctime_nsec;
  961. a->setflag |= TIME_IS_SET;
  962. }
  963. if ((timetype & ARCHIVE_MATCH_OLDER) || JUST_EQUAL(timetype)) {
  964. a->older_ctime_filter = timetype;
  965. a->older_ctime_sec = ctime_sec;
  966. a->older_ctime_nsec = ctime_nsec;
  967. a->setflag |= TIME_IS_SET;
  968. }
  969. }
  970. return (ARCHIVE_OK);
  971. }
  972. static int
  973. set_timefilter_date(struct archive_match *a, int timetype, const char *datestr)
  974. {
  975. time_t t;
  976. if (datestr == NULL || *datestr == '\0') {
  977. archive_set_error(&(a->archive), EINVAL, "date is empty");
  978. return (ARCHIVE_FAILED);
  979. }
  980. t = get_date(a->now, datestr);
  981. if (t == (time_t)-1) {
  982. archive_set_error(&(a->archive), EINVAL, "invalid date string");
  983. return (ARCHIVE_FAILED);
  984. }
  985. return set_timefilter(a, timetype, t, 0, t, 0);
  986. }
  987. static int
  988. set_timefilter_date_w(struct archive_match *a, int timetype,
  989. const wchar_t *datestr)
  990. {
  991. struct archive_string as;
  992. time_t t;
  993. if (datestr == NULL || *datestr == L'\0') {
  994. archive_set_error(&(a->archive), EINVAL, "date is empty");
  995. return (ARCHIVE_FAILED);
  996. }
  997. archive_string_init(&as);
  998. if (archive_string_append_from_wcs(&as, datestr, wcslen(datestr)) < 0) {
  999. archive_string_free(&as);
  1000. if (errno == ENOMEM)
  1001. return (error_nomem(a));
  1002. archive_set_error(&(a->archive), -1,
  1003. "Failed to convert WCS to MBS");
  1004. return (ARCHIVE_FAILED);
  1005. }
  1006. t = get_date(a->now, as.s);
  1007. archive_string_free(&as);
  1008. if (t == (time_t)-1) {
  1009. archive_set_error(&(a->archive), EINVAL, "invalid date string");
  1010. return (ARCHIVE_FAILED);
  1011. }
  1012. return set_timefilter(a, timetype, t, 0, t, 0);
  1013. }
  1014. #if defined(_WIN32) && !defined(__CYGWIN__)
  1015. #define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
  1016. static int
  1017. set_timefilter_find_data(struct archive_match *a, int timetype,
  1018. DWORD ftLastWriteTime_dwHighDateTime, DWORD ftLastWriteTime_dwLowDateTime,
  1019. DWORD ftCreationTime_dwHighDateTime, DWORD ftCreationTime_dwLowDateTime)
  1020. {
  1021. ULARGE_INTEGER utc;
  1022. time_t ctime_sec, mtime_sec;
  1023. long ctime_ns, mtime_ns;
  1024. utc.HighPart = ftCreationTime_dwHighDateTime;
  1025. utc.LowPart = ftCreationTime_dwLowDateTime;
  1026. if (utc.QuadPart >= EPOC_TIME) {
  1027. utc.QuadPart -= EPOC_TIME;
  1028. ctime_sec = (time_t)(utc.QuadPart / 10000000);
  1029. ctime_ns = (long)(utc.QuadPart % 10000000) * 100;
  1030. } else {
  1031. ctime_sec = 0;
  1032. ctime_ns = 0;
  1033. }
  1034. utc.HighPart = ftLastWriteTime_dwHighDateTime;
  1035. utc.LowPart = ftLastWriteTime_dwLowDateTime;
  1036. if (utc.QuadPart >= EPOC_TIME) {
  1037. utc.QuadPart -= EPOC_TIME;
  1038. mtime_sec = (time_t)(utc.QuadPart / 10000000);
  1039. mtime_ns = (long)(utc.QuadPart % 10000000) * 100;
  1040. } else {
  1041. mtime_sec = 0;
  1042. mtime_ns = 0;
  1043. }
  1044. return set_timefilter(a, timetype,
  1045. mtime_sec, mtime_ns, ctime_sec, ctime_ns);
  1046. }
  1047. static int
  1048. set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
  1049. const char *path)
  1050. {
  1051. /* NOTE: stat() on Windows cannot handle nano seconds. */
  1052. HANDLE h;
  1053. WIN32_FIND_DATAA d;
  1054. if (path == NULL || *path == '\0') {
  1055. archive_set_error(&(a->archive), EINVAL, "pathname is empty");
  1056. return (ARCHIVE_FAILED);
  1057. }
  1058. h = FindFirstFileA(path, &d);
  1059. if (h == INVALID_HANDLE_VALUE) {
  1060. la_dosmaperr(GetLastError());
  1061. archive_set_error(&(a->archive), errno,
  1062. "Failed to FindFirstFileA");
  1063. return (ARCHIVE_FAILED);
  1064. }
  1065. FindClose(h);
  1066. return set_timefilter_find_data(a, timetype,
  1067. d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime,
  1068. d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime);
  1069. }
  1070. static int
  1071. set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
  1072. const wchar_t *path)
  1073. {
  1074. HANDLE h;
  1075. WIN32_FIND_DATAW d;
  1076. if (path == NULL || *path == L'\0') {
  1077. archive_set_error(&(a->archive), EINVAL, "pathname is empty");
  1078. return (ARCHIVE_FAILED);
  1079. }
  1080. h = FindFirstFileW(path, &d);
  1081. if (h == INVALID_HANDLE_VALUE) {
  1082. la_dosmaperr(GetLastError());
  1083. archive_set_error(&(a->archive), errno,
  1084. "Failed to FindFirstFile");
  1085. return (ARCHIVE_FAILED);
  1086. }
  1087. FindClose(h);
  1088. return set_timefilter_find_data(a, timetype,
  1089. d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime,
  1090. d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime);
  1091. }
  1092. #else /* _WIN32 && !__CYGWIN__ */
  1093. static int
  1094. set_timefilter_stat(struct archive_match *a, int timetype, struct stat *st)
  1095. {
  1096. struct archive_entry *ae;
  1097. time_t ctime_sec, mtime_sec;
  1098. long ctime_ns, mtime_ns;
  1099. ae = archive_entry_new();
  1100. if (ae == NULL)
  1101. return (error_nomem(a));
  1102. archive_entry_copy_stat(ae, st);
  1103. ctime_sec = archive_entry_ctime(ae);
  1104. ctime_ns = archive_entry_ctime_nsec(ae);
  1105. mtime_sec = archive_entry_mtime(ae);
  1106. mtime_ns = archive_entry_mtime_nsec(ae);
  1107. archive_entry_free(ae);
  1108. return set_timefilter(a, timetype, mtime_sec, mtime_ns,
  1109. ctime_sec, ctime_ns);
  1110. }
  1111. static int
  1112. set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
  1113. const char *path)
  1114. {
  1115. struct stat st;
  1116. if (path == NULL || *path == '\0') {
  1117. archive_set_error(&(a->archive), EINVAL, "pathname is empty");
  1118. return (ARCHIVE_FAILED);
  1119. }
  1120. if (la_stat(path, &st) != 0) {
  1121. archive_set_error(&(a->archive), errno, "Failed to stat()");
  1122. return (ARCHIVE_FAILED);
  1123. }
  1124. return (set_timefilter_stat(a, timetype, &st));
  1125. }
  1126. static int
  1127. set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
  1128. const wchar_t *path)
  1129. {
  1130. struct archive_string as;
  1131. int r;
  1132. if (path == NULL || *path == L'\0') {
  1133. archive_set_error(&(a->archive), EINVAL, "pathname is empty");
  1134. return (ARCHIVE_FAILED);
  1135. }
  1136. /* Convert WCS filename to MBS filename. */
  1137. archive_string_init(&as);
  1138. if (archive_string_append_from_wcs(&as, path, wcslen(path)) < 0) {
  1139. archive_string_free(&as);
  1140. if (errno == ENOMEM)
  1141. return (error_nomem(a));
  1142. archive_set_error(&(a->archive), -1,
  1143. "Failed to convert WCS to MBS");
  1144. return (ARCHIVE_FAILED);
  1145. }
  1146. r = set_timefilter_pathname_mbs(a, timetype, as.s);
  1147. archive_string_free(&as);
  1148. return (r);
  1149. }
  1150. #endif /* _WIN32 && !__CYGWIN__ */
  1151. /*
  1152. * Call back functions for archive_rb.
  1153. */
  1154. static int
  1155. cmp_node_mbs(const struct archive_rb_node *n1,
  1156. const struct archive_rb_node *n2)
  1157. {
  1158. struct match_file *f1 = (struct match_file *)(uintptr_t)n1;
  1159. struct match_file *f2 = (struct match_file *)(uintptr_t)n2;
  1160. const char *p1, *p2;
  1161. archive_mstring_get_mbs(NULL, &(f1->pathname), &p1);
  1162. archive_mstring_get_mbs(NULL, &(f2->pathname), &p2);
  1163. if (p1 == NULL)
  1164. return (1);
  1165. if (p2 == NULL)
  1166. return (-1);
  1167. return (strcmp(p1, p2));
  1168. }
  1169. static int
  1170. cmp_key_mbs(const struct archive_rb_node *n, const void *key)
  1171. {
  1172. struct match_file *f = (struct match_file *)(uintptr_t)n;
  1173. const char *p;
  1174. archive_mstring_get_mbs(NULL, &(f->pathname), &p);
  1175. if (p == NULL)
  1176. return (-1);
  1177. return (strcmp(p, (const char *)key));
  1178. }
  1179. static int
  1180. cmp_node_wcs(const struct archive_rb_node *n1,
  1181. const struct archive_rb_node *n2)
  1182. {
  1183. struct match_file *f1 = (struct match_file *)(uintptr_t)n1;
  1184. struct match_file *f2 = (struct match_file *)(uintptr_t)n2;
  1185. const wchar_t *p1, *p2;
  1186. archive_mstring_get_wcs(NULL, &(f1->pathname), &p1);
  1187. archive_mstring_get_wcs(NULL, &(f2->pathname), &p2);
  1188. if (p1 == NULL)
  1189. return (1);
  1190. if (p2 == NULL)
  1191. return (-1);
  1192. return (wcscmp(p1, p2));
  1193. }
  1194. static int
  1195. cmp_key_wcs(const struct archive_rb_node *n, const void *key)
  1196. {
  1197. struct match_file *f = (struct match_file *)(uintptr_t)n;
  1198. const wchar_t *p;
  1199. archive_mstring_get_wcs(NULL, &(f->pathname), &p);
  1200. if (p == NULL)
  1201. return (-1);
  1202. return (wcscmp(p, (const wchar_t *)key));
  1203. }
  1204. static void
  1205. entry_list_init(struct entry_list *list)
  1206. {
  1207. list->first = NULL;
  1208. list->last = &(list->first);
  1209. list->count = 0;
  1210. }
  1211. static void
  1212. entry_list_free(struct entry_list *list)
  1213. {
  1214. struct match_file *p, *q;
  1215. for (p = list->first; p != NULL; ) {
  1216. q = p;
  1217. p = p->next;
  1218. archive_mstring_clean(&(q->pathname));
  1219. free(q);
  1220. }
  1221. }
  1222. static void
  1223. entry_list_add(struct entry_list *list, struct match_file *file)
  1224. {
  1225. *list->last = file;
  1226. list->last = &(file->next);
  1227. list->count++;
  1228. }
  1229. static int
  1230. add_entry(struct archive_match *a, int flag,
  1231. struct archive_entry *entry)
  1232. {
  1233. struct match_file *f;
  1234. const void *pathname;
  1235. int r;
  1236. f = calloc(1, sizeof(*f));
  1237. if (f == NULL)
  1238. return (error_nomem(a));
  1239. #if defined(_WIN32) && !defined(__CYGWIN__)
  1240. pathname = archive_entry_pathname_w(entry);
  1241. if (pathname == NULL) {
  1242. free(f);
  1243. archive_set_error(&(a->archive), EINVAL, "pathname is NULL");
  1244. return (ARCHIVE_FAILED);
  1245. }
  1246. archive_mstring_copy_wcs(&(f->pathname), pathname);
  1247. a->exclusion_tree.rbt_ops = &rb_ops_wcs;
  1248. #else
  1249. (void)rb_ops_wcs;
  1250. pathname = archive_entry_pathname(entry);
  1251. if (pathname == NULL) {
  1252. free(f);
  1253. archive_set_error(&(a->archive), EINVAL, "pathname is NULL");
  1254. return (ARCHIVE_FAILED);
  1255. }
  1256. archive_mstring_copy_mbs(&(f->pathname), pathname);
  1257. a->exclusion_tree.rbt_ops = &rb_ops_mbs;
  1258. #endif
  1259. f->flag = flag;
  1260. f->mtime_sec = archive_entry_mtime(entry);
  1261. f->mtime_nsec = archive_entry_mtime_nsec(entry);
  1262. f->ctime_sec = archive_entry_ctime(entry);
  1263. f->ctime_nsec = archive_entry_ctime_nsec(entry);
  1264. r = __archive_rb_tree_insert_node(&(a->exclusion_tree), &(f->node));
  1265. if (!r) {
  1266. struct match_file *f2;
  1267. /* Get the duplicated file. */
  1268. f2 = (struct match_file *)__archive_rb_tree_find_node(
  1269. &(a->exclusion_tree), pathname);
  1270. /*
  1271. * We always overwrite comparison condition.
  1272. * If you do not want to overwrite it, you should not
  1273. * call archive_match_exclude_entry(). We cannot know
  1274. * what behavior you really expect since overwriting
  1275. * condition might be different with the flag.
  1276. */
  1277. if (f2 != NULL) {
  1278. f2->flag = f->flag;
  1279. f2->mtime_sec = f->mtime_sec;
  1280. f2->mtime_nsec = f->mtime_nsec;
  1281. f2->ctime_sec = f->ctime_sec;
  1282. f2->ctime_nsec = f->ctime_nsec;
  1283. }
  1284. /* Release the duplicated file. */
  1285. archive_mstring_clean(&(f->pathname));
  1286. free(f);
  1287. return (ARCHIVE_OK);
  1288. }
  1289. entry_list_add(&(a->exclusion_entry_list), f);
  1290. a->setflag |= TIME_IS_SET;
  1291. return (ARCHIVE_OK);
  1292. }
  1293. /*
  1294. * Test if entry is excluded by its timestamp.
  1295. */
  1296. static int
  1297. time_excluded(struct archive_match *a, struct archive_entry *entry)
  1298. {
  1299. struct match_file *f;
  1300. const void *pathname;
  1301. time_t sec;
  1302. long nsec;
  1303. /*
  1304. * If this file/dir is excluded by a time comparison, skip it.
  1305. */
  1306. if (a->newer_ctime_filter) {
  1307. /* If ctime is not set, use mtime instead. */
  1308. if (archive_entry_ctime_is_set(entry))
  1309. sec = archive_entry_ctime(entry);
  1310. else
  1311. sec = archive_entry_mtime(entry);
  1312. if (sec < a->newer_ctime_sec)
  1313. return (1); /* Too old, skip it. */
  1314. if (sec == a->newer_ctime_sec) {
  1315. if (archive_entry_ctime_is_set(entry))
  1316. nsec = archive_entry_ctime_nsec(entry);
  1317. else
  1318. nsec = archive_entry_mtime_nsec(entry);
  1319. if (nsec < a->newer_ctime_nsec)
  1320. return (1); /* Too old, skip it. */
  1321. if (nsec == a->newer_ctime_nsec &&
  1322. (a->newer_ctime_filter & ARCHIVE_MATCH_EQUAL)
  1323. == 0)
  1324. return (1); /* Equal, skip it. */
  1325. }
  1326. }
  1327. if (a->older_ctime_filter) {
  1328. /* If ctime is not set, use mtime instead. */
  1329. if (archive_entry_ctime_is_set(entry))
  1330. sec = archive_entry_ctime(entry);
  1331. else
  1332. sec = archive_entry_mtime(entry);
  1333. if (sec > a->older_ctime_sec)
  1334. return (1); /* Too new, skip it. */
  1335. if (sec == a->older_ctime_sec) {
  1336. if (archive_entry_ctime_is_set(entry))
  1337. nsec = archive_entry_ctime_nsec(entry);
  1338. else
  1339. nsec = archive_entry_mtime_nsec(entry);
  1340. if (nsec > a->older_ctime_nsec)
  1341. return (1); /* Too new, skip it. */
  1342. if (nsec == a->older_ctime_nsec &&
  1343. (a->older_ctime_filter & ARCHIVE_MATCH_EQUAL)
  1344. == 0)
  1345. return (1); /* Equal, skip it. */
  1346. }
  1347. }
  1348. if (a->newer_mtime_filter) {
  1349. sec = archive_entry_mtime(entry);
  1350. if (sec < a->newer_mtime_sec)
  1351. return (1); /* Too old, skip it. */
  1352. if (sec == a->newer_mtime_sec) {
  1353. nsec = archive_entry_mtime_nsec(entry);
  1354. if (nsec < a->newer_mtime_nsec)
  1355. return (1); /* Too old, skip it. */
  1356. if (nsec == a->newer_mtime_nsec &&
  1357. (a->newer_mtime_filter & ARCHIVE_MATCH_EQUAL)
  1358. == 0)
  1359. return (1); /* Equal, skip it. */
  1360. }
  1361. }
  1362. if (a->older_mtime_filter) {
  1363. sec = archive_entry_mtime(entry);
  1364. if (sec > a->older_mtime_sec)
  1365. return (1); /* Too new, skip it. */
  1366. nsec = archive_entry_mtime_nsec(entry);
  1367. if (sec == a->older_mtime_sec) {
  1368. if (nsec > a->older_mtime_nsec)
  1369. return (1); /* Too new, skip it. */
  1370. if (nsec == a->older_mtime_nsec &&
  1371. (a->older_mtime_filter & ARCHIVE_MATCH_EQUAL)
  1372. == 0)
  1373. return (1); /* Equal, skip it. */
  1374. }
  1375. }
  1376. /* If there is no exclusion list, include the file. */
  1377. if (a->exclusion_entry_list.count == 0)
  1378. return (0);
  1379. #if defined(_WIN32) && !defined(__CYGWIN__)
  1380. pathname = archive_entry_pathname_w(entry);
  1381. a->exclusion_tree.rbt_ops = &rb_ops_wcs;
  1382. #else
  1383. (void)rb_ops_wcs;
  1384. pathname = archive_entry_pathname(entry);
  1385. a->exclusion_tree.rbt_ops = &rb_ops_mbs;
  1386. #endif
  1387. if (pathname == NULL)
  1388. return (0);
  1389. f = (struct match_file *)__archive_rb_tree_find_node(
  1390. &(a->exclusion_tree), pathname);
  1391. /* If the file wasn't rejected, include it. */
  1392. if (f == NULL)
  1393. return (0);
  1394. if (f->flag & ARCHIVE_MATCH_CTIME) {
  1395. sec = archive_entry_ctime(entry);
  1396. if (f->ctime_sec > sec) {
  1397. if (f->flag & ARCHIVE_MATCH_OLDER)
  1398. return (1);
  1399. } else if (f->ctime_sec < sec) {
  1400. if (f->flag & ARCHIVE_MATCH_NEWER)
  1401. return (1);
  1402. } else {
  1403. nsec = archive_entry_ctime_nsec(entry);
  1404. if (f->ctime_nsec > nsec) {
  1405. if (f->flag & ARCHIVE_MATCH_OLDER)
  1406. return (1);
  1407. } else if (f->ctime_nsec < nsec) {
  1408. if (f->flag & ARCHIVE_MATCH_NEWER)
  1409. return (1);
  1410. } else if (f->flag & ARCHIVE_MATCH_EQUAL)
  1411. return (1);
  1412. }
  1413. }
  1414. if (f->flag & ARCHIVE_MATCH_MTIME) {
  1415. sec = archive_entry_mtime(entry);
  1416. if (f->mtime_sec > sec) {
  1417. if (f->flag & ARCHIVE_MATCH_OLDER)
  1418. return (1);
  1419. } else if (f->mtime_sec < sec) {
  1420. if (f->flag & ARCHIVE_MATCH_NEWER)
  1421. return (1);
  1422. } else {
  1423. nsec = archive_entry_mtime_nsec(entry);
  1424. if (f->mtime_nsec > nsec) {
  1425. if (f->flag & ARCHIVE_MATCH_OLDER)
  1426. return (1);
  1427. } else if (f->mtime_nsec < nsec) {
  1428. if (f->flag & ARCHIVE_MATCH_NEWER)
  1429. return (1);
  1430. } else if (f->flag & ARCHIVE_MATCH_EQUAL)
  1431. return (1);
  1432. }
  1433. }
  1434. return (0);
  1435. }
  1436. /*
  1437. * Utility functions to manage inclusion owners
  1438. */
  1439. int
  1440. archive_match_include_uid(struct archive *_a, la_int64_t uid)
  1441. {
  1442. struct archive_match *a;
  1443. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  1444. ARCHIVE_STATE_NEW, "archive_match_include_uid");
  1445. a = (struct archive_match *)_a;
  1446. return (add_owner_id(a, &(a->inclusion_uids), uid));
  1447. }
  1448. int
  1449. archive_match_include_gid(struct archive *_a, la_int64_t gid)
  1450. {
  1451. struct archive_match *a;
  1452. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  1453. ARCHIVE_STATE_NEW, "archive_match_include_gid");
  1454. a = (struct archive_match *)_a;
  1455. return (add_owner_id(a, &(a->inclusion_gids), gid));
  1456. }
  1457. int
  1458. archive_match_include_uname(struct archive *_a, const char *uname)
  1459. {
  1460. struct archive_match *a;
  1461. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  1462. ARCHIVE_STATE_NEW, "archive_match_include_uname");
  1463. a = (struct archive_match *)_a;
  1464. return (add_owner_name(a, &(a->inclusion_unames), 1, uname));
  1465. }
  1466. int
  1467. archive_match_include_uname_w(struct archive *_a, const wchar_t *uname)
  1468. {
  1469. struct archive_match *a;
  1470. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  1471. ARCHIVE_STATE_NEW, "archive_match_include_uname_w");
  1472. a = (struct archive_match *)_a;
  1473. return (add_owner_name(a, &(a->inclusion_unames), 0, uname));
  1474. }
  1475. int
  1476. archive_match_include_gname(struct archive *_a, const char *gname)
  1477. {
  1478. struct archive_match *a;
  1479. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  1480. ARCHIVE_STATE_NEW, "archive_match_include_gname");
  1481. a = (struct archive_match *)_a;
  1482. return (add_owner_name(a, &(a->inclusion_gnames), 1, gname));
  1483. }
  1484. int
  1485. archive_match_include_gname_w(struct archive *_a, const wchar_t *gname)
  1486. {
  1487. struct archive_match *a;
  1488. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  1489. ARCHIVE_STATE_NEW, "archive_match_include_gname_w");
  1490. a = (struct archive_match *)_a;
  1491. return (add_owner_name(a, &(a->inclusion_gnames), 0, gname));
  1492. }
  1493. /*
  1494. * Test function for owner(uid, gid, uname, gname).
  1495. *
  1496. * Returns 1 if archive entry is excluded.
  1497. * Returns 0 if archive entry is not excluded.
  1498. * Returns <0 if something error happened.
  1499. */
  1500. int
  1501. archive_match_owner_excluded(struct archive *_a,
  1502. struct archive_entry *entry)
  1503. {
  1504. struct archive_match *a;
  1505. archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
  1506. ARCHIVE_STATE_NEW, "archive_match_id_excluded_ae");
  1507. a = (struct archive_match *)_a;
  1508. if (entry == NULL) {
  1509. archive_set_error(&(a->archive), EINVAL, "entry is NULL");
  1510. return (ARCHIVE_FAILED);
  1511. }
  1512. /* If we don't have inclusion id set at all, the entry is always
  1513. * not excluded. */
  1514. if ((a->setflag & ID_IS_SET) == 0)
  1515. return (0);
  1516. return (owner_excluded(a, entry));
  1517. }
  1518. static int
  1519. add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
  1520. {
  1521. unsigned i;
  1522. if (ids->count + 1 >= ids->size) {
  1523. void *p;
  1524. if (ids->size == 0)
  1525. ids->size = 8;
  1526. else
  1527. ids->size *= 2;
  1528. p = realloc(ids->ids, sizeof(*ids->ids) * ids->size);
  1529. if (p == NULL)
  1530. return (error_nomem(a));
  1531. ids->ids = (int64_t *)p;
  1532. }
  1533. /* Find an insert point. */
  1534. for (i = 0; i < ids->count; i++) {
  1535. if (ids->ids[i] >= id)
  1536. break;
  1537. }
  1538. /* Add owner id. */
  1539. if (i == ids->count)
  1540. ids->ids[ids->count++] = id;
  1541. else if (ids->ids[i] != id) {
  1542. memmove(&(ids->ids[i+1]), &(ids->ids[i]),
  1543. (ids->count - i) * sizeof(ids->ids[0]));
  1544. ids->ids[i] = id;
  1545. ids->count++;
  1546. }
  1547. a->setflag |= ID_IS_SET;
  1548. return (ARCHIVE_OK);
  1549. }
  1550. static int
  1551. match_owner_id(struct id_array *ids, int64_t id)
  1552. {
  1553. unsigned b, m, t;
  1554. t = 0;
  1555. b = (unsigned)ids->count;
  1556. while (t < b) {
  1557. m = (t + b)>>1;
  1558. if (ids->ids[m] == id)
  1559. return (1);
  1560. if (ids->ids[m] < id)
  1561. t = m + 1;
  1562. else
  1563. b = m;
  1564. }
  1565. return (0);
  1566. }
  1567. static int
  1568. add_owner_name(struct archive_match *a, struct match_list *list,
  1569. int mbs, const void *name)
  1570. {
  1571. struct match *match;
  1572. match = calloc(1, sizeof(*match));
  1573. if (match == NULL)
  1574. return (error_nomem(a));
  1575. if (mbs)
  1576. archive_mstring_copy_mbs(&(match->pattern), name);
  1577. else
  1578. archive_mstring_copy_wcs(&(match->pattern), name);
  1579. match_list_add(list, match);
  1580. a->setflag |= ID_IS_SET;
  1581. return (ARCHIVE_OK);
  1582. }
  1583. #if !defined(_WIN32) || defined(__CYGWIN__)
  1584. static int
  1585. match_owner_name_mbs(struct archive_match *a, struct match_list *list,
  1586. const char *name)
  1587. {
  1588. struct match *m;
  1589. const char *p;
  1590. if (name == NULL || *name == '\0')
  1591. return (0);
  1592. for (m = list->first; m; m = m->next) {
  1593. if (archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p)
  1594. < 0 && errno == ENOMEM)
  1595. return (error_nomem(a));
  1596. if (p != NULL && strcmp(p, name) == 0) {
  1597. m->matches++;
  1598. return (1);
  1599. }
  1600. }
  1601. return (0);
  1602. }
  1603. #else
  1604. static int
  1605. match_owner_name_wcs(struct archive_match *a, struct match_list *list,
  1606. const wchar_t *name)
  1607. {
  1608. struct match *m;
  1609. const wchar_t *p;
  1610. if (name == NULL || *name == L'\0')
  1611. return (0);
  1612. for (m = list->first; m; m = m->next) {
  1613. if (archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p)
  1614. < 0 && errno == ENOMEM)
  1615. return (error_nomem(a));
  1616. if (p != NULL && wcscmp(p, name) == 0) {
  1617. m->matches++;
  1618. return (1);
  1619. }
  1620. }
  1621. return (0);
  1622. }
  1623. #endif
  1624. /*
  1625. * Test if entry is excluded by uid, gid, uname or gname.
  1626. */
  1627. static int
  1628. owner_excluded(struct archive_match *a, struct archive_entry *entry)
  1629. {
  1630. int r;
  1631. if (a->inclusion_uids.count) {
  1632. if (!match_owner_id(&(a->inclusion_uids),
  1633. archive_entry_uid(entry)))
  1634. return (1);
  1635. }
  1636. if (a->inclusion_gids.count) {
  1637. if (!match_owner_id(&(a->inclusion_gids),
  1638. archive_entry_gid(entry)))
  1639. return (1);
  1640. }
  1641. if (a->inclusion_unames.count) {
  1642. #if defined(_WIN32) && !defined(__CYGWIN__)
  1643. r = match_owner_name_wcs(a, &(a->inclusion_unames),
  1644. archive_entry_uname_w(entry));
  1645. #else
  1646. r = match_owner_name_mbs(a, &(a->inclusion_unames),
  1647. archive_entry_uname(entry));
  1648. #endif
  1649. if (!r)
  1650. return (1);
  1651. else if (r < 0)
  1652. return (r);
  1653. }
  1654. if (a->inclusion_gnames.count) {
  1655. #if defined(_WIN32) && !defined(__CYGWIN__)
  1656. r = match_owner_name_wcs(a, &(a->inclusion_gnames),
  1657. archive_entry_gname_w(entry));
  1658. #else
  1659. r = match_owner_name_mbs(a, &(a->inclusion_gnames),
  1660. archive_entry_gname(entry));
  1661. #endif
  1662. if (!r)
  1663. return (1);
  1664. else if (r < 0)
  1665. return (r);
  1666. }
  1667. return (0);
  1668. }