1 /* direvent - directory content watcher daemon
2    Copyright (C) 2012-2016 Sergey Poznyakoff
3 
4    Direvent is free software; you can redistribute it and/or modify it
5    under the terms of the GNU General Public License as published by the
6    Free Software Foundation; either version 3 of the License, or (at your
7    option) any later version.
8 
9    Direvent is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License along
15    with direvent. If not, see <http://www.gnu.org/licenses/>. */
16 
17 #include "direvent.h"
18 
19 
20 struct symevt {
21 	char *name;
22 	event_mask mask;
23 	int line;
24 };
25 
26 struct grecs_symtab *evtab;
27 
28 unsigned
hash_string(const char * name,unsigned long hashsize)29 hash_string(const char *name, unsigned long hashsize)
30 {
31 	unsigned i;
32 
33 	for (i = 0; *name; name++) {
34 		i <<= 1;
35 		i ^= *(unsigned char*) name;
36 	}
37 	return i % hashsize;
38 }
39 
40 static unsigned
symevt_hash(void * data,unsigned long hashsize)41 symevt_hash(void *data, unsigned long hashsize)
42 {
43 	struct symevt *sym = data;
44 	return hash_string(sym->name, hashsize);
45 }
46 
47 static int
symevt_cmp(const void * a,const void * b)48 symevt_cmp(const void *a, const void *b)
49 {
50 	struct symevt const *syma = a;
51 	struct symevt const *symb = b;
52 
53 	return strcmp(syma->name, symb->name);
54 }
55 
56 static int
symevt_copy(void * a,void * b)57 symevt_copy(void *a, void *b)
58 {
59 	struct symevt *syma = a;
60 	struct symevt *symb = b;
61 
62 	syma->name = estrdup(symb->name);
63 	return 0;
64 }
65 
66 static void
symevt_free(void * p)67 symevt_free(void *p)
68 {
69 	struct symevt *sym = p;
70 	free(sym->name);
71 	free(sym);
72 }
73 
74 
75 int
defevt(const char * name,event_mask * mask,int line)76 defevt(const char *name, event_mask *mask, int line)
77 {
78 	struct symevt key, *evp;
79 	int install = 1;
80 
81 	if (!evtab) {
82 		evtab = grecs_symtab_create(sizeof(struct symevt),
83 					    symevt_hash, symevt_cmp,
84 					    symevt_copy,
85 					    NULL, symevt_free);
86 		if (!evtab) {
87 			diag(LOG_CRIT, "not enough memory");
88 			exit(1);
89 		}
90 	}
91 
92 	key.name = (char *) name;
93 	evp = grecs_symtab_lookup_or_install(evtab, &key, &install);
94 	if (!install)
95 		return evp->line;
96 	evp->mask = *mask;
97 	evp->line = line;
98 	return 0;
99 }
100 
101 int
getevt(const char * name,event_mask * mask)102 getevt(const char *name, event_mask *mask)
103 {
104 	if (evtab) {
105 		struct symevt key, *evp;
106 		key.name = (char *) name;
107 		evp = grecs_symtab_lookup_or_install(evtab, &key, NULL);
108 		if (evp) {
109 			*mask = evp->mask;
110 			return 0;
111 		}
112 	}
113 	if (trans_strtotok(sysev_transtab, name, &mask->sys_mask))
114 		return -1;
115 	mask->gen_mask = 0;
116 	return 0;
117 }
118 
119 int
evtnullp(event_mask * mask)120 evtnullp(event_mask *mask)
121 {
122 	return mask->gen_mask == 0 && mask->sys_mask == 0;
123 }
124 
125 struct transtab genev_transtab[] = {
126 	{ "create", GENEV_CREATE },
127 	{ "write",  GENEV_WRITE  },
128 	{ "attrib", GENEV_ATTRIB },
129 	{ "delete", GENEV_DELETE },
130 	{ NULL }
131 };
132 
133 event_mask *
event_mask_init(event_mask * m,int fflags,event_mask const * req)134 event_mask_init(event_mask *m, int fflags, event_mask const *req)
135 {
136 	int i;
137 
138 	m->sys_mask = fflags & req->sys_mask;
139 	m->gen_mask = 0;
140 	for (i = 0; i < genev_xlat[i].gen_mask; i++)
141 		if (genev_xlat[i].sys_mask & m->sys_mask)
142 			m->gen_mask |= genev_xlat[i].gen_mask;
143 	if (req->gen_mask)
144 		m->gen_mask &= req->gen_mask;
145 	return m;
146 }
147 
148 void
evtsetall(event_mask * m)149 evtsetall(event_mask *m)
150 {
151 	int i;
152 
153 	m->sys_mask = 0;
154 	m->gen_mask = 0;
155 	for (i = 0; i < genev_xlat[i].gen_mask; i++) {
156 		m->gen_mask |= genev_xlat[i].gen_mask;
157 		m->sys_mask |= genev_xlat[i].sys_mask;
158 	}
159 }
160