1 #include "arch.h"
2 #include "deco.h"
3 #include "extr.h"
4 #include "fs.h"
5 #include "mem.h"
6 #include "msg.h"
7 #include "str.h"
8 
9 #include <dirent.h>
10 #include <errno.h>
11 #include <regex.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <strings.h>
15 #include <sys/types.h>
16 
17 
18 struct extractor *Extractors;
19 
20 
match_extr(struct extractor * x,const char * file)21 regoff_t match_extr(struct extractor *x, const char *file)
22 	{
23 	regmatch_t m;
24 
25 	return (regexec(&x->matcher, file, 1, &m, 0) == 0
26 	        && m.rm_so > 0
27 	        && file[--m.rm_so] == '.') ? m.rm_so : -1;
28 	}
29 
find_extr(struct archive * a)30 void find_extr(struct archive *a)
31 	{
32 	/* caller ensures a->extr == NULL */
33 
34 	regoff_t pos;
35 	struct extractor *x;
36 
37 	for (x = Extractors; x; x = x->next)
38 		{
39 		pos = match_extr(x, a->links.file.e);
40 		if (pos > 0
41 		    && (!a->extr || pos < a->lname)
42 		    && (!Extension || strcasecmp(Extension, a->links.file.e + pos + 1) == 0))
43 			{
44 			a->extr = x;
45 			a->lname = pos;
46 			if (Extension)
47 				return;
48 			}
49 		}
50 	}
51 
add_extrs(const char * p)52 void add_extrs(const char *p)
53 	{
54 	struct path cfg;
55 	size_t lp;
56 	DIR *dir;
57 	struct dirent *ent;
58 	struct extractor *x;
59 
60 	dir = opendir(p);
61 	if (!dir)
62 		return;
63 
64 	lp = strlen(p);
65 	while ((ent = readdir(dir)))
66 		{
67 		if (is_dot(ent->d_name))
68 			continue;
69 
70 		x = alloc(sizeof(struct extractor));
71 
72 		cfg.p = alloc(lp + 1 + strlen(ent->d_name) + sizeof "/subdirectory");
73 		cfg.e = str_cp(str_cp(str_cp(str_cp(cfg.p, p), "("), ent->d_name), ")$") - 1;
74 
75 		if (regcomp(&x->matcher, cfg.p + lp, REG_EXTENDED | REG_ICASE) != 0)
76 			{
77 			err(MSG_REGCOMP, errno, cfg.p + lp);
78 			free(cfg.p);
79 			free(x);
80 			continue;
81 			}
82 
83 		cfg.p[lp] = cfg.e[-1] = '/';
84 
85 		str_cp(cfg.e, "permissions");
86 		x->perms = file_type(true, cfg.p) > None;
87 		str_cp(cfg.e, "subdirectory");
88 		x->subdir = file_type(true, cfg.p) > None;
89 		str_cp(cfg.e, "extract");
90 		x->extract = cfg.p;
91 
92 		x->next = Extractors;
93 		Extractors = x;
94 		}
95 
96 	closedir(dir);
97 	}
98