| | varnish-cache/bin/varnishd/mgt/mgt_symtab.c |
0 |
|
/*- |
1 |
|
* Copyright (c) 2019 Varnish Software AS |
2 |
|
* All rights reserved. |
3 |
|
* |
4 |
|
* Author: Poul-Henning Kamp <phk@phk.freebsd.dk> |
5 |
|
* |
6 |
|
* SPDX-License-Identifier: BSD-2-Clause |
7 |
|
* |
8 |
|
* Redistribution and use in source and binary forms, with or without |
9 |
|
* modification, are permitted provided that the following conditions |
10 |
|
* are met: |
11 |
|
* 1. Redistributions of source code must retain the above copyright |
12 |
|
* notice, this list of conditions and the following disclaimer. |
13 |
|
* 2. Redistributions in binary form must reproduce the above copyright |
14 |
|
* notice, this list of conditions and the following disclaimer in the |
15 |
|
* documentation and/or other materials provided with the distribution. |
16 |
|
* |
17 |
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
18 |
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
19 |
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
20 |
|
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE |
21 |
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
22 |
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
23 |
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
24 |
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
25 |
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
26 |
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
27 |
|
* SUCH DAMAGE. |
28 |
|
* |
29 |
|
* VCL/VMOD symbol table |
30 |
|
*/ |
31 |
|
|
32 |
|
#include "config.h" |
33 |
|
|
34 |
|
#include <fcntl.h> |
35 |
|
#include <stdio.h> |
36 |
|
#include <stdlib.h> |
37 |
|
#include <string.h> |
38 |
|
#include <unistd.h> |
39 |
|
#include <sys/stat.h> |
40 |
|
|
41 |
|
#include "mgt/mgt.h" |
42 |
|
#include "mgt/mgt_vcl.h" |
43 |
|
|
44 |
|
#include "vcli_serve.h" |
45 |
|
#include "vjsn.h" |
46 |
|
|
47 |
|
/*--------------------------------------------------------------------*/ |
48 |
|
|
49 |
|
static const char * |
50 |
81240 |
mgt_vcl_symtab_val(const struct vjsn_val *vv, const char *val) |
51 |
|
{ |
52 |
|
const struct vjsn_val *jv; |
53 |
|
|
54 |
81240 |
jv = vjsn_child(vv, val); |
55 |
81240 |
AN(jv); |
56 |
81240 |
assert(vjsn_is_string(jv)); |
57 |
81240 |
AN(jv->value); |
58 |
81240 |
return (jv->value); |
59 |
|
} |
60 |
|
|
61 |
|
static void |
62 |
840 |
mgt_vcl_import_vcl(struct vclprog *vp1, const struct vjsn_val *vv) |
63 |
|
{ |
64 |
|
struct vclprog *vp2; |
65 |
|
|
66 |
840 |
CHECK_OBJ_NOTNULL(vp1, VCLPROG_MAGIC); |
67 |
840 |
AN(vv); |
68 |
|
|
69 |
840 |
vp2 = mcf_vcl_byname(mgt_vcl_symtab_val(vv, "name")); |
70 |
840 |
CHECK_OBJ_NOTNULL(vp2, VCLPROG_MAGIC); |
71 |
840 |
mgt_vcl_dep_add(vp1, vp2)->vj = vv; |
72 |
840 |
} |
73 |
|
|
74 |
|
static int |
75 |
14240 |
mgt_vcl_cache_vmod(const char *nm, const char *fm, const char *to) |
76 |
|
{ |
77 |
|
int fi, fo; |
78 |
14240 |
int ret = 0; |
79 |
|
ssize_t sz; |
80 |
|
char buf[BUFSIZ]; |
81 |
|
|
82 |
14240 |
fo = open(to, O_WRONLY | O_CREAT | O_EXCL, 0744); |
83 |
14240 |
if (fo < 0 && errno == EEXIST) |
84 |
0 |
return (0); |
85 |
14240 |
if (fo < 0) { |
86 |
0 |
fprintf(stderr, "While creating copy of vmod %s:\n\t%s: %s\n", |
87 |
0 |
nm, to, VAS_errtxt(errno)); |
88 |
0 |
return (1); |
89 |
|
} |
90 |
14240 |
fi = open(fm, O_RDONLY); |
91 |
14240 |
if (fi < 0) { |
92 |
0 |
fprintf(stderr, "Opening vmod %s from %s: %s\n", |
93 |
0 |
nm, fm, VAS_errtxt(errno)); |
94 |
0 |
AZ(unlink(to)); |
95 |
0 |
closefd(&fo); |
96 |
0 |
return (1); |
97 |
|
} |
98 |
2980480 |
while (1) { |
99 |
2980480 |
sz = read(fi, buf, sizeof buf); |
100 |
2980480 |
if (sz == 0) |
101 |
14240 |
break; |
102 |
2966240 |
if (sz < 0 || sz != write(fo, buf, sz)) { |
103 |
0 |
fprintf(stderr, "Copying vmod %s: %s\n", |
104 |
0 |
nm, VAS_errtxt(errno)); |
105 |
0 |
AZ(unlink(to)); |
106 |
0 |
ret = 1; |
107 |
0 |
break; |
108 |
|
} |
109 |
|
} |
110 |
14240 |
closefd(&fi); |
111 |
14240 |
AZ(fchmod(fo, 0444)); |
112 |
14240 |
closefd(&fo); |
113 |
14240 |
return (ret); |
114 |
14240 |
} |
115 |
|
|
116 |
|
static void |
117 |
19920 |
mgt_vcl_import_vmod(struct vclprog *vp, const struct vjsn_val *vv) |
118 |
|
{ |
119 |
|
struct vmodfile *vf; |
120 |
|
struct vmoddep *vd; |
121 |
|
const char *v_name; |
122 |
|
const char *v_file; |
123 |
|
const char *v_dst; |
124 |
|
const struct vjsn_val *jv; |
125 |
|
|
126 |
19920 |
CHECK_OBJ_NOTNULL(vp, VCLPROG_MAGIC); |
127 |
19920 |
AN(vv); |
128 |
|
|
129 |
19920 |
jv = vjsn_child(vv, "vext"); |
130 |
19920 |
if (vjsn_is_true(jv)) |
131 |
40 |
return; |
132 |
19880 |
AN(jv); |
133 |
19880 |
v_name = mgt_vcl_symtab_val(vv, "name"); |
134 |
19880 |
v_file = mgt_vcl_symtab_val(vv, "file"); |
135 |
19880 |
v_dst = mgt_vcl_symtab_val(vv, "dst"); |
136 |
|
|
137 |
25760 |
VTAILQ_FOREACH(vf, &vmodhead, list) |
138 |
11520 |
if (!strcmp(vf->fname, v_dst)) |
139 |
5640 |
break; |
140 |
19880 |
if (vf == NULL) { |
141 |
14240 |
ALLOC_OBJ(vf, VMODFILE_MAGIC); |
142 |
14240 |
AN(vf); |
143 |
14240 |
REPLACE(vf->fname, v_dst); |
144 |
14240 |
VTAILQ_INIT(&vf->vcls); |
145 |
14240 |
AZ(mgt_vcl_cache_vmod(v_name, v_file, v_dst)); |
146 |
14240 |
VTAILQ_INSERT_TAIL(&vmodhead, vf, list); |
147 |
14240 |
} |
148 |
19880 |
ALLOC_OBJ(vd, VMODDEP_MAGIC); |
149 |
19880 |
AN(vd); |
150 |
19880 |
vd->to = vf; |
151 |
19880 |
VTAILQ_INSERT_TAIL(&vp->vmods, vd, lfrom); |
152 |
19880 |
VTAILQ_INSERT_TAIL(&vf->vcls, vd, lto); |
153 |
19920 |
} |
154 |
|
|
155 |
|
void |
156 |
48120 |
mgt_vcl_symtab(struct vclprog *vp, const char *input) |
157 |
|
{ |
158 |
|
struct vjsn *vj; |
159 |
|
struct vjsn_val *v1, *v2; |
160 |
|
const char *typ, *err; |
161 |
|
|
162 |
48120 |
CHECK_OBJ_NOTNULL(vp, VCLPROG_MAGIC); |
163 |
48120 |
AN(input); |
164 |
48120 |
vj = vjsn_parse(input, &err); |
165 |
48120 |
if (err != NULL) { |
166 |
0 |
fprintf(stderr, "FATAL: Symtab parse error: %s\n%s\n", |
167 |
0 |
err, input); |
168 |
0 |
} |
169 |
48120 |
AZ(err); |
170 |
48120 |
AN(vj); |
171 |
48120 |
vp->symtab = vj; |
172 |
48120 |
assert(vjsn_is_array(vj->value)); |
173 |
117000 |
VTAILQ_FOREACH(v1, &vj->value->children, list) { |
174 |
68880 |
assert(vjsn_is_object(v1)); |
175 |
68880 |
v2 = vjsn_child(v1, "dir"); |
176 |
68880 |
if (v2 == NULL) |
177 |
48120 |
continue; |
178 |
20760 |
assert(vjsn_is_string(v2)); |
179 |
20760 |
if (strcmp(v2->value, "import")) |
180 |
0 |
continue; |
181 |
20760 |
typ = mgt_vcl_symtab_val(v1, "type"); |
182 |
20760 |
if (!strcmp(typ, "$VMOD")) |
183 |
19920 |
mgt_vcl_import_vmod(vp, v1); |
184 |
840 |
else if (!strcmp(typ, "$VCL")) |
185 |
840 |
mgt_vcl_import_vcl(vp, v1); |
186 |
|
else |
187 |
0 |
WRONG("Bad symtab import entry"); |
188 |
20760 |
} |
189 |
48120 |
} |
190 |
|
|
191 |
|
void |
192 |
60880 |
mgt_vcl_symtab_clean(struct vclprog *vp) |
193 |
|
{ |
194 |
|
|
195 |
60880 |
if (vp->symtab) |
196 |
48120 |
vjsn_delete(&vp->symtab); |
197 |
60880 |
} |
198 |
|
|
199 |
|
/*--------------------------------------------------------------------*/ |
200 |
|
|
201 |
|
static void |
202 |
4400 |
mcf_vcl_vjsn_dump(struct cli *cli, const struct vjsn_val *vj, int indent) |
203 |
|
{ |
204 |
|
struct vjsn_val *vj1; |
205 |
4400 |
AN(cli); |
206 |
4400 |
AN(vj); |
207 |
|
|
208 |
4400 |
VCLI_Out(cli, "%*s", indent, ""); |
209 |
4400 |
if (vj->name != NULL) |
210 |
2960 |
VCLI_Out(cli, "[\"%s\"]: ", vj->name); |
211 |
4400 |
VCLI_Out(cli, "{%s}", vj->type); |
212 |
4400 |
if (vj->value != NULL) |
213 |
2880 |
VCLI_Out(cli, " <%s>", vj->value); |
214 |
4400 |
VCLI_Out(cli, "\n"); |
215 |
8000 |
VTAILQ_FOREACH(vj1, &vj->children, list) |
216 |
3600 |
mcf_vcl_vjsn_dump(cli, vj1, indent + 2); |
217 |
4400 |
} |
218 |
|
|
219 |
|
void v_matchproto_(cli_func_t) |
220 |
40 |
mcf_vcl_symtab(struct cli *cli, const char * const *av, void *priv) |
221 |
|
{ |
222 |
|
struct vclprog *vp; |
223 |
|
struct vcldep *vd; |
224 |
|
|
225 |
40 |
(void)av; |
226 |
40 |
(void)priv; |
227 |
440 |
VTAILQ_FOREACH(vp, &vclhead, list) { |
228 |
400 |
if (mcf_is_label(vp)) |
229 |
80 |
VCLI_Out(cli, "Label: %s\n", vp->name); |
230 |
|
else |
231 |
320 |
VCLI_Out(cli, "Vcl: %s\n", vp->name); |
232 |
400 |
if (!VTAILQ_EMPTY(&vp->dfrom)) { |
233 |
320 |
VCLI_Out(cli, " imports from:\n"); |
234 |
640 |
VTAILQ_FOREACH(vd, &vp->dfrom, lfrom) { |
235 |
320 |
VCLI_Out(cli, " %s\n", vd->to->name); |
236 |
320 |
if (vd->vj) |
237 |
240 |
mcf_vcl_vjsn_dump(cli, vd->vj, 6); |
238 |
320 |
} |
239 |
320 |
} |
240 |
400 |
if (!VTAILQ_EMPTY(&vp->dto)) { |
241 |
160 |
VCLI_Out(cli, " exports to:\n"); |
242 |
480 |
VTAILQ_FOREACH(vd, &vp->dto, lto) { |
243 |
320 |
VCLI_Out(cli, " %s\n", vd->from->name); |
244 |
320 |
if (vd->vj) |
245 |
240 |
mcf_vcl_vjsn_dump(cli, vd->vj, 6); |
246 |
320 |
} |
247 |
160 |
} |
248 |
400 |
if (vp->symtab != NULL) { |
249 |
320 |
VCLI_Out(cli, " symtab:\n"); |
250 |
320 |
mcf_vcl_vjsn_dump(cli, vp->symtab->value, 4); |
251 |
320 |
} |
252 |
400 |
} |
253 |
40 |
} |