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