Commit 02acb35b authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

More work to turn our VCL dependency tracking into a proper symboltable

with references.
parent 3ef8142a
...@@ -89,6 +89,7 @@ varnishd_SOURCES = \ ...@@ -89,6 +89,7 @@ varnishd_SOURCES = \
mgt/mgt_param_tweak.c \ mgt/mgt_param_tweak.c \
mgt/mgt_pool.c \ mgt/mgt_pool.c \
mgt/mgt_shmem.c \ mgt/mgt_shmem.c \
mgt/mgt_symtab.c \
mgt/mgt_util.c \ mgt/mgt_util.c \
mgt/mgt_vcc.c \ mgt/mgt_vcc.c \
mgt/mgt_vcl.c \ mgt/mgt_vcl.c \
...@@ -137,6 +138,7 @@ noinst_HEADERS = \ ...@@ -137,6 +138,7 @@ noinst_HEADERS = \
http1/cache_http1.h \ http1/cache_http1.h \
http2/cache_http2.h \ http2/cache_http2.h \
mgt/mgt.h \ mgt/mgt.h \
mgt/mgt_vcl.h \
mgt/mgt_param.h \ mgt/mgt_param.h \
storage/storage.h \ storage/storage.h \
storage/storage_persistent.h \ storage/storage_persistent.h \
......
...@@ -215,9 +215,7 @@ void mgt_vcl_init(void); ...@@ -215,9 +215,7 @@ void mgt_vcl_init(void);
void mgt_vcl_startup(struct cli *, const char *vclsrc, const char *origin, void mgt_vcl_startup(struct cli *, const char *vclsrc, const char *origin,
const char *vclname, int Cflag); const char *vclname, int Cflag);
int mgt_push_vcls(struct cli *, unsigned *status, char **p); int mgt_push_vcls(struct cli *, unsigned *status, char **p);
void mgt_vcl_export_labels(struct vcc *);
int mgt_has_vcl(void); int mgt_has_vcl(void);
void mgt_vcl_symtab(struct vclprog *, struct vjsn *);
extern char *mgt_cc_cmd; extern char *mgt_cc_cmd;
extern const char *mgt_vcl_path; extern const char *mgt_vcl_path;
extern const char *mgt_vmod_path; extern const char *mgt_vmod_path;
......
/*-
* Copyright (c) 2019 Varnish Software AS
* All rights reserved.
*
* Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* VCL/VMOD symbol table
*/
#include "config.h"
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include "mgt/mgt.h"
#include "mgt/mgt_vcl.h"
#include "libvcc.h"
#include "vjsn.h"
/*--------------------------------------------------------------------*/
static const char *
mgt_vcl_symtab_val(const struct vjsn_val *vv, const char *val)
{
const struct vjsn_val *jv;
jv = vjsn_child(vv, val);
AN(jv);
assert(jv->type == VJSN_STRING);
AN(jv->value);
return (jv->value);
}
static void
mgt_vcl_import_vcl(struct vclprog *vp1, const struct vjsn_val *vv)
{
struct vclprog *vp2;
CHECK_OBJ_NOTNULL(vp1, VCLPROG_MAGIC);
AN(vv);
vp2 = mcf_vcl_byname(mgt_vcl_symtab_val(vv, "name"));
CHECK_OBJ_NOTNULL(vp2, VCLPROG_MAGIC);
mgt_vcl_dep_add(vp1, vp2);
}
static int
mgt_vcl_cache_vmod(const char *nm, const char *fm, const char *to)
{
int fi, fo;
int ret = 0;
ssize_t sz;
char buf[BUFSIZ];
fo = open(to, O_WRONLY | O_CREAT | O_EXCL, 0744);
if (fo < 0 && errno == EEXIST)
return (0);
if (fo < 0) {
fprintf(stderr, "While creating copy of vmod %s:\n\t%s: %s\n",
nm, to, vstrerror(errno));
return (1);
}
fi = open(fm, O_RDONLY);
if (fi < 0) {
fprintf(stderr, "Opening vmod %s from %s: %s\n",
nm, fm, vstrerror(errno));
AZ(unlink(to));
closefd(&fo);
return (1);
}
while (1) {
sz = read(fi, buf, sizeof buf);
if (sz == 0)
break;
if (sz < 0 || sz != write(fo, buf, sz)) {
fprintf(stderr, "Copying vmod %s: %s\n",
nm, vstrerror(errno));
AZ(unlink(to));
ret = 1;
break;
}
}
closefd(&fi);
AZ(fchmod(fo, 0444));
closefd(&fo);
return (ret);
}
static void
mgt_vcl_import_vmod(struct vclprog *vp, const struct vjsn_val *vv)
{
struct vmodfile *vf;
struct vmoddep *vd;
const char *v_name;
const char *v_file;
const char *v_dst;
CHECK_OBJ_NOTNULL(vp, VCLPROG_MAGIC);
AN(vv);
v_name = mgt_vcl_symtab_val(vv, "name");
v_file = mgt_vcl_symtab_val(vv, "file");
v_dst = mgt_vcl_symtab_val(vv, "dst");
VTAILQ_FOREACH(vf, &vmodhead, list)
if (!strcmp(vf->fname, v_dst))
break;
if (vf == NULL) {
ALLOC_OBJ(vf, VMODFILE_MAGIC);
AN(vf);
REPLACE(vf->fname, v_dst);
AN(vf->fname);
VTAILQ_INIT(&vf->vcls);
AZ(mgt_vcl_cache_vmod(v_name, v_file, v_dst));
VTAILQ_INSERT_TAIL(&vmodhead, vf, list);
}
ALLOC_OBJ(vd, VMODDEP_MAGIC);
AN(vd);
vd->to = vf;
VTAILQ_INSERT_TAIL(&vp->vmods, vd, lfrom);
VTAILQ_INSERT_TAIL(&vf->vcls, vd, lto);
}
void
mgt_vcl_symtab(struct vclprog *vp, const char *input)
{
struct vjsn *vj;
struct vjsn_val *v1, *v2;
const char *typ, *err;
CHECK_OBJ_NOTNULL(vp, VCLPROG_MAGIC);
AN(input);
vj = vjsn_parse(input, &err);
if (err != NULL) {
fprintf(stderr, "FATAL: Symtab parse error: %s\n%s\n",
err, input);
}
AZ(err);
AN(vj);
vp->symtab = vj;
assert(vj->value->type == VJSN_ARRAY);
VTAILQ_FOREACH(v1, &vj->value->children, list) {
assert(v1->type == VJSN_OBJECT);
v2 = vjsn_child(v1, "dir");
if (v2 == NULL)
continue;
assert(v2->type == VJSN_STRING);
if (strcmp(v2->value, "import"))
continue;
typ = mgt_vcl_symtab_val(v1, "type");
if (!strcmp(typ, "$VMOD"))
mgt_vcl_import_vmod(vp, v1);
else if (!strcmp(typ, "$VCL"))
mgt_vcl_import_vcl(vp, v1);
else
WRONG("Bad symtab import entry");
}
}
/*--------------------------------------------------------------------*/
void
mgt_vcl_export_labels(struct vcc *vcc)
{
struct vclprog *vp;
VTAILQ_FOREACH(vp, &vclhead, list) {
if (mcf_is_label(vp))
VCC_Predef(vcc, "VCL_VCL", vp->name);
}
}
/*--------------------------------------------------------------------*/
...@@ -39,25 +39,25 @@ ...@@ -39,25 +39,25 @@
#include <sys/stat.h> #include <sys/stat.h>
#include "mgt/mgt.h" #include "mgt/mgt.h"
#include "mgt/mgt_vcl.h"
#include "common/heritage.h" #include "common/heritage.h"
#include "storage/storage.h" #include "storage/storage.h"
#include "libvcc.h" #include "libvcc.h"
#include "vcli_serve.h" #include "vcli_serve.h"
#include "vfil.h" #include "vfil.h"
#include "vjsn.h"
#include "vsub.h" #include "vsub.h"
#include "vtim.h" #include "vtim.h"
struct vcc_priv { struct vcc_priv {
unsigned magic; unsigned magic;
#define VCC_PRIV_MAGIC 0x70080cb8 #define VCC_PRIV_MAGIC 0x70080cb8
char *dir;
const char *vclsrc; const char *vclsrc;
const char *vclsrcfile; const char *vclsrcfile;
char *csrcfile; struct vsb *dir;
char *libfile; struct vsb *csrcfile;
char *symfile; struct vsb *libfile;
struct vsb *symfile;
}; };
char *mgt_cc_cmd; char *mgt_cc_cmd;
...@@ -96,7 +96,7 @@ run_vcc(void *priv) ...@@ -96,7 +96,7 @@ run_vcc(void *priv)
VJ_subproc(JAIL_SUBPROC_VCC); VJ_subproc(JAIL_SUBPROC_VCC);
CAST_OBJ_NOTNULL(vp, priv, VCC_PRIV_MAGIC); CAST_OBJ_NOTNULL(vp, priv, VCC_PRIV_MAGIC);
AZ(chdir(vp->dir)); AZ(chdir(VSB_data(vp->dir)));
vcc = VCC_New(); vcc = VCC_New();
AN(vcc); AN(vcc);
...@@ -132,7 +132,7 @@ run_cc(void *priv) ...@@ -132,7 +132,7 @@ run_cc(void *priv)
VJ_subproc(JAIL_SUBPROC_CC); VJ_subproc(JAIL_SUBPROC_CC);
CAST_OBJ_NOTNULL(vp, priv, VCC_PRIV_MAGIC); CAST_OBJ_NOTNULL(vp, priv, VCC_PRIV_MAGIC);
AZ(chdir(vp->dir)); AZ(chdir(VSB_data(vp->dir)));
sb = VSB_new_auto(); sb = VSB_new_auto();
AN(sb); AN(sb);
...@@ -180,7 +180,7 @@ run_dlopen(void *priv) ...@@ -180,7 +180,7 @@ run_dlopen(void *priv)
VJ_subproc(JAIL_SUBPROC_VCLLOAD); VJ_subproc(JAIL_SUBPROC_VCLLOAD);
CAST_OBJ_NOTNULL(vp, priv, VCC_PRIV_MAGIC); CAST_OBJ_NOTNULL(vp, priv, VCC_PRIV_MAGIC);
if (VCL_TestLoad(vp->libfile)) if (VCL_TestLoad(VSB_data(vp->libfile)))
exit(1); exit(1);
exit(0); exit(0);
} }
...@@ -215,13 +215,13 @@ static unsigned ...@@ -215,13 +215,13 @@ static unsigned
mgt_vcc_compile(struct vcc_priv *vp, struct vsb *sb, int C_flag) mgt_vcc_compile(struct vcc_priv *vp, struct vsb *sb, int C_flag)
{ {
char *csrc; char *csrc;
const char *err;
unsigned subs; unsigned subs;
struct vjsn *vj;
if (mgt_vcc_touchfile(vp->csrcfile, sb)) AN(sb);
VSB_clear(sb);
if (mgt_vcc_touchfile(VSB_data(vp->csrcfile), sb))
return (2); return (2);
if (mgt_vcc_touchfile(vp->libfile, sb)) if (mgt_vcc_touchfile(VSB_data(vp->libfile), sb))
return (2); return (2);
subs = VSUB_run(sb, run_vcc, vp, "VCC-compiler", -1); subs = VSUB_run(sb, run_vcc, vp, "VCC-compiler", -1);
...@@ -229,20 +229,15 @@ mgt_vcc_compile(struct vcc_priv *vp, struct vsb *sb, int C_flag) ...@@ -229,20 +229,15 @@ mgt_vcc_compile(struct vcc_priv *vp, struct vsb *sb, int C_flag)
return (subs); return (subs);
if (C_flag) { if (C_flag) {
csrc = VFIL_readfile(NULL, vp->csrcfile, NULL); csrc = VFIL_readfile(NULL, VSB_data(vp->csrcfile), NULL);
AN(csrc); AN(csrc);
VSB_cat(sb, csrc); VSB_cat(sb, csrc);
free(csrc); free(csrc);
VSB_printf(sb, "/* EXTERNAL SYMBOL TABLE\n"); VSB_printf(sb, "/* EXTERNAL SYMBOL TABLE\n");
csrc = VFIL_readfile(NULL, vp->symfile, NULL); csrc = VFIL_readfile(NULL, VSB_data(vp->symfile), NULL);
AN(csrc); AN(csrc);
VSB_cat(sb, csrc); VSB_cat(sb, csrc);
vj = vjsn_parse(csrc, &err);
if (err != NULL)
VSB_printf(sb, "# Parse error: %s\n", err);
if (vj != NULL)
vjsn_delete(&vj);
VSB_printf(sb, "*/\n"); VSB_printf(sb, "*/\n");
free(csrc); free(csrc);
} }
...@@ -257,25 +252,53 @@ mgt_vcc_compile(struct vcc_priv *vp, struct vsb *sb, int C_flag) ...@@ -257,25 +252,53 @@ mgt_vcc_compile(struct vcc_priv *vp, struct vsb *sb, int C_flag)
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
static void
mgt_vcc_init_vp(struct vcc_priv *vp)
{
INIT_OBJ(vp, VCC_PRIV_MAGIC);
vp->csrcfile = VSB_new_auto();
AN(vp->csrcfile);
vp->libfile = VSB_new_auto();
AN(vp->libfile);
vp->symfile = VSB_new_auto();
AN(vp->symfile);
vp->dir = VSB_new_auto();
AN(vp->dir);
}
static void
mgt_vcc_fini_vp(struct vcc_priv *vp, int leave_lib)
{
if (!MGT_DO_DEBUG(DBG_VCL_KEEP)) {
(void)unlink(VSB_data(vp->csrcfile));
(void)unlink(VSB_data(vp->symfile));
if (!leave_lib)
(void)unlink(VSB_data(vp->libfile));
}
(void)rmdir(VSB_data(vp->dir));
VSB_destroy(&vp->csrcfile);
VSB_destroy(&vp->libfile);
VSB_destroy(&vp->symfile);
VSB_destroy(&vp->dir);
}
char * char *
mgt_VccCompile(struct cli *cli, struct vclprog *vcl, const char *vclname, mgt_VccCompile(struct cli *cli, struct vclprog *vcl, const char *vclname,
const char *vclsrc, const char *vclsrcfile, int C_flag) const char *vclsrc, const char *vclsrcfile, int C_flag)
{ {
struct vcc_priv vp; struct vcc_priv vp[1];
struct vsb *sb; struct vsb *sb;
struct vjsn *vj;
unsigned status; unsigned status;
const char *err;
char *p; char *p;
AN(cli); AN(cli);
sb = VSB_new_auto(); sb = VSB_new_auto();
XXXAN(sb); AN(sb);
INIT_OBJ(&vp, VCC_PRIV_MAGIC); mgt_vcc_init_vp(vp);
vp.vclsrc = vclsrc; vp->vclsrc = vclsrc;
vp.vclsrcfile = vclsrcfile; vp->vclsrcfile = vclsrcfile;
/* /*
* The subdirectory must have a unique name to 100% certain evade * The subdirectory must have a unique name to 100% certain evade
...@@ -309,56 +332,35 @@ mgt_VccCompile(struct cli *cli, struct vclprog *vcl, const char *vclname, ...@@ -309,56 +332,35 @@ mgt_VccCompile(struct cli *cli, struct vclprog *vcl, const char *vclname,
* *
* The Best way to reproduce this is to have regexps in the VCL. * The Best way to reproduce this is to have regexps in the VCL.
*/ */
VSB_printf(sb, "vcl_%s.%.6f", vclname, VTIM_real());
AZ(VSB_finish(sb));
vp.dir = strdup(VSB_data(sb));
AN(vp.dir);
if (VJ_make_subdir(vp.dir, "VCL", cli->sb)) { VSB_printf(vp->dir, "vcl_%s.%.6f", vclname, VTIM_real());
free(vp.dir); AZ(VSB_finish(vp->dir));
VSB_printf(vp->csrcfile, "%s/%s", VSB_data(vp->dir), VGC_SRC);
AZ(VSB_finish(vp->csrcfile));
VSB_printf(vp->libfile, "%s/%s", VSB_data(vp->dir), VGC_LIB);
AZ(VSB_finish(vp->libfile));
VSB_printf(vp->symfile, "%s/%s", VSB_data(vp->dir), VGC_SYM);
AZ(VSB_finish(vp->symfile));
if (VJ_make_subdir(VSB_data(vp->dir), "VCL", cli->sb)) {
mgt_vcc_fini_vp(vp, 0);
VSB_destroy(&sb); VSB_destroy(&sb);
VCLI_Out(cli, "VCL compilation failed"); VCLI_Out(cli, "VCL compilation failed");
VCLI_SetResult(cli, CLIS_PARAM); VCLI_SetResult(cli, CLIS_PARAM);
return (NULL); return (NULL);
} }
VSB_clear(sb); status = mgt_vcc_compile(vp, sb, C_flag);
VSB_printf(sb, "%s/%s", vp.dir, VGC_SRC);
AZ(VSB_finish(sb));
vp.csrcfile = strdup(VSB_data(sb));
AN(vp.csrcfile);
VSB_clear(sb);
VSB_printf(sb, "%s/%s", vp.dir, VGC_LIB);
AZ(VSB_finish(sb));
vp.libfile = strdup(VSB_data(sb));
AN(vp.csrcfile);
VSB_clear(sb);
VSB_printf(sb, "%s/%s", vp.dir, VGC_SYM);
AZ(VSB_finish(sb));
vp.symfile = strdup(VSB_data(sb));
AN(vp.symfile);
VSB_clear(sb);
status = mgt_vcc_compile(&vp, sb, C_flag);
AZ(VSB_finish(sb)); AZ(VSB_finish(sb));
if (VSB_len(sb) > 0) if (VSB_len(sb) > 0)
VCLI_Out(cli, "%s", VSB_data(sb)); VCLI_Out(cli, "%s", VSB_data(sb));
VSB_destroy(&sb); VSB_destroy(&sb);
if (status || C_flag) { if (status || C_flag) {
if (!MGT_DO_DEBUG(DBG_VCL_KEEP)) { mgt_vcc_fini_vp(vp, 0);
(void)unlink(vp.csrcfile);
(void)unlink(vp.libfile);
(void)unlink(vp.symfile);
(void)rmdir(vp.dir);
}
free(vp.csrcfile);
free(vp.libfile);
free(vp.symfile);
free(vp.dir);
if (status) { if (status) {
VCLI_Out(cli, "VCL compilation failed"); VCLI_Out(cli, "VCL compilation failed");
VCLI_SetResult(cli, CLIS_PARAM); VCLI_SetResult(cli, CLIS_PARAM);
...@@ -366,26 +368,13 @@ mgt_VccCompile(struct cli *cli, struct vclprog *vcl, const char *vclname, ...@@ -366,26 +368,13 @@ mgt_VccCompile(struct cli *cli, struct vclprog *vcl, const char *vclname,
return (NULL); return (NULL);
} }
p = VFIL_readfile(NULL, vp.symfile, NULL); p = VFIL_readfile(NULL, VSB_data(vp->symfile), NULL);
AN(p); AN(p);
vj = vjsn_parse(p, &err); mgt_vcl_symtab(vcl, p);
if (err != NULL)
fprintf(stderr, "FATAL: Symtab parse error: %s\n%s\n",
err, p);
AZ(err);
AN(vj);
free(p);
mgt_vcl_symtab(vcl, vj);
(void)unlink(vp.symfile);
free(vp.symfile);
if (!MGT_DO_DEBUG(DBG_VCL_KEEP))
(void)unlink(vp.csrcfile);
free(vp.csrcfile);
free(vp.dir);
VCLI_Out(cli, "VCL compiled.\n"); VCLI_Out(cli, "VCL compiled.\n");
return (vp.libfile); REPLACE(p, VSB_data(vp->libfile));
mgt_vcc_fini_vp(vp, 1);
return (p);
} }
...@@ -31,17 +31,15 @@ ...@@ -31,17 +31,15 @@
#include "config.h" #include "config.h"
#include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <sys/stat.h>
#include "mgt/mgt.h" #include "mgt/mgt.h"
#include "mgt/mgt_vcl.h"
#include "common/heritage.h" #include "common/heritage.h"
#include "libvcc.h"
#include "vcli_serve.h" #include "vcli_serve.h"
#include "vct.h" #include "vct.h"
#include "vev.h" #include "vev.h"
...@@ -56,53 +54,8 @@ static const char * const VCL_STATE_LABEL = "label"; ...@@ -56,53 +54,8 @@ static const char * const VCL_STATE_LABEL = "label";
static int vcl_count; static int vcl_count;
struct vclprog; struct vclproghead vclhead = VTAILQ_HEAD_INITIALIZER(vclhead);
struct vmodfile; struct vmodfilehead vmodhead = VTAILQ_HEAD_INITIALIZER(vmodhead);
struct vmoddep {
unsigned magic;
#define VMODDEP_MAGIC 0xc1490542
VTAILQ_ENTRY(vmoddep) lfrom;
struct vmodfile *to;
VTAILQ_ENTRY(vmoddep) lto;
};
struct vcldep {
unsigned magic;
#define VCLDEP_MAGIC 0xa9a17dc2
struct vclprog *from;
VTAILQ_ENTRY(vcldep) lfrom;
struct vclprog *to;
VTAILQ_ENTRY(vcldep) lto;
};
struct vclprog {
unsigned magic;
#define VCLPROG_MAGIC 0x9ac09fea
VTAILQ_ENTRY(vclprog) list;
char *name;
char *fname;
unsigned warm;
const char * state;
double go_cold;
struct vjsn *symtab;
VTAILQ_HEAD(, vcldep) dfrom;
VTAILQ_HEAD(, vcldep) dto;
int nto;
int loaded;
VTAILQ_HEAD(, vmoddep) vmods;
};
struct vmodfile {
unsigned magic;
#define VMODFILE_MAGIC 0xffa1a0d5
char *fname;
VTAILQ_ENTRY(vmodfile) list;
VTAILQ_HEAD(, vmoddep) vcls;
};
static VTAILQ_HEAD(, vclprog) vclhead = VTAILQ_HEAD_INITIALIZER(vclhead);
static VTAILQ_HEAD(, vmodfile) vmodhead = VTAILQ_HEAD_INITIALIZER(vmodhead);
static struct vclprog *active_vcl; static struct vclprog *active_vcl;
static struct vev *e_poker; static struct vev *e_poker;
...@@ -127,7 +80,7 @@ mcf_vcl_parse_state(struct cli *cli, const char *s) ...@@ -127,7 +80,7 @@ mcf_vcl_parse_state(struct cli *cli, const char *s)
return (NULL); return (NULL);
} }
static struct vclprog * struct vclprog *
mcf_vcl_byname(const char *name) mcf_vcl_byname(const char *name)
{ {
struct vclprog *vp; struct vclprog *vp;
...@@ -189,7 +142,7 @@ mcf_find_no_vcl(struct cli *cli, const char *name) ...@@ -189,7 +142,7 @@ mcf_find_no_vcl(struct cli *cli, const char *name)
return (1); return (1);
} }
static int int
mcf_is_label(const struct vclprog *vp) mcf_is_label(const struct vclprog *vp)
{ {
return (vp->state == VCL_STATE_LABEL); return (vp->state == VCL_STATE_LABEL);
...@@ -197,7 +150,7 @@ mcf_is_label(const struct vclprog *vp) ...@@ -197,7 +150,7 @@ mcf_is_label(const struct vclprog *vp)
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
static void void
mgt_vcl_dep_add(struct vclprog *vp_from, struct vclprog *vp_to) mgt_vcl_dep_add(struct vclprog *vp_from, struct vclprog *vp_to)
{ {
struct vcldep *vd; struct vcldep *vd;
...@@ -316,135 +269,6 @@ mgt_vcl_del(struct vclprog *vp) ...@@ -316,135 +269,6 @@ mgt_vcl_del(struct vclprog *vp)
FREE_OBJ(vp); FREE_OBJ(vp);
} }
static const char *
mgt_vcl_symtab_val(const struct vjsn_val *vv, const char *val)
{
const struct vjsn_val *jv;
jv = vjsn_child(vv, val);
AN(jv);
assert(jv->type == VJSN_STRING);
AN(jv->value);
return (jv->value);
}
static void
mgt_vcl_import_vcl(struct vclprog *vp1, const struct vjsn_val *vv)
{
struct vclprog *vp2;
CHECK_OBJ_NOTNULL(vp1, VCLPROG_MAGIC);
AN(vv);
vp2 = mcf_vcl_byname(mgt_vcl_symtab_val(vv, "name"));
CHECK_OBJ_NOTNULL(vp2, VCLPROG_MAGIC);
mgt_vcl_dep_add(vp1, vp2);
}
static int
mgt_vcl_cache_vmod(const char *nm, const char *fm, const char *to)
{
int fi, fo;
int ret = 0;
ssize_t sz;
char buf[BUFSIZ];
fo = open(to, O_WRONLY | O_CREAT | O_EXCL, 0744);
if (fo < 0 && errno == EEXIST)
return (0);
if (fo < 0) {
fprintf(stderr, "While creating copy of vmod %s:\n\t%s: %s\n",
nm, to, vstrerror(errno));
return (1);
}
fi = open(fm, O_RDONLY);
if (fi < 0) {
fprintf(stderr, "Opening vmod %s from %s: %s\n",
nm, fm, vstrerror(errno));
AZ(unlink(to));
closefd(&fo);
return (1);
}
while (1) {
sz = read(fi, buf, sizeof buf);
if (sz == 0)
break;
if (sz < 0 || sz != write(fo, buf, sz)) {
fprintf(stderr, "Copying vmod %s: %s\n",
nm, vstrerror(errno));
AZ(unlink(to));
ret = 1;
break;
}
}
closefd(&fi);
AZ(fchmod(fo, 0444));
closefd(&fo);
return (ret);
}
static void
mgt_vcl_import_vmod(struct vclprog *vp, const struct vjsn_val *vv)
{
struct vmodfile *vf;
struct vmoddep *vd;
const char *v_name;
const char *v_file;
const char *v_dst;
CHECK_OBJ_NOTNULL(vp, VCLPROG_MAGIC);
AN(vv);
v_name = mgt_vcl_symtab_val(vv, "name");
v_file = mgt_vcl_symtab_val(vv, "file");
v_dst = mgt_vcl_symtab_val(vv, "dst");
VTAILQ_FOREACH(vf, &vmodhead, list)
if (!strcmp(vf->fname, v_dst))
break;
if (vf == NULL) {
ALLOC_OBJ(vf, VMODFILE_MAGIC);
AN(vf);
REPLACE(vf->fname, v_dst);
AN(vf->fname);
VTAILQ_INIT(&vf->vcls);
AZ(mgt_vcl_cache_vmod(v_name, v_file, v_dst));
VTAILQ_INSERT_TAIL(&vmodhead, vf, list);
}
ALLOC_OBJ(vd, VMODDEP_MAGIC);
AN(vd);
vd->to = vf;
VTAILQ_INSERT_TAIL(&vp->vmods, vd, lfrom);
VTAILQ_INSERT_TAIL(&vf->vcls, vd, lto);
}
void
mgt_vcl_symtab(struct vclprog *vp, struct vjsn *vj)
{
struct vjsn_val *v1, *v2;
const char *typ;
CHECK_OBJ_NOTNULL(vp, VCLPROG_MAGIC);
vp->symtab = vj;
assert(vj->value->type == VJSN_ARRAY);
VTAILQ_FOREACH(v1, &vj->value->children, list) {
assert(v1->type == VJSN_OBJECT);
v2 = vjsn_child(v1, "dir");
if (v2 == NULL)
continue;
assert(v2->type == VJSN_STRING);
if (strcmp(v2->value, "import"))
continue;
typ = mgt_vcl_symtab_val(v1, "type");
if (!strcmp(typ, "$VMOD"))
mgt_vcl_import_vmod(vp, v1);
else if (!strcmp(typ, "$VCL"))
mgt_vcl_import_vcl(vp, v1);
else
WRONG("Bad symtab import entry");
}
}
int int
mgt_has_vcl(void) mgt_has_vcl(void)
{ {
...@@ -673,18 +497,6 @@ mgt_vcl_startup(struct cli *cli, const char *vclsrc, const char *vclname, ...@@ -673,18 +497,6 @@ mgt_vcl_startup(struct cli *cli, const char *vclsrc, const char *vclname,
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
void
mgt_vcl_export_labels(struct vcc *vcc)
{
struct vclprog *vp;
VTAILQ_FOREACH(vp, &vclhead, list) {
if (mcf_is_label(vp))
VCC_Predef(vcc, "VCL_VCL", vp->name);
}
}
/*--------------------------------------------------------------------*/
int int
mgt_push_vcls(struct cli *cli, unsigned *status, char **p) mgt_push_vcls(struct cli *cli, unsigned *status, char **p)
{ {
......
/*-
* Copyright (c) 2019 Varnish Software AS
* All rights reserved.
*
* Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* VCL/VMOD symbol table
*/
struct vclprog;
struct vmodfile;
struct vmoddep {
unsigned magic;
#define VMODDEP_MAGIC 0xc1490542
VTAILQ_ENTRY(vmoddep) lfrom;
struct vmodfile *to;
VTAILQ_ENTRY(vmoddep) lto;
};
struct vcldep {
unsigned magic;
#define VCLDEP_MAGIC 0xa9a17dc2
struct vclprog *from;
VTAILQ_ENTRY(vcldep) lfrom;
struct vclprog *to;
VTAILQ_ENTRY(vcldep) lto;
};
struct vclprog {
unsigned magic;
#define VCLPROG_MAGIC 0x9ac09fea
VTAILQ_ENTRY(vclprog) list;
char *name;
char *fname;
unsigned warm;
const char * state;
double go_cold;
struct vjsn *symtab;
VTAILQ_HEAD(, vcldep) dfrom;
VTAILQ_HEAD(, vcldep) dto;
int nto;
int loaded;
VTAILQ_HEAD(, vmoddep) vmods;
};
struct vmodfile {
unsigned magic;
#define VMODFILE_MAGIC 0xffa1a0d5
char *fname;
VTAILQ_ENTRY(vmodfile) list;
VTAILQ_HEAD(, vmoddep) vcls;
};
extern VTAILQ_HEAD(vclproghead, vclprog) vclhead;
extern VTAILQ_HEAD(vmodfilehead, vmodfile) vmodhead;
struct vclprog *mcf_vcl_byname(const char *name);
void mgt_vcl_dep_add(struct vclprog *vp_from, struct vclprog *vp_to);
int mcf_is_label(const struct vclprog *vp);
void mgt_vcl_export_labels(struct vcc *vcc);
void mgt_vcl_symtab(struct vclprog *vp, const char *input);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment